Merge changes I4589e02a,Id300e8b2 into nyc-dev
* changes:
Switch SurfaceFlinger to HWC 2.0
HWC2On1Adapter: Initialize variables and fix mutex
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index d10ba2f..2645d09 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -32,6 +32,7 @@
#include <list>
#include <set>
+#include <vector>
#define BQ_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGD(x, ...) ALOGD("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
@@ -120,8 +121,9 @@
void freeAllBuffersLocked();
// If delta is positive, makes more slots available. If negative, takes
- // away slots. Returns false if the request can't be met.
- bool adjustAvailableSlotsLocked(int delta);
+ // away slots. Returns false if the request can't be met. Any slots that
+ // were freed will be appended to freedSlots.
+ bool adjustAvailableSlotsLocked(int delta, std::vector<int>* freedSlots);
// waitWhileAllocatingLocked blocks until mIsAllocating is false.
void waitWhileAllocatingLocked() const;
diff --git a/include/gui/IProducerListener.h b/include/gui/IProducerListener.h
index 3848a6c..895da4b 100644
--- a/include/gui/IProducerListener.h
+++ b/include/gui/IProducerListener.h
@@ -41,6 +41,9 @@
// This is called without any lock held and can be called concurrently by
// multiple threads.
virtual void onBufferReleased() = 0; // Asynchronous
+
+ // onSlotFreed is called when the BufferQueue frees a buffer in a slot.
+ virtual void onSlotFreed(int /*slot*/) {}; // Asynchronous
};
class IProducerListener : public ProducerListener, public IInterface
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index 752b004..feec509 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -258,7 +258,7 @@
};
struct MediaImage2 {
- enum Type {
+ enum Type : uint32_t {
MEDIA_IMAGE_TYPE_UNKNOWN = 0,
MEDIA_IMAGE_TYPE_YUV,
MEDIA_IMAGE_TYPE_YUVA,
@@ -267,7 +267,7 @@
MEDIA_IMAGE_TYPE_Y,
};
- enum PlaneIndex {
+ enum PlaneIndex : uint32_t {
Y = 0,
U = 1,
V = 2,
@@ -294,6 +294,8 @@
uint32_t mVertSubsampling; // subsampling compared to the largest plane
};
PlaneInfo mPlane[MAX_NUM_PLANES];
+
+ void initFromV1(const MediaImage&); // for internal use only
};
// A pointer to this struct is passed to OMX_GetParameter when the extension
@@ -324,6 +326,7 @@
// buffers, the component shall set mNumPlanes to 0, and mType to MEDIA_IMAGE_TYPE_UNKNOWN.
// @deprecated: use DescribeColorFormat2Params
+struct DescribeColorFormat2Params;
struct DescribeColorFormatParams {
OMX_U32 nSize;
OMX_VERSIONTYPE nVersion;
@@ -337,6 +340,8 @@
// output: fill out the MediaImage fields
MediaImage sMediaImage;
+
+ DescribeColorFormatParams(const DescribeColorFormat2Params&); // for internal use only
};
// A pointer to this struct is passed to OMX_GetParameter when the extension
@@ -356,6 +361,8 @@
// output: fill out the MediaImage2 fields
MediaImage2 sMediaImage;
+
+ void initFromV1(const DescribeColorFormatParams&); // for internal use only
};
// A pointer to this struct is passed to OMX_SetParameter or OMX_GetParameter
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 4029496..aacbed5 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -277,35 +277,51 @@
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
BQ_LOGV("detachBuffer: slot %d", slot);
- Mutex::Autolock lock(mCore->mMutex);
- if (mCore->mIsAbandoned) {
- BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
- return NO_INIT;
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ if (mCore->mSingleBufferMode || slot == mCore->mSingleBufferSlot) {
+ BQ_LOGE("detachBuffer: detachBuffer not allowed in single buffer"
+ "mode");
+ return BAD_VALUE;
+ }
+
+ if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
+ BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
+ slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ return BAD_VALUE;
+ } else if (!mSlots[slot].mBufferState.isAcquired()) {
+ BQ_LOGE("detachBuffer: slot %d is not owned by the consumer "
+ "(state = %s)", slot, mSlots[slot].mBufferState.string());
+ return BAD_VALUE;
+ }
+
+ mSlots[slot].mBufferState.detachConsumer();
+ mCore->mActiveBuffers.erase(slot);
+ mCore->mFreeSlots.insert(slot);
+ mCore->clearBufferSlotLocked(slot);
+ mCore->mDequeueCondition.broadcast();
+ VALIDATE_CONSISTENCY();
+ producerListener = mCore->mConnectedProducerListener;
+ consumerListener = mCore->mConsumerListener;
}
- if (mCore->mSingleBufferMode || slot == mCore->mSingleBufferSlot) {
- BQ_LOGE("detachBuffer: detachBuffer not allowed in single buffer"
- "mode");
- return BAD_VALUE;
+ // Call back without lock held
+ if (producerListener != NULL) {
+ producerListener->onSlotFreed(slot);
+ }
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
}
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
- slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- } else if (!mSlots[slot].mBufferState.isAcquired()) {
- BQ_LOGE("detachBuffer: slot %d is not owned by the consumer "
- "(state = %s)", slot, mSlots[slot].mBufferState.string());
- return BAD_VALUE;
- }
-
- mSlots[slot].mBufferState.detachConsumer();
- mCore->mActiveBuffers.erase(slot);
- mCore->mFreeSlots.insert(slot);
- mCore->clearBufferSlotLocked(slot);
- mCore->mDequeueCondition.broadcast();
- VALIDATE_CONSISTENCY();
return NO_ERROR;
}
@@ -576,30 +592,40 @@
return BAD_VALUE;
}
- Mutex::Autolock lock(mCore->mMutex);
+ sp<IConsumerListener> listener;
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+ if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("setMaxBufferCount: producer is already connected");
+ return INVALID_OPERATION;
+ }
- if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
- BQ_LOGE("setMaxBufferCount: producer is already connected");
- return INVALID_OPERATION;
+ if (bufferCount < mCore->mMaxAcquiredBufferCount) {
+ BQ_LOGE("setMaxBufferCount: invalid buffer count (%d) less than"
+ "mMaxAcquiredBufferCount (%d)", bufferCount,
+ mCore->mMaxAcquiredBufferCount);
+ return BAD_VALUE;
+ }
+
+ int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
+ mCore->mDequeueBufferCannotBlock, bufferCount) -
+ mCore->getMaxBufferCountLocked();
+ if (!mCore->adjustAvailableSlotsLocked(delta, nullptr)) {
+ BQ_LOGE("setMaxBufferCount: BufferQueue failed to adjust the number"
+ " of available slots. Delta = %d", delta);
+ return BAD_VALUE;
+ }
+
+ mCore->mMaxBufferCount = bufferCount;
+ if (delta < 0) {
+ listener = mCore->mConsumerListener;
+ }
}
- if (bufferCount < mCore->mMaxAcquiredBufferCount) {
- BQ_LOGE("setMaxBufferCount: invalid buffer count (%d) less than"
- "mMaxAcquiredBufferCount (%d)", bufferCount,
- mCore->mMaxAcquiredBufferCount);
- return BAD_VALUE;
+ // Call back without lock held
+ if (listener != NULL) {
+ listener->onBuffersReleased();
}
-
- int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
- mCore->mDequeueBufferCannotBlock, bufferCount) -
- mCore->getMaxBufferCountLocked();
- if (!mCore->adjustAvailableSlotsLocked(delta)) {
- BQ_LOGE("setMaxBufferCount: BufferQueue failed to adjust the number of "
- "available slots. Delta = %d", delta);
- return BAD_VALUE;
- }
-
- mCore->mMaxBufferCount = bufferCount;
return NO_ERROR;
}
@@ -614,7 +640,9 @@
return BAD_VALUE;
}
- sp<IConsumerListener> listener;
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ std::vector<int> freedSlots;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
@@ -651,7 +679,7 @@
}
int delta = maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount;
- if (!mCore->adjustAvailableSlotsLocked(delta)) {
+ if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
return BAD_VALUE;
}
@@ -659,12 +687,19 @@
mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
VALIDATE_CONSISTENCY();
if (delta < 0) {
- listener = mCore->mConsumerListener;
+ consumerListener = mCore->mConsumerListener;
+ producerListener = mCore->mConnectedProducerListener;
}
}
+
// Call back without lock held
- if (listener != NULL) {
- listener->onBuffersReleased();
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
+ }
+ if (producerListener != NULL) {
+ for (int i : freedSlots) {
+ producerListener->onSlotFreed(i);
+ }
}
return NO_ERROR;
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index ba07362..fc3ffed 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -226,7 +226,8 @@
VALIDATE_CONSISTENCY();
}
-bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
+bool BufferQueueCore::adjustAvailableSlotsLocked(int delta,
+ std::vector<int>* freedSlots) {
if (delta >= 0) {
// If we're going to fail, do so before modifying anything
if (delta > static_cast<int>(mUnusedSlots.size())) {
@@ -253,11 +254,17 @@
clearBufferSlotLocked(*slot);
mUnusedSlots.push_back(*slot);
mFreeSlots.erase(slot);
+ if (freedSlots) {
+ freedSlots->push_back(*slot);
+ }
} else if (!mFreeBuffers.empty()) {
int slot = mFreeBuffers.back();
clearBufferSlotLocked(slot);
mUnusedSlots.push_back(slot);
mFreeBuffers.pop_back();
+ if (freedSlots) {
+ freedSlots->push_back(slot);
+ }
} else {
return false;
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 17d4a2c..cb5d773 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -90,7 +90,9 @@
BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
maxDequeuedBuffers);
- sp<IConsumerListener> listener;
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ std::vector<int> freedSlots;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
@@ -142,20 +144,26 @@
}
int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
- if (!mCore->adjustAvailableSlotsLocked(delta)) {
+ if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
return BAD_VALUE;
}
mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
VALIDATE_CONSISTENCY();
if (delta < 0) {
- listener = mCore->mConsumerListener;
+ consumerListener = mCore->mConsumerListener;
+ producerListener = mCore->mConnectedProducerListener;
}
mCore->mDequeueCondition.broadcast();
} // Autolock scope
// Call back without lock held
- if (listener != NULL) {
- listener->onBuffersReleased();
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
+ }
+ if (producerListener != NULL) {
+ for (int i : freedSlots) {
+ producerListener->onSlotFreed(i);
+ }
}
return NO_ERROR;
@@ -165,7 +173,9 @@
ATRACE_CALL();
BQ_LOGV("setAsyncMode: async = %d", async);
- sp<IConsumerListener> listener;
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ std::vector<int> freedSlots;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
@@ -191,7 +201,7 @@
mCore->mDequeueBufferCannotBlock, mCore->mMaxBufferCount)
- mCore->getMaxBufferCountLocked();
- if (!mCore->adjustAvailableSlotsLocked(delta)) {
+ if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
BQ_LOGE("setAsyncMode: BufferQueue failed to adjust the number of "
"available slots. Delta = %d", delta);
return BAD_VALUE;
@@ -199,12 +209,20 @@
mCore->mAsyncMode = async;
VALIDATE_CONSISTENCY();
mCore->mDequeueCondition.broadcast();
- listener = mCore->mConsumerListener;
+ if (delta < 0) {
+ consumerListener = mCore->mConsumerListener;
+ producerListener = mCore->mConnectedProducerListener;
+ }
} // Autolock scope
// Call back without lock held
- if (listener != NULL) {
- listener->onBuffersReleased();
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
+ }
+ if (producerListener != NULL) {
+ for (int i : freedSlots) {
+ producerListener->onSlotFreed(i);
+ }
}
return NO_ERROR;
}
@@ -361,6 +379,9 @@
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
bool attachedByConsumer = false;
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ int found = BufferItem::INVALID_BUFFER_SLOT;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
@@ -378,7 +399,6 @@
height = mCore->mDefaultHeight;
}
- int found = BufferItem::INVALID_BUFFER_SLOT;
while (found == BufferItem::INVALID_BUFFER_SLOT) {
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,
&found);
@@ -408,6 +428,8 @@
mCore->mFreeSlots.insert(found);
mCore->clearBufferSlotLocked(found);
found = BufferItem::INVALID_BUFFER_SLOT;
+ consumerListener = mCore->mConsumerListener;
+ producerListener = mCore->mConnectedProducerListener;
continue;
}
}
@@ -444,6 +466,10 @@
if ((buffer == NULL) ||
buffer->needsReallocation(width, height, format, usage))
{
+ if (buffer != NULL) {
+ consumerListener = mCore->mConsumerListener;
+ producerListener = mCore->mConnectedProducerListener;
+ }
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
mSlots[found].mRequestBufferCalled = false;
@@ -531,6 +557,14 @@
mSlots[*outSlot].mFrameNumber,
mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
+ // Call back without lock held
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
+ }
+ if (producerListener != NULL) {
+ producerListener->onSlotFreed(found);
+ }
+
return returnFlags;
}
@@ -538,44 +572,60 @@
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
BQ_LOGV("detachBuffer: slot %d", slot);
- Mutex::Autolock lock(mCore->mMutex);
- if (mCore->mIsAbandoned) {
- BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
- return NO_INIT;
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ if (mCore->mSingleBufferMode || mCore->mSingleBufferSlot == slot) {
+ BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer "
+ "mode");
+ return BAD_VALUE;
+ }
+
+ if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
+ BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
+ slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ return BAD_VALUE;
+ } else if (!mSlots[slot].mBufferState.isDequeued()) {
+ BQ_LOGE("detachBuffer: slot %d is not owned by the producer "
+ "(state = %s)", slot, mSlots[slot].mBufferState.string());
+ return BAD_VALUE;
+ } else if (!mSlots[slot].mRequestBufferCalled) {
+ BQ_LOGE("detachBuffer: buffer in slot %d has not been requested",
+ slot);
+ return BAD_VALUE;
+ }
+
+ mSlots[slot].mBufferState.detachProducer();
+ mCore->mActiveBuffers.erase(slot);
+ mCore->mFreeSlots.insert(slot);
+ mCore->clearBufferSlotLocked(slot);
+ mCore->mDequeueCondition.broadcast();
+ VALIDATE_CONSISTENCY();
+ producerListener = mCore->mConnectedProducerListener;
+ consumerListener = mCore->mConsumerListener;
}
- if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
- BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
- return NO_INIT;
+ // Call back without lock held
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
}
-
- if (mCore->mSingleBufferMode || mCore->mSingleBufferSlot == slot) {
- BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer mode");
- return BAD_VALUE;
+ if (producerListener != NULL) {
+ producerListener->onSlotFreed(slot);
}
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
- slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- } else if (!mSlots[slot].mBufferState.isDequeued()) {
- BQ_LOGE("detachBuffer: slot %d is not owned by the producer "
- "(state = %s)", slot, mSlots[slot].mBufferState.string());
- return BAD_VALUE;
- } else if (!mSlots[slot].mRequestBufferCalled) {
- BQ_LOGE("detachBuffer: buffer in slot %d has not been requested",
- slot);
- return BAD_VALUE;
- }
-
- mSlots[slot].mBufferState.detachProducer();
- mCore->mActiveBuffers.erase(slot);
- mCore->mFreeSlots.insert(slot);
- mCore->clearBufferSlotLocked(slot);
- mCore->mDequeueCondition.broadcast();
- VALIDATE_CONSISTENCY();
-
return NO_ERROR;
}
@@ -591,41 +641,55 @@
return BAD_VALUE;
}
- Mutex::Autolock lock(mCore->mMutex);
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ int found = BufferQueueCore::INVALID_BUFFER_SLOT;
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
- if (mCore->mIsAbandoned) {
- BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
- return NO_INIT;
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ if (mCore->mSingleBufferMode) {
+ BQ_LOGE("detachNextBuffer: cannot detach a buffer in single buffer"
+ "mode");
+ return BAD_VALUE;
+ }
+
+ mCore->waitWhileAllocatingLocked();
+
+ if (mCore->mFreeBuffers.empty()) {
+ return NO_MEMORY;
+ }
+
+ found = mCore->mFreeBuffers.front();
+ mCore->mFreeBuffers.remove(found);
+ mCore->mFreeSlots.insert(found);
+
+ BQ_LOGV("detachNextBuffer detached slot %d", found);
+
+ *outBuffer = mSlots[found].mGraphicBuffer;
+ *outFence = mSlots[found].mFence;
+ mCore->clearBufferSlotLocked(found);
+ VALIDATE_CONSISTENCY();
+ consumerListener = mCore->mConsumerListener;
+ producerListener = mCore->mConnectedProducerListener;
}
- if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
- BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
- return NO_INIT;
+ // Call back without lock held
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
}
-
- if (mCore->mSingleBufferMode) {
- BQ_LOGE("detachNextBuffer: cannot detach a buffer in single buffer"
- "mode");
- return BAD_VALUE;
+ if (producerListener != NULL) {
+ producerListener->onSlotFreed(found);
}
- mCore->waitWhileAllocatingLocked();
-
- if (mCore->mFreeBuffers.empty()) {
- return NO_MEMORY;
- }
-
- int found = mCore->mFreeBuffers.front();
- mCore->mFreeBuffers.remove(found);
- mCore->mFreeSlots.insert(found);
-
- BQ_LOGV("detachNextBuffer detached slot %d", found);
-
- *outBuffer = mSlots[found].mGraphicBuffer;
- *outFence = mSlots[found].mFence;
- mCore->clearBufferSlotLocked(found);
- VALIDATE_CONSISTENCY();
-
return NO_ERROR;
}
@@ -1020,82 +1084,102 @@
status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
int api, bool producerControlledByApp, QueueBufferOutput *output) {
ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
- mConsumerName = mCore->mConsumerName;
- BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
- producerControlledByApp ? "true" : "false");
-
- if (mCore->mIsAbandoned) {
- BQ_LOGE("connect: BufferQueue has been abandoned");
- return NO_INIT;
- }
-
- if (mCore->mConsumerListener == NULL) {
- BQ_LOGE("connect: BufferQueue has no consumer");
- return NO_INIT;
- }
-
- if (output == NULL) {
- BQ_LOGE("connect: output was NULL");
- return BAD_VALUE;
- }
-
- if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
- BQ_LOGE("connect: already connected (cur=%d req=%d)",
- mCore->mConnectedApi, api);
- return BAD_VALUE;
- }
-
- int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
- mDequeueTimeout < 0 ?
- mCore->mConsumerControlledByApp && producerControlledByApp : false,
- mCore->mMaxBufferCount) -
- mCore->getMaxBufferCountLocked();
- if (!mCore->adjustAvailableSlotsLocked(delta)) {
- BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
- "slots. Delta = %d", delta);
- return BAD_VALUE;
- }
-
int status = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- mCore->mConnectedApi = api;
- output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
- mCore->mTransformHint,
- static_cast<uint32_t>(mCore->mQueue.size()));
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ std::vector<int> freedSlots;
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+ mConsumerName = mCore->mConsumerName;
+ BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
+ producerControlledByApp ? "true" : "false");
- // Set up a death notification so that we can disconnect
- // automatically if the remote producer dies
- if (listener != NULL &&
- IInterface::asBinder(listener)->remoteBinder() != NULL) {
- status = IInterface::asBinder(listener)->linkToDeath(
- static_cast<IBinder::DeathRecipient*>(this));
- if (status != NO_ERROR) {
- BQ_LOGE("connect: linkToDeath failed: %s (%d)",
- strerror(-status), status);
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("connect: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ if (mCore->mConsumerListener == NULL) {
+ BQ_LOGE("connect: BufferQueue has no consumer");
+ return NO_INIT;
+ }
+
+ if (output == NULL) {
+ BQ_LOGE("connect: output was NULL");
+ return BAD_VALUE;
+ }
+
+ if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("connect: already connected (cur=%d req=%d)",
+ mCore->mConnectedApi, api);
+ return BAD_VALUE;
+ }
+
+ bool dequeueBufferCannotBlock = mDequeueTimeout < 0 ?
+ mCore->mConsumerControlledByApp && producerControlledByApp :
+ false;
+ int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
+ dequeueBufferCannotBlock, mCore->mMaxBufferCount) -
+ mCore->getMaxBufferCountLocked();
+
+ if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
+ BQ_LOGE("connect: BufferQueue failed to adjust the number of "
+ "available slots. Delta = %d", delta);
+ return BAD_VALUE;
+ }
+
+ switch (api) {
+ case NATIVE_WINDOW_API_EGL:
+ case NATIVE_WINDOW_API_CPU:
+ case NATIVE_WINDOW_API_MEDIA:
+ case NATIVE_WINDOW_API_CAMERA:
+ mCore->mConnectedApi = api;
+ output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
+ mCore->mTransformHint,
+ static_cast<uint32_t>(mCore->mQueue.size()));
+
+ // Set up a death notification so that we can disconnect
+ // automatically if the remote producer dies
+ if (listener != NULL &&
+ IInterface::asBinder(listener)->remoteBinder() !=
+ NULL) {
+ status = IInterface::asBinder(listener)->linkToDeath(
+ static_cast<IBinder::DeathRecipient*>(this));
+ if (status != NO_ERROR) {
+ BQ_LOGE("connect: linkToDeath failed: %s (%d)",
+ strerror(-status), status);
+ }
}
- }
- mCore->mConnectedProducerListener = listener;
- break;
- default:
- BQ_LOGE("connect: unknown API %d", api);
- status = BAD_VALUE;
- break;
+ mCore->mConnectedProducerListener = listener;
+ break;
+ default:
+ BQ_LOGE("connect: unknown API %d", api);
+ status = BAD_VALUE;
+ break;
+ }
+
+ mCore->mBufferHasBeenQueued = false;
+ mCore->mDequeueBufferCannotBlock = dequeueBufferCannotBlock;
+
+ mCore->mAllowAllocation = true;
+ VALIDATE_CONSISTENCY();
+
+ if (delta < 0) {
+ consumerListener = mCore->mConsumerListener;
+ producerListener = listener;
+ }
}
- mCore->mBufferHasBeenQueued = false;
- mCore->mDequeueBufferCannotBlock = false;
- if (mDequeueTimeout < 0) {
- mCore->mDequeueBufferCannotBlock =
- mCore->mConsumerControlledByApp && producerControlledByApp;
+ // Call back without lock held
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
+ }
+ if (producerListener != NULL) {
+ for (int i : freedSlots) {
+ producerListener->onSlotFreed(i);
+ }
}
- mCore->mAllowAllocation = true;
- VALIDATE_CONSISTENCY();
return status;
}
@@ -1323,19 +1407,40 @@
ATRACE_CALL();
BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
- Mutex::Autolock lock(mCore->mMutex);
- int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
- mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
- if (!mCore->adjustAvailableSlotsLocked(delta)) {
- BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number of "
- "available slots. Delta = %d", delta);
- return BAD_VALUE;
+ sp<IConsumerListener> consumerListener;
+ sp<IProducerListener> producerListener;
+ std::vector<int> freedSlots;
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+ int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
+ mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
+ if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
+ BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number"
+ " of available slots. Delta = %d", delta);
+ return BAD_VALUE;
+ }
+
+ mDequeueTimeout = timeout;
+ mCore->mDequeueBufferCannotBlock = false;
+
+ VALIDATE_CONSISTENCY();
+
+ if (delta < 0) {
+ consumerListener = mCore->mConsumerListener;
+ producerListener = mCore->mConnectedProducerListener;
+ }
}
- mDequeueTimeout = timeout;
- mCore->mDequeueBufferCannotBlock = false;
+ // Call back without lock held
+ if (consumerListener != NULL) {
+ consumerListener->onBuffersReleased();
+ }
+ if (producerListener != NULL) {
+ for (int i : freedSlots) {
+ producerListener->onSlotFreed(i);
+ }
+ }
- VALIDATE_CONSISTENCY();
return NO_ERROR;
}
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 81adc95..39c1da8 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -22,6 +22,7 @@
enum {
ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
+ ON_SLOT_FREED,
};
class BpProducerListener : public BpInterface<IProducerListener>
@@ -37,6 +38,17 @@
data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ virtual void onSlotFreed(int slot) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
+ data.writeInt32(slot);
+ status_t err = remote()->transact(ON_SLOT_FREED, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ if (err != NO_ERROR) {
+ ALOGE("onSlotFreed failed to transact %d", err);
+ }
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -52,6 +64,12 @@
CHECK_INTERFACE(IProducerListener, data, reply);
onBufferReleased();
return NO_ERROR;
+ case ON_SLOT_FREED: {
+ CHECK_INTERFACE(IProducerListener, data, reply);
+ int slot = data.readInt32();
+ onSlotFreed(slot);
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 45b6463..fad0baa 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -727,4 +727,55 @@
ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
}
+struct TestListener : public BnProducerListener {
+ virtual void onBufferReleased() {}
+ virtual void onSlotFreed(int slot) {
+ ASSERT_EQ(1, slot);
+ }
+};
+
+TEST_F(IGraphicBufferProducerTest, SlotFreedListenerReturnsCorrectSlot) {
+ const ::testing::TestInfo* const testInfo =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
+ testInfo->name());
+
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+
+ sp<DummyConsumer> consumerListener = new DummyConsumer;
+ ASSERT_OK(mConsumer->consumerConnect(consumerListener, false));
+
+ sp<TestListener> producerListener = new TestListener;
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_OK(mProducer->connect(producerListener, TEST_API,
+ TEST_CONTROLLED_BY_APP, &output));
+
+ ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
+
+ DequeueBufferResult buffer0;
+ sp<GraphicBuffer> buf;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS, &buffer0));
+ ASSERT_OK(mProducer->requestBuffer(buffer0.slot, &buf));
+
+ DequeueBufferResult buffer1;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS, &buffer1));
+
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ ASSERT_OK(mProducer->queueBuffer(buffer0.slot, input, &output));
+
+ DequeueBufferResult buffer2;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS, &buffer2));
+
+ ASSERT_OK(mProducer->cancelBuffer(buffer1.slot, Fence::NO_FENCE));
+
+ ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1));
+}
+
+
} // namespace android
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index f83846b..693fba4 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -19,7 +19,7 @@
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE:= libhwcTest
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcTestLib.cpp
LOCAL_C_INCLUDES += system/extras/tests/include \
@@ -32,7 +32,7 @@
LOCAL_MODULE:= hwcStress
LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcStress.cpp
@@ -62,7 +62,7 @@
LOCAL_MODULE:= hwcRects
LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcRects.cpp
@@ -92,7 +92,7 @@
LOCAL_MODULE:= hwcColorEquiv
LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcColorEquiv.cpp
@@ -122,7 +122,7 @@
LOCAL_MODULE:= hwcCommit
LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcCommit.cpp
diff --git a/opengl/tests/hwc/hwcColorEquiv.cpp b/opengl/tests/hwc/hwcColorEquiv.cpp
index 06a0191..f1361b8 100644
--- a/opengl/tests/hwc/hwcColorEquiv.cpp
+++ b/opengl/tests/hwc/hwcColorEquiv.cpp
@@ -62,6 +62,8 @@
* frame for cases where an equivalent color does not exist.
*/
+#define LOG_TAG "hwcColorEquivTest"
+
#include <algorithm>
#include <assert.h>
#include <cerrno>
@@ -87,7 +89,6 @@
#include <ui/GraphicBuffer.h>
-#define LOG_TAG "hwcColorEquivTest"
#include <utils/Log.h>
#include <testUtil.h>
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 1bcb860..6b287e9 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -70,6 +70,8 @@
* made and reported for each of the known graphic format.
*/
+#define LOG_TAG "hwcCommitTest"
+
#include <algorithm>
#include <assert.h>
#include <cerrno>
@@ -98,7 +100,6 @@
#include <ui/GraphicBuffer.h>
-#define LOG_TAG "hwcCommitTest"
#include <utils/Log.h>
#include <testUtil.h>
@@ -120,8 +121,6 @@
const ColorFract defaultColor(0.5, 0.5, 0.5);
const float defaultAlpha = 1.0; // Opaque
const HwcTestDim defaultSourceDim(1, 1);
-const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
-const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
// Global Constants
const uint32_t printFieldWidth = 2;
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
index 56c1a2a..2e2b204 100644
--- a/opengl/tests/hwc/hwcRects.cpp
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -80,6 +80,8 @@
* a list of attributes and the format of their expected value.
*/
+#define LOG_TAG "hwcRectsTest"
+
#include <algorithm>
#include <assert.h>
#include <cerrno>
@@ -105,8 +107,6 @@
#include <GLES2/gl2ext.h>
#include <ui/GraphicBuffer.h>
-
-#define LOG_TAG "hwcRectsTest"
#include <utils/Log.h>
#include <testUtil.h>
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp
index b1d6c76..60c29ef 100644
--- a/opengl/tests/hwc/hwcStress.cpp
+++ b/opengl/tests/hwc/hwcStress.cpp
@@ -78,6 +78,8 @@
* a different color from the rest of the rectangle.
*/
+#define LOG_TAG "hwcStressTest"
+
#include <algorithm>
#include <assert.h>
#include <cerrno>
@@ -103,7 +105,6 @@
#include <ui/GraphicBuffer.h>
-#define LOG_TAG "hwcStressTest"
#include <utils/Log.h>
#include <testUtil.h>
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
index e5124ad..4407e7b 100644
--- a/opengl/tests/lib/Android.mk
+++ b/opengl/tests/lib/Android.mk
@@ -22,6 +22,6 @@
LOCAL_C_INCLUDES += system/extras/tests/include \
$(call include-path-for, opengl-tests-includes)
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tests/lib/glTestLib.cpp b/opengl/tests/lib/glTestLib.cpp
index b434fc7..213dffd 100644
--- a/opengl/tests/lib/glTestLib.cpp
+++ b/opengl/tests/lib/glTestLib.cpp
@@ -31,7 +31,6 @@
#include <utils/Log.h>
#include <testUtil.h>
-using namespace std;
using namespace android;
void glTestPrintGLString(const char *name, GLenum s)
diff --git a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
index 47f232d..aa0d2a4 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
@@ -118,22 +118,35 @@
static void
android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
(JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
+ jniThrowException(_env, "java/lang/UnsupportedOperationException", "deprecated");
+}
+
+/* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
+static void
+android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2
+ (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jobject name_buf) {
jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
+ jbyteArray _nameArray = (jbyteArray)0;
+ jint _nameBufferOffset = (jint)0;
jint _lengthRemaining;
GLsizei *length = (GLsizei *) 0;
jint _sizeRemaining;
GLint *size = (GLint *) 0;
jint _typeRemaining;
GLenum *type = (GLenum *) 0;
+ jint _nameRemaining;
+ GLchar* name = (GLchar*)0;
+
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
+ name = (GLchar*)getPointer(_env, name_buf, (jarray*)&_nameArray, &_nameRemaining, &_nameBufferOffset);
if (length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
@@ -146,6 +159,10 @@
char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
+ if (name == NULL) {
+ char* _nameBase = (char *)_env->GetByteArrayElements(_nameArray, (jboolean*)0);
+ name = (GLchar *) (_nameBase + _nameBufferOffset);
+ }
glGetTransformFeedbackVarying(
(GLuint)program,
(GLuint)index,
@@ -153,11 +170,7 @@
(GLsizei *)length,
(GLint *)size,
(GLenum *)type,
- // The cast below is incorrect. The driver will end up writing to the
- // address specified by name, which will always crash the process since
- // it is guaranteed to be in low memory. The additional static_cast
- // suppresses the warning for now. http://b/19478262
- (char *)static_cast<uintptr_t>(name)
+ (GLchar*)name
);
if (_typeArray) {
releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
@@ -168,6 +181,9 @@
if (_lengthArray) {
releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
}
+ if (_nameArray) {
+ releaseArrayPointer<jbyteArray, jbyte*, ByteArrayReleaser>(_env, _nameArray, (jbyte*)name, JNI_TRUE);
+ }
}
/* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
diff --git a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java
index f73bbfe..e54359d 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java
+++ b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java
@@ -15,7 +15,10 @@
);
// C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
-
+ /**
+ * @deprecated
+ * Use the version that takes a ByteBuffer as the last argument, or the versions that return a String.
+ * */
public static native void glGetTransformFeedbackVarying(
int program,
int index,
@@ -28,6 +31,18 @@
// C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
+ public static native void glGetTransformFeedbackVarying(
+ int program,
+ int index,
+ int bufsize,
+ java.nio.IntBuffer length,
+ java.nio.IntBuffer size,
+ java.nio.IntBuffer type,
+ java.nio.ByteBuffer name
+ );
+
+ // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
+
public static native String glGetTransformFeedbackVarying(
int program,
int index,
diff --git a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg
index 412d04c..7f5829b 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg
+++ b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg
@@ -1,4 +1,5 @@
{"glGetTransformFeedbackVarying", "(III[II[II[II[BI)V", (void *) android_glGetTransformFeedbackVarying__III_3II_3II_3II_3BI },
{"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/ByteBuffer;)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2 },
{"glGetTransformFeedbackVarying", "(II[II[II)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying1 },
{"glGetTransformFeedbackVarying", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying2 },
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index 779fedf..85b8ab2 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -16,6 +16,8 @@
include $(CLEAR_VARS)
LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
LOCAL_CFLAGS := -DLOG_TAG=\"vulkan\" \
-std=c99 -fvisibility=hidden -fstrict-aliasing \
-Weverything -Werror \
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 5fefc62..7f944cf 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -511,16 +511,18 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
- uint32_t min_undequeued_buffers;
- err = surface.window->query(
- surface.window.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- reinterpret_cast<int*>(&min_undequeued_buffers));
- if (err != 0) {
+ int query_value;
+ err = surface.window->query(surface.window.get(),
+ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &query_value);
+ if (err != 0 || query_value < 0) {
// TODO(jessehall): Improve error reporting. Can we enumerate possible
// errors and translate them to valid Vulkan result codes?
- ALOGE("window->query failed: %s (%d)", strerror(-err), err);
+ ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
+ query_value);
return VK_ERROR_INITIALIZATION_FAILED;
}
+ uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
// The MIN_UNDEQUEUED_BUFFERS query doesn't know whether we'll be using
// async mode or not, and assumes not. But in async mode, the BufferQueue
// requires an extra undequeued buffer.