1 /*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #define LOG_TAG "RootlessGpuDebug"
19
20 #include <string>
21 #include <vector>
22
23 #include <EGL/egl.h>
24 #include <GLES3/gl3.h>
25 #include <android/log.h>
26 #include <android/native_window.h>
27 #include <jni.h>
28 #include <vulkan/vulkan.h>
29
30 #define ALOGI(msg, ...) \
31 __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
32 #define ALOGE(msg, ...) \
33 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, (msg), __VA_ARGS__)
34 #define ALOGD(msg, ...) \
35 __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, (msg), __VA_ARGS__)
36
37 namespace {
38
39 typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
40
initVulkan()41 std::string initVulkan() {
42 std::string result = "";
43
44 {
45 uint32_t count = 0;
46 vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
47 if (count > 0) {
48 std::vector<VkExtensionProperties> properties(count);
49 vkEnumerateInstanceExtensionProperties(nullptr, &count,
50 properties.data());
51 for (uint32_t i = 0; i < count; ++i) {
52 if (!strcmp("VK_EXT_debug_utils", properties[i].extensionName)) {
53 ALOGI("VK_EXT_debug_utils: %u", properties[i].specVersion);
54 break;
55 }
56 }
57 }
58 }
59
60 const VkApplicationInfo app_info = {
61 VK_STRUCTURE_TYPE_APPLICATION_INFO,
62 nullptr, // pNext
63 "RootlessGpuDebug", // app name
64 0, // app version
65 nullptr, // engine name
66 0, // engine version
67 VK_API_VERSION_1_0,
68 };
69 const VkInstanceCreateInfo instance_info = {
70 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
71 nullptr, // pNext
72 0, // flags
73 &app_info,
74 0, // layer count
75 nullptr, // layers
76 0, // extension count
77 nullptr, // extensions
78 };
79 VkInstance instance;
80 VkResult vkResult = vkCreateInstance(&instance_info, nullptr, &instance);
81 if (vkResult == VK_ERROR_INITIALIZATION_FAILED) {
82 result = "vkCreateInstance failed, meaning layers could not be chained.";
83 } else {
84 result = "vkCreateInstance succeeded.";
85 }
86
87 return result;
88 }
89
initGLES()90 std::string initGLES() {
91 std::string result = "";
92
93 const EGLint attribs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
94 EGL_BLUE_SIZE, 8,
95 EGL_GREEN_SIZE, 8,
96 EGL_RED_SIZE, 8,
97 EGL_NONE};
98
99 // Create an EGL context
100 EGLDisplay display;
101 EGLConfig config;
102 EGLint numConfigs;
103 EGLint format;
104
105 // Check for the EGL_ANDROID_GLES_layers
106 std::string display_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
107 if (display_extensions.find("EGL_ANDROID_GLES_layers") == std::string::npos)
108 {
109 result = "Did not find EGL_ANDROID_GLES_layers extension";
110 return result;
111 }
112
113 if ((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
114 result = "eglGetDisplay() returned error " + std::to_string(eglGetError());
115 return result;
116 }
117
118 if (!eglInitialize(display, 0, 0)) {
119 result = "eglInitialize() returned error " + std::to_string(eglGetError());
120 return result;
121 }
122
123 if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs)) {
124 result =
125 "eglChooseConfig() returned error " + std::to_string(eglGetError());
126 return result;
127 }
128
129 if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {
130 result =
131 "eglGetConfigAttrib() returned error " + std::to_string(eglGetError());
132 return result;
133 }
134
135 eglTerminate(display);
136
137 return result;
138 }
139
android_gputools_cts_RootlessGpuDebug_nativeInitVulkan(JNIEnv * env,jclass)140 jstring android_gputools_cts_RootlessGpuDebug_nativeInitVulkan(
141 JNIEnv* env, jclass /*clazz*/) {
142 std::string result;
143
144 result = initVulkan();
145
146 return env->NewStringUTF(result.c_str());
147 }
148
android_gputools_cts_RootlessGpuDebug_nativeInitGLES(JNIEnv * env,jclass)149 jstring android_gputools_cts_RootlessGpuDebug_nativeInitGLES(JNIEnv* env,
150 jclass /*clazz*/) {
151 std::string result;
152
153 result = initGLES();
154
155 return env->NewStringUTF(result.c_str());
156 }
157
158 static JNINativeMethod gMethods[] = {
159 {"nativeInitVulkan", "()Ljava/lang/String;",
160 (void*)android_gputools_cts_RootlessGpuDebug_nativeInitVulkan},
161 {"nativeInitGLES", "()Ljava/lang/String;",
162 (void*)android_gputools_cts_RootlessGpuDebug_nativeInitGLES}};
163 } // anonymous namespace
164
register_android_gputools_cts_RootlessGpuDebug(JNIEnv * env)165 int register_android_gputools_cts_RootlessGpuDebug(JNIEnv* env) {
166 jclass clazz = env->FindClass(
167 "android/rootlessgpudebug/app/RootlessGpuDebugDeviceActivity");
168 return env->RegisterNatives(clazz, gMethods,
169 sizeof(gMethods) / sizeof(JNINativeMethod));
170 }
171