1 /*
2 * Copyright (C) 2013 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 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <errno.h>
22
23 #include <pthread.h>
24
25 #include <hardware/hardware.h>
26 #include <hardware/gralloc.h>
27 #include <hardware/hwcomposer.h>
28
29 #include <system/window.h>
30 #include <cutils/native_handle.h>
31
32 // normalize and shorten type names
33 typedef struct android_native_base_t aBase;
34 typedef struct ANativeWindowBuffer aBuffer;
35 typedef struct ANativeWindow aWindow;
36
37 static int trace_level = 1;
38
39 #define _TRACE(n,fmt...) \
40 do { if (trace_level >= (n)) fprintf(stderr, "CNW: " fmt); } while (0)
41
42 #define ERROR(fmt...) _TRACE(0, fmt)
43 #define INFO(fmt...) _TRACE(1, fmt)
44 #define LOG(fmt...) _TRACE(2, fmt)
45 #define TRACE(fmt...) _TRACE(3, fmt)
46
47 #define QCT_WORKAROUND 1
48
49 typedef struct CNativeBuffer {
50 aBuffer base;
51 struct CNativeBuffer *next;
52 struct CNativeBuffer *prev;
53 int ffd;
54 } CNativeBuffer;
55
56 typedef struct CNativeWindow {
57 aWindow base;
58
59 hwc_composer_device_1_t *hwc;
60 framebuffer_device_t *fb;
61 alloc_device_t *gr;
62
63 pthread_mutex_t lock;
64 pthread_cond_t cvar;
65
66 aBuffer *front;
67 aBuffer *spare;
68
69 CNativeBuffer free_buffer_queue;
70
71 unsigned width;
72 unsigned height;
73 unsigned xdpi;
74 unsigned ydpi;
75 unsigned format;
76
77 hwc_display_contents_1_t *dclist[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
78
79 hwc_display_contents_1_t dc;
80 hwc_layer_1_t layer[4];
81 } CNativeWindow;
82
from_abuffer(aBuffer * buf)83 static inline CNativeBuffer *from_abuffer(aBuffer *buf) {
84 return (CNativeBuffer*) buf;
85 }
86
get_front(struct CNativeBuffer * queue)87 static CNativeBuffer *get_front(struct CNativeBuffer *queue) {
88 CNativeBuffer *buf = queue->next;
89 if (buf == queue)
90 return 0;
91 buf->next->prev = queue;
92 queue->next = buf->next;
93 buf->next = buf->prev = 0;
94 return buf;
95 }
96
put_front(struct CNativeBuffer * queue,aBuffer * _buf)97 static void put_front(struct CNativeBuffer *queue, aBuffer *_buf) {
98 struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf;
99 buf->prev = queue;
100 buf->next = queue->next;
101 queue->next->prev = buf;
102 queue->next = buf;
103 }
104
put_back(struct CNativeBuffer * queue,aBuffer * _buf)105 static void put_back(struct CNativeBuffer *queue, aBuffer *_buf) {
106 struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf;
107 buf->next = queue;
108 buf->prev = queue->prev;
109 queue->prev->next = buf;
110 queue->prev = buf;
111 }
112
cnw_inc_ref(aBase * base)113 static void cnw_inc_ref(aBase *base) { TRACE("buf %p ref++\n",base); }
cnw_dec_ref(aBase * base)114 static void cnw_dec_ref(aBase *base) { TRACE("buf %p ref--\n",base); }
115
from_base(aWindow * base)116 static inline CNativeWindow *from_base(aWindow *base) {
117 return (CNativeWindow *) base;
118 }
119
from_base_const(const aWindow * base)120 static inline CNativeWindow *from_base_const(const aWindow *base) {
121 return (CNativeWindow *) base;
122 }
123
cnw_set_swap_interval(aWindow * base,int interval)124 static int cnw_set_swap_interval(aWindow *base, int interval) {
125 CNativeWindow *win = from_base(base);
126 if (win->fb && win->fb->setSwapInterval)
127 return win->fb->setSwapInterval(win->fb, interval);
128 return 0;
129 }
130
cnw_dequeue_buffer1(aWindow * base,aBuffer ** buf,int * ffd)131 static int cnw_dequeue_buffer1(aWindow *base, aBuffer **buf, int *ffd) {
132 CNativeWindow *win = from_base(base);
133 CNativeBuffer *cnb;
134
135 pthread_mutex_lock(&win->lock);
136
137 while ((cnb = get_front(&win->free_buffer_queue)) == 0) {
138 pthread_cond_wait(&win->cvar, &win->lock);
139 }
140
141 *ffd = cnb->ffd;
142 *buf = &cnb->base;
143 cnb->ffd = -1;
144 LOG("<< dequeue buffer %p %d\n", *buf, *ffd);
145
146 pthread_mutex_unlock(&win->lock);
147 return 0;
148 }
149
cnw_lock_buffer0(aWindow * base,aBuffer * buffer)150 static int cnw_lock_buffer0(aWindow *base, aBuffer *buffer) {
151 return 0;
152 }
153
set_layer(hwc_layer_1_t * dl,aBuffer * buf,int ffd)154 static void set_layer(hwc_layer_1_t *dl, aBuffer *buf, int ffd) {
155 int right = buf->width;
156 int bottom = buf->height;
157
158 dl->compositionType = HWC_FRAMEBUFFER;
159 dl->hints = 0;
160 dl->flags = 0;
161
162 dl->handle = buf->handle;
163 dl->transform = 0;
164 dl->blending = HWC_BLENDING_NONE;
165 dl->sourceCrop.left = 0;
166 dl->sourceCrop.top = 0;
167 dl->sourceCrop.right = right;
168 dl->sourceCrop.bottom = bottom;
169 dl->displayFrame.left = 0;
170 dl->displayFrame.top = 0;
171 dl->displayFrame.right = right;
172 dl->displayFrame.bottom = bottom;
173 dl->visibleRegionScreen.numRects = 1;
174 dl->visibleRegionScreen.rects = &dl->displayFrame;
175
176 dl->acquireFenceFd = ffd;
177 dl->releaseFenceFd = -1;
178 }
179
hwc_post(CNativeWindow * win,aBuffer * buf,int ffd)180 static void hwc_post(CNativeWindow *win, aBuffer *buf, int ffd) {
181 hwc_composer_device_1_t *hwc = win->hwc;
182 hwc_display_contents_1_t *dc = &(win->dc);
183 hwc_layer_1_t *dl = win->dc.hwLayers;
184 int r;
185
186 dc->retireFenceFd = -1;
187 dc->outbufAcquireFenceFd = -1;
188 dc->flags = HWC_GEOMETRY_CHANGED;
189 dc->numHwLayers = 1;
190
191 // some hwcomposers fail if these are NULL
192 dc->dpy = (void*) 0xdeadbeef;
193 dc->sur = (void*) 0xdeadbeef;
194
195 set_layer(&dl[0], buf, ffd);
196
197 if (QCT_WORKAROUND) {
198 set_layer(&dl[1], win->spare, -1);
199 dl[1].compositionType = HWC_FRAMEBUFFER_TARGET;
200 dc->numHwLayers++;
201 }
202
203 r = hwc->prepare(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist);
204 if (r) {
205 ERROR("hwc->prepare failed r=%d\n",r);
206 return;
207 }
208
209 // for (i = 0; i < dc->numHwLayers; i++)
210 // LOG("dl[%d] ctype=0x%08x hints=0x%08x flags=0x%08x\n", i,
211 // dl[i].compositionType, dl[0].hints, dl[0].flags);
212
213 r = hwc->set(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist);
214 if (r) {
215 ERROR("hwc->set failed, r=%d\n", r);
216 return;
217 }
218
219 if (dc->retireFenceFd != -1)
220 close(dc->retireFenceFd);
221 if (dl->releaseFenceFd != -1) {
222 CNativeBuffer *cnb = from_abuffer(buf);
223 cnb->ffd = dl->releaseFenceFd;
224 }
225 if (QCT_WORKAROUND)
226 if (dl[1].releaseFenceFd != -1)
227 close(dl[1].releaseFenceFd);
228 }
229
cnw_queue_buffer1(aWindow * base,aBuffer * buffer,int ffd)230 static int cnw_queue_buffer1(aWindow *base, aBuffer *buffer, int ffd) {
231 CNativeWindow *win = from_base(base);
232 int res;
233 LOG(">> queue buffer %p %d\n", buffer, ffd);
234 if (win->fb) {
235 res = win->fb->post(win->fb, buffer->handle);
236 if (ffd != -1)
237 close(ffd);
238 } else {
239 hwc_post(win, buffer, ffd);
240 res = 0;
241 }
242 pthread_mutex_lock(&win->lock);
243 if (win->front)
244 put_back(&win->free_buffer_queue, win->front);
245 win->front = buffer;
246 pthread_cond_signal(&win->cvar);
247 pthread_mutex_unlock(&win->lock);
248
249 return res;
250 }
251
cnw_cancel_buffer1(aWindow * base,aBuffer * buf,int ffd)252 static int cnw_cancel_buffer1(aWindow *base, aBuffer *buf, int ffd) {
253 CNativeWindow *win = from_base(base);
254 CNativeBuffer *cnb = from_abuffer(buf);
255 LOG("<< cancel buffer %p %d\n", buf, ffd);
256 cnb->ffd = ffd;
257 pthread_mutex_lock(&win->lock);
258 put_front(&win->free_buffer_queue, buf);
259 pthread_mutex_unlock(&win->lock);
260 return 0;
261 }
262
cnw_dequeue_buffer0(aWindow * base,aBuffer ** buf)263 static int cnw_dequeue_buffer0(aWindow *base, aBuffer **buf) {
264 int ffd = -1;
265 int r;
266 r = cnw_dequeue_buffer1(base, buf, &ffd);
267 if (ffd != -1)
268 close(ffd);
269 return r;
270 }
271
cnw_queue_buffer0(aWindow * base,aBuffer * buf)272 static int cnw_queue_buffer0(aWindow *base, aBuffer *buf) {
273 return cnw_queue_buffer1(base, buf, -1);
274 }
275
cnw_cancel_buffer0(aWindow * base,aBuffer * buf)276 static int cnw_cancel_buffer0(aWindow *base, aBuffer *buf) {
277 return cnw_cancel_buffer1(base, buf, -1);
278 }
279
cnw_query(const aWindow * base,int what,int * value)280 static int cnw_query(const aWindow *base, int what, int *value) {
281 CNativeWindow *win = from_base_const(base);
282
283 switch (what) {
284 case NATIVE_WINDOW_WIDTH:
285 case NATIVE_WINDOW_DEFAULT_WIDTH:
286 *value = win->width;
287 TRACE("query window width: %d\n", *value);
288 return 0;
289 case NATIVE_WINDOW_HEIGHT:
290 case NATIVE_WINDOW_DEFAULT_HEIGHT:
291 *value = win->height;
292 TRACE("query window height: %d\n", *value);
293 return 0;
294 case NATIVE_WINDOW_FORMAT:
295 *value = win->format;
296 TRACE("query window format: %d\n", *value);
297 return 0;
298 case NATIVE_WINDOW_TRANSFORM_HINT:
299 TRACE("query transform hint: 0\n");
300 *value = 0;
301 return 0;
302 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
303 TRACE("query min undequeued buffers: 1\n");
304 *value = 1;
305 return 0;
306 default:
307 *value = 0;
308 ERROR("query %d unknown!\n", what);
309 return -EINVAL;
310 }
311 }
312
cnw_perform(aWindow * base,int op,...)313 static int cnw_perform(aWindow *base, int op, ...) {
314 CNativeWindow *win = from_base(base);
315 va_list ap;
316 va_start(ap, op);
317
318 switch (op) {
319 case NATIVE_WINDOW_SET_USAGE:
320 TRACE("set usage %d\n", va_arg(ap,int));
321 return 0;
322 case NATIVE_WINDOW_CONNECT:
323 case NATIVE_WINDOW_DISCONNECT:
324 case NATIVE_WINDOW_API_CONNECT:
325 case NATIVE_WINDOW_API_DISCONNECT:
326 return 0;
327 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
328 TRACE("set buffers format %d\n", va_arg(ap,int));
329 return 0;
330 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
331 TRACE("set buffers transform %d\n", va_arg(ap,int));
332 return 0;
333 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
334 TRACE("set buffers timestamp %lld\n", va_arg(ap,long long));
335 return 0;
336 case NATIVE_WINDOW_SET_SCALING_MODE:
337 TRACE("set scaling mode %d\n", va_arg(ap,int));
338 return 0;
339 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
340 unsigned int w = va_arg(ap,unsigned int);
341 unsigned int h = va_arg(ap,unsigned int);
342 if ((w == win->width) && (h == win->height)) {
343 TRACE("set buffers dimensions %d x %d\n", w, h);
344 return 0;
345 }
346 ERROR("cannot resize buffers to %d x %d\n", w, h);
347 return -1;
348 }
349 default:
350 ERROR("perform %d unknown!\n", op);
351 return -ENODEV;
352 }
353 }
354
hwc_invalidate(const struct hwc_procs * procs)355 static void hwc_invalidate(const struct hwc_procs *procs) {}
hwc_vsync(const struct hwc_procs * procs,int disp,int64_t ts)356 static void hwc_vsync(const struct hwc_procs *procs, int disp, int64_t ts) {}
hwc_hotplug(const struct hwc_procs * procs,int disp,int conn)357 static void hwc_hotplug(const struct hwc_procs *procs, int disp, int conn) {}
358
359 struct hwc_procs hprocs = {
360 .invalidate = hwc_invalidate,
361 .vsync = hwc_vsync,
362 .hotplug = hwc_hotplug,
363 };
364
365 uint32_t attrs[] = {
366 HWC_DISPLAY_WIDTH,
367 HWC_DISPLAY_HEIGHT,
368 HWC_DISPLAY_VSYNC_PERIOD,
369 HWC_DISPLAY_DPI_X,
370 HWC_DISPLAY_DPI_Y,
371 HWC_DISPLAY_NO_ATTRIBUTE,
372 };
373
hwc_init(CNativeWindow * win)374 static int hwc_init(CNativeWindow *win) {
375 hw_module_t const* module;
376 hwc_composer_device_1_t *hwc;
377 unsigned i;
378 int r;
379 uint32_t configs[32];
380 size_t numconfigs = 32;
381 int32_t values[8];
382
383 if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
384 ERROR("cannot open hw composer module\n");
385 return -ENODEV;
386 }
387
388 if (hwc_open_1(module, &hwc)) {
389 ERROR("cannot open hwc device\n");
390 return -ENODEV;
391 }
392 win->hwc = hwc;
393
394 LOG("hwc version 0x%08x\n", hwc->common.version);
395
396 if ((hwc->common.version & 0xFFFF0000) < 0x01010000) {
397 ERROR("hwc version less than 1.1\n");
398 hwc_close_1(hwc);
399 return -ENODEV;
400 }
401
402 hwc->registerProcs(hwc, &hprocs);
403
404 if (hwc->getDisplayConfigs(hwc, 0, configs, &numconfigs)) {
405 ERROR("cannot get configs\n");
406 return -ENODEV;
407 }
408 for (i = 0; i < numconfigs; i++)
409 LOG("cfg[%d] = 0x%08x\n", i, configs[i]);
410
411 if ((r = hwc->getDisplayAttributes(hwc, 0, configs[0], attrs, values))) {
412 ERROR("cannot get attributes %d\n", r);
413 return -ENODEV;
414 }
415
416 win->width = values[0];
417 win->height = values[1];
418 win->xdpi = values[3];
419 win->ydpi = values[4];
420 win->format = HAL_PIXEL_FORMAT_RGBA_8888;
421
422 hwc->blank(hwc, 0, 0);
423
424 win->dclist[0] = &(win->dc);
425 return 0;
426 }
427
cnw_alloc(CNativeWindow * win,unsigned format,unsigned usage)428 static aBuffer *cnw_alloc(CNativeWindow *win, unsigned format, unsigned usage) {
429 CNativeBuffer *cnb;
430 aBuffer *buf;
431 int err;
432
433 if (!(cnb = malloc(sizeof(CNativeBuffer))))
434 return 0;
435
436 buf = &cnb->base;
437 cnb->ffd = -1;
438
439 buf->common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
440 buf->common.version = sizeof(aBuffer);
441 buf->common.incRef = cnw_inc_ref;
442 buf->common.decRef = cnw_dec_ref;
443
444 buf->width = win->width;
445 buf->height = win->height;
446 buf->format = format;
447 buf->usage = usage;
448
449 err = win->gr->alloc(win->gr, win->width, win->height,
450 format, usage, &buf->handle, &buf->stride);
451 if (err) {
452 ERROR("gralloc of %d x %d failed: err=%d\n",
453 win->width, win->height, err);
454 free(buf);
455 return 0;
456 }
457 INFO("alloc buffer %p %d x %d\n", buf, win->width, win->height);
458 return buf;
459 }
460
cnw_init(CNativeWindow * win)461 static int cnw_init(CNativeWindow *win) {
462 hw_module_t const* module;
463 framebuffer_device_t *fb = NULL;
464 alloc_device_t *gr;
465 int err, i;
466 unsigned usage;
467
468 memset(win, 0, sizeof(CNativeWindow));
469
470 win->free_buffer_queue.next = &(win->free_buffer_queue);
471 win->free_buffer_queue.prev = &(win->free_buffer_queue);
472
473 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
474 ERROR("cannot open gralloc module\n");
475 return -ENODEV;
476 }
477
478 if (hwc_init(win)) {
479 ERROR("cannot open hwcomposer, trying legacy fb HAL\n");
480 err = framebuffer_open(module, &fb);
481 if (err) {
482 ERROR("cannot open fb HAL (%s)", strerror(-err));
483 return -ENODEV;
484 }
485 win->width = fb->width;
486 win->height = fb->height;
487 win->format = fb->format;
488 win->xdpi = fb->xdpi;
489 win->ydpi = fb->ydpi;
490 win->fb = fb;
491 }
492
493 INFO("display %d x %d fmt=%d\n",
494 win->width, win->height, win->format);
495
496 err = gralloc_open(module, &gr);
497 if (err) {
498 ERROR("couldn't open gralloc HAL (%s)", strerror(-err));
499 return -ENODEV;
500 }
501 win->gr = gr;
502
503 usage = GRALLOC_USAGE_HW_FB |
504 GRALLOC_USAGE_HW_COMPOSER |
505 GRALLOC_USAGE_HW_RENDER;
506
507 for (i = 0; i < 2; i++) {
508 aBuffer *buf = cnw_alloc(win, win->format, usage);
509 if (!buf)
510 return -ENOMEM;
511 put_back(&win->free_buffer_queue, buf);
512 }
513
514 if (!win->fb && QCT_WORKAROUND) {
515 win->spare = cnw_alloc(win, win->format, usage);
516 if (!win->spare)
517 return -ENOMEM;
518 }
519
520 // Disgusting, but we need to init these "const" fields
521 // and unlike C++ we can't use const_cast<>
522 *((float*) &win->base.xdpi) = win->xdpi;
523 *((float*) &win->base.ydpi) = win->ydpi;
524 *((int*) &win->base.minSwapInterval) = 1;
525 *((int*) &win->base.maxSwapInterval) = 1;
526
527 win->base.common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
528 win->base.common.version = sizeof(aWindow);
529 win->base.common.incRef = cnw_inc_ref;
530 win->base.common.decRef = cnw_dec_ref;
531
532 win->base.setSwapInterval = cnw_set_swap_interval;
533 win->base.dequeueBuffer_DEPRECATED = cnw_dequeue_buffer0;
534 win->base.lockBuffer_DEPRECATED = cnw_lock_buffer0;
535 win->base.queueBuffer_DEPRECATED = cnw_queue_buffer0;
536 win->base.query = cnw_query;
537 win->base.perform = cnw_perform;
538 win->base.cancelBuffer_DEPRECATED = cnw_cancel_buffer0;
539 win->base.dequeueBuffer = cnw_dequeue_buffer1;
540 win->base.queueBuffer = cnw_queue_buffer1;
541 win->base.cancelBuffer = cnw_cancel_buffer1;
542
543 pthread_mutex_init(&win->lock, NULL);
544 pthread_cond_init(&win->cvar, NULL);
545
546 return 0;
547 }
548
cnw_destroy(CNativeWindow * win)549 void cnw_destroy(CNativeWindow *win) {
550 if (win->fb)
551 framebuffer_close(win->fb);
552 if (win->hwc)
553 hwc_close_1(win->hwc);
554 if (win->gr)
555 gralloc_close(win->gr);
556 free(win);
557 }
558
cnw_create(void)559 CNativeWindow *cnw_create(void) {
560 CNativeWindow *win;
561 char *x;
562 if ((x = getenv("CNWDEBUG")))
563 trace_level = atoi(x);
564 if (!(win = malloc(sizeof(CNativeWindow))))
565 return NULL;
566 if (cnw_init(win)) {
567 cnw_destroy(win);
568 return NULL;
569 }
570 return win;
571 }
572
cnw_info(CNativeWindow * win,unsigned * w,unsigned * h,unsigned * fmt)573 void cnw_info(CNativeWindow *win, unsigned *w, unsigned *h, unsigned *fmt) {
574 *w = win->width;
575 *h = win->height;
576 *fmt = win->format;
577 }
578
579