Merge "[SurfaceFlinger] Add composition unit tests"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..f8f0265
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,3 @@
+[Hook Scripts]
+owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
+installd_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/installd/"
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
new file mode 100644
index 0000000..50440f1
--- /dev/null
+++ b/cmds/installd/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+calin@google.com
+agampe@google.com
+jsharkey@android.com
+toddke@google.com
+ngeoffray@google.com
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 6b340a8..d776682 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -403,7 +403,11 @@
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
+#ifdef VENDORSERVICEMANAGER
+ cb.func_log = selinux_vendor_log_callback;
+#else
cb.func_log = selinux_log_callback;
+#endif
selinux_set_callback(SELINUX_CB_LOG, cb);
#ifdef VENDORSERVICEMANAGER
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 76d5a73..e5c68b5 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -24,10 +24,10 @@
],
srcs: [
- "ABinderProcess.cpp",
- "AIBinder.cpp",
- "AParcel.cpp",
- "AServiceManager.cpp",
+ "ibinder.cpp",
+ "parcel.cpp",
+ "process.cpp",
+ "service_manager.cpp",
],
shared_libs: [
diff --git a/libs/binder/ndk/AIBinder.cpp b/libs/binder/ndk/ibinder.cpp
similarity index 64%
rename from libs/binder/ndk/AIBinder.cpp
rename to libs/binder/ndk/ibinder.cpp
index 83972f7..8a1ec05 100644
--- a/libs/binder/ndk/AIBinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -15,13 +15,15 @@
*/
#include <android/binder_ibinder.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
#include <android/binder_status.h>
-#include "AParcel_internal.h"
+#include "parcel_internal.h"
#include <android-base/logging.h>
+using DeathRecipient = ::android::IBinder::DeathRecipient;
+
using ::android::IBinder;
using ::android::Parcel;
using ::android::sp;
@@ -32,10 +34,10 @@
static const void* kId = "ABBinder";
static void* kValue = static_cast<void*>(new bool{true});
-void cleanId(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
+void clean(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
static void attach(const sp<IBinder>& binder) {
- binder->attachObject(kId, kValue, nullptr /*cookie*/, cleanId);
+ binder->attachObject(kId, kValue, nullptr /*cookie*/, clean);
}
static bool has(const sp<IBinder>& binder) {
return binder != nullptr && binder->findObject(kId) == kValue;
@@ -43,6 +45,21 @@
} // namespace ABBinderTag
+namespace ABpBinderTag {
+
+static std::mutex gLock;
+static const void* kId = "ABpBinder";
+struct Value {
+ wp<ABpBinder> binder;
+};
+void clean(const void* id, void* obj, void* cookie) {
+ CHECK(id == kId) << id << " " << obj << " " << cookie;
+
+ delete static_cast<Value*>(obj);
+};
+
+} // namespace ABpBinderTag
+
AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
AIBinder::~AIBinder() {}
@@ -121,14 +138,51 @@
}
ABpBinder::~ABpBinder() {}
-sp<AIBinder> ABpBinder::fromBinder(const ::android::sp<::android::IBinder>& binder) {
+void ABpBinder::onLastStrongRef(const void* id) {
+ {
+ std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
+ // Since ABpBinder is OBJECT_LIFETIME_WEAK, we must remove this weak reference in order for
+ // the ABpBinder to be deleted. Since a strong reference to this ABpBinder object should no
+ // longer be able to exist at the time of this method call, there is no longer a need to
+ // recover it.
+
+ ABpBinderTag::Value* value =
+ static_cast<ABpBinderTag::Value*>(remote()->findObject(ABpBinderTag::kId));
+ if (value != nullptr) {
+ value->binder = nullptr;
+ }
+ }
+
+ BpRefBase::onLastStrongRef(id);
+}
+
+sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android::IBinder>& binder) {
if (binder == nullptr) {
return nullptr;
}
if (ABBinderTag::has(binder)) {
return static_cast<ABBinder*>(binder.get());
}
- return new ABpBinder(binder);
+
+ // The following code ensures that for a given binder object (remote or local), if it is not an
+ // ABBinder then at most one ABpBinder object exists in a given process representing it.
+ std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
+
+ ABpBinderTag::Value* value =
+ static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
+ if (value == nullptr) {
+ value = new ABpBinderTag::Value;
+ binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value), nullptr /*cookie*/,
+ ABpBinderTag::clean);
+ }
+
+ sp<ABpBinder> ret = value->binder.promote();
+ if (ret == nullptr) {
+ ret = new ABpBinder(binder);
+ value->binder = ret;
+ }
+
+ return ret;
}
struct AIBinder_Weak {
@@ -179,6 +233,63 @@
return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
}
+void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
+ CHECK(who == mWho);
+
+ mOnDied(mCookie);
+ mWho = nullptr;
+}
+
+AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied)
+ : mOnDied(onDied) {
+ CHECK(onDied != nullptr);
+}
+
+binder_status_t AIBinder_DeathRecipient::linkToDeath(AIBinder* binder, void* cookie) {
+ CHECK(binder != nullptr);
+
+ std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
+
+ sp<TransferDeathRecipient> recipient =
+ new TransferDeathRecipient(binder->getBinder(), cookie, mOnDied);
+
+ binder_status_t status = binder->getBinder()->linkToDeath(recipient, cookie, 0 /*flags*/);
+ if (status != EX_NONE) {
+ return status;
+ }
+
+ mDeathRecipients.push_back(recipient);
+ return EX_NONE;
+}
+
+binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* cookie) {
+ CHECK(binder != nullptr);
+
+ std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
+
+ for (auto it = mDeathRecipients.rbegin(); it != mDeathRecipients.rend(); ++it) {
+ sp<TransferDeathRecipient> recipient = *it;
+
+ if (recipient->getCookie() == cookie &&
+
+ recipient->getWho() == binder->getBinder()) {
+ mDeathRecipients.erase(it.base() - 1);
+
+ binder_status_t status =
+ binder->getBinder()->unlinkToDeath(recipient, cookie, 0 /*flags*/);
+ if (status != EX_NONE) {
+ LOG(ERROR) << __func__
+ << ": removed reference to death recipient but unlink failed.";
+ }
+ return status;
+ }
+ }
+
+ return -ENOENT;
+}
+
+// start of C-API methods
+
AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
if (clazz == nullptr) {
LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
@@ -218,6 +329,26 @@
return binder->getBinder()->pingBinder();
}
+binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie) {
+ if (binder == nullptr || recipient == nullptr) {
+ LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+ return EX_NULL_POINTER;
+ }
+
+ return recipient->linkToDeath(binder, cookie);
+}
+
+binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie) {
+ if (binder == nullptr || recipient == nullptr) {
+ LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+ return EX_NULL_POINTER;
+ }
+
+ return recipient->unlinkToDeath(binder, cookie);
+}
+
void AIBinder_incStrong(AIBinder* binder) {
if (binder == nullptr) {
LOG(ERROR) << __func__ << ": on null binder";
@@ -285,6 +416,13 @@
return EX_ILLEGAL_STATE;
}
+ if (!binder->isRemote()) {
+ LOG(WARNING) << "A binder object at " << binder
+ << " is being transacted on, however, this object is in the same process as "
+ "its proxy. Transacting with this binder is expensive compared to just "
+ "calling the corresponding functionality in the same process.";
+ }
+
*in = new AParcel(binder);
binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
if (status != EX_NONE) {
@@ -340,3 +478,21 @@
return parcelStatus;
}
+
+AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
+ AIBinder_DeathRecipient_onBinderDied onBinderDied) {
+ if (onBinderDied == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null onBinderDied parameter.";
+ return nullptr;
+ }
+ return new AIBinder_DeathRecipient(onBinderDied);
+}
+
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient) {
+ if (recipient == nullptr) {
+ return;
+ }
+
+ delete *recipient;
+ *recipient = nullptr;
+}
diff --git a/libs/binder/ndk/AIBinder_internal.h b/libs/binder/ndk/ibinder_internal.h
similarity index 65%
rename from libs/binder/ndk/AIBinder_internal.h
rename to libs/binder/ndk/ibinder_internal.h
index 23949bb..fcf1b0b 100644
--- a/libs/binder/ndk/AIBinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -17,9 +17,11 @@
#pragma once
#include <android/binder_ibinder.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
#include <atomic>
+#include <mutex>
+#include <vector>
#include <binder/Binder.h>
#include <binder/IBinder.h>
@@ -79,13 +81,18 @@
void* mUserData;
};
-// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
-// a class.
+// This binder object may be remote or local (even though it is 'Bp'). The implication if it is
+// local is that it is an IBinder object created outside of the domain of libbinder_ndk.
struct ABpBinder : public AIBinder, public ::android::BpRefBase {
- static ::android::sp<AIBinder> fromBinder(const ::android::sp<::android::IBinder>& binder);
+ // Looks up to see if this object has or is an existing ABBinder or ABpBinder object, otherwise
+ // it creates an ABpBinder object.
+ static ::android::sp<AIBinder> lookupOrCreateFromBinder(
+ const ::android::sp<::android::IBinder>& binder);
virtual ~ABpBinder();
+ void onLastStrongRef(const void* id) override;
+
::android::sp<::android::IBinder> getBinder() override { return remote(); }
ABpBinder* asABpBinder() override { return this; }
@@ -108,3 +115,38 @@
// one.
const ::android::String16 mInterfaceDescriptor;
};
+
+// Ownership is like this (when linked to death):
+//
+// AIBinder_DeathRecipient -sp-> TransferDeathRecipient <-wp-> IBinder
+//
+// When the AIBinder_DeathRecipient is dropped, so are the actual underlying death recipients. When
+// the IBinder dies, only a wp to it is kept.
+struct AIBinder_DeathRecipient {
+ // One of these is created for every linkToDeath. This is to be able to recover data when a
+ // binderDied receipt only gives us information about the IBinder.
+ struct TransferDeathRecipient : ::android::IBinder::DeathRecipient {
+ TransferDeathRecipient(const ::android::wp<::android::IBinder>& who, void* cookie,
+ const AIBinder_DeathRecipient_onBinderDied& onDied)
+ : mWho(who), mCookie(cookie), mOnDied(onDied) {}
+
+ void binderDied(const ::android::wp<::android::IBinder>& who) override;
+
+ const ::android::wp<::android::IBinder>& getWho() { return mWho; }
+ void* getCookie() { return mCookie; }
+
+ private:
+ ::android::wp<::android::IBinder> mWho;
+ void* mCookie;
+ const AIBinder_DeathRecipient_onBinderDied& mOnDied;
+ };
+
+ AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
+ binder_status_t linkToDeath(AIBinder* binder, void* cookie);
+ binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);
+
+private:
+ std::mutex mDeathRecipientsMutex;
+ std::vector<::android::sp<TransferDeathRecipient>> mDeathRecipients;
+ AIBinder_DeathRecipient_onBinderDied mOnDied;
+};
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index aa29437..7dca5a4 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -14,6 +14,16 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_ibinder.h
+ * @brief Object which can receive transactions and be sent across processes.
+ */
+
#pragma once
#include <stdint.h>
@@ -84,6 +94,16 @@
* implementation (usually a callback) to transfer all ownership to a remote process and
* automatically be deleted when the remote process is done with it or dies. Other memory models are
* possible, but this is the standard one.
+ *
+ * If the process containing an AIBinder dies, it is possible to be holding a strong reference to
+ * an object which does not exist. In this case, transactions to this binder will return
+ * EX_DEAD_OBJECT. See also AIBinder_linkToDeath, AIBinder_unlinkToDeath, and AIBinder_isAlive.
+ *
+ * Once an AIBinder is created, anywhere it is passed (remotely or locally), there is a 1-1
+ * correspondence between the address of an AIBinder and the object it represents. This means that
+ * when two AIBinder pointers point to the same address, they represent the same object (whether
+ * that object is local or remote). This correspondance can be broken accidentally if AIBinder_new
+ * is erronesouly called to create the same object multiple times.
*/
struct AIBinder;
typedef struct AIBinder AIBinder;
@@ -97,6 +117,12 @@
typedef struct AIBinder_Weak AIBinder_Weak;
/**
+ * Represents a handle on a death notification. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
+ */
+struct AIBinder_DeathRecipient;
+typedef struct AIBinder_DeathRecipient AIBinder_DeathRecipient;
+
+/**
* This is called whenever a new AIBinder object is needed of a specific class.
*
* These arguments are passed from AIBinder_new. The return value is stored and can be retrieved
@@ -138,6 +164,14 @@
*
* When this is called, the refcount is implicitly 1. So, calling decStrong exactly one time is
* required to delete this object.
+ *
+ * Once an AIBinder object is created using this API, re-creating that AIBinder for the same
+ * instance of the same class will break pointer equality for that specific AIBinder object. For
+ * instance, if someone erroneously created two AIBinder instances representing the same callback
+ * object and passed one to a hypothetical addCallback function and then later another one to a
+ * hypothetical removeCallback function, the remote process would have no way to determine that
+ * these two objects are actually equal using the AIBinder pointer alone (which they should be able
+ * to do). Also see the suggested memory ownership model suggested above.
*/
__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args);
@@ -163,6 +197,26 @@
binder_status_t AIBinder_ping(AIBinder* binder);
/**
+ * Registers for notifications that the associated binder is dead. The same death recipient may be
+ * associated with multiple different binders. If the binder is local, then no death recipient will
+ * be given (since if the local process dies, then no recipient will exist to recieve a
+ * transaction). The cookie is passed to recipient in the case that this binder dies and can be
+ * null. The exact cookie must also be used to unlink this transaction (see AIBinder_linkToDeath).
+ * This function may return a binder transaction failure. The cookie can be used both for
+ * identification and holding user data.
+ */
+binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie);
+
+/**
+ * Stops registration for the associated binder dying. Does not delete the recipient. This function
+ * may return a binder transaction failure and in case the death recipient cannot be found, it
+ * returns -ENOENT.
+ */
+binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+ void* cookie);
+
+/**
* This can only be called if a strong reference to this object already exists in process.
*/
void AIBinder_incStrong(AIBinder* binder);
@@ -254,4 +308,23 @@
*/
__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder);
+/**
+ * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
+ */
+typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie);
+
+/**
+ * Creates a new binder death recipient. This can be attached to multiple different binder objects.
+ */
+__attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
+ AIBinder_DeathRecipient_onBinderDied onBinderDied);
+
+/**
+ * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
+ * calling this as these will all be automatically unlinked.
+ */
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient);
+
__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 19925f7..e871ed1 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -14,6 +14,16 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_parcel.h
+ * @brief A collection of data that can be sent as a single packet.
+ */
+
#pragma once
#include <sys/cdefs.h>
@@ -150,3 +160,5 @@
// @END
__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index d414c99..e97e181 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_status.h
+ */
+
#pragma once
#include <stdint.h>
@@ -54,3 +63,5 @@
typedef int32_t binder_status_t;
__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/AParcel.cpp b/libs/binder/ndk/parcel.cpp
similarity index 91%
rename from libs/binder/ndk/AParcel.cpp
rename to libs/binder/ndk/parcel.cpp
index 93384d6..ccdfc7b 100644
--- a/libs/binder/ndk/AParcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -15,9 +15,9 @@
*/
#include <android/binder_parcel.h>
-#include "AParcel_internal.h"
+#include "parcel_internal.h"
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
#include <binder/Parcel.h>
@@ -35,7 +35,8 @@
}
binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
- return (*parcel)->writeStrongBinder(binder->getBinder());
+ sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
+ return (*parcel)->writeStrongBinder(writeBinder);
}
binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
sp<IBinder> readBinder = nullptr;
@@ -43,7 +44,7 @@
if (status != EX_NONE) {
return status;
}
- sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+ sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
AIBinder_incStrong(ret.get());
*binder = ret.get();
return status;
@@ -54,7 +55,7 @@
if (status != EX_NONE) {
return status;
}
- sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+ sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
AIBinder_incStrong(ret.get());
*binder = ret.get();
return status;
diff --git a/libs/binder/ndk/AParcel_internal.h b/libs/binder/ndk/parcel_internal.h
similarity index 98%
rename from libs/binder/ndk/AParcel_internal.h
rename to libs/binder/ndk/parcel_internal.h
index 9f30a2f..b6a9110 100644
--- a/libs/binder/ndk/AParcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
#include <binder/Parcel.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
struct AParcel {
const ::android::Parcel* operator->() const { return mParcel; }
diff --git a/libs/binder/ndk/ABinderProcess.cpp b/libs/binder/ndk/process.cpp
similarity index 100%
rename from libs/binder/ndk/ABinderProcess.cpp
rename to libs/binder/ndk/process.cpp
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
index 5c0b936..794afe2 100755
--- a/libs/binder/ndk/scripts/gen_parcel_helper.py
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -81,7 +81,7 @@
source += "}\n\n"
replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header)
- replaceFileTags(ROOT + "AParcel.cpp", source)
+ replaceFileTags(ROOT + "parcel.cpp", source)
print("Updating DONE.")
diff --git a/libs/binder/ndk/AServiceManager.cpp b/libs/binder/ndk/service_manager.cpp
similarity index 93%
rename from libs/binder/ndk/AServiceManager.cpp
rename to libs/binder/ndk/service_manager.cpp
index 3979945..5bc69b0 100644
--- a/libs/binder/ndk/AServiceManager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -15,7 +15,7 @@
*/
#include <android/binder_manager.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
#include <binder/IServiceManager.h>
@@ -41,7 +41,7 @@
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(instance));
- sp<AIBinder> ret = ABpBinder::fromBinder(binder);
+ sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
AIBinder_incStrong(ret.get());
return ret.get();
}
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index 967789f..b8518d7 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -16,6 +16,7 @@
#include <android-base/logging.h>
#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <gtest/gtest.h>
#include <iface/iface.h>
@@ -45,6 +46,28 @@
AIBinder_decStrong(binder);
}
+void OnBinderDeath(void* cookie) {
+ LOG(ERROR) << "BINDER DIED. COOKIE: " << cookie;
+}
+
+TEST(NdkBinder, LinkToDeath) {
+ ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications
+ ABinderProcess_startThreadPool();
+
+ AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binder);
+
+ AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath);
+ ASSERT_NE(nullptr, recipient);
+
+ EXPECT_EQ(EX_NONE, AIBinder_linkToDeath(binder, recipient, nullptr));
+ EXPECT_EQ(EX_NONE, AIBinder_unlinkToDeath(binder, recipient, nullptr));
+ EXPECT_EQ(-ENOENT, AIBinder_unlinkToDeath(binder, recipient, nullptr));
+
+ AIBinder_DeathRecipient_delete(&recipient);
+ AIBinder_decStrong(binder);
+}
+
class MyTestFoo : public IFoo {
int32_t doubleNumber(int32_t in) override {
LOG(INFO) << "doubleNumber " << in;
@@ -64,6 +87,34 @@
EXPECT_EQ(2, getFoo->doubleNumber(1));
}
+TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
+ AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binderA);
+
+ AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binderB);
+
+ EXPECT_EQ(binderA, binderB);
+
+ AIBinder_decStrong(binderA);
+ AIBinder_decStrong(binderB);
+}
+
+TEST(NdkBinder, ABpBinderRefCount) {
+ AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+ AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);
+
+ ASSERT_NE(nullptr, binder);
+ EXPECT_EQ(1, AIBinder_debugGetRefCount(binder));
+
+ AIBinder_decStrong(binder);
+
+ // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here
+ ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder));
+
+ AIBinder_Weak_delete(&wBinder);
+}
+
TEST(NdkBinder, AddServiceMultipleTimes) {
static const char* kInstanceName1 = "test-multi-1";
static const char* kInstanceName2 = "test-multi-2";
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index ef3e592..98264ac 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -31,6 +31,7 @@
"-Werror",
],
cppflags: [
+ "-std=c++1z",
"-Weverything",
// The static constructors and destructors in this library have not been noted to
@@ -58,7 +59,7 @@
"-Wno-weak-vtables",
// Allow four-character integer literals
- "-Wno-four-char-constants",
+ "-Wno-four-char-constants",
// Allow documentation warnings
"-Wno-documentation",
@@ -116,7 +117,7 @@
"SyncFeatures.cpp",
"view/Surface.cpp",
"bufferqueue/1.0/B2HProducerListener.cpp",
- "bufferqueue/1.0/H2BGraphicBufferProducer.cpp"
+ "bufferqueue/1.0/H2BGraphicBufferProducer.cpp",
],
shared_libs: [
@@ -124,7 +125,7 @@
"libsync",
"libbinder",
"libbufferhub",
- "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
+ "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
"libpdx_default_transport",
"libcutils",
"libEGL",
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index deb8ea8..5a8d8db 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "LayerState"
+
#include <utils/Errors.h>
#include <binder/Parcel.h>
#include <gui/ISurfaceComposerClient.h>
@@ -313,8 +315,10 @@
sidebandStream = other.sidebandStream;
}
- if (other.what != what) {
- ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating?");
+ if ((other.what & what) != other.what) {
+ ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
+ "other.what=0x%X what=0x%X",
+ other.what, what);
}
}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index e3ef2a9..1605050 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -26,6 +26,7 @@
"-Werror",
],
cppflags: [
+ "-std=c++1z",
"-Weverything",
// The static constructors and destructors in this library have not been noted to
diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp
index 1414766..340231d 100644
--- a/libs/ui/FenceTime.cpp
+++ b/libs/ui/FenceTime.cpp
@@ -33,18 +33,6 @@
const auto FenceTime::NO_FENCE = std::make_shared<FenceTime>(Fence::NO_FENCE);
-void* FenceTime::operator new(size_t byteCount) noexcept {
- void *p = nullptr;
- if (posix_memalign(&p, alignof(FenceTime), byteCount)) {
- return nullptr;
- }
- return p;
-}
-
-void FenceTime::operator delete(void *p) {
- free(p);
-}
-
FenceTime::FenceTime(const sp<Fence>& fence)
: mState(((fence.get() != nullptr) && fence->isValid()) ?
State::VALID : State::INVALID),
diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h
index 871fcf2..a5a1fcb 100644
--- a/libs/ui/include/ui/FenceTime.h
+++ b/libs/ui/include/ui/FenceTime.h
@@ -113,11 +113,6 @@
void signalForTest(nsecs_t signalTime);
- // Override new and delete since this needs 8-byte alignment, which
- // is not guaranteed on x86.
- static void* operator new(size_t nbytes) noexcept;
- static void operator delete(void *p);
-
private:
// For tests only. If forceValidForTest is true, then getSignalTime will
// never return SIGNAL_TIME_INVALID and isValid will always return true.
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 1f2c517..a296d20 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -440,6 +440,9 @@
Status<std::vector<size_t>> ProducerQueue::AllocateBuffers(
uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
uint64_t usage, size_t buffer_count) {
+ if (buffer_count == 0) {
+ return {};
+ }
if (capacity() + buffer_count > kMaxQueueCapacity) {
ALOGE(
"ProducerQueue::AllocateBuffers: queue is at capacity: %zu, cannot "
@@ -481,10 +484,13 @@
}
}
- if (buffer_slots.size() == 0) {
- // Error out if no buffer is allocated and improted.
- ALOGE_IF(TRACE, "ProducerQueue::AllocateBuffers: no buffer allocated.");
- ErrorStatus(ENOMEM);
+ if (buffer_slots.size() != buffer_count) {
+ // Error out if the count of allocated/imported buffer(s) is not correct.
+ ALOGE(
+ "ProducerQueue::AllocateBuffers: requested to import %zu "
+ "buffers, but actually imported %zu buffers.",
+ buffer_count, buffer_slots.size());
+ return ErrorStatus(ENOMEM);
}
return {std::move(buffer_slots)};
@@ -502,12 +508,6 @@
status.GetErrorMessage().c_str());
return status.error_status();
}
-
- if (status.get().size() == 0) {
- ALOGE_IF(TRACE, "ProducerQueue::AllocateBuffer: no buffer allocated.");
- ErrorStatus(ENOMEM);
- }
-
return {status.get()[0]};
}
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 2975f56..c1f322c 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -562,6 +562,28 @@
ASSERT_EQ(cs2, ps2);
}
+TEST_F(BufferHubQueueTest, TestAllocateTwoBuffers) {
+ ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
+ ASSERT_EQ(producer_queue_->capacity(), 0);
+
+ auto status = producer_queue_->AllocateBuffers(
+ kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+ kBufferUsage, 2);
+ ASSERT_TRUE(status.ok());
+ ASSERT_EQ(producer_queue_->capacity(), 2);
+}
+
+TEST_F(BufferHubQueueTest, TestAllocateZeroBuffers) {
+ ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
+ ASSERT_EQ(producer_queue_->capacity(), 0);
+
+ auto status = producer_queue_->AllocateBuffers(
+ kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+ kBufferUsage, 0);
+ ASSERT_TRUE(status.ok());
+ ASSERT_EQ(producer_queue_->capacity(), 0);
+}
+
TEST_F(BufferHubQueueTest, TestUsageSetMask) {
const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
ASSERT_TRUE(
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 10974b4..4839bfb 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -433,6 +433,10 @@
if (mFlinger->isLayerTripleBufferingDisabled()) {
mProducer->setMaxDequeuedBufferCount(2);
}
+
+ if (const auto display = mFlinger->getDefaultDisplayDevice()) {
+ updateTransformHint(display);
+ }
}
status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 2c94a0e..d963ab6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -160,11 +160,13 @@
std::optional<DisplayId> displayId;
- uint8_t port;
- DisplayIdentificationData data;
- if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
- displayId = generateDisplayId(port, data);
- ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId);
+ if (connection == HWC2::Connection::Connected) {
+ uint8_t port;
+ DisplayIdentificationData data;
+ if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
+ displayId = generateDisplayId(port, data);
+ ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId);
+ }
}
// Disconnect is handled through HWComposer::disconnectDisplay via
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 29de50c..a1e45b0 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -284,7 +284,7 @@
}
Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
- const Layer::State& s(getDrawingState());
+ const State& s(getDrawingState());
Rect win(getActiveWidth(s), getActiveHeight(s));
Rect crop = getCrop(s);
@@ -319,12 +319,12 @@
}
FloatRect Layer::computeBounds() const {
- const Layer::State& s(getDrawingState());
+ const State& s(getDrawingState());
return computeBounds(getActiveTransparentRegion(s));
}
FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
- const Layer::State& s(getDrawingState());
+ const State& s(getDrawingState());
Rect win(getActiveWidth(s), getActiveHeight(s));
Rect crop = getCrop(s);
@@ -762,7 +762,7 @@
}
bool Layer::isSecure() const {
- const Layer::State& s(mDrawingState);
+ const State& s(mDrawingState);
return (s.flags & layer_state_t::eLayerSecure);
}
@@ -885,7 +885,7 @@
}
uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) {
- const Layer::State& s(getDrawingState());
+ const State& s(getDrawingState());
const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) ||
(stateToCommit->requested_legacy.h != s.requested_legacy.h);
@@ -941,7 +941,7 @@
// latching configuration. See Layer.h for a detailed discussion of
// how geometry latching is controlled.
if (!(flags & eDontUpdateGeometryState)) {
- Layer::State& editCurrentState(getCurrentState());
+ State& editCurrentState(getCurrentState());
// If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize
// mode, which causes attributes which normally latch regardless of scaling mode,
@@ -974,14 +974,14 @@
ATRACE_CALL();
pushPendingState();
- Layer::State c = getCurrentState();
+ State c = getCurrentState();
if (!applyPendingStates(&c)) {
return 0;
}
flags = doTransactionResize(flags, &c);
- const Layer::State& s(getDrawingState());
+ const State& s(getDrawingState());
if (getActiveGeometry(c) != getActiveGeometry(s)) {
// invalidate and recompute the visible regions if needed
@@ -1272,7 +1272,7 @@
// ----------------------------------------------------------------------------
bool Layer::isHiddenByPolicy() const {
- const Layer::State& s(mDrawingState);
+ const State& s(mDrawingState);
const auto& parent = mDrawingParent.promote();
if (parent != nullptr && parent->isHiddenByPolicy()) {
return true;
@@ -1315,7 +1315,7 @@
// TODO(marissaw): add new layer state info to layer debugging
LayerDebugInfo Layer::getLayerDebugInfo() const {
LayerDebugInfo info;
- const Layer::State& ds = getDrawingState();
+ const State& ds = getDrawingState();
info.mName = getName();
sp<Layer> parent = getParent();
info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string());
@@ -1392,7 +1392,7 @@
result.appendFormat(" %s\n", name.string());
- const Layer::State& layerState(getDrawingState());
+ const State& layerState(getDrawingState());
const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId);
if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
result.appendFormat(" rel %6d | ", layerState.z);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index f00367f..3b54873 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -16,152 +16,33 @@
#include <renderengine/RenderEngine.h>
-#include <vector>
-
+#include <cutils/properties.h>
#include <log/log.h>
#include <private/gui/SyncFeatures.h>
-#include <renderengine/Image.h>
-#include <renderengine/Mesh.h>
-#include <renderengine/Surface.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <utils/KeyedVector.h>
#include "gl/GLES20RenderEngine.h"
-#include "gl/GLExtensions.h"
-#include "gl/ProgramCache.h"
-
-using namespace android::renderengine::gl;
-
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
namespace android {
namespace renderengine {
+std::unique_ptr<impl::RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
+ char prop[PROPERTY_VALUE_MAX];
+ property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles");
+ if (strcmp(prop, "gles") == 0) {
+ ALOGD("RenderEngine GLES Backend");
+ return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+ }
+ ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop);
+ return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+}
+
RenderEngine::~RenderEngine() = default;
namespace impl {
-std::unique_ptr<RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
- // initialize EGL for the default display
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (!eglInitialize(display, nullptr, nullptr)) {
- LOG_ALWAYS_FATAL("failed to initialize EGL");
- }
-
- GLExtensions& extensions = GLExtensions::getInstance();
- extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION),
- eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS));
-
- // The code assumes that ES2 or later is available if this extension is
- // supported.
- EGLConfig config = EGL_NO_CONFIG;
- if (!extensions.hasNoConfigContext()) {
- config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
- }
-
- EGLint renderableType = 0;
- if (config == EGL_NO_CONFIG) {
- renderableType = EGL_OPENGL_ES2_BIT;
- } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
- LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
- }
- EGLint contextClientVersion = 0;
- if (renderableType & EGL_OPENGL_ES2_BIT) {
- contextClientVersion = 2;
- } else if (renderableType & EGL_OPENGL_ES_BIT) {
- contextClientVersion = 1;
- } else {
- LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
- }
-
- std::vector<EGLint> contextAttributes;
- contextAttributes.reserve(6);
- contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
- contextAttributes.push_back(contextClientVersion);
- bool useContextPriority = extensions.hasContextPriority() &&
- (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT);
- if (useContextPriority) {
- contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
- contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
- }
- contextAttributes.push_back(EGL_NONE);
-
- EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data());
-
- // if can't create a GL context, we can only abort.
- LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
-
- // now figure out what version of GL did we actually get
- // NOTE: a dummy surface is not needed if KHR_create_context is supported
-
- EGLConfig dummyConfig = config;
- if (dummyConfig == EGL_NO_CONFIG) {
- dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
- }
- EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
- EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
- LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
- EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
- LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
-
- extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
- glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
-
- GlesVersion version = parseGlesVersion(extensions.getVersion());
-
- // initialize the renderer while GL is current
-
- std::unique_ptr<RenderEngine> engine;
- switch (version) {
- case GLES_VERSION_1_0:
- case GLES_VERSION_1_1:
- LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
- break;
- case GLES_VERSION_2_0:
- case GLES_VERSION_3_0:
- engine = std::make_unique<GLES20RenderEngine>(featureFlags);
- break;
- }
- engine->setEGLHandles(display, config, ctxt);
-
- ALOGI("OpenGL ES informations:");
- ALOGI("vendor : %s", extensions.getVendor());
- ALOGI("renderer : %s", extensions.getRenderer());
- ALOGI("version : %s", extensions.getVersion());
- ALOGI("extensions: %s", extensions.getExtensions());
- ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
- ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
-
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroySurface(display, dummy);
-
- return engine;
-}
-
RenderEngine::RenderEngine(uint32_t featureFlags)
- : mEGLDisplay(EGL_NO_DISPLAY),
- mEGLConfig(nullptr),
- mEGLContext(EGL_NO_CONTEXT),
- mFeatureFlags(featureFlags) {}
+ : mFeatureFlags(featureFlags) {}
-RenderEngine::~RenderEngine() {
- eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglTerminate(mEGLDisplay);
-}
-
-void RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
- mEGLDisplay = display;
- mEGLConfig = config;
- mEGLContext = ctxt;
-}
-
-EGLDisplay RenderEngine::getEGLDisplay() const {
- return mEGLDisplay;
-}
-
-EGLConfig RenderEngine::getEGLConfig() const {
- return mEGLConfig;
-}
+RenderEngine::~RenderEngine() = default;
bool RenderEngine::useNativeFenceSync() const {
return SyncFeatures::getInstance().useNativeFenceSync();
@@ -171,185 +52,6 @@
return SyncFeatures::getInstance().useWaitSync();
}
-RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
- int major, minor;
- if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
- if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
- ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
- return GLES_VERSION_1_0;
- }
- }
-
- if (major == 1 && minor == 0) return GLES_VERSION_1_0;
- if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
- if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
- if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
-
- ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
- return GLES_VERSION_1_0;
-}
-
-void RenderEngine::dump(String8& result) {
- const GLExtensions& extensions = GLExtensions::getInstance();
-
- result.appendFormat("EGL implementation : %s\n", extensions.getEGLVersion());
- result.appendFormat("%s\n", extensions.getEGLExtensions());
-
- result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
- extensions.getVersion());
- result.appendFormat("%s\n", extensions.getExtensions());
-}
-
-static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
- EGLint wanted, EGLConfig* outConfig) {
- EGLint numConfigs = -1, n = 0;
- eglGetConfigs(dpy, nullptr, 0, &numConfigs);
- EGLConfig* const configs = new EGLConfig[numConfigs];
- eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
-
- if (n) {
- if (attribute != EGL_NONE) {
- for (int i = 0; i < n; i++) {
- EGLint value = 0;
- eglGetConfigAttrib(dpy, configs[i], attribute, &value);
- if (wanted == value) {
- *outConfig = configs[i];
- delete[] configs;
- return NO_ERROR;
- }
- }
- } else {
- // just pick the first one
- *outConfig = configs[0];
- delete[] configs;
- return NO_ERROR;
- }
- }
- delete[] configs;
- return NAME_NOT_FOUND;
-}
-
-class EGLAttributeVector {
- struct Attribute;
- class Adder;
- friend class Adder;
- KeyedVector<Attribute, EGLint> mList;
- struct Attribute {
- Attribute() : v(0){};
- explicit Attribute(EGLint v) : v(v) {}
- EGLint v;
- bool operator<(const Attribute& other) const {
- // this places EGL_NONE at the end
- EGLint lhs(v);
- EGLint rhs(other.v);
- if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
- if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
- return lhs < rhs;
- }
- };
- class Adder {
- friend class EGLAttributeVector;
- EGLAttributeVector& v;
- EGLint attribute;
- Adder(EGLAttributeVector& v, EGLint attribute) : v(v), attribute(attribute) {}
-
- public:
- void operator=(EGLint value) {
- if (attribute != EGL_NONE) {
- v.mList.add(Attribute(attribute), value);
- }
- }
- operator EGLint() const { return v.mList[attribute]; }
- };
-
-public:
- EGLAttributeVector() { mList.add(Attribute(EGL_NONE), EGL_NONE); }
- void remove(EGLint attribute) {
- if (attribute != EGL_NONE) {
- mList.removeItem(Attribute(attribute));
- }
- }
- Adder operator[](EGLint attribute) { return Adder(*this, attribute); }
- EGLint operator[](EGLint attribute) const { return mList[attribute]; }
- // cast-operator to (EGLint const*)
- operator EGLint const*() const { return &mList.keyAt(0).v; }
-};
-
-static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
- EGLConfig* config) {
- // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
- // it is to be used with WIFI displays
- status_t err;
- EGLint wantedAttribute;
- EGLint wantedAttributeValue;
-
- EGLAttributeVector attribs;
- if (renderableType) {
- attribs[EGL_RENDERABLE_TYPE] = renderableType;
- attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
- attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
- attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
- attribs[EGL_RED_SIZE] = 8;
- attribs[EGL_GREEN_SIZE] = 8;
- attribs[EGL_BLUE_SIZE] = 8;
- attribs[EGL_ALPHA_SIZE] = 8;
- wantedAttribute = EGL_NONE;
- wantedAttributeValue = EGL_NONE;
- } else {
- // if no renderable type specified, fallback to a simplified query
- wantedAttribute = EGL_NATIVE_VISUAL_ID;
- wantedAttributeValue = format;
- }
-
- err = selectConfigForAttribute(display, attribs, wantedAttribute, wantedAttributeValue, config);
- if (err == NO_ERROR) {
- EGLint caveat;
- if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
- ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
- }
-
- return err;
-}
-
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
- status_t err;
- EGLConfig config;
-
- // First try to get an ES2 config
- err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
- if (err != NO_ERROR) {
- // If ES2 fails, try ES1
- err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
- if (err != NO_ERROR) {
- // still didn't work, probably because we're on the emulator...
- // try a simplified query
- ALOGW("no suitable EGLConfig found, trying a simpler query");
- err = selectEGLConfig(display, format, 0, &config);
- if (err != NO_ERROR) {
- // this EGL is too lame for android
- LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
- }
- }
- }
-
- if (logConfig) {
- // print some debugging info
- EGLint r, g, b, a;
- eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
- eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
- eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
- eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
- ALOGI("EGL information:");
- ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
- ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
- ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
- ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
- ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
- }
-
- return config;
-}
-
} // namespace impl
} // namespace renderengine
} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index 61df675..0f0ff62 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -44,6 +44,8 @@
#include "Program.h"
#include "ProgramCache.h"
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
bool checkGlError(const char* op, int lineNumber) {
bool errorFound = false;
GLint error = glGetError();
@@ -109,8 +111,259 @@
using ui::Dataspace;
+static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
+ EGLint wanted, EGLConfig* outConfig) {
+ EGLint numConfigs = -1, n = 0;
+ eglGetConfigs(dpy, nullptr, 0, &numConfigs);
+ EGLConfig* const configs = new EGLConfig[numConfigs];
+ eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
+
+ if (n) {
+ if (attribute != EGL_NONE) {
+ for (int i = 0; i < n; i++) {
+ EGLint value = 0;
+ eglGetConfigAttrib(dpy, configs[i], attribute, &value);
+ if (wanted == value) {
+ *outConfig = configs[i];
+ delete[] configs;
+ return NO_ERROR;
+ }
+ }
+ } else {
+ // just pick the first one
+ *outConfig = configs[0];
+ delete[] configs;
+ return NO_ERROR;
+ }
+ }
+ delete[] configs;
+ return NAME_NOT_FOUND;
+}
+
+class EGLAttributeVector {
+ struct Attribute;
+ class Adder;
+ friend class Adder;
+ KeyedVector<Attribute, EGLint> mList;
+ struct Attribute {
+ Attribute() : v(0){};
+ explicit Attribute(EGLint v) : v(v) {}
+ EGLint v;
+ bool operator<(const Attribute& other) const {
+ // this places EGL_NONE at the end
+ EGLint lhs(v);
+ EGLint rhs(other.v);
+ if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
+ if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
+ return lhs < rhs;
+ }
+ };
+ class Adder {
+ friend class EGLAttributeVector;
+ EGLAttributeVector& v;
+ EGLint attribute;
+ Adder(EGLAttributeVector& v, EGLint attribute) : v(v), attribute(attribute) {}
+
+ public:
+ void operator=(EGLint value) {
+ if (attribute != EGL_NONE) {
+ v.mList.add(Attribute(attribute), value);
+ }
+ }
+ operator EGLint() const { return v.mList[attribute]; }
+ };
+
+public:
+ EGLAttributeVector() { mList.add(Attribute(EGL_NONE), EGL_NONE); }
+ void remove(EGLint attribute) {
+ if (attribute != EGL_NONE) {
+ mList.removeItem(Attribute(attribute));
+ }
+ }
+ Adder operator[](EGLint attribute) { return Adder(*this, attribute); }
+ EGLint operator[](EGLint attribute) const { return mList[attribute]; }
+ // cast-operator to (EGLint const*)
+ operator EGLint const*() const { return &mList.keyAt(0).v; }
+};
+
+static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
+ EGLConfig* config) {
+ // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
+ // it is to be used with WIFI displays
+ status_t err;
+ EGLint wantedAttribute;
+ EGLint wantedAttributeValue;
+
+ EGLAttributeVector attribs;
+ if (renderableType) {
+ attribs[EGL_RENDERABLE_TYPE] = renderableType;
+ attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
+ attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+ attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
+ attribs[EGL_RED_SIZE] = 8;
+ attribs[EGL_GREEN_SIZE] = 8;
+ attribs[EGL_BLUE_SIZE] = 8;
+ attribs[EGL_ALPHA_SIZE] = 8;
+ wantedAttribute = EGL_NONE;
+ wantedAttributeValue = EGL_NONE;
+ } else {
+ // if no renderable type specified, fallback to a simplified query
+ wantedAttribute = EGL_NATIVE_VISUAL_ID;
+ wantedAttributeValue = format;
+ }
+
+ err = selectConfigForAttribute(display, attribs, wantedAttribute, wantedAttributeValue, config);
+ if (err == NO_ERROR) {
+ EGLint caveat;
+ if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
+ ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
+ }
+
+ return err;
+}
+
+std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat,
+ uint32_t featureFlags) {
+ // initialize EGL for the default display
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (!eglInitialize(display, nullptr, nullptr)) {
+ LOG_ALWAYS_FATAL("failed to initialize EGL");
+ }
+
+ GLExtensions& extensions = GLExtensions::getInstance();
+ extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION),
+ eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS));
+
+ // The code assumes that ES2 or later is available if this extension is
+ // supported.
+ EGLConfig config = EGL_NO_CONFIG;
+ if (!extensions.hasNoConfigContext()) {
+ config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
+ }
+
+ EGLint renderableType = 0;
+ if (config == EGL_NO_CONFIG) {
+ renderableType = EGL_OPENGL_ES2_BIT;
+ } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
+ LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
+ }
+ EGLint contextClientVersion = 0;
+ if (renderableType & EGL_OPENGL_ES2_BIT) {
+ contextClientVersion = 2;
+ } else if (renderableType & EGL_OPENGL_ES_BIT) {
+ contextClientVersion = 1;
+ } else {
+ LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
+ }
+
+ std::vector<EGLint> contextAttributes;
+ contextAttributes.reserve(6);
+ contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttributes.push_back(contextClientVersion);
+ bool useContextPriority = extensions.hasContextPriority() &&
+ (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT);
+ if (useContextPriority) {
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
+ contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ }
+ contextAttributes.push_back(EGL_NONE);
+
+ EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data());
+
+ // if can't create a GL context, we can only abort.
+ LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
+
+ // now figure out what version of GL did we actually get
+ // NOTE: a dummy surface is not needed if KHR_create_context is supported
+
+ EGLConfig dummyConfig = config;
+ if (dummyConfig == EGL_NO_CONFIG) {
+ dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
+ }
+ EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
+ EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
+ LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
+ EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
+ LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
+
+ extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
+ glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
+
+ GlesVersion version = parseGlesVersion(extensions.getVersion());
+
+ // initialize the renderer while GL is current
+
+ std::unique_ptr<GLES20RenderEngine> engine;
+ switch (version) {
+ case GLES_VERSION_1_0:
+ case GLES_VERSION_1_1:
+ LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
+ break;
+ case GLES_VERSION_2_0:
+ case GLES_VERSION_3_0:
+ engine = std::make_unique<GLES20RenderEngine>(featureFlags);
+ break;
+ }
+ engine->setEGLHandles(display, config, ctxt);
+
+ ALOGI("OpenGL ES informations:");
+ ALOGI("vendor : %s", extensions.getVendor());
+ ALOGI("renderer : %s", extensions.getRenderer());
+ ALOGI("version : %s", extensions.getVersion());
+ ALOGI("extensions: %s", extensions.getExtensions());
+ ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
+ ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
+
+ eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(display, dummy);
+
+ return engine;
+}
+
+EGLConfig GLES20RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
+ status_t err;
+ EGLConfig config;
+
+ // First try to get an ES2 config
+ err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
+ if (err != NO_ERROR) {
+ // If ES2 fails, try ES1
+ err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
+ if (err != NO_ERROR) {
+ // still didn't work, probably because we're on the emulator...
+ // try a simplified query
+ ALOGW("no suitable EGLConfig found, trying a simpler query");
+ err = selectEGLConfig(display, format, 0, &config);
+ if (err != NO_ERROR) {
+ // this EGL is too lame for android
+ LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
+ }
+ }
+ }
+
+ if (logConfig) {
+ // print some debugging info
+ EGLint r, g, b, a;
+ eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
+ eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+ eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
+ eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+ ALOGI("EGL information:");
+ ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
+ ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
+ ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
+ ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
+ ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+ }
+
+ return config;
+}
+
GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
- : RenderEngine(featureFlags),
+ : renderengine::impl::RenderEngine(featureFlags),
+ mEGLDisplay(EGL_NO_DISPLAY),
+ mEGLConfig(nullptr),
+ mEGLContext(EGL_NO_CONTEXT),
mVpWidth(0),
mVpHeight(0),
mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
@@ -154,7 +407,10 @@
}
}
-GLES20RenderEngine::~GLES20RenderEngine() {}
+GLES20RenderEngine::~GLES20RenderEngine() {
+ eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(mEGLDisplay);
+}
std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() {
return std::make_unique<GLFramebuffer>(*this);
@@ -278,35 +534,35 @@
return true;
}
-void GLES20RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
- float green, float blue, float alpha) {
+void GLES20RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+ glClearColor(red, green, blue, alpha);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void GLES20RenderEngine::fillRegionWithColor(const Region& region, float red, float green,
+ float blue, float alpha) {
size_t c;
Rect const* r = region.getArray(&c);
Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
for (size_t i = 0; i < c; i++, r++) {
position[i * 6 + 0].x = r->left;
- position[i * 6 + 0].y = height - r->top;
+ position[i * 6 + 0].y = r->top;
position[i * 6 + 1].x = r->left;
- position[i * 6 + 1].y = height - r->bottom;
+ position[i * 6 + 1].y = r->bottom;
position[i * 6 + 2].x = r->right;
- position[i * 6 + 2].y = height - r->bottom;
+ position[i * 6 + 2].y = r->bottom;
position[i * 6 + 3].x = r->left;
- position[i * 6 + 3].y = height - r->top;
+ position[i * 6 + 3].y = r->top;
position[i * 6 + 4].x = r->right;
- position[i * 6 + 4].y = height - r->bottom;
+ position[i * 6 + 4].y = r->bottom;
position[i * 6 + 5].x = r->right;
- position[i * 6 + 5].y = height - r->top;
+ position[i * 6 + 5].y = r->top;
}
setupFillWithColor(red, green, blue, alpha);
drawMesh(mesh);
}
-void GLES20RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
- glClearColor(red, green, blue, alpha);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
void GLES20RenderEngine::setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
glScissor(left, bottom, right, top);
glEnable(GL_SCISSOR_TEST);
@@ -632,12 +888,37 @@
}
void GLES20RenderEngine::dump(String8& result) {
- RenderEngine::dump(result);
+ const GLExtensions& extensions = GLExtensions::getInstance();
+
+ result.appendFormat("EGL implementation : %s\n", extensions.getEGLVersion());
+ result.appendFormat("%s\n", extensions.getEGLExtensions());
+
+ result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
+ extensions.getVersion());
+ result.appendFormat("%s\n", extensions.getExtensions());
result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n",
dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
}
+GLES20RenderEngine::GlesVersion GLES20RenderEngine::parseGlesVersion(const char* str) {
+ int major, minor;
+ if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
+ if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
+ ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
+ return GLES_VERSION_1_0;
+ }
+ }
+
+ if (major == 1 && minor == 0) return GLES_VERSION_1_0;
+ if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
+ if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
+ if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
+
+ ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
+ return GLES_VERSION_1_0;
+}
+
bool GLES20RenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
const Dataspace standard = static_cast<Dataspace>(dataSpace & Dataspace::STANDARD_MASK);
const Dataspace transfer = static_cast<Dataspace>(dataSpace & Dataspace::TRANSFER_MASK);
@@ -665,6 +946,12 @@
return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
}
+void GLES20RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
+ mEGLDisplay = display;
+ mEGLConfig = config;
+ mEGLContext = ctxt;
+}
+
} // namespace gl
} // namespace renderengine
} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
index 04dc1b1..1abc5ba 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -20,10 +20,14 @@
#include <stdint.h>
#include <sys/types.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/private/Description.h>
+#define EGL_NO_CONFIG ((EGLConfig)0)
+
namespace android {
class String8;
@@ -40,6 +44,9 @@
class GLES20RenderEngine : public impl::RenderEngine {
public:
+ static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+ static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
+
GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
~GLES20RenderEngine() override;
@@ -55,8 +62,8 @@
bool finish() override;
bool waitFence(base::unique_fd fenceFd) override;
void clearWithColor(float red, float green, float blue, float alpha) override;
- void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
- float blue, float alpha) override;
+ void fillRegionWithColor(const Region& region, float red, float green, float blue,
+ float alpha) override;
void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override;
void disableScissor() override;
void genTextures(size_t count, uint32_t* names) override;
@@ -67,19 +74,16 @@
void unbindFrameBuffer(Framebuffer* framebuffer) override;
void checkErrors() const override;
+ // internal to RenderEngine
+ EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
+ EGLConfig getEGLConfig() const { return mEGLConfig; }
+
protected:
void dump(String8& result) override;
void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
ui::Transform::orientation_flags rotation) override;
void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
const half4& color) override;
-
- // Color management related functions and state
- void setSourceY410BT2020(bool enable) override;
- void setSourceDataSpace(ui::Dataspace source) override;
- void setOutputDataSpace(ui::Dataspace dataspace) override;
- void setDisplayMaxLuminance(const float maxLuminance) override;
-
void setupLayerTexturing(const Texture& texture) override;
void setupLayerBlackedOut() override;
void setupFillWithColor(float r, float g, float b, float a) override;
@@ -87,17 +91,37 @@
void disableTexturing() override;
void disableBlending() override;
+ // HDR and color management related functions and state
+ void setSourceY410BT2020(bool enable) override;
+ void setSourceDataSpace(ui::Dataspace source) override;
+ void setOutputDataSpace(ui::Dataspace dataspace) override;
+ void setDisplayMaxLuminance(const float maxLuminance) override;
+
+ // drawing
void drawMesh(const Mesh& mesh) override;
size_t getMaxTextureSize() const override;
size_t getMaxViewportDims() const override;
private:
+ enum GlesVersion {
+ GLES_VERSION_1_0 = 0x10000,
+ GLES_VERSION_1_1 = 0x10001,
+ GLES_VERSION_2_0 = 0x20000,
+ GLES_VERSION_3_0 = 0x30000,
+ };
+
+ static GlesVersion parseGlesVersion(const char* str);
+
// A data space is considered HDR data space if it has BT2020 color space
// with PQ or HLG transfer function.
bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
bool needsXYZTransformMatrix() const;
+ void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
+ EGLDisplay mEGLDisplay;
+ EGLConfig mEGLConfig;
+ EGLContext mEGLContext;
GLuint mProtectedTexName;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 2e2ba1c..17d8782 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -21,8 +21,6 @@
#include <sys/types.h>
#include <memory>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
#include <android-base/unique_fd.h>
#include <math/mat4.h>
#include <renderengine/Framebuffer.h>
@@ -30,7 +28,10 @@
#include <ui/GraphicTypes.h>
#include <ui/Transform.h>
-#define EGL_NO_CONFIG ((EGLConfig)0)
+/**
+ * Allows to set RenderEngine backend to GLES (default) or Vulkan (NOT yet supported).
+ */
+#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend"
struct ANativeWindowBuffer;
@@ -59,6 +60,8 @@
USE_HIGH_PRIORITY_CONTEXT = 1 << 1, // Use high priority context
};
+ static std::unique_ptr<impl::RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+
virtual ~RenderEngine() = 0;
virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
@@ -90,10 +93,9 @@
virtual bool waitFence(base::unique_fd fenceFd) = 0;
virtual void clearWithColor(float red, float green, float blue, float alpha) = 0;
- virtual void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+ virtual void fillRegionWithColor(const Region& region, float red, float green,
float blue, float alpha) = 0;
- // common to all GL versions
virtual void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) = 0;
virtual void disableScissor() = 0;
virtual void genTextures(size_t count, uint32_t* names) = 0;
@@ -155,43 +157,18 @@
namespace impl {
+// impl::RenderEngine contains common implementation that is graphics back-end agnostic.
class RenderEngine : public renderengine::RenderEngine {
-protected:
- enum GlesVersion {
- GLES_VERSION_1_0 = 0x10000,
- GLES_VERSION_1_1 = 0x10001,
- GLES_VERSION_2_0 = 0x20000,
- GLES_VERSION_3_0 = 0x30000,
- };
- static GlesVersion parseGlesVersion(const char* str);
-
- EGLDisplay mEGLDisplay;
- EGLConfig mEGLConfig;
- EGLContext mEGLContext;
- void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
-
- RenderEngine(uint32_t featureFlags);
-
- const uint32_t mFeatureFlags;
-
public:
virtual ~RenderEngine() = 0;
- static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
-
- static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
-
- // dump the extension strings. always call the base class.
- void dump(String8& result) override;
-
bool useNativeFenceSync() const override;
bool useWaitSync() const override;
-
void setupColorTransform(const mat4& /* colorTransform */) override {}
- // internal to RenderEngine
- EGLDisplay getEGLDisplay() const;
- EGLConfig getEGLConfig() const;
+protected:
+ RenderEngine(uint32_t featureFlags);
+ const uint32_t mFeatureFlags;
};
} // namespace impl
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index bb85f4c..54e19c7 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -39,7 +39,7 @@
Scheduler::~Scheduler() = default;
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
- const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
@@ -56,13 +56,15 @@
}
std::unique_ptr<EventThread> Scheduler::makeEventThread(
- const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
+ const std::string sourceName = connectionName + "Source";
std::unique_ptr<VSyncSource> eventThreadSource =
- std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+ std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, sourceName.c_str());
+ const std::string threadName = connectionName + "Thread";
return std::make_unique<impl::EventThread>(std::move(eventThreadSource), resyncCallback,
- interceptCallback, connectionName);
+ interceptCallback, threadName.c_str());
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 8efbff4..fcb46e6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -56,7 +56,7 @@
/** Creates an EventThread connection. */
sp<ConnectionHandle> createConnection(
- const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback);
sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle);
@@ -79,7 +79,7 @@
protected:
virtual std::unique_ptr<EventThread> makeEventThread(
- const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+ const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback);
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 7dfad43..ea8ca4c 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -67,6 +67,14 @@
mAppEventThread = appEventThread;
}
+ void setSchedulerAndHandles(Scheduler* scheduler,
+ Scheduler::ConnectionHandle* appConnectionHandle,
+ Scheduler::ConnectionHandle* sfConnectionHandle) {
+ mScheduler = scheduler;
+ mAppConnectionHandle = appConnectionHandle;
+ mSfConnectionHandle = sfConnectionHandle;
+ }
+
void setTransactionStart(TransactionStart transactionStart) {
if (transactionStart == TransactionStart::EARLY) {
mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
@@ -108,11 +116,19 @@
bool changed = false;
if (desired.sf != current.sf) {
- mSfEventThread->setPhaseOffset(desired.sf);
+ if (mSfConnectionHandle != nullptr) {
+ mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
+ } else {
+ mSfEventThread->setPhaseOffset(desired.sf);
+ }
changed = true;
}
if (desired.app != current.app) {
- mAppEventThread->setPhaseOffset(desired.app);
+ if (mSfConnectionHandle != nullptr) {
+ mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
+ } else {
+ mAppEventThread->setPhaseOffset(desired.app);
+ }
changed = true;
}
@@ -138,6 +154,10 @@
EventThread* mSfEventThread = nullptr;
EventThread* mAppEventThread = nullptr;
+ Scheduler* mScheduler = nullptr;
+ Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
+ Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;
+
std::atomic<Offsets> mOffsets;
std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a5bd73a..9537ccc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -632,8 +632,8 @@
});
mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
- mVsyncModulator.setEventThreads(mScheduler->getEventThread(mSfConnectionHandle),
- mScheduler->getEventThread(mAppConnectionHandle));
+ mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
+ mSfConnectionHandle.get());
} else {
mEventThreadSource =
std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
@@ -667,8 +667,8 @@
// TODO(b/77156734): We need to stop casting and use HAL types when possible.
getBE().mRenderEngine =
- renderengine::impl::RenderEngine::create(static_cast<int32_t>(compositionPixelFormat),
- renderEngineFeature);
+ renderengine::RenderEngine::create(static_cast<int32_t>(compositionPixelFormat),
+ renderEngineFeature);
LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
@@ -1688,9 +1688,8 @@
doComposeSurfaces(display);
// and draw the dirty region
- const int32_t height = display->getHeight();
auto& engine(getRenderEngine());
- engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
+ engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
display->swapBuffers(getHwComposer());
}
@@ -3194,7 +3193,7 @@
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
- drawWormhole(display, region);
+ drawWormhole(region);
}
}
@@ -3231,9 +3230,10 @@
case HWC2::Composition::Sideband:
case HWC2::Composition::SolidColor: {
const Layer::State& state(compositionInfo.layer->mLayer->getDrawingState());
- const bool opaque = compositionInfo.layer->mLayer->isOpaque(state);
- if (compositionInfo.hwc.clearClientTarget && !firstLayer &&
- opaque && (state.color.a == 1.0f) && hasClientComposition) {
+ const bool opaque = compositionInfo.layer->mLayer->isOpaque(state) &&
+ compositionInfo.layer->mLayer->getAlpha() == 1.0f;
+ if (compositionInfo.hwc.clearClientTarget && !firstLayer && opaque &&
+ hasClientComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
compositionInfo.layer->clear(getRenderEngine());
@@ -3262,11 +3262,9 @@
return true;
}
-void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& display,
- const Region& region) const {
- const int32_t height = display->getHeight();
+void SurfaceFlinger::drawWormhole(const Region& region) const {
auto& engine(getRenderEngine());
- engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
+ engine.fillRegionWithColor(region, 0, 0, 0, 0);
}
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 72ede93..00ee2c4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -710,7 +710,7 @@
void postFramebuffer(const sp<DisplayDevice>& display);
void postFrame();
- void drawWormhole(const sp<const DisplayDevice>& display, const Region& region) const;
+ void drawWormhole(const Region& region) const;
/* ------------------------------------------------------------------------
* Display management
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index a8b7770..6fe52d3 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// Copyright 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,6 +16,12 @@
name: "libsurfaceflinger_unittest",
defaults: ["libsurfaceflinger_defaults"],
test_suites: ["device-tests"],
+ sanitize: {
+ // Using the address sanitizer not only helps uncover issues in the code
+ // covered by the tests, but also covers some of the tricky injection of
+ // fakes the unit tests currently do.
+ address: true,
+ },
srcs: [
":libsurfaceflinger_sources",
"CompositionTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index 9113171..4f1c99e 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -77,20 +77,23 @@
}
TEST(DisplayIdentificationTest, parseEdid) {
- auto edid = parseEdid(asDisplayIdentificationData(kInternalEdid));
+ auto data = asDisplayIdentificationData(kInternalEdid);
+ auto edid = parseEdid(data);
ASSERT_TRUE(edid);
EXPECT_EQ(0x4ca3u, edid->manufacturerId);
EXPECT_STREQ("SEC", edid->pnpId.data());
// ASCII text should be used as fallback if display name and serial number are missing.
EXPECT_EQ("121AT11-801", edid->displayName);
- edid = parseEdid(asDisplayIdentificationData(kExternalEdid));
+ data = asDisplayIdentificationData(kExternalEdid);
+ edid = parseEdid(data);
ASSERT_TRUE(edid);
EXPECT_EQ(0x22f0u, edid->manufacturerId);
EXPECT_STREQ("HWP", edid->pnpId.data());
EXPECT_EQ("HP ZR30w", edid->displayName);
- edid = parseEdid(asDisplayIdentificationData(kExternalEedid));
+ data = asDisplayIdentificationData(kExternalEedid);
+ edid = parseEdid(data);
ASSERT_TRUE(edid);
EXPECT_EQ(0x4c2du, edid->manufacturerId);
EXPECT_STREQ("SAM", edid->pnpId.data());
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 32712c7..aa377af 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -662,7 +662,7 @@
using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
using HwcVirtualDisplayCase =
Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
- HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
+ HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
using WideColorP3ColorimetricDisplayCase =
Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>,
@@ -1304,6 +1304,8 @@
// Call Expectations
EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*mComposer, getDisplayIdentificationData(Case::Display::HWC_DISPLAY_ID, _, _))
+ .Times(0);
setupCommonCallExpectationsForDisconnectProcessing<Case>();
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index c809e82..df0d982 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -40,7 +40,7 @@
: mEventThread(std::move(eventThread)) {}
std::unique_ptr<EventThread> makeEventThread(
- const char* /* connectionName */, DispSync* /* dispSync */,
+ const std::string& /* connectionName */, DispSync* /* dispSync */,
nsecs_t /* phaseOffsetNs */,
impl::EventThread::ResyncWithRateLimitCallback /* resyncCallback */,
impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 8d3be7f..39ed622 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -49,7 +49,7 @@
MOCK_METHOD1(waitFence, bool(base::unique_fd*));
bool waitFence(base::unique_fd fd) override { return waitFence(&fd); };
MOCK_METHOD4(clearWithColor, void(float, float, float, float));
- MOCK_METHOD6(fillRegionWithColor, void(const Region&, uint32_t, float, float, float, float));
+ MOCK_METHOD5(fillRegionWithColor, void(const Region&, float, float, float, float));
MOCK_METHOD4(setScissor, void(uint32_t, uint32_t, uint32_t, uint32_t));
MOCK_METHOD0(disableScissor, void());
MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 76eca35..8817e8d 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
// API version (major.minor.patch)
define VERSION_MAJOR 1
define VERSION_MINOR 1
-define VERSION_PATCH 82
+define VERSION_PATCH 84
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -221,6 +221,10 @@
@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
+// 68
+@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
+@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
+
// 70
@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_SPEC_VERSION 2
@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
@@ -437,6 +441,10 @@
@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1
@extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
+// 139
+@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
+@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
+
// 141
@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
@extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
@@ -526,8 +534,8 @@
@extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
// 191
-@extension("VK_EXT_vertex_attribute_divisor") define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
-@extension("VK_EXT_vertex_attribute_divisor") define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
+@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
+@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
// 199
@extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
@@ -537,6 +545,10 @@
@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
@extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
+// 212
+@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
+@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
+
/////////////
// Types //
/////////////
@@ -697,6 +709,9 @@
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 0x00000008,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 0x00000009,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 0x0000000a,
+
+ //@extension("VK_EXT_inline_uniform_block") // 139
+ VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
}
enum VkQueryType {
@@ -1416,6 +1431,10 @@
//@extension("VK_NN_vi_surface") // 63
VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+ //@extension("VK_EXT_astc_decode_mode") // 68
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001,
+
//@extension("VK_KHR_device_group_creation") // 71
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = 1000070000,
VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = 1000070001,
@@ -1595,6 +1614,12 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
+ //@extension("VK_EXT_inline_uniform_block") // 139
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003,
+
//@extension("VK_EXT_sample_locations") // 144
VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001,
@@ -1667,10 +1692,14 @@
//@extension("VK_EXT_vertex_attribute_divisor") // 191
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
//@extension("VK_NV_device_diagnostic_checkpoints") // 207
VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
+
+ //@extension("VK_KHR_vulkan_memory_model") // 212
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
}
enum VkSubpassContents {
@@ -5354,6 +5383,20 @@
void* window
}
+@extension("VK_EXT_astc_decode_mode") // 68
+class VkImageViewASTCDecodeModeEXT {
+ VkStructureType sType
+ const void* pNext
+ VkFormat decodeMode
+}
+
+@extension("VK_EXT_astc_decode_mode") // 68
+class VkPhysicalDeviceASTCDecodeFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 decodeModeSharedExponent
+}
+
@extension("VK_KHR_device_group_creation") // 71
class VkPhysicalDeviceGroupPropertiesKHR {
VkStructureType sType
@@ -6386,6 +6429,40 @@
VkBool32 filterMinmaxImageComponentMapping
}
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 inlineUniformBlock
+ VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
+ VkStructureType sType
+ void* pNext
+ u32 maxInlineUniformBlockSize
+ u32 maxPerStageDescriptorInlineUniformBlocks
+ u32 maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks
+ u32 maxDescriptorSetInlineUniformBlocks
+ u32 maxDescriptorSetUpdateAfterBindInlineUniformBlocks
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkWriteDescriptorSetInlineUniformBlockEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 dataSize
+ const void* pData
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 maxInlineUniformBlockBindings
+}
+
@extension("VK_EXT_sample_locations") // 144
class VkSampleLocationEXT {
f32 x
@@ -6796,6 +6873,14 @@
const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors
}
+@extension("VK_EXT_vertex_attribute_divisor") // 191
+class VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
+ VkStructureType sType
+ void* pNext
+ VkBool32 vertexAttributeInstanceRateDivisor
+ VkBool32 vertexAttributeInstanceRateZeroDivisor
+}
+
@extension("VK_NV_device_diagnostic_checkpoints") // 207
class VkQueueFamilyCheckpointPropertiesNV {
VkStructureType sType
@@ -6811,6 +6896,14 @@
void* pCheckpointMarker
}
+@extension("VK_KHR_vulkan_memory_model") // 212
+class VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 vulkanMemoryModel
+ VkBool32 vulkanMemoryModelDeviceScope
+}
+
////////////////
// Commands //
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index d511015..fe45014 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,7 +43,7 @@
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 82
+#define VK_HEADER_VERSION 84
#define VK_NULL_HANDLE 0
@@ -305,6 +305,8 @@
VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001,
VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002,
@@ -380,6 +382,10 @@
VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003,
VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001,
VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002,
@@ -406,8 +412,11 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
+ VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,
@@ -442,6 +451,7 @@
VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
@@ -1120,6 +1130,7 @@
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+ VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
@@ -4575,7 +4586,6 @@
#define VK_KHR_SURFACE_SPEC_VERSION 25
#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"
-#define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
typedef enum VkColorSpaceKHR {
@@ -4594,6 +4604,7 @@
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014,
+ VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
@@ -5981,13 +5992,24 @@
+#define VK_KHR_vulkan_memory_model 1
+#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
+#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
+
+typedef struct VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 vulkanMemoryModel;
+ VkBool32 vulkanMemoryModelDeviceScope;
+} VkPhysicalDeviceVulkanMemoryModelFeaturesKHR;
+
+
+
#define VK_EXT_debug_report 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
-#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
-#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT
typedef enum VkDebugReportObjectTypeEXT {
@@ -6027,6 +6049,8 @@
VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33,
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
@@ -6431,6 +6455,24 @@
#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
+#define VK_EXT_astc_decode_mode 1
+#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
+#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
+
+typedef struct VkImageViewASTCDecodeModeEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat decodeMode;
+} VkImageViewASTCDecodeModeEXT;
+
+typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 decodeModeSharedExponent;
+} VkPhysicalDeviceASTCDecodeFeaturesEXT;
+
+
+
#define VK_EXT_conditional_rendering 1
#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
@@ -6746,7 +6788,6 @@
#define VK_EXT_display_surface_counter 1
#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
-#define VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT
typedef enum VkSurfaceCounterFlagBitsEXT {
@@ -7300,6 +7341,42 @@
#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
+#define VK_EXT_inline_uniform_block 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
+
+typedef struct VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 inlineUniformBlock;
+ VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind;
+} VkPhysicalDeviceInlineUniformBlockFeaturesEXT;
+
+typedef struct VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxInlineUniformBlockSize;
+ uint32_t maxPerStageDescriptorInlineUniformBlocks;
+ uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
+ uint32_t maxDescriptorSetInlineUniformBlocks;
+ uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
+} VkPhysicalDeviceInlineUniformBlockPropertiesEXT;
+
+typedef struct VkWriteDescriptorSetInlineUniformBlockEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t dataSize;
+ const void* pData;
+} VkWriteDescriptorSetInlineUniformBlockEXT;
+
+typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t maxInlineUniformBlockBindings;
+} VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
+
+
+
#define VK_EXT_shader_stencil_export 1
#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
@@ -7483,7 +7560,6 @@
#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
-#define VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT
typedef enum VkValidationCacheHeaderVersionEXT {
@@ -7734,7 +7810,7 @@
#define VK_EXT_vertex_attribute_divisor 1
-#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3
#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
@@ -7755,6 +7831,13 @@
const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors;
} VkPipelineVertexInputDivisorStateCreateInfoEXT;
+typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 vertexAttributeInstanceRateDivisor;
+ VkBool32 vertexAttributeInstanceRateZeroDivisor;
+} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT;
+
#define VK_NV_shader_subgroup_partitioned 1
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 96c5563..b32977a 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -165,8 +165,13 @@
std::lock_guard<std::mutex> lock(mutex_);
if (--refcount_ == 0) {
ALOGV("closing layer library '%s'", path_.c_str());
- dlclose(dlhandle_);
- dlhandle_ = nullptr;
+ std::string error_msg;
+ if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
+ ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg.c_str());
+ refcount_++;
+ } else {
+ dlhandle_ = nullptr;
+ }
}
}