native_android.cpp revision 4c222ff4fea46ee5b740575df4b256fa2064984f
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.12 4 * 5 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com> 6 * Copyright (C) 2010-2011 LunarG Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 * DEALINGS IN THE SOFTWARE. 25 */ 26 27#define LOG_TAG "MESA-EGL" 28#include <cutils/log.h> 29#include <cutils/properties.h> 30#include <hardware/gralloc.h> 31#include <ui/android_native_buffer.h> 32 33extern "C" { 34#include "egllog.h" 35} 36 37#include "util/u_memory.h" 38#include "util/u_inlines.h" 39#include "util/u_format.h" 40#include "common/native.h" 41#include "common/native_helper.h" 42#include "android/android_sw_winsys.h" 43#include "state_tracker/drm_driver.h" 44 45struct android_config; 46 47struct android_display { 48 struct native_display base; 49 50 boolean use_drm; 51 const struct native_event_handler *event_handler; 52 struct android_config *configs; 53 int num_configs; 54}; 55 56struct android_surface { 57 struct native_surface base; 58 59 struct android_display *adpy; 60 android_native_window_t *win; 61 62 uint stamp; 63 android_native_buffer_t *buf; 64 struct pipe_resource *res; 65 66 /* cache the current back buffers */ 67 struct { 68 int width; 69 int height; 70 int format; 71 } cache_key; 72 void *cache_handles[2]; 73 struct pipe_resource *cache_resources[2]; 74}; 75 76struct android_config { 77 struct native_config base; 78}; 79 80static INLINE struct android_display * 81android_display(const struct native_display *ndpy) 82{ 83 return (struct android_display *) ndpy; 84} 85 86static INLINE struct android_surface * 87android_surface(const struct native_surface *nsurf) 88{ 89 return (struct android_surface *) nsurf; 90} 91 92static INLINE struct android_config * 93android_config(const struct native_config *nconf) 94{ 95 return (struct android_config *) nconf; 96} 97 98namespace android { 99 100static enum pipe_format 101get_pipe_format(int native) 102{ 103 enum pipe_format fmt; 104 105 switch (native) { 106 case HAL_PIXEL_FORMAT_RGBA_8888: 107 fmt = PIPE_FORMAT_R8G8B8A8_UNORM; 108 break; 109 case HAL_PIXEL_FORMAT_RGBX_8888: 110 fmt = PIPE_FORMAT_R8G8B8X8_UNORM; 111 break; 112 case HAL_PIXEL_FORMAT_RGB_888: 113 fmt = PIPE_FORMAT_R8G8B8_UNORM; 114 break; 115 case HAL_PIXEL_FORMAT_RGB_565: 116 fmt = PIPE_FORMAT_B5G6R5_UNORM; 117 break; 118 case HAL_PIXEL_FORMAT_BGRA_8888: 119 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 120 break; 121 case HAL_PIXEL_FORMAT_RGBA_5551: 122 /* fmt = PIPE_FORMAT_A1B5G5R5_UNORM; */ 123 case HAL_PIXEL_FORMAT_RGBA_4444: 124 /* fmt = PIPE_FORMAT_A4B4G4R4_UNORM; */ 125 default: 126 LOGE("unsupported native format 0x%x", native); 127 fmt = PIPE_FORMAT_NONE; 128 break; 129 } 130 131 return fmt; 132} 133 134#include <gralloc_drm_handle.h> 135static int 136get_handle_name(buffer_handle_t handle) 137{ 138 struct gralloc_drm_handle_t *dh; 139 140 /* check that the buffer is allocated by drm_gralloc and cast */ 141 dh = gralloc_drm_handle(handle); 142 143 return (dh) ? dh->name : 0; 144} 145 146/** 147 * Import an android_native_buffer_t allocated by the server. 148 */ 149static struct pipe_resource * 150import_buffer(struct android_display *adpy, const struct pipe_resource *templ, 151 struct android_native_buffer_t *abuf) 152{ 153 struct pipe_screen *screen = adpy->base.screen; 154 struct pipe_resource *res; 155 156 if (templ->bind & PIPE_BIND_RENDER_TARGET) { 157 if (!screen->is_format_supported(screen, templ->format, 158 templ->target, 0, PIPE_BIND_RENDER_TARGET)) 159 LOGW("importing unsupported buffer as render target"); 160 } 161 if (templ->bind & PIPE_BIND_SAMPLER_VIEW) { 162 if (!screen->is_format_supported(screen, templ->format, 163 templ->target, 0, PIPE_BIND_SAMPLER_VIEW)) 164 LOGW("importing unsupported buffer as sampler view"); 165 } 166 167 if (adpy->use_drm) { 168 struct winsys_handle handle; 169 170 memset(&handle, 0, sizeof(handle)); 171 handle.type = DRM_API_HANDLE_TYPE_SHARED; 172 /* for DRM, we need the GEM name */ 173 handle.handle = get_handle_name(abuf->handle); 174 if (!handle.handle) { 175 LOGE("unable to import invalid buffer %p", abuf); 176 return NULL; 177 } 178 179 handle.stride = 180 abuf->stride * util_format_get_blocksize(templ->format); 181 182 res = screen->resource_from_handle(screen, templ, &handle); 183 } 184 else { 185 struct android_winsys_handle handle; 186 187 memset(&handle, 0, sizeof(handle)); 188 handle.handle = abuf->handle; 189 handle.stride = 190 abuf->stride * util_format_get_blocksize(templ->format); 191 192 res = screen->resource_from_handle(screen, 193 templ, (struct winsys_handle *) &handle); 194 } 195 196 if (!res) 197 LOGE("failed to import buffer %p", abuf); 198 199 return res; 200} 201 202static void 203android_surface_clear_cache(struct native_surface *nsurf) 204{ 205 struct android_surface *asurf = android_surface(nsurf); 206 int i; 207 208 for (i = 0; i < Elements(asurf->cache_handles); i++) { 209 asurf->cache_handles[i] = NULL; 210 pipe_resource_reference(&asurf->cache_resources[i], NULL); 211 } 212 213 memset(&asurf->cache_key, 0, sizeof(asurf->cache_key)); 214} 215 216static struct pipe_resource * 217android_surface_add_cache(struct native_surface *nsurf, 218 struct android_native_buffer_t *abuf) 219{ 220 struct android_surface *asurf = android_surface(nsurf); 221 void *handle; 222 int idx; 223 224 /* how about abuf->usage? */ 225 if (asurf->cache_key.width != abuf->width || 226 asurf->cache_key.height != abuf->height || 227 asurf->cache_key.format != abuf->format) 228 android_surface_clear_cache(&asurf->base); 229 230 if (asurf->adpy->use_drm) 231 handle = (void *) get_handle_name(abuf->handle); 232 else 233 handle = (void *) abuf->handle; 234 /* NULL is invalid */ 235 if (!handle) { 236 LOGE("invalid buffer native buffer %p", abuf); 237 return NULL; 238 } 239 240 /* find the slot to use */ 241 for (idx = 0; idx < Elements(asurf->cache_handles); idx++) { 242 if (asurf->cache_handles[idx] == handle || !asurf->cache_handles[idx]) 243 break; 244 } 245 if (idx == Elements(asurf->cache_handles)) { 246 LOGW("cache full: buf %p, width %d, height %d, format %d, usage 0x%x", 247 abuf, abuf->width, abuf->height, abuf->format, abuf->usage); 248 android_surface_clear_cache(&asurf->base); 249 idx = 0; 250 } 251 252 if (idx == 0) { 253 asurf->cache_key.width = abuf->width; 254 asurf->cache_key.height = abuf->height; 255 asurf->cache_key.format = abuf->format; 256 } 257 258 if (!asurf->cache_handles[idx]) { 259 struct pipe_resource templ; 260 261 assert(!asurf->cache_resources[idx]); 262 263 memset(&templ, 0, sizeof(templ)); 264 templ.target = PIPE_TEXTURE_2D; 265 templ.format = get_pipe_format(asurf->buf->format); 266 templ.bind = PIPE_BIND_RENDER_TARGET; 267 if (!asurf->adpy->use_drm) { 268 templ.bind |= PIPE_BIND_TRANSFER_WRITE | 269 PIPE_BIND_TRANSFER_READ; 270 } 271 272 templ.width0 = asurf->buf->width; 273 templ.height0 = asurf->buf->height; 274 templ.depth0 = 1; 275 templ.array_size = 1; 276 277 if (templ.format != PIPE_FORMAT_NONE) { 278 asurf->cache_resources[idx] = 279 import_buffer(asurf->adpy, &templ, asurf->buf); 280 } 281 else { 282 asurf->cache_resources[idx] = NULL; 283 } 284 285 asurf->cache_handles[idx] = handle; 286 } 287 288 return asurf->cache_resources[idx]; 289} 290 291/** 292 * Dequeue the next back buffer for rendering. 293 */ 294static boolean 295android_surface_dequeue_buffer(struct native_surface *nsurf) 296{ 297 struct android_surface *asurf = android_surface(nsurf); 298 struct pipe_resource *res; 299 300 if (asurf->win->dequeueBuffer(asurf->win, &asurf->buf) != NO_ERROR) { 301 LOGE("failed to dequeue window %p", asurf->win); 302 return FALSE; 303 } 304 305 asurf->buf->common.incRef(&asurf->buf->common); 306 asurf->win->lockBuffer(asurf->win, asurf->buf); 307 308 res = android_surface_add_cache(&asurf->base, asurf->buf); 309 if (!res) 310 return FALSE; 311 312 pipe_resource_reference(&asurf->res, res); 313 314 return TRUE; 315} 316 317/** 318 * Enqueue the back buffer. This will make it the next front buffer. 319 */ 320static boolean 321android_surface_enqueue_buffer(struct native_surface *nsurf) 322{ 323 struct android_surface *asurf = android_surface(nsurf); 324 325 pipe_resource_reference(&asurf->res, NULL); 326 327 asurf->win->queueBuffer(asurf->win, asurf->buf); 328 329 asurf->buf->common.decRef(&asurf->buf->common); 330 asurf->buf = NULL; 331 332 return TRUE; 333} 334 335static boolean 336android_surface_swap_buffers(struct native_surface *nsurf) 337{ 338 struct android_surface *asurf = android_surface(nsurf); 339 struct android_display *adpy = asurf->adpy; 340 341 if (!asurf->buf) 342 return TRUE; 343 344 android_surface_enqueue_buffer(&asurf->base); 345 346 asurf->stamp++; 347 adpy->event_handler->invalid_surface(&adpy->base, 348 &asurf->base, asurf->stamp); 349 350 return TRUE; 351} 352 353static boolean 354android_surface_present(struct native_surface *nsurf, 355 enum native_attachment natt, 356 boolean preserve, 357 uint swap_interval) 358{ 359 boolean ret; 360 361 if (swap_interval || natt != NATIVE_ATTACHMENT_BACK_LEFT) 362 return FALSE; 363 364 return android_surface_swap_buffers(nsurf); 365} 366 367static boolean 368android_surface_validate(struct native_surface *nsurf, uint attachment_mask, 369 unsigned int *seq_num, struct pipe_resource **textures, 370 int *width, int *height) 371{ 372 struct android_surface *asurf = android_surface(nsurf); 373 struct winsys_handle handle; 374 375 if (!asurf->buf) { 376 if (!android_surface_dequeue_buffer(&asurf->base)) 377 return FALSE; 378 } 379 380 if (textures) { 381 /* we have access to only the back buffer */ 382 const enum native_attachment att = NATIVE_ATTACHMENT_BACK_LEFT; 383 384 if (native_attachment_mask_test(attachment_mask, att)) { 385 textures[att] = NULL; 386 pipe_resource_reference(&textures[att], asurf->res); 387 } 388 } 389 390 if (seq_num) 391 *seq_num = asurf->stamp; 392 if (width) 393 *width = asurf->buf->width; 394 if (height) 395 *height = asurf->buf->height; 396 397 return TRUE; 398} 399 400static void 401android_surface_wait(struct native_surface *nsurf) 402{ 403} 404 405static void 406android_surface_destroy(struct native_surface *nsurf) 407{ 408 struct android_surface *asurf = android_surface(nsurf); 409 int i; 410 411 if (asurf->buf) 412 android_surface_enqueue_buffer(&asurf->base); 413 414 android_surface_clear_cache(&asurf->base); 415 416 asurf->win->common.decRef(&asurf->win->common); 417 418 FREE(asurf); 419} 420 421static struct native_surface * 422android_display_create_window_surface(struct native_display *ndpy, 423 EGLNativeWindowType win, 424 const struct native_config *nconf) 425{ 426 struct android_display *adpy = android_display(ndpy); 427 struct android_config *aconf = android_config(nconf); 428 struct android_surface *asurf; 429 enum pipe_format format; 430 int val; 431 432 if (win->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { 433 LOGE("invalid native window with magic 0x%x", win->common.magic); 434 return NULL; 435 } 436 if (win->query(win, NATIVE_WINDOW_FORMAT, &val)) { 437 LOGE("failed to query native window format"); 438 return NULL; 439 } 440 format = get_pipe_format(val); 441 if (format != nconf->color_format) { 442 LOGW("native window format 0x%x != config format 0x%x", 443 format, nconf->color_format); 444 if (!adpy->base.screen->is_format_supported(adpy->base.screen, 445 format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { 446 LOGE("and the native window cannot be used as a render target"); 447 return NULL; 448 } 449 } 450 451 asurf = CALLOC_STRUCT(android_surface); 452 if (!asurf) 453 return NULL; 454 455 asurf->adpy = adpy; 456 asurf->win = win; 457 asurf->win->common.incRef(&asurf->win->common); 458 459 /* request buffers that are for CPU access */ 460 if (!adpy->use_drm) { 461 native_window_set_usage(asurf->win, 462 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 463 } 464 465 asurf->base.destroy = android_surface_destroy; 466 asurf->base.present = android_surface_present; 467 asurf->base.validate = android_surface_validate; 468 asurf->base.wait = android_surface_wait; 469 470 return &asurf->base; 471} 472 473static boolean 474android_display_init_configs(struct native_display *ndpy) 475{ 476 struct android_display *adpy = android_display(ndpy); 477 const int native_formats[] = { 478 HAL_PIXEL_FORMAT_RGBA_8888, 479 HAL_PIXEL_FORMAT_RGBX_8888, 480 HAL_PIXEL_FORMAT_RGB_888, 481 HAL_PIXEL_FORMAT_RGB_565, 482 HAL_PIXEL_FORMAT_BGRA_8888, 483 }; 484 int i; 485 486 adpy->configs = (struct android_config *) 487 CALLOC(Elements(native_formats), sizeof(*adpy->configs)); 488 if (!adpy->configs) 489 return FALSE; 490 491 for (i = 0; i < Elements(native_formats); i++) { 492 enum pipe_format color_format; 493 struct android_config *aconf; 494 495 color_format = get_pipe_format(native_formats[i]); 496 if (color_format == PIPE_FORMAT_NONE || 497 !adpy->base.screen->is_format_supported(adpy->base.screen, 498 color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { 499 LOGI("skip unsupported native format 0x%x", native_formats[i]); 500 continue; 501 } 502 503 aconf = &adpy->configs[adpy->num_configs++]; 504 /* only the back buffer */ 505 aconf->base.buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT; 506 aconf->base.color_format = color_format; 507 aconf->base.window_bit = TRUE; 508 509 aconf->base.native_visual_id = native_formats[i]; 510 aconf->base.native_visual_type = native_formats[i]; 511 } 512 513 return TRUE; 514} 515 516static boolean 517android_display_init_drm(struct native_display *ndpy) 518{ 519 struct android_display *adpy = android_display(ndpy); 520 const hw_module_t *mod; 521 int fd, err; 522 523 /* get the authorized fd from gralloc */ 524 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); 525 if (!err) { 526 const gralloc_module_t *gr = (gralloc_module_t *) mod; 527 528 err = -EINVAL; 529 if (gr->perform) 530 err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd); 531 } 532 if (!err && fd >= 0) { 533 adpy->base.screen = 534 adpy->event_handler->new_drm_screen(&adpy->base, NULL, fd); 535 } 536 537 if (adpy->base.screen) { 538 LOGI("using DRM screen"); 539 return TRUE; 540 } 541 else { 542 LOGE("failed to create DRM screen"); 543 return FALSE; 544 } 545} 546 547static boolean 548android_display_init_sw(struct native_display *ndpy) 549{ 550 struct android_display *adpy = android_display(ndpy); 551 struct sw_winsys *ws; 552 553 ws = android_create_sw_winsys(); 554 if (ws) { 555 adpy->base.screen = 556 adpy->event_handler->new_sw_screen(&adpy->base, ws); 557 } 558 559 if (adpy->base.screen) { 560 LOGI("using SW screen"); 561 return TRUE; 562 } 563 else { 564 LOGE("failed to create SW screen"); 565 return FALSE; 566 } 567} 568 569static boolean 570android_display_init_screen(struct native_display *ndpy) 571{ 572 struct android_display *adpy = android_display(ndpy); 573 574 if (adpy->use_drm) 575 android_display_init_drm(&adpy->base); 576 else 577 android_display_init_sw(&adpy->base); 578 579 if (!adpy->base.screen) 580 return FALSE; 581 582 if (!android_display_init_configs(&adpy->base)) { 583 adpy->base.screen->destroy(adpy->base.screen); 584 adpy->base.screen = NULL; 585 return FALSE; 586 } 587 588 return TRUE; 589} 590 591static void 592android_display_destroy(struct native_display *ndpy) 593{ 594 struct android_display *adpy = android_display(ndpy); 595 596 FREE(adpy->configs); 597 if (adpy->base.screen) 598 adpy->base.screen->destroy(adpy->base.screen); 599 FREE(adpy); 600} 601 602static const struct native_config ** 603android_display_get_configs(struct native_display *ndpy, int *num_configs) 604{ 605 struct android_display *adpy = android_display(ndpy); 606 const struct native_config **configs; 607 int i; 608 609 configs = (const struct native_config **) 610 MALLOC(adpy->num_configs * sizeof(*configs)); 611 if (configs) { 612 for (i = 0; i < adpy->num_configs; i++) 613 configs[i] = (const struct native_config *) &adpy->configs[i]; 614 if (num_configs) 615 *num_configs = adpy->num_configs; 616 } 617 618 return configs; 619} 620 621static int 622android_display_get_param(struct native_display *ndpy, 623 enum native_param_type param) 624{ 625 int val; 626 627 switch (param) { 628 default: 629 val = 0; 630 break; 631 } 632 633 return val; 634} 635 636static struct pipe_resource * 637android_display_import_buffer(struct native_display *ndpy, 638 struct native_buffer *nbuf) 639{ 640 struct android_display *adpy = android_display(ndpy); 641 struct android_native_buffer_t *abuf; 642 enum pipe_format format; 643 struct pipe_resource templ; 644 645 if (nbuf->type != NATIVE_BUFFER_ANDROID) 646 return NULL; 647 648 abuf = nbuf->u.android; 649 650 if (!abuf || abuf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || 651 abuf->common.version != sizeof(*abuf)) { 652 LOGE("invalid android native buffer"); 653 return NULL; 654 } 655 656 format = get_pipe_format(abuf->format); 657 if (format == PIPE_FORMAT_NONE) 658 return NULL; 659 660 memset(&templ, 0, sizeof(templ)); 661 templ.target = PIPE_TEXTURE_2D; 662 templ.format = format; 663 /* assume for texturing only */ 664 templ.bind = PIPE_BIND_SAMPLER_VIEW; 665 templ.width0 = abuf->width; 666 templ.height0 = abuf->height; 667 templ.depth0 = 1; 668 templ.array_size = 1; 669 670 return import_buffer(adpy, &templ, abuf); 671} 672 673static boolean 674android_display_export_buffer(struct native_display *ndpy, 675 struct pipe_resource *res, 676 struct native_buffer *nbuf) 677{ 678 return FALSE; 679} 680 681static struct native_display_buffer android_display_buffer = { 682 android_display_import_buffer, 683 android_display_export_buffer 684}; 685 686static struct android_display * 687android_display_create(const struct native_event_handler *event_handler, 688 boolean use_sw) 689{ 690 struct android_display *adpy; 691 char value[PROPERTY_VALUE_MAX]; 692 boolean force_sw; 693 694 /* check if SW renderer is forced */ 695 if (property_get("debug.mesa.software", value, NULL)) 696 force_sw = (atoi(value) != 0); 697 else 698 force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); 699 if (force_sw) 700 use_sw = TRUE; 701 702 adpy = CALLOC_STRUCT(android_display); 703 if (!adpy) 704 return NULL; 705 706 adpy->event_handler = event_handler; 707 adpy->use_drm = !use_sw; 708 709 adpy->base.init_screen = android_display_init_screen; 710 adpy->base.destroy = android_display_destroy; 711 adpy->base.get_param = android_display_get_param; 712 adpy->base.get_configs = android_display_get_configs; 713 adpy->base.create_window_surface = android_display_create_window_surface; 714 715 adpy->base.buffer = &android_display_buffer; 716 717 return adpy; 718} 719 720static const struct native_event_handler *android_event_handler; 721 722static struct native_display * 723native_create_display(void *dpy, boolean use_sw) 724{ 725 struct android_display *adpy; 726 727 adpy = android_display_create(android_event_handler, use_sw); 728 729 return (adpy) ? &adpy->base : NULL; 730} 731 732static const struct native_platform android_platform = { 733 "Android", /* name */ 734 native_create_display 735}; 736 737}; /* namespace android */ 738 739using namespace android; 740 741static void 742android_log(EGLint level, const char *msg) 743{ 744 switch (level) { 745 case _EGL_DEBUG: 746 LOGD("%s", msg); 747 break; 748 case _EGL_INFO: 749 LOGI("%s", msg); 750 break; 751 case _EGL_WARNING: 752 LOGW("%s", msg); 753 break; 754 case _EGL_FATAL: 755 LOG_FATAL("%s", msg); 756 break; 757 default: 758 break; 759 } 760} 761 762const struct native_platform * 763native_get_android_platform(const struct native_event_handler *event_handler) 764{ 765 android_event_handler = event_handler; 766 /* use Android logger */ 767 _eglSetLogProc(android_log); 768 769 return &android_platform; 770} 771