platform_android.c revision af7abc512c422183a761ce3d687086abe282fa74
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#include <fcntl.h> 33#include <xf86drm.h> 34 35#if ANDROID_VERSION >= 0x402 36#include <sync/sync.h> 37#endif 38 39#include "loader.h" 40#include "egl_dri2.h" 41#include "egl_dri2_fallbacks.h" 42#include "gralloc_drm.h" 43 44#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1)) 45 46static int 47get_format_bpp(int native) 48{ 49 int bpp; 50 51 switch (native) { 52 case HAL_PIXEL_FORMAT_RGBA_8888: 53 case HAL_PIXEL_FORMAT_RGBX_8888: 54 case HAL_PIXEL_FORMAT_BGRA_8888: 55 bpp = 4; 56 break; 57 case HAL_PIXEL_FORMAT_RGB_888: 58 bpp = 3; 59 break; 60 case HAL_PIXEL_FORMAT_RGB_565: 61 bpp = 2; 62 break; 63 case HAL_PIXEL_FORMAT_YV12: 64 bpp = 1; 65 break; 66 default: 67 bpp = 0; 68 break; 69 } 70 71 return bpp; 72} 73 74/* createImageFromFds requires fourcc format */ 75static int get_fourcc(int native) 76{ 77 switch (native) { 78 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FOURCC_RGB565; 79 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FOURCC_ARGB8888; 80 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FOURCC_ABGR8888; 81 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FOURCC_XBGR8888; 82 case HAL_PIXEL_FORMAT_YV12: return __DRI_IMAGE_FOURCC_YVU420; 83 default: 84 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native); 85 } 86 return -1; 87} 88 89static int get_format(int format) 90{ 91 switch (format) { 92 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888; 93 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565; 94 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888; 95 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888; 96 case HAL_PIXEL_FORMAT_RGB_888: 97 /* unsupported */ 98 default: 99 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format); 100 } 101 return -1; 102} 103 104static int 105get_native_buffer_fd(struct ANativeWindowBuffer *buf) 106{ 107 native_handle_t *handle = (native_handle_t *)buf->handle; 108 /* 109 * Various gralloc implementations exist, but the dma-buf fd tends 110 * to be first. Access it directly to avoid a dependency on specific 111 * gralloc versions. 112 */ 113 return (handle && handle->numFds) ? handle->data[0] : -1; 114} 115 116static int 117get_native_buffer_name(struct ANativeWindowBuffer *buf) 118{ 119 return gralloc_drm_get_gem_handle(buf->handle); 120} 121 122static EGLBoolean 123droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) 124{ 125#if ANDROID_VERSION >= 0x0402 126 int fence_fd; 127 128 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer, 129 &fence_fd)) 130 return EGL_FALSE; 131 132 /* If access to the buffer is controlled by a sync fence, then block on the 133 * fence. 134 * 135 * It may be more performant to postpone blocking until there is an 136 * immediate need to write to the buffer. But doing so would require adding 137 * hooks to the DRI2 loader. 138 * 139 * From the ANativeWindow::dequeueBuffer documentation: 140 * 141 * The libsync fence file descriptor returned in the int pointed to by 142 * the fenceFd argument will refer to the fence that must signal 143 * before the dequeued buffer may be written to. A value of -1 144 * indicates that the caller may access the buffer immediately without 145 * waiting on a fence. If a valid file descriptor is returned (i.e. 146 * any value except -1) then the caller is responsible for closing the 147 * file descriptor. 148 */ 149 if (fence_fd >= 0) { 150 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>: 151 * 152 * Waits indefinitely if timeout < 0. 153 */ 154 int timeout = -1; 155 sync_wait(fence_fd, timeout); 156 close(fence_fd); 157 } 158 159 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common); 160#else 161 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer)) 162 return EGL_FALSE; 163 164 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common); 165 dri2_surf->window->lockBuffer(dri2_surf->window, dri2_surf->buffer); 166#endif 167 168 return EGL_TRUE; 169} 170 171static EGLBoolean 172droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf) 173{ 174 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 175 176 /* To avoid blocking other EGL calls, release the display mutex before 177 * we enter droid_window_enqueue_buffer() and re-acquire the mutex upon 178 * return. 179 */ 180 mtx_unlock(&disp->Mutex); 181 182#if ANDROID_VERSION >= 0x0402 183 /* Queue the buffer without a sync fence. This informs the ANativeWindow 184 * that it may access the buffer immediately. 185 * 186 * From ANativeWindow::dequeueBuffer: 187 * 188 * The fenceFd argument specifies a libsync fence file descriptor for 189 * a fence that must signal before the buffer can be accessed. If 190 * the buffer can be accessed immediately then a value of -1 should 191 * be used. The caller must not use the file descriptor after it 192 * is passed to queueBuffer, and the ANativeWindow implementation 193 * is responsible for closing it. 194 */ 195 int fence_fd = -1; 196 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer, 197 fence_fd); 198#else 199 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer); 200#endif 201 202 dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common); 203 dri2_surf->buffer = NULL; 204 205 mtx_lock(&disp->Mutex); 206 207 if (dri2_surf->dri_image) { 208 dri2_dpy->image->destroyImage(dri2_surf->dri_image); 209 dri2_surf->dri_image = NULL; 210 } 211 212 return EGL_TRUE; 213} 214 215static void 216droid_window_cancel_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf) 217{ 218 /* no cancel buffer? */ 219 droid_window_enqueue_buffer(disp, dri2_surf); 220} 221 222static __DRIbuffer * 223droid_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 224 unsigned int att, unsigned int format) 225{ 226 struct dri2_egl_display *dri2_dpy = 227 dri2_egl_display(dri2_surf->base.Resource.Display); 228 229 if (att >= ARRAY_SIZE(dri2_surf->local_buffers)) 230 return NULL; 231 232 if (!dri2_surf->local_buffers[att]) { 233 dri2_surf->local_buffers[att] = 234 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format, 235 dri2_surf->base.Width, dri2_surf->base.Height); 236 } 237 238 return dri2_surf->local_buffers[att]; 239} 240 241static void 242droid_free_local_buffers(struct dri2_egl_surface *dri2_surf) 243{ 244 struct dri2_egl_display *dri2_dpy = 245 dri2_egl_display(dri2_surf->base.Resource.Display); 246 int i; 247 248 for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) { 249 if (dri2_surf->local_buffers[i]) { 250 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 251 dri2_surf->local_buffers[i]); 252 dri2_surf->local_buffers[i] = NULL; 253 } 254 } 255} 256 257static _EGLSurface * 258droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, 259 _EGLConfig *conf, void *native_window, 260 const EGLint *attrib_list) 261{ 262 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 263 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 264 struct dri2_egl_surface *dri2_surf; 265 struct ANativeWindow *window = native_window; 266 const __DRIconfig *config; 267 268 dri2_surf = calloc(1, sizeof *dri2_surf); 269 if (!dri2_surf) { 270 _eglError(EGL_BAD_ALLOC, "droid_create_surface"); 271 return NULL; 272 } 273 274 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) 275 goto cleanup_surface; 276 277 if (type == EGL_WINDOW_BIT) { 278 int format; 279 280 if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { 281 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 282 goto cleanup_surface; 283 } 284 if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) { 285 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 286 goto cleanup_surface; 287 } 288 289 if (format != dri2_conf->base.NativeVisualID) { 290 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x", 291 format, dri2_conf->base.NativeVisualID); 292 } 293 294 window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width); 295 window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height); 296 } 297 298 config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT, 299 dri2_surf->base.GLColorspace); 300 if (!config) 301 goto cleanup_surface; 302 303 dri2_surf->dri_drawable = 304 (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config, 305 dri2_surf); 306 if (dri2_surf->dri_drawable == NULL) { 307 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); 308 goto cleanup_surface; 309 } 310 311 if (window) { 312 window->common.incRef(&window->common); 313 dri2_surf->window = window; 314 } 315 316 return &dri2_surf->base; 317 318cleanup_surface: 319 free(dri2_surf); 320 321 return NULL; 322} 323 324static _EGLSurface * 325droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 326 _EGLConfig *conf, void *native_window, 327 const EGLint *attrib_list) 328{ 329 return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf, 330 native_window, attrib_list); 331} 332 333static _EGLSurface * 334droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, 335 _EGLConfig *conf, const EGLint *attrib_list) 336{ 337 return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, 338 NULL, attrib_list); 339} 340 341static EGLBoolean 342droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 343{ 344 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 345 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 346 347 droid_free_local_buffers(dri2_surf); 348 349 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 350 if (dri2_surf->buffer) 351 droid_window_cancel_buffer(disp, dri2_surf); 352 353 dri2_surf->window->common.decRef(&dri2_surf->window->common); 354 } 355 356 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); 357 358 free(dri2_surf); 359 360 return EGL_TRUE; 361} 362 363static int 364update_buffers(struct dri2_egl_surface *dri2_surf) 365{ 366 if (dri2_surf->base.Type != EGL_WINDOW_BIT) 367 return 0; 368 369 /* try to dequeue the next back buffer */ 370 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) { 371 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window"); 372 return -1; 373 } 374 375 /* free outdated buffers and update the surface size */ 376 if (dri2_surf->base.Width != dri2_surf->buffer->width || 377 dri2_surf->base.Height != dri2_surf->buffer->height) { 378 droid_free_local_buffers(dri2_surf); 379 dri2_surf->base.Width = dri2_surf->buffer->width; 380 dri2_surf->base.Height = dri2_surf->buffer->height; 381 } 382 383 return 0; 384} 385 386static int 387get_back_bo(struct dri2_egl_surface *dri2_surf) 388{ 389 struct dri2_egl_display *dri2_dpy = 390 dri2_egl_display(dri2_surf->base.Resource.Display); 391 int fourcc, pitch; 392 int offset = 0, fd; 393 394 if (dri2_surf->dri_image) 395 return 0; 396 397 if (!dri2_surf->buffer) 398 return -1; 399 400 fd = get_native_buffer_fd(dri2_surf->buffer); 401 if (fd < 0) { 402 _eglLog(_EGL_WARNING, "Could not get native buffer FD"); 403 return -1; 404 } 405 406 fourcc = get_fourcc(dri2_surf->buffer->format); 407 408 pitch = dri2_surf->buffer->stride * 409 get_format_bpp(dri2_surf->buffer->format); 410 411 if (fourcc == -1 || pitch == 0) { 412 _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)", 413 fourcc, pitch); 414 return -1; 415 } 416 417 dri2_surf->dri_image = 418 dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, 419 dri2_surf->base.Width, 420 dri2_surf->base.Height, 421 fourcc, 422 &fd, 423 1, 424 &pitch, 425 &offset, 426 dri2_surf); 427 if (!dri2_surf->dri_image) 428 return -1; 429 430 return 0; 431} 432 433static int 434droid_image_get_buffers(__DRIdrawable *driDrawable, 435 unsigned int format, 436 uint32_t *stamp, 437 void *loaderPrivate, 438 uint32_t buffer_mask, 439 struct __DRIimageList *images) 440{ 441 struct dri2_egl_surface *dri2_surf = loaderPrivate; 442 443 images->image_mask = 0; 444 445 if (update_buffers(dri2_surf) < 0) 446 return 0; 447 448 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) { 449 /* 450 * We don't support front buffers and GLES doesn't require them for 451 * window surfaces, but some DRI drivers will request them anyway. 452 * We just ignore such request as other platforms backends do. 453 */ 454 } 455 456 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) { 457 if (get_back_bo(dri2_surf) < 0) 458 return 0; 459 460 images->back = dri2_surf->dri_image; 461 images->image_mask |= __DRI_IMAGE_BUFFER_BACK; 462 } 463 464 return 1; 465} 466 467static EGLBoolean 468droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 469{ 470 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 471 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 472 473 if (dri2_surf->base.Type != EGL_WINDOW_BIT) 474 return EGL_TRUE; 475 476 dri2_flush_drawable_for_swapbuffers(disp, draw); 477 478 if (dri2_surf->buffer) 479 droid_window_enqueue_buffer(disp, dri2_surf); 480 481 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); 482 483 return EGL_TRUE; 484} 485 486static _EGLImage * 487droid_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx, 488 struct ANativeWindowBuffer *buf, int fd) 489{ 490 unsigned int offsets[3] = { 0, 0, 0 }; 491 unsigned int pitches[3] = { 0, 0, 0 }; 492 493 const int fourcc = get_fourcc(buf->format); 494 if (fourcc == -1) { 495 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 496 return NULL; 497 } 498 499 pitches[0] = buf->stride * get_format_bpp(buf->format); 500 if (pitches[0] == 0) { 501 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 502 return NULL; 503 } 504 505 switch (buf->format) { 506 case HAL_PIXEL_FORMAT_YV12: 507 /* Y plane is assumed to be at offset 0. */ 508 /* Cr plane is located after Y plane */ 509 offsets[1] = offsets[0] + pitches[0] * buf->height; 510 pitches[1] = ALIGN(pitches[0] / 2, 16); 511 /* Cb plane is located after Cr plane */ 512 offsets[2] = offsets[1] + pitches[1] * buf->height / 2; 513 pitches[2] = pitches[1]; 514 515 const EGLint attr_list_yv12[] = { 516 EGL_WIDTH, buf->width, 517 EGL_HEIGHT, buf->height, 518 EGL_LINUX_DRM_FOURCC_EXT, fourcc, 519 EGL_DMA_BUF_PLANE0_FD_EXT, fd, 520 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0], 521 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0], 522 EGL_DMA_BUF_PLANE1_FD_EXT, fd, 523 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1], 524 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1], 525 EGL_DMA_BUF_PLANE2_FD_EXT, fd, 526 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2], 527 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2], 528 EGL_NONE, 0 529 }; 530 531 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_yv12); 532 } 533 534 const EGLint attr_list[] = { 535 EGL_WIDTH, buf->width, 536 EGL_HEIGHT, buf->height, 537 EGL_LINUX_DRM_FOURCC_EXT, fourcc, 538 EGL_DMA_BUF_PLANE0_FD_EXT, fd, 539 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0], 540 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, 541 EGL_NONE, 0 542 }; 543 544 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list); 545} 546 547static _EGLImage * 548droid_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx, 549 struct ANativeWindowBuffer *buf) 550{ 551 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 552 struct dri2_egl_image *dri2_img; 553 int name; 554 int format; 555 556 name = get_native_buffer_name(buf); 557 if (!name) { 558 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 559 return NULL; 560 } 561 562 format = get_format(buf->format); 563 if (format == -1) 564 return NULL; 565 566 dri2_img = calloc(1, sizeof(*dri2_img)); 567 if (!dri2_img) { 568 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); 569 return NULL; 570 } 571 572 if (!_eglInitImage(&dri2_img->base, disp)) { 573 free(dri2_img); 574 return NULL; 575 } 576 577 dri2_img->dri_image = 578 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 579 buf->width, 580 buf->height, 581 format, 582 name, 583 buf->stride, 584 dri2_img); 585 if (!dri2_img->dri_image) { 586 free(dri2_img); 587 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); 588 return NULL; 589 } 590 591 return &dri2_img->base; 592} 593 594static EGLBoolean 595droid_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 596 EGLint attribute, EGLint *value) 597{ 598 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 599 switch (attribute) { 600 case EGL_WIDTH: 601 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) { 602 dri2_surf->window->query(dri2_surf->window, 603 NATIVE_WINDOW_DEFAULT_WIDTH, value); 604 return EGL_TRUE; 605 } 606 break; 607 case EGL_HEIGHT: 608 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) { 609 dri2_surf->window->query(dri2_surf->window, 610 NATIVE_WINDOW_DEFAULT_HEIGHT, value); 611 return EGL_TRUE; 612 } 613 break; 614 default: 615 break; 616 } 617 return _eglQuerySurface(drv, dpy, surf, attribute, value); 618} 619 620static _EGLImage * 621dri2_create_image_android_native_buffer(_EGLDisplay *disp, 622 _EGLContext *ctx, 623 struct ANativeWindowBuffer *buf) 624{ 625 int fd; 626 627 if (ctx != NULL) { 628 /* From the EGL_ANDROID_image_native_buffer spec: 629 * 630 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not 631 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated. 632 */ 633 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for " 634 "EGL_NATIVE_BUFFER_ANDROID, the context must be " 635 "EGL_NO_CONTEXT"); 636 return NULL; 637 } 638 639 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || 640 buf->common.version != sizeof(*buf)) { 641 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 642 return NULL; 643 } 644 645 fd = get_native_buffer_fd(buf); 646 if (fd >= 0) 647 return droid_create_image_from_prime_fd(disp, ctx, buf, fd); 648 649 return droid_create_image_from_name(disp, ctx, buf); 650} 651 652static _EGLImage * 653droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 654 _EGLContext *ctx, EGLenum target, 655 EGLClientBuffer buffer, const EGLint *attr_list) 656{ 657 switch (target) { 658 case EGL_NATIVE_BUFFER_ANDROID: 659 return dri2_create_image_android_native_buffer(disp, ctx, 660 (struct ANativeWindowBuffer *) buffer); 661 default: 662 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); 663 } 664} 665 666static void 667droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 668{ 669} 670 671static int 672droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf, 673 unsigned int *attachments, int count) 674{ 675 int num_buffers = 0, i; 676 677 /* fill dri2_surf->buffers */ 678 for (i = 0; i < count * 2; i += 2) { 679 __DRIbuffer *buf, *local; 680 681 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers)); 682 buf = &dri2_surf->buffers[num_buffers]; 683 684 switch (attachments[i]) { 685 case __DRI_BUFFER_BACK_LEFT: 686 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 687 buf->attachment = attachments[i]; 688 buf->name = get_native_buffer_name(dri2_surf->buffer); 689 buf->cpp = get_format_bpp(dri2_surf->buffer->format); 690 buf->pitch = dri2_surf->buffer->stride * buf->cpp; 691 buf->flags = 0; 692 693 if (buf->name) 694 num_buffers++; 695 696 break; 697 } 698 /* fall through for pbuffers */ 699 case __DRI_BUFFER_DEPTH: 700 case __DRI_BUFFER_STENCIL: 701 case __DRI_BUFFER_ACCUM: 702 case __DRI_BUFFER_DEPTH_STENCIL: 703 case __DRI_BUFFER_HIZ: 704 local = droid_alloc_local_buffer(dri2_surf, 705 attachments[i], attachments[i + 1]); 706 707 if (local) { 708 *buf = *local; 709 num_buffers++; 710 } 711 break; 712 case __DRI_BUFFER_FRONT_LEFT: 713 case __DRI_BUFFER_FRONT_RIGHT: 714 case __DRI_BUFFER_FAKE_FRONT_LEFT: 715 case __DRI_BUFFER_FAKE_FRONT_RIGHT: 716 case __DRI_BUFFER_BACK_RIGHT: 717 default: 718 /* no front or right buffers */ 719 break; 720 } 721 } 722 723 return num_buffers; 724} 725 726static __DRIbuffer * 727droid_get_buffers_with_format(__DRIdrawable * driDrawable, 728 int *width, int *height, 729 unsigned int *attachments, int count, 730 int *out_count, void *loaderPrivate) 731{ 732 struct dri2_egl_surface *dri2_surf = loaderPrivate; 733 734 if (update_buffers(dri2_surf) < 0) 735 return NULL; 736 737 dri2_surf->buffer_count = 738 droid_get_buffers_parse_attachments(dri2_surf, attachments, count); 739 740 if (width) 741 *width = dri2_surf->base.Width; 742 if (height) 743 *height = dri2_surf->base.Height; 744 745 *out_count = dri2_surf->buffer_count; 746 747 return dri2_surf->buffers; 748} 749 750static EGLBoolean 751droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy) 752{ 753 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 754 static const struct { 755 int format; 756 unsigned int rgba_masks[4]; 757 } visuals[] = { 758 { HAL_PIXEL_FORMAT_RGBA_8888, { 0xff, 0xff00, 0xff0000, 0xff000000 } }, 759 { HAL_PIXEL_FORMAT_RGBX_8888, { 0xff, 0xff00, 0xff0000, 0x0 } }, 760 { HAL_PIXEL_FORMAT_RGB_888, { 0xff, 0xff00, 0xff0000, 0x0 } }, 761 { HAL_PIXEL_FORMAT_RGB_565, { 0xf800, 0x7e0, 0x1f, 0x0 } }, 762 { HAL_PIXEL_FORMAT_BGRA_8888, { 0xff0000, 0xff00, 0xff, 0xff000000 } }, 763 }; 764 EGLint config_attrs[] = { 765 EGL_NATIVE_VISUAL_ID, 0, 766 EGL_NATIVE_VISUAL_TYPE, 0, 767 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE, 768 EGL_RECORDABLE_ANDROID, EGL_TRUE, 769 EGL_MAX_PBUFFER_WIDTH, _EGL_MAX_PBUFFER_WIDTH, 770 EGL_MAX_PBUFFER_HEIGHT, _EGL_MAX_PBUFFER_HEIGHT, 771 EGL_NONE 772 }; 773 unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 }; 774 int count, i, j; 775 776 count = 0; 777 for (i = 0; dri2_dpy->driver_configs[i]; i++) { 778 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; 779 struct dri2_egl_config *dri2_conf; 780 unsigned int double_buffered = 0; 781 782 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], 783 __DRI_ATTRIB_DOUBLE_BUFFER, &double_buffered); 784 785 /* support only double buffered configs */ 786 if (!double_buffered) 787 continue; 788 789 for (j = 0; j < ARRAY_SIZE(visuals); j++) { 790 config_attrs[1] = visuals[j].format; 791 config_attrs[3] = visuals[j].format; 792 793 dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[i], 794 count + 1, surface_type, config_attrs, visuals[j].rgba_masks); 795 if (dri2_conf) { 796 count++; 797 format_count[j]++; 798 } 799 } 800 } 801 802 for (i = 0; i < ARRAY_SIZE(format_count); i++) { 803 if (!format_count[i]) { 804 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x", 805 visuals[i].format); 806 } 807 } 808 809 return (count != 0); 810} 811 812static int 813droid_open_device(void) 814{ 815 const hw_module_t *mod; 816 int fd = -1, err; 817 818 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); 819 if (!err) { 820 const gralloc_module_t *gr = (gralloc_module_t *) mod; 821 822 err = -EINVAL; 823 if (gr->perform) 824 err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd); 825 } 826 if (err || fd < 0) { 827 _eglLog(_EGL_WARNING, "fail to get drm fd"); 828 fd = -1; 829 } 830 831 return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1; 832} 833 834/* support versions < JellyBean */ 835#ifndef ALOGW 836#define ALOGW LOGW 837#endif 838#ifndef ALOGD 839#define ALOGD LOGD 840#endif 841#ifndef ALOGI 842#define ALOGI LOGI 843#endif 844 845static void 846droid_log(EGLint level, const char *msg) 847{ 848 switch (level) { 849 case _EGL_DEBUG: 850 ALOGD("%s", msg); 851 break; 852 case _EGL_INFO: 853 ALOGI("%s", msg); 854 break; 855 case _EGL_WARNING: 856 ALOGW("%s", msg); 857 break; 858 case _EGL_FATAL: 859 LOG_FATAL("%s", msg); 860 break; 861 default: 862 break; 863 } 864} 865 866static struct dri2_egl_display_vtbl droid_display_vtbl = { 867 .authenticate = NULL, 868 .create_window_surface = droid_create_window_surface, 869 .create_pixmap_surface = dri2_fallback_create_pixmap_surface, 870 .create_pbuffer_surface = droid_create_pbuffer_surface, 871 .destroy_surface = droid_destroy_surface, 872 .create_image = droid_create_image_khr, 873 .swap_interval = dri2_fallback_swap_interval, 874 .swap_buffers = droid_swap_buffers, 875 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, 876 .swap_buffers_region = dri2_fallback_swap_buffers_region, 877 .post_sub_buffer = dri2_fallback_post_sub_buffer, 878 .copy_buffers = dri2_fallback_copy_buffers, 879 .query_buffer_age = dri2_fallback_query_buffer_age, 880 .query_surface = droid_query_surface, 881 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, 882 .get_sync_values = dri2_fallback_get_sync_values, 883 .get_dri_drawable = dri2_surface_get_dri_drawable, 884}; 885 886static const __DRIdri2LoaderExtension droid_dri2_loader_extension = { 887 .base = { __DRI_DRI2_LOADER, 3 }, 888 889 .getBuffers = NULL, 890 .flushFrontBuffer = droid_flush_front_buffer, 891 .getBuffersWithFormat = droid_get_buffers_with_format, 892}; 893 894static const __DRIimageLoaderExtension droid_image_loader_extension = { 895 .base = { __DRI_IMAGE_LOADER, 1 }, 896 897 .getBuffers = droid_image_get_buffers, 898 .flushFrontBuffer = droid_flush_front_buffer, 899}; 900 901static const __DRIextension *droid_dri2_loader_extensions[] = { 902 &droid_dri2_loader_extension.base, 903 &image_lookup_extension.base, 904 &use_invalidate.base, 905 NULL, 906}; 907 908static const __DRIextension *droid_image_loader_extensions[] = { 909 &droid_image_loader_extension.base, 910 &image_lookup_extension.base, 911 &use_invalidate.base, 912 NULL, 913}; 914 915EGLBoolean 916dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy) 917{ 918 struct dri2_egl_display *dri2_dpy; 919 const char *err; 920 921 _eglSetLogProc(droid_log); 922 923 loader_set_logger(_eglLog); 924 925 dri2_dpy = calloc(1, sizeof(*dri2_dpy)); 926 if (!dri2_dpy) 927 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 928 929 dpy->DriverData = (void *) dri2_dpy; 930 931 dri2_dpy->fd = droid_open_device(); 932 if (dri2_dpy->fd < 0) { 933 err = "DRI2: failed to open device"; 934 goto cleanup_display; 935 } 936 937 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); 938 if (dri2_dpy->driver_name == NULL) { 939 err = "DRI2: failed to get driver name"; 940 goto cleanup_device; 941 } 942 943 if (!dri2_load_driver(dpy)) { 944 err = "DRI2: failed to load driver"; 945 goto cleanup_driver_name; 946 } 947 948 dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; 949 950 /* render nodes cannot use Gem names, and thus do not support 951 * the __DRI_DRI2_LOADER extension */ 952 if (!dri2_dpy->is_render_node) 953 dri2_dpy->loader_extensions = droid_dri2_loader_extensions; 954 else 955 dri2_dpy->loader_extensions = droid_image_loader_extensions; 956 957 if (!dri2_create_screen(dpy)) { 958 err = "DRI2: failed to create screen"; 959 goto cleanup_driver; 960 } 961 962 if (!droid_add_configs_for_visuals(drv, dpy)) { 963 err = "DRI2: failed to add configs"; 964 goto cleanup_screen; 965 } 966 967 dpy->Extensions.ANDROID_framebuffer_target = EGL_TRUE; 968 dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; 969 dpy->Extensions.ANDROID_recordable = EGL_TRUE; 970 971 /* Fill vtbl last to prevent accidentally calling virtual function during 972 * initialization. 973 */ 974 dri2_dpy->vtbl = &droid_display_vtbl; 975 976 return EGL_TRUE; 977 978cleanup_screen: 979 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 980cleanup_driver: 981 dlclose(dri2_dpy->driver); 982cleanup_driver_name: 983 free(dri2_dpy->driver_name); 984cleanup_device: 985 close(dri2_dpy->fd); 986cleanup_display: 987 free(dri2_dpy); 988 dpy->DriverData = NULL; 989 990 return _eglError(EGL_NOT_INITIALIZED, err); 991} 992