Merge "egl: add EGL_KHR_mutable_render_buffer" into nyc-dev
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 6892b57..917c813 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -28,6 +28,11 @@
// output. All of the dumpstate output is written to stdout, including
// any errors encountered while reading/writing the output.
int main() {
+
+ fprintf(stderr, "=============================================================================\n");
+ fprintf(stderr, "WARNING: flat bugreports are deprecated, use adb bugreport <zip_file> instead\n");
+ fprintf(stderr, "=============================================================================\n\n\n");
+
// Start the dumpstate service.
property_set("ctl.start", "dumpstate");
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
new file mode 100644
index 0000000..14ba225
--- /dev/null
+++ b/cmds/bugreportz/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= bugreportz.cpp
+
+LOCAL_MODULE:= bugreportz
+
+LOCAL_CFLAGS := -Wall
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
new file mode 100644
index 0000000..b6856bb
--- /dev/null
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+
+// TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
+// should be reused instead.
+int main() {
+
+ // Start the dumpstatez service.
+ property_set("ctl.start", "dumpstatez");
+
+ // Socket will not be available until service starts.
+ int s;
+ for (int i = 0; i < 20; i++) {
+ s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (s >= 0)
+ break;
+ // Try again in 1 second.
+ sleep(1);
+ }
+
+ if (s == -1) {
+ printf("Failed to connect to dumpstatez service: %s\n", strerror(errno));
+ return 1;
+ }
+
+ // Set a timeout so that if nothing is read in 10 minutes, we'll stop
+ // reading and quit. No timeout in dumpstate is longer than 60 seconds,
+ // so this gives lots of leeway in case of unforeseen time outs.
+ struct timeval tv;
+ tv.tv_sec = 10 * 60;
+ tv.tv_usec = 0;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
+ printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
+ }
+
+ while (1) {
+ char buffer[65536];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(
+ read(s, buffer, sizeof(buffer)));
+ if (bytes_read == 0) {
+ break;
+ } else if (bytes_read == -1) {
+ // EAGAIN really means time out, so change the errno.
+ if (errno == EAGAIN) {
+ errno = ETIMEDOUT;
+ }
+ printf("\nBugreport read terminated abnormally (%s).\n",
+ strerror(errno));
+ break;
+ }
+
+ ssize_t bytes_to_send = bytes_read;
+ ssize_t bytes_written;
+ do {
+ bytes_written = TEMP_FAILURE_RETRY(
+ write(STDOUT_FILENO, buffer + bytes_read - bytes_to_send,
+ bytes_to_send));
+ if (bytes_written == -1) {
+ printf(
+ "Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
+ bytes_read, bytes_to_send, strerror(errno));
+ return 1;
+ }
+ bytes_to_send -= bytes_written;
+ } while (bytes_written != 0 && bytes_to_send > 0);
+ }
+
+ close(s);
+ return 0;
+
+}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index af95d16..ea14c66 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -63,6 +63,7 @@
void add_mountinfo();
static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
static bool add_zip_entry_from_fd(const std::string& entry_name, int fd);
+static int control_socket_fd;
#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
@@ -929,15 +930,17 @@
static void usage() {
fprintf(stderr,
- "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
- "[-z]] [-s] [-q] [-B] [-P] [-R] [-V version]\n"
+ "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
+ "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
+ " -h: display this help message\n"
" -b: play sound file instead of vibrate, at beginning of job\n"
" -e: play sound file instead of vibrate, at end of job\n"
" -o: write to file (instead of stdout)\n"
" -d: append date to filename (requires -o)\n"
" -p: capture screenshot to filename.png (requires -o)\n"
- " -z: generates zipped file (requires -o)\n"
+ " -z: generate zipped file (requires -o)\n"
" -s: write output to control socket (for init)\n"
+ " -S: write file location to control socket (for init; requires -o and -z)"
" -q: disable vibrate\n"
" -B: send broadcast when finished (requires -o)\n"
" -P: send broadcast when started and update system properties on "
@@ -1017,6 +1020,7 @@
int do_vibrate = 1;
char* use_outfile = 0;
int use_socket = 0;
+ int use_control_socket = 0;
int do_fb = 0;
int do_broadcast = 0;
int do_early_screenshot = 0;
@@ -1025,15 +1029,6 @@
now = time(NULL);
- if (getuid() != 0) {
- // Old versions of the adb client would call the
- // dumpstate command directly. Newer clients
- // call /system/bin/bugreport instead. If we detect
- // we're being called incorrectly, then exec the
- // correct program.
- return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL);
- }
-
MYLOGI("begin\n");
/* gets the sequential id */
@@ -1062,12 +1057,13 @@
format_args(argc, const_cast<const char **>(argv), &args);
MYLOGD("Dumpstate command line: %s\n", args.c_str());
int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRV:")) != -1) {
+ while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
switch (c) {
case 'd': do_add_date = 1; break;
case 'z': do_zip_file = 1; break;
case 'o': use_outfile = optarg; break;
case 's': use_socket = 1; break;
+ case 'S': use_control_socket = 1; break;
case 'v': break; // compatibility no-op
case 'q': do_vibrate = 0; break;
case 'p': do_fb = 1; break;
@@ -1087,6 +1083,11 @@
exit(1);
}
+ if (use_control_socket && !do_zip_file) {
+ usage();
+ exit(1);
+ }
+
if (do_update_progress && !do_broadcast) {
usage();
exit(1);
@@ -1112,6 +1113,11 @@
redirect_to_socket(stdout, "dumpstate");
}
+ if (use_control_socket) {
+ MYLOGD("Opening control socket\n");
+ control_socket_fd = open_socket("dumpstate");
+ }
+
/* full path of the directory where the bugreport files will be written */
std::string bugreport_dir;
@@ -1351,6 +1357,14 @@
path.clear();
}
}
+ if (use_control_socket) {
+ if (do_text_file) {
+ dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
+ "for more details\n", log_path.c_str());
+ } else {
+ dprintf(control_socket_fd, "OK:%s\n", path.c_str());
+ }
+ }
}
/* vibrate a few but shortly times to let user know it's finished */
@@ -1398,5 +1412,10 @@
fclose(stderr);
}
+ if (use_control_socket && control_socket_fd >= 0) {
+ MYLOGD("Closing control socket\n");
+ close(control_socket_fd);
+ }
+
return 0;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index baba0f9..c51c79a 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -130,6 +130,9 @@
/* prints all the system properties */
void print_properties();
+/** opens a socket and returns its file descriptor */
+int open_socket(const char *service);
+
/* redirect output to a service control socket */
void redirect_to_socket(FILE *redirect, const char *service);
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 96232c4..1f56d21 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -9,6 +9,15 @@
disabled
oneshot
+# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
+# it is finished.
+service dumpstatez /system/bin/dumpstate -S -d -z \
+ -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+ socket dumpstate stream 0660 shell log
+ class main
+ disabled
+ oneshot
+
# bugreportplus is an enhanced version of bugreport that provides a better
# user interface (like displaying progress and allowing user to enter details).
# It's typically triggered by the power button or developer settings.
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index d9738bb..da4b5ad 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -909,8 +909,7 @@
printf("\n");
}
-/* redirect output to a service control socket */
-void redirect_to_socket(FILE *redirect, const char *service) {
+int open_socket(const char *service) {
int s = android_get_control_socket(service);
if (s < 0) {
MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
@@ -930,11 +929,18 @@
exit(1);
}
+ return fd;
+}
+
+/* redirect output to a service control socket */
+void redirect_to_socket(FILE *redirect, const char *service) {
+ int fd = open_socket(service);
fflush(redirect);
dup2(fd, fileno(redirect));
close(fd);
}
+// TODO: should call is_valid_output_file and/or be merged into it.
void create_parent_dirs(const char *path) {
char *chp = const_cast<char *> (path);
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 878fb2d..5c2ad2d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -104,11 +104,16 @@
struct dirent* ent;
while ((ent = readdir(dir))) {
if (ent->d_ino == ce_data_inode) {
+ auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ if (resolved != fallback) {
+ LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
+ << " instead of " << fallback;
+ }
closedir(dir);
- return StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ return resolved;
}
}
- LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name;
+ LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
closedir(dir);
return fallback;
} else {
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index 8ed8460..ab89ef5 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -24,15 +24,11 @@
-->
<permissions>
<feature name="android.hardware.audio.output" />
- <feature name="android.hardware.camera" />
<feature name="android.hardware.location" />
<feature name="android.hardware.location.network" />
- <feature name="android.hardware.sensor.compass" />
- <feature name="android.hardware.sensor.accelerometer" />
<feature name="android.hardware.bluetooth" />
<feature name="android.hardware.touchscreen" />
<feature name="android.hardware.microphone" />
- <feature name="android.hardware.screen.landscape" />
<!-- Feature to specify if the device is a car -->
<feature name="android.hardware.type.automotive" />
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 5d1d7bf..f76a9be 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -122,6 +122,13 @@
// See IGraphicBufferProducer::setDequeueTimeout
status_t setDequeueTimeout(nsecs_t timeout);
+ /*
+ * Wait for frame number to increase past lastFrame for at most
+ * timeoutNs. Useful for one thread to wait for another unknown
+ * thread to queue a buffer.
+ */
+ bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
+
protected:
virtual ~Surface();
@@ -348,6 +355,8 @@
// This is true if the shared buffer has already been queued/canceled. It's
// used to prevent a mismatch between the number of queue/dequeue calls.
bool mSharedBufferHasBeenQueued;
+
+ Condition mQueueBufferCondition;
};
namespace view {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 33fe26c..b221e51 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -40,12 +40,12 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/types.h>
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
#define DEFAULT_MAX_BINDER_THREADS 15
-
-// ---------------------------------------------------------------------------
+// -------------------------------------------------------------------------
namespace android {
@@ -278,8 +278,9 @@
String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
+ pid_t pid = getpid();
String8 name;
- name.appendFormat("Binder_%X", s);
+ name.appendFormat("Binder:%d_%X", pid, s);
return name;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 76b62f1..5efc333 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -480,6 +480,8 @@
mSharedBufferHasBeenQueued = true;
}
+ mQueueBufferCondition.broadcast();
+
return err;
}
@@ -1259,6 +1261,15 @@
return err;
}
+bool Surface::waitForNextFrame(uint64_t lastFrame, nsecs_t timeout) {
+ Mutex::Autolock lock(mMutex);
+ uint64_t currentFrame = mGraphicBufferProducer->getNextFrameNumber();
+ if (currentFrame > lastFrame) {
+ return true;
+ }
+ return mQueueBufferCondition.waitRelative(mMutex, timeout) == OK;
+}
+
namespace view {
status_t Surface::writeToParcel(Parcel* parcel) const {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index f031296..418892a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -291,6 +291,9 @@
s->w = w;
s->h = h;
+ // Resizing a surface makes the transaction synchronous.
+ mForceSynchronous = true;
+
return NO_ERROR;
}
@@ -451,6 +454,7 @@
s.viewport = layerStackRect;
s.frame = displayRect;
s.what |= DisplayState::eDisplayProjectionChanged;
+ mForceSynchronous = true; // TODO: do we actually still need this?
}
void Composer::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index dd8fa09..bef5f02 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -602,8 +602,8 @@
#define EGL_ANDROID_create_native_client_buffer 1
#define EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
-#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID 0x00000002
-#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID 0x00000004
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLClientBuffer eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
#else
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 52f6859..613b63b 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -604,6 +604,7 @@
EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
if (result == EGL_TRUE) {
_s.terminate();
+ dp->removeSurface(surface);
}
return result;
}
@@ -1815,21 +1816,17 @@
case EGL_NATIVE_BUFFER_USAGE_ANDROID:
if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
usage |= GRALLOC_USAGE_PROTECTED;
- // If we are using QCOM then add in extra bits. This
- // should be removed before launch. These correspond to:
- // USAGE_PRIVATE_MM_HEAP | USAGE_PRIVATE_UNCACHED
- usage |= 0x82000000;
}
- if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) {
+ if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
usage |= GRALLOC_USAGE_HW_RENDER;
}
- if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID) {
+ if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
usage |= GRALLOC_USAGE_HW_TEXTURE;
}
// The buffer must be used for either a texture or a
// renderbuffer.
- if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) &&
- (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID)) {
+ if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
+ (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
}
break;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 6a9d7b6..d849693 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -89,6 +89,31 @@
return false;
}
+void egl_display_t::addContext(egl_context_t* context) {
+ Mutex::Autolock _l(lock);
+ contexts.add(context);
+}
+
+void egl_display_t::removeContext(egl_context_t* context) {
+ Mutex::Autolock _l(lock);
+ contexts.remove(context);
+}
+
+void egl_display_t::removeSurface(EGLSurface surface) const {
+ Mutex::Autolock _l(lock);
+ for (size_t i = 0; i < contexts.size(); i++) {
+ egl_context_t* context = contexts[i];
+ if (context->read == surface) {
+ SurfaceRef _r(get_surface(context->read));
+ _r.release();
+ }
+ if (context->draw == surface) {
+ SurfaceRef _d(get_surface(context->draw));
+ _d.release();
+ }
+ }
+}
+
EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
if (uintptr_t(disp) >= NUM_DISPLAYS)
return NULL;
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 2d86295..0ede705 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -68,6 +68,13 @@
// add reference to this object. returns true if this is a valid object.
bool getObject(egl_object_t* object) const;
+ // add context to this display's list
+ void addContext(egl_context_t* context);
+ // remove context from this display's list
+ void removeContext(egl_context_t* context);
+ // search for surface on all contexts and remove the references
+ void removeSurface(EGLSurface surface) const;
+
// These notifications allow the display to keep track of how many window
// surfaces exist, which it uses to decide whether to hibernate the
// underlying EGL implementation. They can be called by any thread without
@@ -135,6 +142,7 @@
mutable Mutex lock, refLock;
mutable Condition refCond;
SortedVector<egl_object_t*> objects;
+ SortedVector<egl_context_t*> contexts;
String8 mVendorString;
String8 mVersionString;
String8 mClientApiString;
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 918faa8..8859387 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -91,6 +91,12 @@
egl_connection_t const* cnx, int version) :
egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context),
config(config), read(0), draw(0), cnx(cnx), version(version) {
+ get_display_nowake(dpy)->addContext(this);
+}
+
+void egl_context_t::terminate() {
+ display->removeContext(this);
+ egl_object_t::terminate();
}
void egl_context_t::onLooseCurrent() {
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 17a8304..8268900 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -40,11 +40,12 @@
class egl_display_t;
class egl_object_t {
- egl_display_t *display;
mutable volatile int32_t count;
protected:
virtual ~egl_object_t();
+ virtual void terminate();
+ egl_display_t *display;
public:
egl_object_t(egl_display_t* display);
@@ -55,7 +56,6 @@
inline egl_display_t* getDisplay() const { return display; }
private:
- void terminate();
static bool get(egl_display_t const* display, egl_object_t* object);
public:
@@ -143,6 +143,7 @@
class egl_context_t: public egl_object_t {
protected:
~egl_context_t() {}
+ void terminate() override;
public:
typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
diff --git a/vulkan/include/vulkan/vk_layer_interface.h b/vulkan/include/vulkan/vk_layer_interface.h
index 5aae51e..f2a5232 100644
--- a/vulkan/include/vulkan/vk_layer_interface.h
+++ b/vulkan/include/vulkan/vk_layer_interface.h
@@ -14,10 +14,6 @@
* The above copyright notice(s) and this permission notice shall be included in
* all copies or substantial portions of the Materials.
*
- * The Materials are Confidential Information as defined by the Khronos
- * Membership Agreement until designated non-confidential by Khronos, at which
- * point this condition clause shall be removed.
- *
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -37,38 +33,18 @@
typedef enum VkLayerFunction_ {
VK_LAYER_FUNCTION_LINK = 0,
- VK_LAYER_FUNCTION_DEVICE = 1,
- VK_LAYER_FUNCTION_INSTANCE = 2
+ VK_LAYER_FUNCTION_DATA_CALLBACK = 1
} VkLayerFunction;
-/*
- * When creating the device chain the loader needs to pass
- * down information about it's device structure needed at
- * the end of the chain. Passing the data via the
- * VkLayerInstanceInfo avoids issues with finding the
- * exact instance being used.
- */
-typedef struct VkLayerInstanceInfo_ {
- void* instance_info;
- PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
-} VkLayerInstanceInfo;
-
typedef struct VkLayerInstanceLink_ {
struct VkLayerInstanceLink_* pNext;
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
} VkLayerInstanceLink;
-/*
- * When creating the device chain the loader needs to pass
- * down information about it's device structure needed at
- * the end of the chain. Passing the data via the
- * VkLayerDeviceInfo avoids issues with finding the
- * exact instance being used.
- */
-typedef struct VkLayerDeviceInfo_ {
- void* device_info;
- PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
-} VkLayerDeviceInfo;
+typedef VkResult(VKAPI_PTR* PFN_vkSetInstanceLoaderData)(VkInstance instance,
+ void* object);
+typedef VkResult(VKAPI_PTR* PFN_vkSetDeviceLoaderData)(VkDevice device,
+ void* object);
typedef struct {
VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
@@ -76,7 +52,7 @@
VkLayerFunction function;
union {
VkLayerInstanceLink* pLayerInfo;
- VkLayerInstanceInfo instanceInfo;
+ PFN_vkSetInstanceLoaderData pfnSetInstanceLoaderData;
} u;
} VkLayerInstanceCreateInfo;
@@ -92,6 +68,6 @@
VkLayerFunction function;
union {
VkLayerDeviceLink* pLayerInfo;
- VkLayerDeviceInfo deviceInfo;
+ PFN_vkSetDeviceLoaderData pfnSetDeviceLoaderData;
} u;
} VkLayerDeviceCreateInfo;
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 4e19af5..eeb32d4 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -431,6 +431,11 @@
uint32_t count,
const VkAllocationCallbacks& allocator);
+ static VKAPI_ATTR VkResult SetInstanceLoaderData(VkInstance instance,
+ void* object);
+ static VKAPI_ATTR VkResult SetDeviceLoaderData(VkDevice device,
+ void* object);
+
static VKAPI_ATTR VkBool32
DebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT obj_type,
@@ -454,8 +459,8 @@
PFN_vkGetDeviceProcAddr get_device_proc_addr_;
union {
- VkLayerInstanceCreateInfo instance_chain_info_;
- VkLayerDeviceCreateInfo device_chain_info_;
+ VkLayerInstanceCreateInfo instance_chain_info_[2];
+ VkLayerDeviceCreateInfo device_chain_info_[2];
};
VkExtensionProperties* driver_extensions_;
@@ -616,18 +621,19 @@
void LayerChain::ModifyCreateInfo(VkInstanceCreateInfo& info) {
if (layer_count_) {
- const ActiveLayer& layer = layers_[0];
+ auto& link_info = instance_chain_info_[1];
+ link_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ link_info.pNext = info.pNext;
+ link_info.function = VK_LAYER_FUNCTION_LINK;
+ link_info.u.pLayerInfo = &layers_[0].instance_link;
- instance_chain_info_.sType =
- VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
- instance_chain_info_.function = VK_LAYER_FUNCTION_LINK;
- // TODO fix vk_layer_interface.h and get rid of const_cast?
- instance_chain_info_.u.pLayerInfo =
- const_cast<VkLayerInstanceLink*>(&layer.instance_link);
+ auto& cb_info = instance_chain_info_[0];
+ cb_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ cb_info.pNext = &link_info;
+ cb_info.function = VK_LAYER_FUNCTION_DATA_CALLBACK;
+ cb_info.u.pfnSetInstanceLoaderData = SetInstanceLoaderData;
- // insert layer info
- instance_chain_info_.pNext = info.pNext;
- info.pNext = &instance_chain_info_;
+ info.pNext = &cb_info;
}
if (override_layers_.Count()) {
@@ -643,17 +649,19 @@
void LayerChain::ModifyCreateInfo(VkDeviceCreateInfo& info) {
if (layer_count_) {
- const ActiveLayer& layer = layers_[0];
+ auto& link_info = device_chain_info_[1];
+ link_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+ link_info.pNext = info.pNext;
+ link_info.function = VK_LAYER_FUNCTION_LINK;
+ link_info.u.pLayerInfo = &layers_[0].device_link;
- device_chain_info_.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
- device_chain_info_.function = VK_LAYER_FUNCTION_LINK;
- // TODO fix vk_layer_interface.h and get rid of const_cast?
- device_chain_info_.u.pLayerInfo =
- const_cast<VkLayerDeviceLink*>(&layer.device_link);
+ auto& cb_info = device_chain_info_[0];
+ cb_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+ cb_info.pNext = &link_info;
+ cb_info.function = VK_LAYER_FUNCTION_DATA_CALLBACK;
+ cb_info.u.pfnSetDeviceLoaderData = SetDeviceLoaderData;
- // insert layer info
- device_chain_info_.pNext = info.pNext;
- info.pNext = &device_chain_info_;
+ info.pNext = &cb_info;
}
if (override_layers_.Count()) {
@@ -890,6 +898,24 @@
allocator.pfnFree(allocator.pUserData, layers);
}
+VkResult LayerChain::SetInstanceLoaderData(VkInstance instance, void* object) {
+ driver::InstanceDispatchable dispatchable =
+ reinterpret_cast<driver::InstanceDispatchable>(object);
+
+ return (driver::SetDataInternal(dispatchable, &driver::GetData(instance)))
+ ? VK_SUCCESS
+ : VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VkResult LayerChain::SetDeviceLoaderData(VkDevice device, void* object) {
+ driver::DeviceDispatchable dispatchable =
+ reinterpret_cast<driver::DeviceDispatchable>(object);
+
+ return (driver::SetDataInternal(dispatchable, &driver::GetData(device)))
+ ? VK_SUCCESS
+ : VK_ERROR_INITIALIZATION_FAILED;
+}
+
VkBool32 LayerChain::DebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT obj_type,
uint64_t obj,
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 0c4cd9a..a8cca59 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -272,11 +272,14 @@
std::binary_search(
known_non_device_names, known_non_device_names + count, pName,
[](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
- ALOGE("vkGetDeviceProcAddr called with %s", pName);
+ ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
return nullptr;
}
// clang-format off
+ if (strcmp(pName, "vkGetDeviceProcAddr") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr);
+ if (strcmp(pName, "vkDestroyDevice") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyDevice);
+
return vulkan::api::GetData(device).dispatch.GetDeviceProcAddr(device, pName);
}
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index afe0d84..7517e91 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -529,11 +529,25 @@
std::binary_search(
known_non_device_names, known_non_device_names + count, pName,
[](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
- ALOGE("vkGetDeviceProcAddr called with %s", pName);
+ ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
return nullptr;
}
// clang-format off
¶
+ {{range $f := AllCommands $}}
+ {{if (Macro "IsDeviceDispatched" $f)}}
+ {{ if (Macro "api.IsIntercepted" $f)}}
+ if (strcmp(pName, "{{$f.Name}}") == 0) return §
+ reinterpret_cast<PFN_vkVoidFunction>(§
+ vulkan::api::{{Macro "BaseName" $f}});
+ {{else if eq $f.Name "vkGetDeviceProcAddr"}}
+ if (strcmp(pName, "{{$f.Name}}") == 0) return §
+ reinterpret_cast<PFN_vkVoidFunction>(§
+ {{$f.Name}});
+ {{end}}
+ {{end}}
+ {{end}}
+ ¶
{{end}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 72b0981..c5ea20b 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -331,11 +331,13 @@
if (strcmp(name, props.extensionName) != 0)
continue;
- if (ext_bit == ProcHook::ANDROID_native_buffer)
- hook_extensions_.set(ProcHook::KHR_swapchain);
-
filter.names[filter.name_count++] = name;
- hal_extensions_.set(ext_bit);
+ if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
+ if (ext_bit == ProcHook::ANDROID_native_buffer)
+ hook_extensions_.set(ProcHook::KHR_swapchain);
+
+ hal_extensions_.set(ext_bit);
+ }
break;
}
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 22db93f..5543792 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -64,6 +64,9 @@
namespace driver {
+VK_DEFINE_HANDLE(InstanceDispatchable)
+VK_DEFINE_HANDLE(DeviceDispatchable)
+
struct InstanceData {
InstanceData(const VkAllocationCallbacks& alloc)
: opaque_api_data(),
@@ -127,12 +130,15 @@
template <typename DispatchableType>
void StaticAssertDispatchable(DispatchableType) {
- static_assert(std::is_same<DispatchableType, VkInstance>::value ||
- std::is_same<DispatchableType, VkPhysicalDevice>::value ||
- std::is_same<DispatchableType, VkDevice>::value ||
- std::is_same<DispatchableType, VkQueue>::value ||
- std::is_same<DispatchableType, VkCommandBuffer>::value,
- "unrecognized dispatchable type");
+ static_assert(
+ std::is_same<DispatchableType, VkInstance>::value ||
+ std::is_same<DispatchableType, VkPhysicalDevice>::value ||
+ std::is_same<DispatchableType, VkDevice>::value ||
+ std::is_same<DispatchableType, InstanceDispatchable>::value ||
+ std::is_same<DispatchableType, VkQueue>::value ||
+ std::is_same<DispatchableType, VkCommandBuffer>::value ||
+ std::is_same<DispatchableType, DeviceDispatchable>::value,
+ "unrecognized dispatchable type");
}
template <typename DispatchableType>
@@ -170,6 +176,11 @@
return SetDataInternal(physical_dev, &data);
}
+inline bool SetData(InstanceDispatchable dispatchable,
+ const InstanceData& data) {
+ return SetDataInternal(dispatchable, &data);
+}
+
inline bool SetData(VkDevice dev, const DeviceData& data) {
return SetDataInternal(dev, &data);
}
@@ -182,6 +193,10 @@
return SetDataInternal(cmd, &data);
}
+inline bool SetData(DeviceDispatchable dispatchable, const DeviceData& data) {
+ return SetDataInternal(dispatchable, &data);
+}
+
inline InstanceData& GetData(VkInstance instance) {
return *reinterpret_cast<InstanceData*>(GetDataInternal(instance));
}
@@ -190,6 +205,10 @@
return *reinterpret_cast<InstanceData*>(GetDataInternal(physical_dev));
}
+inline InstanceData& GetData(InstanceDispatchable dispatchable) {
+ return *reinterpret_cast<InstanceData*>(GetDataInternal(dispatchable));
+}
+
inline DeviceData& GetData(VkDevice dev) {
return *reinterpret_cast<DeviceData*>(GetDataInternal(dev));
}
@@ -202,6 +221,10 @@
return *reinterpret_cast<DeviceData*>(GetDataInternal(cmd));
}
+inline DeviceData& GetData(DeviceDispatchable dispatchable) {
+ return *reinterpret_cast<DeviceData*>(GetDataInternal(dispatchable));
+}
+
} // namespace driver
} // namespace vulkan