1 /*
2 * Copyright (C) 2016 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 #define LOG_TAG "VrHALImpl"
18
19 #include <cutils/log.h>
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26
27 #include <hardware/vr.h>
28 #include <hardware/hardware.h>
29
30
31 // Angler has two inflight numbers. By default, inflight=15 and inflight_low_latency=4.
32 // Inflight is only used when there is a single GL context, when there is more than one
33 // context, inflight_low_latency is used. Since we are only interested in affecting
34 // performance when there is context preemption, we only have to modify the low latency
35 // parameter.
36 static const int DEFAULT_GPU_INFLIGHT = 4;
37 static const int VR_MODE_GPU_INFLIGHT = 2;
38 static const char* GPU_INFLIGHT_PATH = "/sys/class/kgsl/kgsl-3d0/dispatch/inflight_low_latency";
39
40 /**
41 * Write 'len' characters from 'input' character array into file at path 'outFile.'
42 *
43 * Return 0 on success, or a negative error code.
44 */
write_string(const char * input,size_t len,const char * outFile)45 static int write_string(const char* input, size_t len, const char* outFile) {
46 int fd = -1;
47 ssize_t err = 0;
48
49 // Check input strings.
50 if (input == NULL || outFile == NULL) {
51 ALOGE("%s: Invalid input to write", __FUNCTION__);
52 return -1;
53 }
54
55 // Open file, check for errors.
56 fd = open(outFile, O_WRONLY);
57 if (fd < 0) {
58 ALOGE("%s: Failed to open file %s, error %s (%d)", __FUNCTION__, outFile, strerror(errno),
59 -errno);
60 return -errno;
61 }
62
63 // Write file, check for errors.
64 err = write(fd, input, len);
65 if (err < 0) {
66 ALOGE("%s: Failed to write file %s, error %s (%d)", __FUNCTION__, outFile, strerror(errno),
67 -errno);
68 close(fd);
69 return -errno;
70 }
71
72 // Close and return success.
73 close(fd);
74 return 0;
75 }
76
77 /**
78 * Write integer 'input' formatted as a character string into the file at path 'outFile.'
79 *
80 * Return 0 on success, or a negative error code.
81 */
write_int(int input,const char * outFile)82 static int write_int(int input, const char* outFile) {
83 char buffer[128] = {0,};
84 int bytes = snprintf(buffer, sizeof(buffer), "%d", input);
85
86 if (bytes < 0 || (size_t) bytes >= sizeof(buffer)) {
87 ALOGE("%s: Failed to format integer %d", __FUNCTION__, input);
88 return -EINVAL;
89 }
90
91 return write_string(buffer, (size_t) bytes, outFile);
92 }
93
94 // Set global display/GPU/scheduler configuration to used for VR apps.
set_vr_performance_configuration()95 static void set_vr_performance_configuration() {
96 int err = 0;
97
98 // Set in-flight buffers to 2.
99 err = write_int(VR_MODE_GPU_INFLIGHT, GPU_INFLIGHT_PATH);
100
101 if (err < 0) {
102 ALOGW("%s: Error while setting configuration for VR mode.", __FUNCTION__);
103 }
104 }
105
106 // Reset to default global display/GPU/scheduler configuration.
unset_vr_performance_configuration()107 static void unset_vr_performance_configuration() {
108 int err = 0;
109
110 // Set in-flight buffers back to default (15).
111 err = write_int(DEFAULT_GPU_INFLIGHT, GPU_INFLIGHT_PATH);
112
113 if (err < 0) {
114 ALOGW("%s: Error while setting configuration for VR mode.", __FUNCTION__);
115 }
116 }
117
vr_init(struct vr_module * module)118 static void vr_init(struct vr_module *module) {
119 // NOOP
120 }
121
vr_set_vr_mode(struct vr_module * module,bool enabled)122 static void vr_set_vr_mode(struct vr_module *module, bool enabled) {
123 if (enabled) {
124 set_vr_performance_configuration();
125 } else {
126 unset_vr_performance_configuration();
127 }
128 }
129
130 static struct hw_module_methods_t vr_module_methods = {
131 .open = NULL, // There are no devices for this HAL interface.
132 };
133
134
135 vr_module_t HAL_MODULE_INFO_SYM = {
136 .common = {
137 .tag = HARDWARE_MODULE_TAG,
138 .module_api_version = VR_MODULE_API_VERSION_1_0,
139 .hal_api_version = HARDWARE_HAL_API_VERSION,
140 .id = VR_HARDWARE_MODULE_ID,
141 .name = "Angler VR HAL",
142 .author = "The Android Open Source Project",
143 .methods = &vr_module_methods,
144 },
145
146 .init = vr_init,
147 .set_vr_mode = vr_set_vr_mode,
148 };
149