platform_android.c revision bc8b07a65722ad25aa52aa4918b51e236a13b09e
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com> 5 * Copyright (C) 2010-2011 LunarG Inc. 6 * 7 * Based on platform_x11, which has 8 * 9 * Copyright © 2011 Intel Corporation 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining a 12 * copy of this software and associated documentation files (the "Software"), 13 * to deal in the Software without restriction, including without limitation 14 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 * and/or sell copies of the Software, and to permit persons to whom the 16 * Software is furnished to do so, subject to the following conditions: 17 * 18 * The above copyright notice and this permission notice shall be included 19 * in all copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 * DEALINGS IN THE SOFTWARE. 28 */ 29 30#include <errno.h> 31#include <dlfcn.h> 32 33#if ANDROID_VERSION >= 0x402 34#include <sync/sync.h> 35#endif 36 37#include "loader.h" 38#include "egl_dri2.h" 39#include "egl_dri2_fallbacks.h" 40#include "gralloc_drm.h" 41 42static int 43get_format_bpp(int native) 44{ 45 int bpp; 46 47 switch (native) { 48 case HAL_PIXEL_FORMAT_RGBA_8888: 49 case HAL_PIXEL_FORMAT_RGBX_8888: 50 case HAL_PIXEL_FORMAT_BGRA_8888: 51 bpp = 4; 52 break; 53 case HAL_PIXEL_FORMAT_RGB_888: 54 bpp = 3; 55 break; 56 case HAL_PIXEL_FORMAT_RGB_565: 57 case HAL_PIXEL_FORMAT_RGBA_5551: 58 case HAL_PIXEL_FORMAT_RGBA_4444: 59 bpp = 2; 60 break; 61 default: 62 bpp = 0; 63 break; 64 } 65 66 return bpp; 67} 68 69static int 70get_native_buffer_name(struct ANativeWindowBuffer *buf) 71{ 72 return gralloc_drm_get_gem_handle(buf->handle); 73} 74 75static EGLBoolean 76droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) 77{ 78#if ANDROID_VERSION >= 0x0402 79 int fence_fd; 80 81 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer, 82 &fence_fd)) 83 return EGL_FALSE; 84 85 /* If access to the buffer is controlled by a sync fence, then block on the 86 * fence. 87 * 88 * It may be more performant to postpone blocking until there is an 89 * immediate need to write to the buffer. But doing so would require adding 90 * hooks to the DRI2 loader. 91 * 92 * From the ANativeWindow::dequeueBuffer documentation: 93 * 94 * The libsync fence file descriptor returned in the int pointed to by 95 * the fenceFd argument will refer to the fence that must signal 96 * before the dequeued buffer may be written to. A value of -1 97 * indicates that the caller may access the buffer immediately without 98 * waiting on a fence. If a valid file descriptor is returned (i.e. 99 * any value except -1) then the caller is responsible for closing the 100 * file descriptor. 101 */ 102 if (fence_fd >= 0) { 103 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>: 104 * 105 * Waits indefinitely if timeout < 0. 106 */ 107 int timeout = -1; 108 sync_wait(fence_fd, timeout); 109 close(fence_fd); 110 } 111 112 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common); 113#else 114 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer)) 115 return EGL_FALSE; 116 117 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common); 118 dri2_surf->window->lockBuffer(dri2_surf->window, dri2_surf->buffer); 119#endif 120 121 return EGL_TRUE; 122} 123 124static EGLBoolean 125droid_window_enqueue_buffer(struct dri2_egl_surface *dri2_surf) 126{ 127#if ANDROID_VERSION >= 0x0402 128 /* Queue the buffer without a sync fence. This informs the ANativeWindow 129 * that it may access the buffer immediately. 130 * 131 * From ANativeWindow::dequeueBuffer: 132 * 133 * The fenceFd argument specifies a libsync fence file descriptor for 134 * a fence that must signal before the buffer can be accessed. If 135 * the buffer can be accessed immediately then a value of -1 should 136 * be used. The caller must not use the file descriptor after it 137 * is passed to queueBuffer, and the ANativeWindow implementation 138 * is responsible for closing it. 139 */ 140 int fence_fd = -1; 141 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer, 142 fence_fd); 143#else 144 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer); 145#endif 146 147 dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common); 148 dri2_surf->buffer = NULL; 149 150 return EGL_TRUE; 151} 152 153static void 154droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf) 155{ 156 /* no cancel buffer? */ 157 droid_window_enqueue_buffer(dri2_surf); 158} 159 160static __DRIbuffer * 161droid_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 162 unsigned int att, unsigned int format) 163{ 164 struct dri2_egl_display *dri2_dpy = 165 dri2_egl_display(dri2_surf->base.Resource.Display); 166 167 if (att >= ARRAY_SIZE(dri2_surf->local_buffers)) 168 return NULL; 169 170 if (!dri2_surf->local_buffers[att]) { 171 dri2_surf->local_buffers[att] = 172 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format, 173 dri2_surf->base.Width, dri2_surf->base.Height); 174 } 175 176 return dri2_surf->local_buffers[att]; 177} 178 179static void 180droid_free_local_buffers(struct dri2_egl_surface *dri2_surf) 181{ 182 struct dri2_egl_display *dri2_dpy = 183 dri2_egl_display(dri2_surf->base.Resource.Display); 184 int i; 185 186 for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) { 187 if (dri2_surf->local_buffers[i]) { 188 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 189 dri2_surf->local_buffers[i]); 190 dri2_surf->local_buffers[i] = NULL; 191 } 192 } 193} 194 195static _EGLSurface * 196droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, 197 _EGLConfig *conf, EGLNativeWindowType window, 198 const EGLint *attrib_list) 199{ 200 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 201 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 202 struct dri2_egl_surface *dri2_surf; 203 dri2_surf = calloc(1, sizeof *dri2_surf); 204 if (!dri2_surf) { 205 _eglError(EGL_BAD_ALLOC, "droid_create_surface"); 206 return NULL; 207 } 208 209 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) 210 goto cleanup_surface; 211 212 if (type == EGL_WINDOW_BIT) { 213 int format; 214 215 if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { 216 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 217 goto cleanup_surface; 218 } 219 if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) { 220 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 221 goto cleanup_surface; 222 } 223 224 if (format != dri2_conf->base.NativeVisualID) { 225 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x", 226 format, dri2_conf->base.NativeVisualID); 227 } 228 229 window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width); 230 window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height); 231 } 232 233 dri2_surf->dri_drawable = 234 (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, 235 dri2_conf->dri_double_config, 236 dri2_surf); 237 if (dri2_surf->dri_drawable == NULL) { 238 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); 239 goto cleanup_surface; 240 } 241 242 if (window) { 243 window->common.incRef(&window->common); 244 dri2_surf->window = window; 245 } 246 247 return &dri2_surf->base; 248 249cleanup_surface: 250 free(dri2_surf); 251 252 return NULL; 253} 254 255static _EGLSurface * 256droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 257 _EGLConfig *conf, EGLNativeWindowType window, 258 const EGLint *attrib_list) 259{ 260 return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf, 261 window, attrib_list); 262} 263 264static _EGLSurface * 265droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, 266 _EGLConfig *conf, const EGLint *attrib_list) 267{ 268 return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, 269 NULL, attrib_list); 270} 271 272static EGLBoolean 273droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 274{ 275 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 276 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 277 278 if (!_eglPutSurface(surf)) 279 return EGL_TRUE; 280 281 droid_free_local_buffers(dri2_surf); 282 283 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 284 if (dri2_surf->buffer) 285 droid_window_cancel_buffer(dri2_surf); 286 287 dri2_surf->window->common.decRef(&dri2_surf->window->common); 288 } 289 290 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); 291 292 free(dri2_surf); 293 294 return EGL_TRUE; 295} 296 297static EGLBoolean 298droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 299{ 300 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 301 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 302 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 303 _EGLContext *ctx; 304 305 if (dri2_surf->base.Type != EGL_WINDOW_BIT) 306 return EGL_TRUE; 307 308 if (dri2_drv->glFlush) { 309 ctx = _eglGetCurrentContext(); 310 if (ctx && ctx->DrawSurface == &dri2_surf->base) 311 dri2_drv->glFlush(); 312 } 313 314 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 315 316 if (dri2_surf->buffer) 317 droid_window_enqueue_buffer(dri2_surf); 318 319 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); 320 321 return EGL_TRUE; 322} 323 324static _EGLImage * 325dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx, 326 struct ANativeWindowBuffer *buf) 327{ 328 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 329 struct dri2_egl_image *dri2_img; 330 int name; 331 EGLint format; 332 333 if (ctx != NULL) { 334 /* From the EGL_ANDROID_image_native_buffer spec: 335 * 336 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not 337 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated. 338 */ 339 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for " 340 "EGL_NATIVE_BUFFER_ANDROID, the context must be " 341 "EGL_NO_CONTEXT"); 342 return NULL; 343 } 344 345 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || 346 buf->common.version != sizeof(*buf)) { 347 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 348 return NULL; 349 } 350 351 name = get_native_buffer_name(buf); 352 if (!name) { 353 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 354 return NULL; 355 } 356 357 /* see the table in droid_add_configs_for_visuals */ 358 switch (buf->format) { 359 case HAL_PIXEL_FORMAT_BGRA_8888: 360 format = __DRI_IMAGE_FORMAT_ARGB8888; 361 break; 362 case HAL_PIXEL_FORMAT_RGB_565: 363 format = __DRI_IMAGE_FORMAT_RGB565; 364 break; 365 case HAL_PIXEL_FORMAT_RGBA_8888: 366 format = __DRI_IMAGE_FORMAT_ABGR8888; 367 break; 368 case HAL_PIXEL_FORMAT_RGBX_8888: 369 format = __DRI_IMAGE_FORMAT_XBGR8888; 370 break; 371 case HAL_PIXEL_FORMAT_RGB_888: 372 case HAL_PIXEL_FORMAT_RGBA_5551: 373 case HAL_PIXEL_FORMAT_RGBA_4444: 374 /* unsupported */ 375 default: 376 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", buf->format); 377 return NULL; 378 break; 379 } 380 381 dri2_img = calloc(1, sizeof(*dri2_img)); 382 if (!dri2_img) { 383 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); 384 return NULL; 385 } 386 387 if (!_eglInitImage(&dri2_img->base, disp)) { 388 free(dri2_img); 389 return NULL; 390 } 391 392 dri2_img->dri_image = 393 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 394 buf->width, 395 buf->height, 396 format, 397 name, 398 buf->stride, 399 dri2_img); 400 if (!dri2_img->dri_image) { 401 free(dri2_img); 402 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); 403 return NULL; 404 } 405 406 return &dri2_img->base; 407} 408 409static _EGLImage * 410droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 411 _EGLContext *ctx, EGLenum target, 412 EGLClientBuffer buffer, const EGLint *attr_list) 413{ 414 switch (target) { 415 case EGL_NATIVE_BUFFER_ANDROID: 416 return dri2_create_image_android_native_buffer(disp, ctx, 417 (struct ANativeWindowBuffer *) buffer); 418 default: 419 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); 420 } 421} 422 423static void 424droid_init_driver_functions(_EGLDriver *drv) 425{ 426 drv->API.CreatePbufferSurface = droid_create_pbuffer_surface; 427 drv->API.DestroySurface = droid_destroy_surface; 428 429 drv->API.CreateImageKHR = droid_create_image_khr; 430} 431 432static void 433droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 434{ 435} 436 437static int 438droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf, 439 unsigned int *attachments, int count) 440{ 441 int num_buffers = 0, i; 442 443 /* fill dri2_surf->buffers */ 444 for (i = 0; i < count * 2; i += 2) { 445 __DRIbuffer *buf, *local; 446 447 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers)); 448 buf = &dri2_surf->buffers[num_buffers]; 449 450 switch (attachments[i]) { 451 case __DRI_BUFFER_BACK_LEFT: 452 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 453 buf->attachment = attachments[i]; 454 buf->name = get_native_buffer_name(dri2_surf->buffer); 455 buf->cpp = get_format_bpp(dri2_surf->buffer->format); 456 buf->pitch = dri2_surf->buffer->stride * buf->cpp; 457 buf->flags = 0; 458 459 if (buf->name) 460 num_buffers++; 461 462 break; 463 } 464 /* fall through for pbuffers */ 465 case __DRI_BUFFER_DEPTH: 466 case __DRI_BUFFER_STENCIL: 467 case __DRI_BUFFER_ACCUM: 468 case __DRI_BUFFER_DEPTH_STENCIL: 469 case __DRI_BUFFER_HIZ: 470 local = droid_alloc_local_buffer(dri2_surf, 471 attachments[i], attachments[i + 1]); 472 473 if (local) { 474 *buf = *local; 475 num_buffers++; 476 } 477 break; 478 case __DRI_BUFFER_FRONT_LEFT: 479 case __DRI_BUFFER_FRONT_RIGHT: 480 case __DRI_BUFFER_FAKE_FRONT_LEFT: 481 case __DRI_BUFFER_FAKE_FRONT_RIGHT: 482 case __DRI_BUFFER_BACK_RIGHT: 483 default: 484 /* no front or right buffers */ 485 break; 486 } 487 } 488 489 return num_buffers; 490} 491 492static __DRIbuffer * 493droid_get_buffers_with_format(__DRIdrawable * driDrawable, 494 int *width, int *height, 495 unsigned int *attachments, int count, 496 int *out_count, void *loaderPrivate) 497{ 498 struct dri2_egl_surface *dri2_surf = loaderPrivate; 499 struct dri2_egl_display *dri2_dpy = 500 dri2_egl_display(dri2_surf->base.Resource.Display); 501 int i; 502 503 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 504 /* try to dequeue the next back buffer */ 505 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) 506 return NULL; 507 508 /* free outdated buffers and update the surface size */ 509 if (dri2_surf->base.Width != dri2_surf->buffer->width || 510 dri2_surf->base.Height != dri2_surf->buffer->height) { 511 droid_free_local_buffers(dri2_surf); 512 dri2_surf->base.Width = dri2_surf->buffer->width; 513 dri2_surf->base.Height = dri2_surf->buffer->height; 514 } 515 } 516 517 dri2_surf->buffer_count = 518 droid_get_buffers_parse_attachments(dri2_surf, attachments, count); 519 520 if (width) 521 *width = dri2_surf->base.Width; 522 if (height) 523 *height = dri2_surf->base.Height; 524 525 *out_count = dri2_surf->buffer_count;; 526 527 return dri2_surf->buffers; 528} 529 530static EGLBoolean 531droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy) 532{ 533 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 534 const struct { 535 int format; 536 unsigned int rgba_masks[4]; 537 } visuals[] = { 538 { HAL_PIXEL_FORMAT_RGBA_8888, { 0xff, 0xff00, 0xff0000, 0xff000000 } }, 539 { HAL_PIXEL_FORMAT_RGBX_8888, { 0xff, 0xff00, 0xff0000, 0x0 } }, 540 { HAL_PIXEL_FORMAT_RGB_888, { 0xff, 0xff00, 0xff0000, 0x0 } }, 541 { HAL_PIXEL_FORMAT_RGB_565, { 0xf800, 0x7e0, 0x1f, 0x0 } }, 542 { HAL_PIXEL_FORMAT_BGRA_8888, { 0xff0000, 0xff00, 0xff, 0xff000000 } }, 543 { 0, 0, { 0, 0, 0, 0 } } 544 }; 545 int count, i, j; 546 547 count = 0; 548 for (i = 0; visuals[i].format; i++) { 549 int format_count = 0; 550 551 for (j = 0; dri2_dpy->driver_configs[j]; j++) { 552 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; 553 struct dri2_egl_config *dri2_conf; 554 unsigned int double_buffered = 0; 555 556 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[j], 557 __DRI_ATTRIB_DOUBLE_BUFFER, &double_buffered); 558 559 /* support only double buffered configs */ 560 if (!double_buffered) 561 continue; 562 563 dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[j], 564 count + 1, surface_type, NULL, visuals[i].rgba_masks); 565 if (dri2_conf) { 566 dri2_conf->base.NativeVisualID = visuals[i].format; 567 dri2_conf->base.NativeVisualType = visuals[i].format; 568 count++; 569 format_count++; 570 } 571 } 572 573 if (!format_count) { 574 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x", 575 visuals[i].format); 576 } 577 } 578 579 /* post-process configs */ 580 for (i = 0; i < dpy->Configs->Size; i++) { 581 struct dri2_egl_config *dri2_conf = dri2_egl_config(dpy->Configs->Elements[i]); 582 583 /* there is no front buffer so no OpenGL */ 584 dri2_conf->base.RenderableType &= ~EGL_OPENGL_BIT; 585 dri2_conf->base.Conformant &= ~EGL_OPENGL_BIT; 586 } 587 588 return (count != 0); 589} 590 591static int 592droid_open_device(void) 593{ 594 const hw_module_t *mod; 595 int fd = -1, err; 596 597 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); 598 if (!err) { 599 const gralloc_module_t *gr = (gralloc_module_t *) mod; 600 601 err = -EINVAL; 602 if (gr->perform) 603 err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd); 604 } 605 if (err || fd < 0) { 606 _eglLog(_EGL_WARNING, "fail to get drm fd"); 607 fd = -1; 608 } 609 610 return (fd >= 0) ? dup(fd) : -1; 611} 612 613/* support versions < JellyBean */ 614#ifndef ALOGW 615#define ALOGW LOGW 616#endif 617#ifndef ALOGD 618#define ALOGD LOGD 619#endif 620#ifndef ALOGI 621#define ALOGI LOGI 622#endif 623 624static void 625droid_log(EGLint level, const char *msg) 626{ 627 switch (level) { 628 case _EGL_DEBUG: 629 ALOGD("%s", msg); 630 break; 631 case _EGL_INFO: 632 ALOGI("%s", msg); 633 break; 634 case _EGL_WARNING: 635 ALOGW("%s", msg); 636 break; 637 case _EGL_FATAL: 638 LOG_FATAL("%s", msg); 639 break; 640 default: 641 break; 642 } 643} 644 645static struct dri2_egl_display_vtbl droid_display_vtbl = { 646 .authenticate = NULL, 647 .create_window_surface = droid_create_window_surface, 648 .create_pixmap_surface = dri2_fallback_pixmap_surface, 649 .swap_interval = dri2_fallback_swap_interval, 650 .swap_buffers = droid_swap_buffers, 651 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, 652}; 653 654EGLBoolean 655dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy) 656{ 657 struct dri2_egl_display *dri2_dpy; 658 const char *err; 659 660 _eglSetLogProc(droid_log); 661 662 loader_set_logger(_eglLog); 663 664 dri2_dpy = calloc(1, sizeof(*dri2_dpy)); 665 if (!dri2_dpy) 666 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 667 668 dpy->DriverData = (void *) dri2_dpy; 669 670 dri2_dpy->fd = droid_open_device(); 671 if (dri2_dpy->fd < 0) { 672 err = "DRI2: failed to open device"; 673 goto cleanup_display; 674 } 675 676 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0); 677 if (dri2_dpy->driver_name == NULL) { 678 err = "DRI2: failed to get driver name"; 679 goto cleanup_device; 680 } 681 682 if (!dri2_load_driver(dpy)) { 683 err = "DRI2: failed to load driver"; 684 goto cleanup_driver_name; 685 } 686 687 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; 688 dri2_dpy->dri2_loader_extension.base.version = 3; 689 dri2_dpy->dri2_loader_extension.getBuffers = NULL; 690 dri2_dpy->dri2_loader_extension.flushFrontBuffer = droid_flush_front_buffer; 691 dri2_dpy->dri2_loader_extension.getBuffersWithFormat = 692 droid_get_buffers_with_format; 693 694 dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base; 695 dri2_dpy->extensions[1] = &image_lookup_extension.base; 696 dri2_dpy->extensions[2] = &use_invalidate.base; 697 dri2_dpy->extensions[3] = NULL; 698 699 if (!dri2_create_screen(dpy)) { 700 err = "DRI2: failed to create screen"; 701 goto cleanup_driver; 702 } 703 704 if (!droid_add_configs_for_visuals(drv, dpy)) { 705 err = "DRI2: failed to add configs"; 706 goto cleanup_screen; 707 } 708 709 dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; 710 dpy->Extensions.KHR_image_base = EGL_TRUE; 711 712 /* we're supporting EGL 1.4 */ 713 dpy->VersionMajor = 1; 714 dpy->VersionMinor = 4; 715 716 droid_init_driver_functions(drv); 717 718 /* Fill vtbl last to prevent accidentally calling virtual function during 719 * initialization. 720 */ 721 dri2_dpy->vtbl = &droid_display_vtbl; 722 723 return EGL_TRUE; 724 725cleanup_screen: 726 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 727cleanup_driver: 728 dlclose(dri2_dpy->driver); 729cleanup_driver_name: 730 free(dri2_dpy->driver_name); 731cleanup_device: 732 close(dri2_dpy->fd); 733cleanup_display: 734 free(dri2_dpy); 735 736 return _eglError(EGL_NOT_INITIALIZED, err); 737} 738