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