1 // Copyright 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.#pragma once
14 #include "AndroidWindow.h"
15
16 #include "AndroidHostCommon.h"
17
18 #include <errno.h>
19 #include <hardware/gralloc.h>
20 #include <stdio.h>
21 #include <cassert>
22
23 #define AW_DEBUG 1
24
25 #define E(fmt,...) \
26 fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__); \
27
28 #if AW_DEBUG
29 #define D(fmt,...) \
30 fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__); \
31
32 #else
33 #define D(fmt,...)
34 #endif
35
36 namespace aemu {
37
38 // Declarations for the ANativeWindow implementation.
39
40 static int hook_setSwapInterval(struct ANativeWindow* window, int interval);
41 static int hook_dequeueBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer);
42 static int hook_lockBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);
43 static int hook_queueBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);
44 static int hook_query(const struct ANativeWindow* window, int what, int* value);
45 static int hook_perform(struct ANativeWindow* window, int operation, ... );
46 static int hook_cancelBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);
47 static int hook_dequeueBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd);
48 static int hook_queueBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);
49 static int hook_cancelBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);
50 static void hook_incRef(struct android_native_base_t* common);
51 static void hook_decRef(struct android_native_base_t* common);
52
AndroidWindow(int _width,int _height)53 AndroidWindow::AndroidWindow(int _width, int _height)
54 : width(_width), height(_height) {
55 // Initialize the ANativeWindow function pointers.
56 ANativeWindow::setSwapInterval = hook_setSwapInterval;
57 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
58 ANativeWindow::cancelBuffer = hook_cancelBuffer;
59 ANativeWindow::queueBuffer = hook_queueBuffer;
60 ANativeWindow::query = hook_query;
61 ANativeWindow::perform = hook_perform;
62
63 ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
64 ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
65 ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
66 ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
67
68 const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
69 const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
70
71 common.incRef = hook_incRef;
72 common.decRef = hook_decRef;
73 }
74
setProducer(AndroidBufferQueue * _fromProducer,AndroidBufferQueue * _toProducer)75 void AndroidWindow::setProducer(AndroidBufferQueue* _fromProducer,
76 AndroidBufferQueue* _toProducer) {
77 fromProducer = _fromProducer;
78 toProducer = _toProducer;
79 }
80
dequeueBuffer(ANativeWindowBuffer ** buffer,int * fenceFd)81 int AndroidWindow::dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) {
82 assert(fromProducer);
83 AndroidBufferQueue::Item item;
84 fromProducer->dequeueBuffer(&item);
85 *buffer = item.buffer;
86 if (fenceFd)
87 *fenceFd = item.fenceFd;
88 return 0;
89 }
90
queueBuffer(ANativeWindowBuffer * buffer,int fenceFd)91 int AndroidWindow::queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) {
92 assert(toProducer);
93 toProducer->queueBuffer({buffer, fenceFd});
94 return 0;
95 }
96
cancelBuffer(ANativeWindowBuffer * buffer,int fenceFd)97 int AndroidWindow::cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd) {
98 assert(toProducer);
99 fromProducer->cancelBuffer({buffer, fenceFd});
100 return 0;
101 }
102
query(int what,int * value) const103 int AndroidWindow::query(int what, int* value) const {
104 switch (what) {
105 case ANATIVEWINDOW_QUERY_DEFAULT_WIDTH:
106 case NATIVE_WINDOW_WIDTH:
107 *value = width;
108 break;
109 case ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT:
110 case NATIVE_WINDOW_HEIGHT:
111 *value = height;
112 break;
113 case NATIVE_WINDOW_FORMAT:
114 *value = HAL_PIXEL_FORMAT_RGBA_8888;
115 break;
116 case NATIVE_WINDOW_TRANSFORM_HINT:
117 *value = 0;
118 break;
119 case NATIVE_WINDOW_MAX_BUFFER_COUNT:
120 *value = 2;
121 break;
122 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
123 *value = 2;
124 break;
125
126 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
127 case NATIVE_WINDOW_CONCRETE_TYPE:
128 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
129 case NATIVE_WINDOW_BUFFER_AGE:
130 case NATIVE_WINDOW_LAST_DEQUEUE_DURATION:
131 case NATIVE_WINDOW_LAST_QUEUE_DURATION:
132 case NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT:
133 case NATIVE_WINDOW_IS_VALID:
134 case NATIVE_WINDOW_DATASPACE:
135 default:
136 E("Unknown query 0x%x, not implemented.", what);
137 return -EINVAL;
138 }
139 return 0;
140 }
141
perform(int operation,va_list args)142 int AndroidWindow::perform(int operation, va_list args)
143 {
144 int res = 0;
145 switch (operation) {
146 case NATIVE_WINDOW_CONNECT:
147 // deprecated. must return NO_ERROR.
148 break;
149 case NATIVE_WINDOW_DISCONNECT:
150 // deprecated. must return NO_ERROR.
151 break;
152 case NATIVE_WINDOW_GET_CONSUMER_USAGE64: {
153 uint64_t* usage = va_arg(args, uint64_t*);
154 *usage =
155 GRALLOC_USAGE_HW_TEXTURE |
156 GRALLOC_USAGE_HW_RENDER;
157 va_end(args);
158 break;
159 }
160 case NATIVE_WINDOW_API_CONNECT:
161 case NATIVE_WINDOW_API_DISCONNECT: {
162 break;
163 }
164 case NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT: {
165 bool* outSupport = va_arg(args, bool*);
166 *outSupport = false;
167 va_end(args);
168 break;
169 }
170 case NATIVE_WINDOW_SET_BUFFER_COUNT: {
171 size_t bufferCount = va_arg(args, size_t);
172 va_end(args);
173 break;
174 }
175 case NATIVE_WINDOW_SET_AUTO_REFRESH:
176 case NATIVE_WINDOW_SET_SHARED_BUFFER_MODE:
177 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
178 case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
179 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
180 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
181 case NATIVE_WINDOW_SET_SCALING_MODE:
182 case NATIVE_WINDOW_SET_USAGE:
183 case NATIVE_WINDOW_SET_USAGE64:
184 case NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION:
185 case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
186 break;
187 case NATIVE_WINDOW_SET_CROP:
188 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
189 case NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM:
190 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
191 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
192 case NATIVE_WINDOW_LOCK:
193 case NATIVE_WINDOW_UNLOCK_AND_POST:
194 case NATIVE_WINDOW_SET_SIDEBAND_STREAM:
195 case NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA:
196 case NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA:
197 // case NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA:
198 case NATIVE_WINDOW_GET_NEXT_FRAME_ID:
199 case NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS:
200 case NATIVE_WINDOW_GET_COMPOSITOR_TIMING:
201 case NATIVE_WINDOW_GET_FRAME_TIMESTAMPS:
202 case NATIVE_WINDOW_GET_HDR_SUPPORT:
203
204 default:
205 E("Unknown perform 0x%x, not implemented.", operation);
206 res = -EINVAL;
207 break;
208 }
209 return res;
210 }
211
212 // Android native window implementation
hook_setSwapInterval(struct ANativeWindow * window,int interval)213 static int hook_setSwapInterval(struct ANativeWindow* window, int interval) {
214 AndroidWindow* aw = AndroidWindow::getSelf(window);
215 aw->swapInterval = interval;
216 return 0;
217 }
218
hook_dequeueBuffer_DEPRECATED(struct ANativeWindow * window,struct ANativeWindowBuffer ** buffer)219 static int hook_dequeueBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer) {
220 AndroidWindow* aw = AndroidWindow::getSelf(window);
221 return aw->dequeueBuffer(buffer, nullptr);
222 }
223
hook_lockBuffer_DEPRECATED(struct ANativeWindow * window,struct ANativeWindowBuffer * buffer)224 static int hook_lockBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer) {
225 E("Not implemented");
226 return 0;
227 }
228
hook_queueBuffer_DEPRECATED(struct ANativeWindow * window,struct ANativeWindowBuffer * buffer)229 static int hook_queueBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer) {
230 E("Not implemented");
231 return 0;
232 }
233
hook_query(const struct ANativeWindow * window,int what,int * value)234 static int hook_query(const struct ANativeWindow* window, int what, int* value) {
235 const AndroidWindow* aw = AndroidWindow::getSelfConst(window);
236 return aw->query(what, value);
237 }
238
hook_perform(struct ANativeWindow * window,int operation,...)239 static int hook_perform(struct ANativeWindow* window, int operation, ... ) {
240 va_list args;
241 va_start(args, operation);
242 AndroidWindow* w = AndroidWindow::getSelf(window);
243 int result = w->perform(operation, args);
244 va_end(args);
245 return result;
246 }
247
hook_cancelBuffer_DEPRECATED(struct ANativeWindow * window,struct ANativeWindowBuffer * buffer)248 static int hook_cancelBuffer_DEPRECATED(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer) {
249 E("Not implemented");
250 return 0;
251 }
252
hook_dequeueBuffer(struct ANativeWindow * window,struct ANativeWindowBuffer ** buffer,int * fenceFd)253 static int hook_dequeueBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd) {
254 AndroidWindow* aw = AndroidWindow::getSelf(window);
255 return aw->dequeueBuffer(buffer, fenceFd);
256 }
257
hook_queueBuffer(struct ANativeWindow * window,struct ANativeWindowBuffer * buffer,int fenceFd)258 static int hook_queueBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd) {
259 AndroidWindow* aw = AndroidWindow::getSelf(window);
260 return aw->queueBuffer(buffer, fenceFd);
261 }
262
hook_cancelBuffer(struct ANativeWindow * window,struct ANativeWindowBuffer * buffer,int fenceFd)263 static int hook_cancelBuffer(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd) {
264 AndroidWindow* aw = AndroidWindow::getSelf(window);
265 return aw->cancelBuffer(buffer, fenceFd);
266 }
267
hook_incRef(struct android_native_base_t * common)268 static void hook_incRef(struct android_native_base_t* common) {
269 }
270
hook_decRef(struct android_native_base_t * common)271 static void hook_decRef(struct android_native_base_t* common) {
272 }
273
274 } // namespace aemu
275
276 extern "C" {
277
create_host_anativewindow(int width,int height)278 EXPORT ANativeWindow* create_host_anativewindow(int width, int height) {
279 aemu::AndroidWindow* res =
280 new aemu::AndroidWindow(width, height);
281
282 return (ANativeWindow*)res;
283 }
284
destroy_host_anativewindow(ANativeWindow * window)285 EXPORT void destroy_host_anativewindow(ANativeWindow* window) {
286 delete aemu::AndroidWindow::getSelf(window);
287 }
288
289 } // extern "C"
290