native_android.cpp revision 8ccafbbbcc797dc15daed883b09250165ab980b3
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 front and back resources */ 67 void *cache_handles[2]; 68 struct pipe_resource *cache_resources[2]; 69}; 70 71struct android_config { 72 struct native_config base; 73}; 74 75static INLINE struct android_display * 76android_display(const struct native_display *ndpy) 77{ 78 return (struct android_display *) ndpy; 79} 80 81static INLINE struct android_surface * 82android_surface(const struct native_surface *nsurf) 83{ 84 return (struct android_surface *) nsurf; 85} 86 87static INLINE struct android_config * 88android_config(const struct native_config *nconf) 89{ 90 return (struct android_config *) nconf; 91} 92 93namespace android { 94 95static enum pipe_format 96get_pipe_format(int native) 97{ 98 enum pipe_format fmt; 99 100 switch (native) { 101 case HAL_PIXEL_FORMAT_RGBA_8888: 102 fmt = PIPE_FORMAT_R8G8B8A8_UNORM; 103 break; 104 case HAL_PIXEL_FORMAT_RGBX_8888: 105 fmt = PIPE_FORMAT_R8G8B8X8_UNORM; 106 break; 107 case HAL_PIXEL_FORMAT_RGB_888: 108 fmt = PIPE_FORMAT_R8G8B8_UNORM; 109 break; 110 case HAL_PIXEL_FORMAT_RGB_565: 111 fmt = PIPE_FORMAT_B5G6R5_UNORM; 112 break; 113 case HAL_PIXEL_FORMAT_BGRA_8888: 114 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 115 break; 116 case HAL_PIXEL_FORMAT_RGBA_5551: 117 /* fmt = PIPE_FORMAT_A1B5G5R5_UNORM; */ 118 case HAL_PIXEL_FORMAT_RGBA_4444: 119 /* fmt = PIPE_FORMAT_A4B4G4R4_UNORM; */ 120 default: 121 LOGE("unsupported native format 0x%x", native); 122 fmt = PIPE_FORMAT_NONE; 123 break; 124 } 125 126 return fmt; 127} 128 129#include <gralloc_drm_handle.h> 130static int 131get_handle_name(buffer_handle_t handle) 132{ 133 struct gralloc_drm_handle_t *dh; 134 135 /* check that the buffer is allocated by drm_gralloc and cast */ 136 dh = gralloc_drm_handle(handle); 137 138 return (dh) ? dh->name : 0; 139} 140 141/** 142 * Import an android_native_buffer_t allocated by the server. 143 */ 144static struct pipe_resource * 145import_buffer(struct android_display *adpy, const struct pipe_resource *templ, 146 struct android_native_buffer_t *abuf) 147{ 148 struct pipe_screen *screen = adpy->base.screen; 149 struct pipe_resource *res; 150 151 if (templ->bind & PIPE_BIND_RENDER_TARGET) { 152 if (!screen->is_format_supported(screen, templ->format, 153 templ->target, 0, PIPE_BIND_RENDER_TARGET)) 154 LOGW("importing unsupported buffer as render target"); 155 } 156 if (templ->bind & PIPE_BIND_SAMPLER_VIEW) { 157 if (!screen->is_format_supported(screen, templ->format, 158 templ->target, 0, PIPE_BIND_SAMPLER_VIEW)) 159 LOGW("importing unsupported buffer as sampler view"); 160 } 161 162 if (adpy->use_drm) { 163 struct winsys_handle handle; 164 165 memset(&handle, 0, sizeof(handle)); 166 handle.type = DRM_API_HANDLE_TYPE_SHARED; 167 /* for DRM, we need the GEM name */ 168 handle.handle = get_handle_name(abuf->handle); 169 if (!handle.handle) { 170 LOGE("unable to import invalid buffer %p", abuf); 171 return NULL; 172 } 173 174 handle.stride = 175 abuf->stride * util_format_get_blocksize(templ->format); 176 177 res = screen->resource_from_handle(screen, templ, &handle); 178 } 179 else { 180 struct android_winsys_handle handle; 181 182 memset(&handle, 0, sizeof(handle)); 183 handle.handle = abuf->handle; 184 handle.stride = 185 abuf->stride * util_format_get_blocksize(templ->format); 186 187 res = screen->resource_from_handle(screen, 188 templ, (struct winsys_handle *) &handle); 189 } 190 191 if (!res) 192 LOGE("failed to import buffer %p", abuf); 193 194 return res; 195} 196 197/** 198 * Dequeue the next back buffer for rendering. 199 */ 200static boolean 201android_surface_dequeue_buffer(struct native_surface *nsurf) 202{ 203 struct android_surface *asurf = android_surface(nsurf); 204 void *handle; 205 int idx; 206 207 if (asurf->win->dequeueBuffer(asurf->win, &asurf->buf) != NO_ERROR) { 208 LOGE("failed to dequeue window %p", asurf->win); 209 return FALSE; 210 } 211 212 asurf->buf->common.incRef(&asurf->buf->common); 213 asurf->win->lockBuffer(asurf->win, asurf->buf); 214 215 if (asurf->adpy->use_drm) 216 handle = (void *) get_handle_name(asurf->buf->handle); 217 else 218 handle = (void *) asurf->buf->handle; 219 /* NULL is invalid */ 220 if (!handle) { 221 LOGE("window %p returned an invalid buffer", asurf->win); 222 return TRUE; 223 } 224 225 /* find the slot to use */ 226 for (idx = 0; idx < Elements(asurf->cache_handles); idx++) { 227 if (asurf->cache_handles[idx] == handle || !asurf->cache_handles[idx]) 228 break; 229 } 230 if (idx == Elements(asurf->cache_handles)) { 231 /* buffer reallocated; clear the cache */ 232 for (idx = 0; idx < Elements(asurf->cache_handles); idx++) { 233 asurf->cache_handles[idx] = 0; 234 pipe_resource_reference(&asurf->cache_resources[idx], NULL); 235 } 236 idx = 0; 237 } 238 239 /* update the cache */ 240 if (!asurf->cache_handles[idx]) { 241 struct pipe_resource templ; 242 243 assert(!asurf->cache_resources[idx]); 244 245 memset(&templ, 0, sizeof(templ)); 246 templ.target = PIPE_TEXTURE_2D; 247 templ.last_level = 0; 248 templ.width0 = asurf->buf->width; 249 templ.height0 = asurf->buf->height; 250 templ.depth0 = 1; 251 templ.bind = PIPE_BIND_RENDER_TARGET; 252 if (!asurf->adpy->use_drm) { 253 templ.bind |= PIPE_BIND_TRANSFER_WRITE | 254 PIPE_BIND_TRANSFER_READ; 255 } 256 257 templ.format = get_pipe_format(asurf->buf->format); 258 if (templ.format != PIPE_FORMAT_NONE) { 259 asurf->cache_resources[idx] = 260 import_buffer(asurf->adpy, &templ, asurf->buf); 261 } 262 else { 263 asurf->cache_resources[idx] = NULL; 264 } 265 266 asurf->cache_handles[idx] = handle; 267 } 268 269 pipe_resource_reference(&asurf->res, asurf->cache_resources[idx]); 270 271 return TRUE; 272} 273 274/** 275 * Enqueue the back buffer. This will make it the next front buffer. 276 */ 277static boolean 278android_surface_enqueue_buffer(struct native_surface *nsurf) 279{ 280 struct android_surface *asurf = android_surface(nsurf); 281 282 pipe_resource_reference(&asurf->res, NULL); 283 284 asurf->win->queueBuffer(asurf->win, asurf->buf); 285 286 asurf->buf->common.decRef(&asurf->buf->common); 287 asurf->buf = NULL; 288 289 return TRUE; 290} 291 292static boolean 293android_surface_swap_buffers(struct native_surface *nsurf) 294{ 295 struct android_surface *asurf = android_surface(nsurf); 296 struct android_display *adpy = asurf->adpy; 297 298 if (!asurf->buf) 299 return FALSE; 300 301 android_surface_enqueue_buffer(&asurf->base); 302 303 asurf->stamp++; 304 adpy->event_handler->invalid_surface(&adpy->base, 305 &asurf->base, asurf->stamp); 306 307 return TRUE; 308} 309 310static boolean 311android_surface_present(struct native_surface *nsurf, 312 enum native_attachment natt, 313 boolean preserve, 314 uint swap_interval) 315{ 316 boolean ret; 317 318 if (swap_interval || natt != NATIVE_ATTACHMENT_BACK_LEFT) 319 return FALSE; 320 321 return android_surface_swap_buffers(nsurf); 322} 323 324static boolean 325android_surface_validate(struct native_surface *nsurf, uint attachment_mask, 326 unsigned int *seq_num, struct pipe_resource **textures, 327 int *width, int *height) 328{ 329 struct android_surface *asurf = android_surface(nsurf); 330 struct winsys_handle handle; 331 332 if (!asurf->buf) { 333 if (!android_surface_dequeue_buffer(&asurf->base)) 334 return FALSE; 335 } 336 337 if (textures) { 338 /* we have access to only the back buffer */ 339 const enum native_attachment att = NATIVE_ATTACHMENT_BACK_LEFT; 340 341 if (native_attachment_mask_test(attachment_mask, att)) { 342 textures[att] = NULL; 343 pipe_resource_reference(&textures[att], asurf->res); 344 } 345 } 346 347 if (seq_num) 348 *seq_num = asurf->stamp; 349 if (width) 350 *width = asurf->buf->width; 351 if (height) 352 *height = asurf->buf->height; 353 354 return TRUE; 355} 356 357static void 358android_surface_wait(struct native_surface *nsurf) 359{ 360} 361 362static void 363android_surface_destroy(struct native_surface *nsurf) 364{ 365 struct android_surface *asurf = android_surface(nsurf); 366 int i; 367 368 if (asurf->buf) 369 android_surface_enqueue_buffer(&asurf->base); 370 371 for (i = 0; i < Elements(asurf->cache_handles); i++) 372 pipe_resource_reference(&asurf->cache_resources[i], NULL); 373 374 asurf->win->common.decRef(&asurf->win->common); 375 376 FREE(asurf); 377} 378 379static struct native_surface * 380android_display_create_window_surface(struct native_display *ndpy, 381 EGLNativeWindowType win, 382 const struct native_config *nconf) 383{ 384 struct android_display *adpy = android_display(ndpy); 385 struct android_config *aconf = android_config(nconf); 386 struct android_surface *asurf; 387 enum pipe_format format; 388 int val; 389 390 if (win->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { 391 LOGE("invalid native window with magic 0x%x", win->common.magic); 392 return NULL; 393 } 394 if (win->query(win, NATIVE_WINDOW_FORMAT, &val)) { 395 LOGE("failed to query native window format"); 396 return NULL; 397 } 398 format = get_pipe_format(val); 399 if (format != nconf->color_format) { 400 LOGW("native window format 0x%x != config format 0x%x", 401 format, nconf->color_format); 402 if (!adpy->base.screen->is_format_supported(adpy->base.screen, 403 format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { 404 LOGE("and the native window cannot be used as a render target"); 405 return NULL; 406 } 407 } 408 409 asurf = CALLOC_STRUCT(android_surface); 410 if (!asurf) 411 return NULL; 412 413 asurf->adpy = adpy; 414 asurf->win = win; 415 asurf->win->common.incRef(&asurf->win->common); 416 417 /* request buffers that are for CPU access */ 418 if (!adpy->use_drm) { 419 native_window_set_usage(asurf->win, 420 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 421 } 422 423 asurf->base.destroy = android_surface_destroy; 424 asurf->base.present = android_surface_present; 425 asurf->base.validate = android_surface_validate; 426 asurf->base.wait = android_surface_wait; 427 428 return &asurf->base; 429} 430 431static boolean 432android_display_init_configs(struct native_display *ndpy) 433{ 434 struct android_display *adpy = android_display(ndpy); 435 const int native_formats[] = { 436 HAL_PIXEL_FORMAT_RGBA_8888, 437 HAL_PIXEL_FORMAT_RGBX_8888, 438 HAL_PIXEL_FORMAT_RGB_888, 439 HAL_PIXEL_FORMAT_RGB_565, 440 HAL_PIXEL_FORMAT_BGRA_8888, 441 }; 442 int i; 443 444 adpy->configs = (struct android_config *) 445 CALLOC(Elements(native_formats), sizeof(*adpy->configs)); 446 if (!adpy->configs) 447 return FALSE; 448 449 for (i = 0; i < Elements(native_formats); i++) { 450 enum pipe_format color_format; 451 struct android_config *aconf; 452 453 color_format = get_pipe_format(native_formats[i]); 454 if (color_format == PIPE_FORMAT_NONE || 455 !adpy->base.screen->is_format_supported(adpy->base.screen, 456 color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { 457 LOGI("skip unsupported native format 0x%x", native_formats[i]); 458 continue; 459 } 460 461 aconf = &adpy->configs[adpy->num_configs++]; 462 /* only the back buffer */ 463 aconf->base.buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT; 464 aconf->base.color_format = color_format; 465 aconf->base.window_bit = TRUE; 466 467 aconf->base.native_visual_id = native_formats[i]; 468 aconf->base.native_visual_type = native_formats[i]; 469 } 470 471 return TRUE; 472} 473 474static boolean 475android_display_init_drm(struct native_display *ndpy) 476{ 477 struct android_display *adpy = android_display(ndpy); 478 const hw_module_t *mod; 479 int fd, err; 480 481 /* get the authorized fd from gralloc */ 482 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); 483 if (!err) { 484 const gralloc_module_t *gr = (gralloc_module_t *) mod; 485 486 err = -EINVAL; 487 if (gr->perform) 488 err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd); 489 } 490 if (!err && fd >= 0) { 491 adpy->base.screen = 492 adpy->event_handler->new_drm_screen(&adpy->base, NULL, fd); 493 } 494 495 if (adpy->base.screen) { 496 LOGI("using DRM screen"); 497 return TRUE; 498 } 499 else { 500 LOGE("failed to create DRM screen"); 501 return FALSE; 502 } 503} 504 505static boolean 506android_display_init_sw(struct native_display *ndpy) 507{ 508 struct android_display *adpy = android_display(ndpy); 509 struct sw_winsys *ws; 510 511 ws = android_create_sw_winsys(); 512 if (ws) { 513 adpy->base.screen = 514 adpy->event_handler->new_sw_screen(&adpy->base, ws); 515 } 516 517 if (adpy->base.screen) { 518 LOGI("using SW screen"); 519 return TRUE; 520 } 521 else { 522 LOGE("failed to create SW screen"); 523 return FALSE; 524 } 525} 526 527static boolean 528android_display_init_screen(struct native_display *ndpy) 529{ 530 struct android_display *adpy = android_display(ndpy); 531 532 if (adpy->use_drm) 533 android_display_init_drm(&adpy->base); 534 else 535 android_display_init_sw(&adpy->base); 536 537 if (!adpy->base.screen) 538 return FALSE; 539 540 if (!android_display_init_configs(&adpy->base)) { 541 adpy->base.screen->destroy(adpy->base.screen); 542 adpy->base.screen = NULL; 543 return FALSE; 544 } 545 546 return TRUE; 547} 548 549static void 550android_display_destroy(struct native_display *ndpy) 551{ 552 struct android_display *adpy = android_display(ndpy); 553 554 FREE(adpy->configs); 555 if (adpy->base.screen) 556 adpy->base.screen->destroy(adpy->base.screen); 557 FREE(adpy); 558} 559 560static const struct native_config ** 561android_display_get_configs(struct native_display *ndpy, int *num_configs) 562{ 563 struct android_display *adpy = android_display(ndpy); 564 const struct native_config **configs; 565 int i; 566 567 configs = (const struct native_config **) 568 MALLOC(adpy->num_configs * sizeof(*configs)); 569 if (configs) { 570 for (i = 0; i < adpy->num_configs; i++) 571 configs[i] = (const struct native_config *) &adpy->configs[i]; 572 if (num_configs) 573 *num_configs = adpy->num_configs; 574 } 575 576 return configs; 577} 578 579static int 580android_display_get_param(struct native_display *ndpy, 581 enum native_param_type param) 582{ 583 int val; 584 585 switch (param) { 586 default: 587 val = 0; 588 break; 589 } 590 591 return val; 592} 593 594static struct pipe_resource * 595android_display_import_buffer(struct native_display *ndpy, 596 struct native_buffer *nbuf) 597{ 598 struct android_display *adpy = android_display(ndpy); 599 struct android_native_buffer_t *abuf; 600 enum pipe_format format; 601 struct pipe_resource templ; 602 603 if (nbuf->type != NATIVE_BUFFER_ANDROID) 604 return NULL; 605 606 abuf = nbuf->u.android; 607 608 if (!abuf || abuf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || 609 abuf->common.version != sizeof(*abuf)) { 610 LOGE("invalid android native buffer"); 611 return NULL; 612 } 613 614 format = get_pipe_format(abuf->format); 615 if (format == PIPE_FORMAT_NONE) 616 return NULL; 617 618 memset(&templ, 0, sizeof(templ)); 619 templ.target = PIPE_TEXTURE_2D; 620 templ.format = format; 621 /* assume for texturing only */ 622 templ.bind = PIPE_BIND_SAMPLER_VIEW; 623 templ.width0 = abuf->width; 624 templ.height0 = abuf->height; 625 templ.depth0 = 1; 626 templ.array_size = 1; 627 628 return import_buffer(adpy, &templ, abuf); 629} 630 631static boolean 632android_display_export_buffer(struct native_display *ndpy, 633 struct pipe_resource *res, 634 struct native_buffer *nbuf) 635{ 636 return FALSE; 637} 638 639static struct native_display_buffer android_display_buffer = { 640 android_display_import_buffer, 641 android_display_export_buffer 642}; 643 644static struct android_display * 645android_display_create(const struct native_event_handler *event_handler, 646 boolean use_sw) 647{ 648 struct android_display *adpy; 649 char value[PROPERTY_VALUE_MAX]; 650 boolean force_sw; 651 652 /* check if SW renderer is forced */ 653 if (property_get("debug.mesa.software", value, NULL)) 654 force_sw = (atoi(value) != 0); 655 else 656 force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); 657 if (force_sw) 658 use_sw = TRUE; 659 660 adpy = CALLOC_STRUCT(android_display); 661 if (!adpy) 662 return NULL; 663 664 adpy->event_handler = event_handler; 665 adpy->use_drm = !use_sw; 666 667 adpy->base.init_screen = android_display_init_screen; 668 adpy->base.destroy = android_display_destroy; 669 adpy->base.get_param = android_display_get_param; 670 adpy->base.get_configs = android_display_get_configs; 671 adpy->base.create_window_surface = android_display_create_window_surface; 672 673 adpy->base.buffer = &android_display_buffer; 674 675 return adpy; 676} 677 678static const struct native_event_handler *android_event_handler; 679 680static struct native_display * 681native_create_display(void *dpy, boolean use_sw) 682{ 683 struct android_display *adpy; 684 685 adpy = android_display_create(android_event_handler, use_sw); 686 687 return (adpy) ? &adpy->base : NULL; 688} 689 690static const struct native_platform android_platform = { 691 "Android", /* name */ 692 native_create_display 693}; 694 695}; /* namespace android */ 696 697using namespace android; 698 699static void 700android_log(EGLint level, const char *msg) 701{ 702 switch (level) { 703 case _EGL_DEBUG: 704 LOGD("%s", msg); 705 break; 706 case _EGL_INFO: 707 LOGI("%s", msg); 708 break; 709 case _EGL_WARNING: 710 LOGW("%s", msg); 711 break; 712 case _EGL_FATAL: 713 LOG_FATAL("%s", msg); 714 break; 715 default: 716 break; 717 } 718} 719 720const struct native_platform * 721native_get_android_platform(const struct native_event_handler *event_handler) 722{ 723 android_event_handler = event_handler; 724 /* use Android logger */ 725 _eglSetLogProc(android_log); 726 727 return &android_platform; 728} 729