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 int w = va_arg(ap,int); 341 int h = va_arg(ap,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 uint32_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