diff options
Diffstat (limited to 'services/surfaceflinger/GpuService.cpp')
-rw-r--r-- | services/surfaceflinger/GpuService.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/services/surfaceflinger/GpuService.cpp b/services/surfaceflinger/GpuService.cpp new file mode 100644 index 0000000000..0c2997191c --- /dev/null +++ b/services/surfaceflinger/GpuService.cpp @@ -0,0 +1,175 @@ +/* + * Copyright 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 "GpuService.h" + +#include <binder/Parcel.h> +#include <utils/String8.h> +#include <vkjson.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +class BpGpuService : public BpInterface<IGpuService> +{ +public: + BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {} +}; + +IMPLEMENT_META_INTERFACE(GpuService, "android.ui.IGpuService"); + +status_t BnGpuService::onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags) +{ + switch (code) { + case SHELL_COMMAND_TRANSACTION: { + int in = data.readFileDescriptor(); + int out = data.readFileDescriptor(); + int err = data.readFileDescriptor(); + int argc = data.readInt32(); + Vector<String16> args; + for (int i = 0; i < argc && data.dataAvail() > 0; i++) { + args.add(data.readString16()); + } + return shellCommand(in, out, err, args); + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +namespace { + status_t cmd_help(int out); + status_t cmd_vkjson(int out, int err); +} + +const char* const GpuService::SERVICE_NAME = "gpu"; + +GpuService::GpuService() {} + +status_t GpuService::shellCommand(int /*in*/, int out, int err, + Vector<String16>& args) +{ + ALOGV("GpuService::shellCommand"); + for (size_t i = 0, n = args.size(); i < n; i++) + ALOGV(" arg[%zu]: '%s'", i, String8(args[i]).string()); + + if (args[0] == String16("vkjson")) + return cmd_vkjson(out, err); + else if (args[0] == String16("help")) + return cmd_help(out); + + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +namespace { + +status_t cmd_help(int out) { + FILE* outs = fdopen(out, "w"); + if (!outs) { + ALOGE("vkjson: failed to create out stream: %s (%d)", strerror(errno), + errno); + return BAD_VALUE; + } + fprintf(outs, + "GPU Service commands:\n" + " vkjson dump Vulkan device capabilities as JSON\n"); + fclose(outs); + return NO_ERROR; +} + +VkResult vkjsonPrint(FILE* out, FILE* err) { + VkResult result; + + const VkApplicationInfo app_info = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, + "vkjson", 1, /* app name, version */ + "", 0, /* engine name, version */ + VK_API_VERSION + }; + const VkInstanceCreateInfo instance_info = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, + 0, /* flags */ + &app_info, + 0, nullptr, /* layers */ + 0, nullptr, /* extensions */ + }; + VkInstance instance; + result = vkCreateInstance(&instance_info, nullptr, &instance); + if (result != VK_SUCCESS) { + fprintf(err, "vkCreateInstance failed: %d\n", result); + return result; + } + + uint32_t ngpu = 0; + result = vkEnumeratePhysicalDevices(instance, &ngpu, nullptr); + if (result != VK_SUCCESS) { + fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result); + return result; + } + std::vector<VkPhysicalDevice> gpus(ngpu, VK_NULL_HANDLE); + result = vkEnumeratePhysicalDevices(instance, &ngpu, gpus.data()); + if (result != VK_SUCCESS) { + fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result); + return result; + } + + for (size_t i = 0, n = gpus.size(); i < n; i++) { + auto props = VkJsonGetAllProperties(gpus[i]); + std::string json = VkJsonAllPropertiesToJson(props); + fwrite(json.data(), 1, json.size(), out); + if (i < n - 1) + fputc(',', out); + fputc('\n', out); + } + + vkDestroyInstance(instance, nullptr); + + return VK_SUCCESS; +} + +status_t cmd_vkjson(int out, int err) { + int errnum; + FILE* outs = fdopen(out, "w"); + if (!outs) { + errnum = errno; + ALOGE("vkjson: failed to create output stream: %s", strerror(errnum)); + return -errnum; + } + FILE* errs = fdopen(err, "w"); + if (!errs) { + errnum = errno; + ALOGE("vkjson: failed to create error stream: %s", strerror(errnum)); + fclose(outs); + return -errnum; + } + fprintf(outs, "[\n"); + VkResult result = vkjsonPrint(outs, errs); + fprintf(outs, "]\n"); + fclose(errs); + fclose(outs); + return result >= 0 ? NO_ERROR : UNKNOWN_ERROR; +} + +} // anonymous namespace + +} // namespace android |