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, i;
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, n;
466 	unsigned usage, format;
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