Merge "omx: Add AllocateNativeHandleParams structure" into nyc-dev
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index a4b5ff1..a588ef4 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -18,7 +18,7 @@
# ZipArchive support, the order matters here to get all symbols.
LOCAL_STATIC_LIBRARIES := libziparchive libz libbase libmincrypt
LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
-LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter -std=gnu99
+LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
LOCAL_INIT_RC := dumpstate.rc
include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 462cf7d..128681f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -488,7 +488,8 @@
MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n", entry_name.c_str());
return false;
}
- MYLOGD("Adding zip entry %s\n", entry_name.c_str());
+ // Logging statement below is useful to time how long each entry takes, but it's too verbose.
+ // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(),
ZipWriter::kCompress, get_mtime(fd, now));
if (err) {
@@ -1237,10 +1238,18 @@
if (is_redirecting) {
redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
+ if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
+ MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
+ log_path.c_str(), strerror(errno));
+ }
/* TODO: rather than generating a text file now and zipping it later,
it would be more efficient to redirect stdout to the zip entry
directly, but the libziparchive doesn't support that option yet. */
redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
+ if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
+ MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
+ tmp_path.c_str(), strerror(errno));
+ }
}
// NOTE: there should be no stdout output until now, otherwise it would break the header.
// In particular, DurationReport objects should be created passing 'title, NULL', so their
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 9d42939..282a772 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -324,10 +324,10 @@
// field 42 is iotime
unsigned long long utime = 0, stime = 0, iotime = 0;
if (sscanf(buffer,
- "%*llu %*s %*s %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld "
- "%*lld %*lld %llu %llu %*lld %*lld %*lld %*lld %*lld %*lld "
- "%*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld "
- "%*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %*lld %llu ",
+ "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
&utime, &stime, &iotime) != 3) {
return;
}
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index e2e73a0..7b90aa1 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/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 92285e5..b025280 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -274,35 +274,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;
}
@@ -573,30 +589,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;
}
@@ -611,7 +637,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();
@@ -648,7 +676,7 @@
}
int delta = maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount;
- if (!mCore->adjustAvailableSlotsLocked(delta)) {
+ if (!mCore->adjustAvailableSlotsLocked(delta, &freedSlots)) {
return BAD_VALUE;
}
@@ -656,12 +684,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 f785db0..df7376e 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -225,7 +225,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())) {
@@ -252,11 +253,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 136a14a..46e7591 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;
}
@@ -1313,19 +1397,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/Surface.cpp b/libs/gui/Surface.cpp
index 6fc55c3..ebbeae6 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -838,10 +838,6 @@
}
}
- if (err == NO_ERROR) {
- freeAllBuffers();
- }
-
ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
bufferCount, strerror(-err));
@@ -858,10 +854,6 @@
ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) "
"returned %s", maxDequeuedBuffers, strerror(-err));
- if (err == NO_ERROR) {
- freeAllBuffers();
- }
-
return err;
}
@@ -874,10 +866,6 @@
ALOGE_IF(err, "IGraphicBufferProducer::setAsyncMode(%d) returned %s",
async, strerror(-err));
- if (err == NO_ERROR) {
- freeAllBuffers();
- }
-
return err;
}
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/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 6f0104a..0de60c9 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -232,4 +232,30 @@
EXPECT_STREQ("TestConsumer", surface->getConsumerName().string());
}
+TEST_F(SurfaceTest, DynamicSetBufferCount) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(window.get(),
+ NATIVE_WINDOW_API_CPU));
+ native_window_set_buffer_count(window.get(), 4);
+
+ int fence;
+ ANativeWindowBuffer* buffer;
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+ native_window_set_buffer_count(window.get(), 3);
+ ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+ native_window_set_buffer_count(window.get(), 2);
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+ ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+}
+
}
diff --git a/vulkan/libvulkan/dispatch.tmpl b/vulkan/libvulkan/dispatch.tmpl
index 1a584e3..306aae4 100644
--- a/vulkan/libvulkan/dispatch.tmpl
+++ b/vulkan/libvulkan/dispatch.tmpl
@@ -465,7 +465,7 @@
{{define "IsInstanceDispatched"}}
{{AssertType $ "Function"}}
{{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
- {{if (ne $.Name "vkGetInstanceProcAddr")}}true{{end}}
+ {{if and (ne $.Name "vkEnumerateDeviceLayerProperties") (ne $.Name "vkGetInstanceProcAddr")}}true{{end}}
{{end}}
{{end}}
@@ -561,6 +561,8 @@
{{else if eq $.Name "vkGetDeviceQueue"}}true
{{else if eq $.Name "vkAllocateCommandBuffers"}}true
{{else if eq $.Name "vkCreateDevice"}}true
+ {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
+ {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
{{/* vkDestroy for dispatchable objects needs to handle VK_NULL_HANDLE;
trying to dispatch through that would crash. */}}
diff --git a/vulkan/libvulkan/dispatch_gen.cpp b/vulkan/libvulkan/dispatch_gen.cpp
index 9028c3f..b41efb8 100644
--- a/vulkan/libvulkan/dispatch_gen.cpp
+++ b/vulkan/libvulkan/dispatch_gen.cpp
@@ -215,6 +215,8 @@
{"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance_Top))},
{"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice_Top))},
{"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyInstance>(DestroyInstance_Top))},
+ {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceExtensionProperties>(EnumerateDeviceExtensionProperties_Top))},
+ {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties_Top))},
{"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties_Top))},
{"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties_Top))},
{"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr_Top))},
@@ -296,7 +298,6 @@
{"vkDestroyInstance", offsetof(InstanceDispatchTable, DestroyInstance)},
{"vkDestroySurfaceKHR", offsetof(InstanceDispatchTable, DestroySurfaceKHR)},
{"vkEnumerateDeviceExtensionProperties", offsetof(InstanceDispatchTable, EnumerateDeviceExtensionProperties)},
- {"vkEnumerateDeviceLayerProperties", offsetof(InstanceDispatchTable, EnumerateDeviceLayerProperties)},
{"vkEnumeratePhysicalDevices", offsetof(InstanceDispatchTable, EnumeratePhysicalDevices)},
{"vkGetPhysicalDeviceFeatures", offsetof(InstanceDispatchTable, GetPhysicalDeviceFeatures)},
{"vkGetPhysicalDeviceFormatProperties", offsetof(InstanceDispatchTable, GetPhysicalDeviceFormatProperties)},
@@ -522,11 +523,6 @@
ALOGE("missing instance proc: %s", "vkCreateDevice");
success = false;
}
- dispatch.EnumerateDeviceLayerProperties = reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(get_proc_addr(instance, "vkEnumerateDeviceLayerProperties"));
- if (UNLIKELY(!dispatch.EnumerateDeviceLayerProperties)) {
- ALOGE("missing instance proc: %s", "vkEnumerateDeviceLayerProperties");
- success = false;
- }
dispatch.EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(get_proc_addr(instance, "vkEnumerateDeviceExtensionProperties"));
if (UNLIKELY(!dispatch.EnumerateDeviceExtensionProperties)) {
ALOGE("missing instance proc: %s", "vkEnumerateDeviceExtensionProperties");
@@ -1271,11 +1267,6 @@
ALOGE("missing driver proc: %s", "vkCreateDevice");
success = false;
}
- dispatch.EnumerateDeviceLayerProperties = reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(get_proc_addr(instance, "vkEnumerateDeviceLayerProperties"));
- if (UNLIKELY(!dispatch.EnumerateDeviceLayerProperties)) {
- ALOGE("missing driver proc: %s", "vkEnumerateDeviceLayerProperties");
- success = false;
- }
dispatch.EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(get_proc_addr(instance, "vkEnumerateDeviceExtensionProperties"));
if (UNLIKELY(!dispatch.EnumerateDeviceExtensionProperties)) {
ALOGE("missing driver proc: %s", "vkEnumerateDeviceExtensionProperties");
@@ -1422,12 +1413,12 @@
__attribute__((visibility("default")))
VKAPI_ATTR VkResult vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
- return GetDispatchTable(physicalDevice).EnumerateDeviceLayerProperties(physicalDevice, pPropertyCount, pProperties);
+ return EnumerateDeviceLayerProperties_Top(physicalDevice, pPropertyCount, pProperties);
}
__attribute__((visibility("default")))
VKAPI_ATTR VkResult vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
- return GetDispatchTable(physicalDevice).EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
+ return EnumerateDeviceExtensionProperties_Top(physicalDevice, pLayerName, pPropertyCount, pProperties);
}
__attribute__((visibility("default")))
diff --git a/vulkan/libvulkan/dispatch_gen.h b/vulkan/libvulkan/dispatch_gen.h
index 14a4b95..7bab6ca 100644
--- a/vulkan/libvulkan/dispatch_gen.h
+++ b/vulkan/libvulkan/dispatch_gen.h
@@ -34,7 +34,6 @@
PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
PFN_vkCreateDevice CreateDevice;
- PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
@@ -190,7 +189,6 @@
PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
PFN_vkCreateDevice CreateDevice;
- PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index a0c142e..1a57c22 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -454,12 +454,6 @@
bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
const char* extension_name,
const VkAllocationCallbacks* alloc) {
- for (uint32_t i = 0; i < local_create_info.enabledExtensionCount; ++i) {
- if (!strcmp(extension_name,
- local_create_info.ppEnabledExtensionNames[i])) {
- return false;
- }
- }
uint32_t extension_count = local_create_info.enabledExtensionCount;
local_create_info.enabledExtensionCount++;
void* mem = alloc->pfnAllocation(
@@ -821,55 +815,25 @@
properties);
}
+// This is a no-op, the Top function returns the aggregate layer property
+// data. This is to keep the dispatch generator happy.
VKAPI_ATTR
VkResult EnumerateDeviceExtensionProperties_Bottom(
- VkPhysicalDevice gpu,
- const char* layer_name,
- uint32_t* properties_count,
- VkExtensionProperties* properties) {
- const VkExtensionProperties* extensions = nullptr;
- uint32_t num_extensions = 0;
- if (layer_name) {
- GetDeviceLayerExtensions(layer_name, &extensions, &num_extensions);
- } else {
- Instance& instance = GetDispatchParent(gpu);
- size_t gpu_idx = 0;
- while (instance.physical_devices[gpu_idx] != gpu)
- gpu_idx++;
- const DeviceExtensionSet driver_extensions =
- instance.physical_device_driver_extensions[gpu_idx];
-
- // We only support VK_KHR_swapchain if the GPU supports
- // VK_ANDROID_native_buffer
- VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
- alloca(kDeviceExtensionCount * sizeof(VkExtensionProperties)));
- if (driver_extensions[kANDROID_native_buffer]) {
- available[num_extensions++] = VkExtensionProperties{
- VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION};
- }
-
- // TODO(jessehall): We need to also enumerate extensions supported by
- // implicitly-enabled layers. Currently we don't have that list of
- // layers until instance creation.
- extensions = available;
- }
-
- if (!properties || *properties_count > num_extensions)
- *properties_count = num_extensions;
- if (properties)
- std::copy(extensions, extensions + *properties_count, properties);
- return *properties_count < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
+ VkPhysicalDevice /*pdev*/,
+ const char* /*layer_name*/,
+ uint32_t* /*properties_count*/,
+ VkExtensionProperties* /*properties*/) {
+ return VK_SUCCESS;
}
+// This is a no-op, the Top function returns the aggregate layer property
+// data. This is to keep the dispatch generator happy.
VKAPI_ATTR
-VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice /*pdev*/,
- uint32_t* properties_count,
- VkLayerProperties* properties) {
- uint32_t layer_count =
- EnumerateDeviceLayers(properties ? *properties_count : 0, properties);
- if (!properties || *properties_count > layer_count)
- *properties_count = layer_count;
- return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
+VkResult EnumerateDeviceLayerProperties_Bottom(
+ VkPhysicalDevice /*pdev*/,
+ uint32_t* /*properties_count*/,
+ VkLayerProperties* /*properties*/) {
+ return VK_SUCCESS;
}
VKAPI_ATTR
@@ -1061,6 +1025,51 @@
return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
}
+VKAPI_ATTR
+VkResult EnumerateDeviceExtensionProperties_Top(
+ VkPhysicalDevice gpu,
+ const char* layer_name,
+ uint32_t* properties_count,
+ VkExtensionProperties* properties) {
+ const VkExtensionProperties* extensions = nullptr;
+ uint32_t num_extensions = 0;
+
+ ALOGV("EnumerateDeviceExtensionProperties_Top:");
+ if (layer_name) {
+ ALOGV(" layer %s", layer_name);
+ GetDeviceLayerExtensions(layer_name, &extensions, &num_extensions);
+ } else {
+ ALOGV(" no layer");
+ Instance& instance = GetDispatchParent(gpu);
+ size_t gpu_idx = 0;
+ while (instance.physical_devices[gpu_idx] != gpu)
+ gpu_idx++;
+ const DeviceExtensionSet driver_extensions =
+ instance.physical_device_driver_extensions[gpu_idx];
+
+ // We only support VK_KHR_swapchain if the GPU supports
+ // VK_ANDROID_native_buffer
+ VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
+ alloca(kDeviceExtensionCount * sizeof(VkExtensionProperties)));
+ if (driver_extensions[kANDROID_native_buffer]) {
+ available[num_extensions++] = VkExtensionProperties{
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION};
+ }
+
+ // TODO(jessehall): We need to also enumerate extensions supported by
+ // implicitly-enabled layers. Currently we don't have that list of
+ // layers until instance creation.
+ extensions = available;
+ }
+
+ ALOGV(" num: %d, extensions: %p", num_extensions, extensions);
+ if (!properties || *properties_count > num_extensions)
+ *properties_count = num_extensions;
+ if (properties)
+ std::copy(extensions, extensions + *properties_count, properties);
+ return *properties_count < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
+}
+
VkResult CreateInstance_Top(const VkInstanceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkInstance* instance_out) {
@@ -1149,8 +1158,23 @@
instance_create_info.pNext = local_create_info.pNext;
local_create_info.pNext = &instance_create_info;
+ // Force enable callback extension if required
+ bool enable_callback = false;
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
+ enable_callback =
+ property_get_bool("debug.vulkan.enable_callback", false);
+ if (enable_callback) {
+ enable_callback = AddExtensionToCreateInfo(
+ local_create_info, "VK_EXT_debug_report", instance->alloc);
+ }
+ }
+
result = create_instance(&local_create_info, allocator, &local_instance);
+ if (enable_callback) {
+ FreeAllocatedCreateInfo(local_create_info, allocator);
+ }
+
if (result != VK_SUCCESS) {
DestroyInstance_Bottom(instance->handle, allocator);
TeardownInstance(instance->handle, allocator);
@@ -1177,20 +1201,7 @@
}
*instance_out = local_instance;
- // Force enable callback extension if required
- bool enable_callback = false;
- bool enable_logging = false;
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
- enable_callback =
- property_get_bool("debug.vulkan.enable_callback", false);
- enable_logging = enable_callback;
- if (enable_callback) {
- enable_callback = AddExtensionToCreateInfo(
- local_create_info, "VK_EXT_debug_report", instance->alloc);
- }
- }
-
- if (enable_logging) {
+ if (enable_callback) {
const VkDebugReportCallbackCreateInfoEXT callback_create_info = {
.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
.flags =
@@ -1239,6 +1250,17 @@
}
VKAPI_ATTR
+VkResult EnumerateDeviceLayerProperties_Top(VkPhysicalDevice /*pdev*/,
+ uint32_t* properties_count,
+ VkLayerProperties* properties) {
+ uint32_t layer_count =
+ EnumerateDeviceLayers(properties ? *properties_count : 0, properties);
+ if (!properties || *properties_count > layer_count)
+ *properties_count = layer_count;
+ return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
+}
+
+VKAPI_ATTR
VkResult CreateDevice_Top(VkPhysicalDevice gpu,
const VkDeviceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index 8081c0e..77c8ebe 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -94,6 +94,8 @@
VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr_Top(VkDevice drv_device, const char* name);
VKAPI_ATTR void GetDeviceQueue_Top(VkDevice drv_device, uint32_t family, uint32_t index, VkQueue* out_queue);
VKAPI_ATTR VkResult AllocateCommandBuffers_Top(VkDevice device, const VkCommandBufferAllocateInfo* alloc_info, VkCommandBuffer* cmdbufs);
+VKAPI_ATTR VkResult EnumerateDeviceLayerProperties_Top(VkPhysicalDevice pdev, uint32_t* properties_count, VkLayerProperties* properties);
+VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties_Top(VkPhysicalDevice pdev, const char * layer_name, uint32_t* properties_count, VkExtensionProperties* properties);
VKAPI_ATTR VkResult CreateDevice_Top(VkPhysicalDevice pdev, const VkDeviceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkDevice* device_out);
VKAPI_ATTR void DestroyDevice_Top(VkDevice drv_device, const VkAllocationCallbacks* allocator);
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index 42bdb9d..b88c35d 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -168,12 +168,28 @@
.queueCount = 1,
queue_priorities
};
+ // clang-format off
+ const char *kValidationLayers[] = {
+ "VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_device_limits",
+ "VK_LAYER_LUNARG_draw_state",
+ "VK_LAYER_LUNARG_image",
+ "VK_LAYER_LUNARG_mem_tracker",
+ "VK_LAYER_LUNARG_object_tracker",
+ "VK_LAYER_LUNARG_param_checker",
+ "VK_LAYER_LUNARG_swapchain",
+ "VK_LAYER_GOOGLE_unique_objects"
+ };
+ // clang-format on
+ uint32_t num_layers = sizeof(kValidationLayers) / sizeof(char*);
const VkDeviceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queue_create_info,
.enabledExtensionCount = num_extensions,
.ppEnabledExtensionNames = extensions,
+ .enabledLayerCount = num_layers,
+ .ppEnabledLayerNames = kValidationLayers,
.pEnabledFeatures = &info.features,
};
result = vkCreateDevice(gpu, &create_info, nullptr, &device);
@@ -218,10 +234,27 @@
extensions[num_extensions++] = desired_ext;
}
+ // clang-format off
+ const char *kValidationLayers[] = {
+ "VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_device_limits",
+ "VK_LAYER_LUNARG_draw_state",
+ "VK_LAYER_LUNARG_image",
+ "VK_LAYER_LUNARG_mem_tracker",
+ "VK_LAYER_LUNARG_object_tracker",
+ "VK_LAYER_LUNARG_param_checker",
+ "VK_LAYER_LUNARG_swapchain",
+ "VK_LAYER_GOOGLE_unique_objects"
+ };
+ // clang-format on
+ uint32_t num_layers = sizeof(kValidationLayers) / sizeof(char*);
+
const VkInstanceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.enabledExtensionCount = num_extensions,
.ppEnabledExtensionNames = extensions,
+ .enabledLayerCount = num_layers,
+ .ppEnabledLayerNames = kValidationLayers,
};
VkInstance instance;
result = vkCreateInstance(&create_info, nullptr, &instance);
@@ -477,6 +510,7 @@
// ----------------------------------------------------------------------------
int main(int argc, char const* argv[]) {
+ static volatile bool startup_pause = false;
Options options = {
.layer_description = false, .layer_extensions = false,
};
@@ -488,9 +522,15 @@
options.layer_description = true;
} else if (strcmp(argv[argi], "-layer_extensions") == 0) {
options.layer_extensions = true;
+ } else if (strcmp(argv[argi], "-debug_pause") == 0) {
+ startup_pause = true;
}
}
+ while (startup_pause) {
+ sleep(0);
+ }
+
VulkanInfo info;
GatherInfo(&info);
PrintInfo(info, options);