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 <EGL/egl.h>
21 #include <GLES3/gl3.h>
22 #include <android/log.h>
23 #include <android/native_window.h>
24 #include <jni.h>
25 #include <vulkan/vulkan.h>
26
27 #include <sstream>
28 #include <string>
29 #include <vector>
30
31 #define ALOGI(msg, ...) \
32 __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
33 #define ALOGE(msg, ...) \
34 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, (msg), __VA_ARGS__)
35 #define ALOGD(msg, ...) \
36 __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, (msg), __VA_ARGS__)
37
38 namespace {
39
40 typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
41
initVulkan()42 std::string initVulkan() {
43 std::stringstream result;
44
45 {
46 uint32_t count = 0;
47 vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
48 if (count > 0) {
49 std::vector<VkExtensionProperties> properties(count);
50 vkEnumerateInstanceExtensionProperties(nullptr, &count,
51 properties.data());
52 for (uint32_t i = 0; i < count; ++i) {
53 if (!strcmp("VK_EXT_debug_utils", properties[i].extensionName)) {
54 ALOGI("VK_EXT_debug_utils: %u", properties[i].specVersion);
55 break;
56 }
57 }
58 }
59 }
60
61 const VkApplicationInfo app_info = {
62 VK_STRUCTURE_TYPE_APPLICATION_INFO,
63 nullptr, // pNext
64 "RootlessGpuDebug", // app name
65 0, // app version
66 nullptr, // engine name
67 0, // engine version
68 VK_API_VERSION_1_0,
69 };
70 const VkInstanceCreateInfo instance_info = {
71 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
72 nullptr, // pNext
73 0, // flags
74 &app_info,
75 0, // layer count
76 nullptr, // layers
77 0, // extension count
78 nullptr, // extensions
79 };
80 VkInstance instance;
81 VkResult vkResult = vkCreateInstance(&instance_info, nullptr, &instance);
82 if (vkResult == VK_SUCCESS) {
83 result << "vkCreateInstance succeeded.";
84 } else {
85 result << "vkCreateInstance failed with VkResult: " << vkResult;
86 }
87
88 return result.str();
89 }
90
initGLES()91 std::string initGLES() {
92 std::string result = "";
93
94 const EGLint attribs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
95 EGL_BLUE_SIZE, 8,
96 EGL_GREEN_SIZE, 8,
97 EGL_RED_SIZE, 8,
98 EGL_NONE};
99
100 // Create an EGL context
101 EGLDisplay display;
102 EGLConfig config;
103 EGLint numConfigs;
104 EGLint format;
105
106 // Check for the EGL_ANDROID_GLES_layers
107 std::string display_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
108 if (display_extensions.find("EGL_ANDROID_GLES_layers") == std::string::npos)
109 {
110 result = "Did not find EGL_ANDROID_GLES_layers extension";
111 return result;
112 }
113
114 if ((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
115 result = "eglGetDisplay() returned error " + std::to_string(eglGetError());
116 return result;
117 }
118
119 if (!eglInitialize(display, 0, 0)) {
120 result = "eglInitialize() returned error " + std::to_string(eglGetError());
121 return result;
122 }
123
124 if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs)) {
125 result =
126 "eglChooseConfig() returned error " + std::to_string(eglGetError());
127 return result;
128 }
129
130 if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {
131 result =
132 "eglGetConfigAttrib() returned error " + std::to_string(eglGetError());
133 return result;
134 }
135
136 eglTerminate(display);
137
138 return result;
139 }
140
android_gputools_cts_RootlessGpuDebug_nativeInitVulkan(JNIEnv * env,jclass)141 jstring android_gputools_cts_RootlessGpuDebug_nativeInitVulkan(
142 JNIEnv* env, jclass /*clazz*/) {
143 std::string result;
144
145 result = initVulkan();
146
147 return env->NewStringUTF(result.c_str());
148 }
149
android_gputools_cts_RootlessGpuDebug_nativeInitGLES(JNIEnv * env,jclass)150 jstring android_gputools_cts_RootlessGpuDebug_nativeInitGLES(JNIEnv* env,
151 jclass /*clazz*/) {
152 std::string result;
153
154 result = initGLES();
155
156 return env->NewStringUTF(result.c_str());
157 }
158
159 static JNINativeMethod gMethods[] = {
160 {"nativeInitVulkan", "()Ljava/lang/String;",
161 (void*)android_gputools_cts_RootlessGpuDebug_nativeInitVulkan},
162 {"nativeInitGLES", "()Ljava/lang/String;",
163 (void*)android_gputools_cts_RootlessGpuDebug_nativeInitGLES}};
164 } // anonymous namespace
165
register_android_gputools_cts_RootlessGpuDebug(JNIEnv * env)166 int register_android_gputools_cts_RootlessGpuDebug(JNIEnv* env) {
167 jclass clazz = env->FindClass("android/rootlessgpudebug/app/RootlessGpuDebugService");
168 return env->RegisterNatives(clazz, gMethods,
169 sizeof(gMethods) / sizeof(JNINativeMethod));
170 }
171