Home | History | Annotate | Download | only in hwc
      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 
     83 static inline CNativeBuffer *from_abuffer(aBuffer *buf) {
     84 	return (CNativeBuffer*) buf;
     85 }
     86 
     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 
     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 
    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 
    113 static void cnw_inc_ref(aBase *base) { TRACE("buf %p ref++\n",base); }
    114 static void cnw_dec_ref(aBase *base) { TRACE("buf %p ref--\n",base); }
    115 
    116 static inline CNativeWindow *from_base(aWindow *base) {
    117 	return (CNativeWindow *) base;
    118 }
    119 
    120 static inline CNativeWindow *from_base_const(const aWindow *base) {
    121 	return (CNativeWindow *) base;
    122 }
    123 
    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 
    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 
    150 static int cnw_lock_buffer0(aWindow *base, aBuffer *buffer) {
    151 	return 0;
    152 }
    153 
    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 
    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 
    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 
    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 
    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 
    272 static int cnw_queue_buffer0(aWindow *base, aBuffer *buf) {
    273 	return cnw_queue_buffer1(base, buf, -1);
    274 }
    275 
    276 static int cnw_cancel_buffer0(aWindow *base, aBuffer *buf) {
    277 	return cnw_cancel_buffer1(base, buf, -1);
    278 }
    279 
    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 
    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 
    355 static void hwc_invalidate(const struct hwc_procs *procs) {}
    356 static void hwc_vsync(const struct hwc_procs *procs, int disp, int64_t ts) {}
    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 
    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 
    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 
    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 
    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 
    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 
    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