Merge changes from topic "sf-re-2"
* changes:
libgui: add a helper for GLConsumer::getCurrentCrop
libgui: use mat4 in GLConsumer
libgui: remove unused GLConsumer methods
libgui: add more IGBC wrappers to ConsumerBase
libgui: tidy up CpuConsumer
libgui: fix and clean up CpuConsumer::unlockBuffer
libgui: fix a race in CpuConsumer::lockNextBuffer
libgui: add helper to initialize CpuConsumer::LockedBuffer
libgui: add helper to find CpuConsumer::AcquiredBuffer
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index da42956..34e6d80 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -49,16 +49,6 @@
BufferItemConsumer::~BufferItemConsumer() {}
-void BufferItemConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- BI_LOGE("setName: BufferItemConsumer is abandoned!");
- return;
- }
- mName = name;
- mConsumer->setConsumerName(name);
-}
-
void BufferItemConsumer::setBufferFreedListener(
const wp<BufferFreedListener>& listener) {
Mutex::Autolock _l(mMutex);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 7aa7872..f9e292e 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -182,6 +182,16 @@
return mAbandoned;
}
+void ConsumerBase::setName(const String8& name) {
+ Mutex::Autolock _l(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setName: ConsumerBase is abandoned!");
+ return;
+ }
+ mName = name;
+ mConsumer->setConsumerName(name);
+}
+
void ConsumerBase::setFrameAvailableListener(
const wp<FrameAvailableListener>& listener) {
CB_LOGV("setFrameAvailableListener");
@@ -237,6 +247,50 @@
return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
}
+status_t ConsumerBase::setConsumerUsageBits(uint64_t usage) {
+ Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setConsumerUsageBits: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->setConsumerUsageBits(usage);
+}
+
+status_t ConsumerBase::setTransformHint(uint32_t hint) {
+ Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setTransformHint: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->setTransformHint(hint);
+}
+
+status_t ConsumerBase::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
+ Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setMaxAcquiredBufferCount: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+}
+
+sp<NativeHandle> ConsumerBase::getSidebandStream() const {
+ Mutex::Autolock _l(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("getSidebandStream: ConsumerBase is abandoned!");
+ return nullptr;
+ }
+
+ sp<NativeHandle> stream;
+ status_t err = mConsumer->getSidebandStream(&stream);
+ if (err != NO_ERROR) {
+ CB_LOGE("failed to get sideband stream: %d", err);
+ return nullptr;
+ }
+
+ return stream;
+}
+
status_t ConsumerBase::getOccupancyHistory(bool forceFlush,
std::vector<OccupancyTracker::Segment>* outHistory) {
Mutex::Autolock _l(mMutex);
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index ae7c65c..8edf604 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -18,11 +18,11 @@
#define LOG_TAG "CpuConsumer"
//#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <cutils/compiler.h>
-#include <utils/Log.h>
-#include <gui/BufferItem.h>
#include <gui/CpuConsumer.h>
+#include <gui/BufferItem.h>
+#include <utils/Log.h>
+
#define CC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define CC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define CC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
@@ -44,20 +44,19 @@
mConsumer->setMaxAcquiredBufferCount(static_cast<int32_t>(maxLockedBuffers));
}
-CpuConsumer::~CpuConsumer() {
- // ConsumerBase destructor does all the work.
+size_t CpuConsumer::findAcquiredBufferLocked(uintptr_t id) const {
+ for (size_t i = 0; i < mMaxLockedBuffers; i++) {
+ const auto& ab = mAcquiredBuffers[i];
+ // note that this finds AcquiredBuffer::kUnusedId as well
+ if (ab.mLockedBufferId == id) {
+ return i;
+ }
+ }
+ return mMaxLockedBuffers; // an invalid index
}
-
-
-void CpuConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- CC_LOGE("setName: CpuConsumer is abandoned!");
- return;
- }
- mName = name;
- mConsumer->setConsumerName(name);
+static uintptr_t getLockedBufferId(const CpuConsumer::LockedBuffer& buffer) {
+ return reinterpret_cast<uintptr_t>(buffer.data);
}
static bool isPossiblyYUV(PixelFormat format) {
@@ -88,10 +87,74 @@
}
}
+status_t CpuConsumer::lockBufferItem(const BufferItem& item, LockedBuffer* outBuffer) const {
+ android_ycbcr ycbcr = android_ycbcr();
+
+ PixelFormat format = item.mGraphicBuffer->getPixelFormat();
+ PixelFormat flexFormat = format;
+ if (isPossiblyYUV(format)) {
+ int fenceFd = item.mFence.get() ? item.mFence->dup() : -1;
+ status_t err = item.mGraphicBuffer->lockAsyncYCbCr(GraphicBuffer::USAGE_SW_READ_OFTEN,
+ item.mCrop, &ycbcr, fenceFd);
+ if (err == OK) {
+ flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+ if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ CC_LOGV("locking buffer of format %#x as flex YUV", format);
+ }
+ } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)", strerror(-err), err);
+ return err;
+ }
+ }
+
+ if (ycbcr.y != nullptr) {
+ outBuffer->data = reinterpret_cast<uint8_t*>(ycbcr.y);
+ outBuffer->stride = static_cast<uint32_t>(ycbcr.ystride);
+ outBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
+ outBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
+ outBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
+ outBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
+ } else {
+ // not flexible YUV; try lockAsync
+ void* bufferPointer = nullptr;
+ int fenceFd = item.mFence.get() ? item.mFence->dup() : -1;
+ status_t err = item.mGraphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN,
+ item.mCrop, &bufferPointer, fenceFd);
+ if (err != OK) {
+ CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err), err);
+ return err;
+ }
+
+ outBuffer->data = reinterpret_cast<uint8_t*>(bufferPointer);
+ outBuffer->stride = item.mGraphicBuffer->getStride();
+ outBuffer->dataCb = nullptr;
+ outBuffer->dataCr = nullptr;
+ outBuffer->chromaStride = 0;
+ outBuffer->chromaStep = 0;
+ }
+
+ outBuffer->width = item.mGraphicBuffer->getWidth();
+ outBuffer->height = item.mGraphicBuffer->getHeight();
+ outBuffer->format = format;
+ outBuffer->flexFormat = flexFormat;
+
+ outBuffer->crop = item.mCrop;
+ outBuffer->transform = item.mTransform;
+ outBuffer->scalingMode = item.mScalingMode;
+ outBuffer->timestamp = item.mTimestamp;
+ outBuffer->dataSpace = item.mDataSpace;
+ outBuffer->frameNumber = item.mFrameNumber;
+
+ return OK;
+}
+
status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
status_t err;
if (!nativeBuffer) return BAD_VALUE;
+
+ Mutex::Autolock _l(mMutex);
+
if (mCurrentLockedBuffers == mMaxLockedBuffers) {
CC_LOGW("Max buffers have been locked (%zd), cannot lock anymore.",
mMaxLockedBuffers);
@@ -99,9 +162,6 @@
}
BufferItem b;
-
- Mutex::Autolock _l(mMutex);
-
err = acquireBufferLocked(&b, 0);
if (err != OK) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
@@ -112,94 +172,23 @@
}
}
- int slot = b.mSlot;
-
- void *bufferPointer = NULL;
- android_ycbcr ycbcr = android_ycbcr();
-
- PixelFormat format = mSlots[slot].mGraphicBuffer->getPixelFormat();
- PixelFormat flexFormat = format;
- if (isPossiblyYUV(format)) {
- if (b.mFence.get()) {
- err = mSlots[slot].mGraphicBuffer->lockAsyncYCbCr(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &ycbcr,
- b.mFence->dup());
- } else {
- err = mSlots[slot].mGraphicBuffer->lockYCbCr(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &ycbcr);
- }
- if (err == OK) {
- bufferPointer = ycbcr.y;
- flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
- if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
- CC_LOGV("locking buffer of format %#x as flex YUV", format);
- }
- } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
- }
+ if (b.mGraphicBuffer == nullptr) {
+ b.mGraphicBuffer = mSlots[b.mSlot].mGraphicBuffer;
}
- if (bufferPointer == NULL) { // not flexible YUV
- if (b.mFence.get()) {
- err = mSlots[slot].mGraphicBuffer->lockAsync(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &bufferPointer,
- b.mFence->dup());
- } else {
- err = mSlots[slot].mGraphicBuffer->lock(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &bufferPointer);
- }
- if (err != OK) {
- CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
- }
+ err = lockBufferItem(b, nativeBuffer);
+ if (err != OK) {
+ return err;
}
- size_t lockedIdx = 0;
- for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) {
- if (mAcquiredBuffers[lockedIdx].mSlot ==
- BufferQueue::INVALID_BUFFER_SLOT) {
- break;
- }
- }
- assert(lockedIdx < mMaxLockedBuffers);
+ // find an unused AcquiredBuffer
+ size_t lockedIdx = findAcquiredBufferLocked(AcquiredBuffer::kUnusedId);
+ ALOG_ASSERT(lockedIdx < mMaxLockedBuffers);
+ AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx);
- AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
- ab.mSlot = slot;
- ab.mBufferPointer = bufferPointer;
- ab.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
-
- nativeBuffer->data =
- reinterpret_cast<uint8_t*>(bufferPointer);
- nativeBuffer->width = mSlots[slot].mGraphicBuffer->getWidth();
- nativeBuffer->height = mSlots[slot].mGraphicBuffer->getHeight();
- nativeBuffer->format = format;
- nativeBuffer->flexFormat = flexFormat;
- nativeBuffer->stride = (ycbcr.y != NULL) ?
- static_cast<uint32_t>(ycbcr.ystride) :
- mSlots[slot].mGraphicBuffer->getStride();
-
- nativeBuffer->crop = b.mCrop;
- nativeBuffer->transform = b.mTransform;
- nativeBuffer->scalingMode = b.mScalingMode;
- nativeBuffer->timestamp = b.mTimestamp;
- nativeBuffer->dataSpace = b.mDataSpace;
- nativeBuffer->frameNumber = b.mFrameNumber;
-
- nativeBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
- nativeBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
- nativeBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
- nativeBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
+ ab.mSlot = b.mSlot;
+ ab.mGraphicBuffer = b.mGraphicBuffer;
+ ab.mLockedBufferId = getLockedBufferId(*nativeBuffer);
mCurrentLockedBuffers++;
@@ -208,60 +197,34 @@
status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
Mutex::Autolock _l(mMutex);
- size_t lockedIdx = 0;
- void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
- for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) {
- if (bufPtr == mAcquiredBuffers[lockedIdx].mBufferPointer) break;
- }
+ uintptr_t id = getLockedBufferId(nativeBuffer);
+ size_t lockedIdx =
+ (id != AcquiredBuffer::kUnusedId) ? findAcquiredBufferLocked(id) : mMaxLockedBuffers;
if (lockedIdx == mMaxLockedBuffers) {
CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
return BAD_VALUE;
}
- return releaseAcquiredBufferLocked(lockedIdx);
-}
+ AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx);
-status_t CpuConsumer::releaseAcquiredBufferLocked(size_t lockedIdx) {
- status_t err;
- int fd = -1;
-
- err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlockAsync(&fd);
+ int fenceFd = -1;
+ status_t err = ab.mGraphicBuffer->unlockAsync(&fenceFd);
if (err != OK) {
CC_LOGE("%s: Unable to unlock graphic buffer %zd", __FUNCTION__,
lockedIdx);
return err;
}
- int buf = mAcquiredBuffers[lockedIdx].mSlot;
- if (CC_LIKELY(fd != -1)) {
- sp<Fence> fence(new Fence(fd));
- addReleaseFenceLocked(
- mAcquiredBuffers[lockedIdx].mSlot,
- mSlots[buf].mGraphicBuffer,
- fence);
- }
- // release the buffer if it hasn't already been freed by the BufferQueue.
- // This can happen, for example, when the producer of this buffer
- // disconnected after this buffer was acquired.
- if (CC_LIKELY(mAcquiredBuffers[lockedIdx].mGraphicBuffer ==
- mSlots[buf].mGraphicBuffer)) {
- releaseBufferLocked(
- buf, mAcquiredBuffers[lockedIdx].mGraphicBuffer,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
- }
+ sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
+ addReleaseFenceLocked(ab.mSlot, ab.mGraphicBuffer, fence);
+ releaseBufferLocked(ab.mSlot, ab.mGraphicBuffer);
- AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
- ab.mSlot = BufferQueue::INVALID_BUFFER_SLOT;
- ab.mBufferPointer = NULL;
- ab.mGraphicBuffer.clear();
+ ab.reset();
mCurrentLockedBuffers--;
- return OK;
-}
-void CpuConsumer::freeBufferLocked(int slotIndex) {
- ConsumerBase::freeBufferLocked(slotIndex);
+ return OK;
}
} // namespace android
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 14d9937..788a6eb 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -31,6 +31,8 @@
#include <hardware/hardware.h>
+#include <math/mat4.h>
+
#include <gui/BufferItem.h>
#include <gui/GLConsumer.h>
#include <gui/ISurfaceComposer.h>
@@ -75,33 +77,7 @@
"_______________"
};
-// Transform matrices
-static float mtxIdentity[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
-};
-static float mtxFlipH[16] = {
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxFlipV[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-static float mtxRot90[16] = {
- 0, 1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-
-static void mtxMul(float out[16], const float a[16], const float b[16]);
+static const mat4 mtxIdentity;
Mutex GLConsumer::sStaticInitLock;
sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
@@ -173,7 +149,7 @@
{
GLC_LOGV("GLConsumer");
- memcpy(mCurrentTransformMatrix, mtxIdentity,
+ memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
@@ -202,7 +178,7 @@
{
GLC_LOGV("GLConsumer");
- memcpy(mCurrentTransformMatrix, mtxIdentity,
+ memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
@@ -758,25 +734,6 @@
return OK;
}
-bool GLConsumer::isExternalFormat(PixelFormat format)
-{
- switch (format) {
- // supported YUV formats
- case HAL_PIXEL_FORMAT_YV12:
- // Legacy/deprecated YUV formats
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return true;
- }
-
- // Any OEM format needs to be considered
- if (format>=0x100 && format<=0x1FF)
- return true;
-
- return false;
-}
-
uint32_t GLConsumer::getCurrentTextureTarget() const {
return mTexTarget;
}
@@ -820,34 +777,37 @@
void GLConsumer::computeTransformMatrix(float outTransform[16],
const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
bool filtering) {
+ // Transform matrices
+ static const mat4 mtxFlipH(
+ -1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 0, 0, 1
+ );
+ static const mat4 mtxFlipV(
+ 1, 0, 0, 0,
+ 0, -1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 1, 0, 1
+ );
+ static const mat4 mtxRot90(
+ 0, 1, 0, 0,
+ -1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 1, 0, 0, 1
+ );
- float xform[16];
- for (int i = 0; i < 16; i++) {
- xform[i] = mtxIdentity[i];
- }
+ mat4 xform;
if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- float result[16];
- mtxMul(result, xform, mtxFlipH);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxFlipH;
}
if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- float result[16];
- mtxMul(result, xform, mtxFlipV);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxFlipV;
}
if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float result[16];
- mtxMul(result, xform, mtxRot90);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxRot90;
}
- float mtxBeforeFlipV[16];
if (!cropRect.isEmpty()) {
float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
float bufferWidth = buf->getWidth();
@@ -893,25 +853,63 @@
sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
bufferHeight;
}
- float crop[16] = {
+
+ mat4 crop(
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, 1, 0,
- tx, ty, 0, 1,
- };
-
- mtxMul(mtxBeforeFlipV, crop, xform);
- } else {
- for (int i = 0; i < 16; i++) {
- mtxBeforeFlipV[i] = xform[i];
- }
+ tx, ty, 0, 1
+ );
+ xform = crop * xform;
}
// SurfaceFlinger expects the top of its window textures to be at a Y
// coordinate of 0, so GLConsumer must behave the same way. We don't
// want to expose this to applications, however, so we must add an
// additional vertical flip to the transform after all the other transforms.
- mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
+ xform = mtxFlipV * xform;
+
+ memcpy(outTransform, xform.asArray(), sizeof(xform));
+}
+
+Rect GLConsumer::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
+ Rect outCrop = crop;
+
+ uint32_t newWidth = static_cast<uint32_t>(crop.width());
+ uint32_t newHeight = static_cast<uint32_t>(crop.height());
+
+ if (newWidth * bufferHeight > newHeight * bufferWidth) {
+ newWidth = newHeight * bufferWidth / bufferHeight;
+ ALOGV("too wide: newWidth = %d", newWidth);
+ } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
+ newHeight = newWidth * bufferHeight / bufferWidth;
+ ALOGV("too tall: newHeight = %d", newHeight);
+ }
+
+ uint32_t currentWidth = static_cast<uint32_t>(crop.width());
+ uint32_t currentHeight = static_cast<uint32_t>(crop.height());
+
+ // The crop is too wide
+ if (newWidth < currentWidth) {
+ uint32_t dw = currentWidth - newWidth;
+ auto halfdw = dw / 2;
+ outCrop.left += halfdw;
+ // Not halfdw because it would subtract 1 too few when dw is odd
+ outCrop.right -= (dw - halfdw);
+ // The crop is too tall
+ } else if (newHeight < currentHeight) {
+ uint32_t dh = currentHeight - newHeight;
+ auto halfdh = dh / 2;
+ outCrop.top += halfdh;
+ // Not halfdh because it would subtract 1 too few when dh is odd
+ outCrop.bottom -= (dh - halfdh);
+ }
+
+ ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
+ outCrop.left, outCrop.top,
+ outCrop.right,outCrop.bottom);
+
+ return outCrop;
}
nsecs_t GLConsumer::getTimestamp() {
@@ -945,45 +943,9 @@
Rect GLConsumer::getCurrentCrop() const {
Mutex::Autolock lock(mMutex);
-
- Rect outCrop = mCurrentCrop;
- if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
- uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
- uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
-
- if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
- newWidth = newHeight * mDefaultWidth / mDefaultHeight;
- GLC_LOGV("too wide: newWidth = %d", newWidth);
- } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
- newHeight = newWidth * mDefaultHeight / mDefaultWidth;
- GLC_LOGV("too tall: newHeight = %d", newHeight);
- }
-
- uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
- uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
-
- // The crop is too wide
- if (newWidth < currentWidth) {
- uint32_t dw = currentWidth - newWidth;
- auto halfdw = dw / 2;
- outCrop.left += halfdw;
- // Not halfdw because it would subtract 1 too few when dw is odd
- outCrop.right -= (dw - halfdw);
- // The crop is too tall
- } else if (newHeight < currentHeight) {
- uint32_t dh = currentHeight - newHeight;
- auto halfdh = dh / 2;
- outCrop.top += halfdh;
- // Not halfdh because it would subtract 1 too few when dh is odd
- outCrop.bottom -= (dh - halfdh);
- }
-
- GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
- outCrop.left, outCrop.top,
- outCrop.right,outCrop.bottom);
- }
-
- return outCrop;
+ return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
+ ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
+ : mCurrentCrop;
}
uint32_t GLConsumer::getCurrentTransform() const {
@@ -1006,11 +968,6 @@
return mCurrentFenceTime;
}
-status_t GLConsumer::doGLFenceWait() const {
- Mutex::Autolock lock(mMutex);
- return doGLFenceWaitLocked();
-}
-
status_t GLConsumer::doGLFenceWaitLocked() const {
EGLDisplay dpy = eglGetCurrentDisplay();
@@ -1086,61 +1043,8 @@
ConsumerBase::abandonLocked();
}
-void GLConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setName: GLConsumer is abandoned!");
- return;
- }
- mName = name;
- mConsumer->setConsumerName(name);
-}
-
-status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setDefaultBufferFormat(defaultFormat);
-}
-
-status_t GLConsumer::setDefaultBufferDataSpace(
- android_dataspace defaultDataSpace) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
-}
-
status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
- return NO_INIT;
- }
- usage |= DEFAULT_USAGE_FLAGS;
- return mConsumer->setConsumerUsageBits(usage);
-}
-
-status_t GLConsumer::setTransformHint(uint32_t hint) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setTransformHint(hint);
-}
-
-status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+ return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
}
void GLConsumer::dumpLocked(String8& result, const char* prefix) const
@@ -1155,28 +1059,6 @@
ConsumerBase::dumpLocked(result, prefix);
}
-static void mtxMul(float out[16], const float a[16], const float b[16]) {
- out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
- out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
- out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
- out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
-
- out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
- out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
- out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
- out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
-
- out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
- out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
- out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
- out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
-
- out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
- out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
- out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
- out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
-}
-
GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
mGraphicBuffer(graphicBuffer),
mEglImage(EGL_NO_IMAGE_KHR),
diff --git a/libs/gui/include/gui/BufferItemConsumer.h b/libs/gui/include/gui/BufferItemConsumer.h
index d9c5775..a905610 100644
--- a/libs/gui/include/gui/BufferItemConsumer.h
+++ b/libs/gui/include/gui/BufferItemConsumer.h
@@ -57,10 +57,6 @@
~BufferItemConsumer() override;
- // set the name of the BufferItemConsumer that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
// setBufferFreedListener sets the listener object that will be notified
// when an old buffer is being freed.
void setBufferFreedListener(const wp<BufferFreedListener>& listener);
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index 4a86021..366ced3 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -89,6 +89,18 @@
// See IGraphicBufferConsumer::setDefaultBufferDataSpace
status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
+ // See IGraphicBufferConsumer::setConsumerUsageBits
+ status_t setConsumerUsageBits(uint64_t usage);
+
+ // See IGraphicBufferConsumer::setTransformHint
+ status_t setTransformHint(uint32_t hint);
+
+ // See IGraphicBufferConsumer::setMaxAcquiredBufferCount
+ status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
+
+ // See IGraphicBufferConsumer::getSidebandStream
+ sp<NativeHandle> getSidebandStream() const;
+
// See IGraphicBufferConsumer::getOccupancyHistory
status_t getOccupancyHistory(bool forceFlush,
std::vector<OccupancyTracker::Segment>* outHistory);
diff --git a/libs/gui/include/gui/CpuConsumer.h b/libs/gui/include/gui/CpuConsumer.h
index 58602bf..d375611 100644
--- a/libs/gui/include/gui/CpuConsumer.h
+++ b/libs/gui/include/gui/CpuConsumer.h
@@ -94,12 +94,6 @@
CpuConsumer(const sp<IGraphicBufferConsumer>& bq,
size_t maxLockedBuffers, bool controlledByApp = false);
- virtual ~CpuConsumer();
-
- // set the name of the CpuConsumer that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
// Gets the next graphics buffer from the producer and locks it for CPU use,
// filling out the passed-in locked buffer structure with the native pointer
// and metadata. Returns BAD_VALUE if no new buffer is available, and
@@ -119,31 +113,39 @@
private:
// Maximum number of buffers that can be locked at a time
- size_t mMaxLockedBuffers;
-
- status_t releaseAcquiredBufferLocked(size_t lockedIdx);
-
- virtual void freeBufferLocked(int slotIndex);
+ const size_t mMaxLockedBuffers;
// Tracking for buffers acquired by the user
struct AcquiredBuffer {
+ static constexpr uintptr_t kUnusedId = 0;
+
// Need to track the original mSlot index and the buffer itself because
// the mSlot entry may be freed/reused before the acquired buffer is
// released.
int mSlot;
sp<GraphicBuffer> mGraphicBuffer;
- void *mBufferPointer;
+ uintptr_t mLockedBufferId;
AcquiredBuffer() :
mSlot(BufferQueue::INVALID_BUFFER_SLOT),
- mBufferPointer(NULL) {
+ mLockedBufferId(kUnusedId) {
+ }
+
+ void reset() {
+ mSlot = BufferQueue::INVALID_BUFFER_SLOT;
+ mGraphicBuffer.clear();
+ mLockedBufferId = kUnusedId;
}
};
+
+ size_t findAcquiredBufferLocked(uintptr_t id) const;
+
+ status_t lockBufferItem(const BufferItem& item, LockedBuffer* outBuffer) const;
+
Vector<AcquiredBuffer> mAcquiredBuffers;
// Count of currently locked buffers
size_t mCurrentLockedBuffers;
-
};
} // namespace android
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 75f2cca..71ed3bf 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -138,6 +138,10 @@
const sp<GraphicBuffer>& buf, const Rect& cropRect,
uint32_t transform, bool filtering);
+ // Scale the crop down horizontally or vertically such that it has the
+ // same aspect ratio as the buffer does.
+ static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight);
+
// getTimestamp retrieves the timestamp associated with the texture image
// set by the most recent call to updateTexImage.
//
@@ -197,22 +201,9 @@
// buffer is ready to be read from.
std::shared_ptr<FenceTime> getCurrentFenceTime() const;
- // doGLFenceWait inserts a wait command into the OpenGL ES command stream
- // to ensure that it is safe for future OpenGL ES commands to access the
- // current texture buffer.
- status_t doGLFenceWait() const;
-
- // set the name of the GLConsumer that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // These functions call the corresponding BufferQueue implementation
- // so the refactoring can proceed smoothly
- status_t setDefaultBufferFormat(PixelFormat defaultFormat);
- status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
+ // setConsumerUsageBits overrides the ConsumerBase method to OR
+ // DEFAULT_USAGE_FLAGS to usage.
status_t setConsumerUsageBits(uint64_t usage);
- status_t setTransformHint(uint32_t hint);
- status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
// detachFromContext detaches the GLConsumer from the calling thread's
// current OpenGL ES context. This context must be the same as the context
@@ -267,8 +258,6 @@
return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
}
- static bool isExternalFormat(PixelFormat format);
-
struct PendingRelease {
PendingRelease() : isPending(false), currentTexture(-1),
graphicBuffer(), display(nullptr), fence(nullptr) {}
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 588e541..36be7d9 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -33,6 +33,7 @@
#include <utils/Mutex.h>
#include <utils/Condition.h>
+#include <thread>
#include <vector>
#define CPU_CONSUMER_TEST_FORMAT_RAW 0
#define CPU_CONSUMER_TEST_FORMAT_Y8 0
@@ -681,6 +682,70 @@
}
}
+TEST_P(CpuConsumerTest, FromCpuInvalid) {
+ status_t err = mCC->lockNextBuffer(nullptr);
+ ASSERT_EQ(BAD_VALUE, err) << "lockNextBuffer did not fail";
+
+ CpuConsumer::LockedBuffer b;
+ err = mCC->unlockBuffer(b);
+ ASSERT_EQ(BAD_VALUE, err) << "unlockBuffer did not fail";
+}
+
+TEST_P(CpuConsumerTest, FromCpuMultiThread) {
+ CpuConsumerTestParams params = GetParam();
+ ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, params.maxLockedBuffers + 1));
+
+ for (int i = 0; i < 10; i++) {
+ std::atomic<int> threadReadyCount(0);
+ auto lockAndUnlock = [&]() {
+ threadReadyCount++;
+ // busy wait
+ while (threadReadyCount < params.maxLockedBuffers + 1);
+
+ CpuConsumer::LockedBuffer b;
+ status_t err = mCC->lockNextBuffer(&b);
+ if (err == NO_ERROR) {
+ usleep(1000);
+ err = mCC->unlockBuffer(b);
+ ASSERT_NO_ERROR(err, "Could not unlock buffer: ");
+ } else if (err == NOT_ENOUGH_DATA) {
+ // there are params.maxLockedBuffers+1 threads so one of the
+ // threads might get this error
+ } else {
+ FAIL() << "Could not lock buffer";
+ }
+ };
+
+ // produce buffers
+ for (int j = 0; j < params.maxLockedBuffers + 1; j++) {
+ const int64_t time = 1234L;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, &stride));
+ }
+
+ // spawn threads
+ std::vector<std::thread> threads;
+ for (int j = 0; j < params.maxLockedBuffers + 1; j++) {
+ threads.push_back(std::thread(lockAndUnlock));
+ }
+
+ // join threads
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ // we produced N+1 buffers, but the threads might only consume N
+ CpuConsumer::LockedBuffer b;
+ if (mCC->lockNextBuffer(&b) == NO_ERROR) {
+ mCC->unlockBuffer(b);
+ }
+
+ if (HasFatalFailure()) {
+ break;
+ }
+ }
+}
+
CpuConsumerTestParams y8TestSets[] = {
{ 512, 512, 1, HAL_PIXEL_FORMAT_Y8},
{ 512, 512, 3, HAL_PIXEL_FORMAT_Y8},
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index e17bb58..d5ba09d 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -134,12 +134,6 @@
return mSurfaceDamage;
}
-sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const {
- sp<NativeHandle> stream;
- mConsumer->getSidebandStream(&stream);
- return stream;
-}
-
// We need to determine the time when a buffer acquired now will be
// displayed. This can be calculated:
// time when previous buffer's actual-present fence was signaled
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 53b4915..7397f2d 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -76,8 +76,6 @@
// ConsumerBase::setFrameAvailableListener().
void setContentsChangedListener(const wp<ContentsChangedListener>& listener);
- sp<NativeHandle> getSidebandStream() const;
-
nsecs_t computeExpectedPresent(const DispSync& dispSync);
sp<Fence> getPrevFinalReleaseFence() const;