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