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