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