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#include <stdbool.h> 35#include <sync/sync.h> 36 37#include "loader.h" 38#include "egl_dri2.h" 39#include "egl_dri2_fallbacks.h" 40#include "platform_android_gralloc_drm.h" 41 42#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1)) 43 44struct droid_yuv_format { 45 /* Lookup keys */ 46 int native; /* HAL_PIXEL_FORMAT_ */ 47 int is_ycrcb; /* 0 if chroma order is {Cb, Cr}, 1 if {Cr, Cb} */ 48 int chroma_step; /* Distance in bytes between subsequent chroma pixels. */ 49 50 /* Result */ 51 int fourcc; /* __DRI_IMAGE_FOURCC_ */ 52}; 53 54/* The following table is used to look up a DRI image FourCC based 55 * on native format and information contained in android_ycbcr struct. */ 56static const struct droid_yuv_format droid_yuv_formats[] = { 57 /* Native format, YCrCb, Chroma step, DRI image FourCC */ 58 { HAL_PIXEL_FORMAT_YCbCr_420_888, 0, 2, __DRI_IMAGE_FOURCC_NV12 }, 59 { HAL_PIXEL_FORMAT_YCbCr_420_888, 0, 1, __DRI_IMAGE_FOURCC_YUV420 }, 60 { HAL_PIXEL_FORMAT_YCbCr_420_888, 1, 1, __DRI_IMAGE_FOURCC_YVU420 }, 61 { HAL_PIXEL_FORMAT_YV12, 1, 1, __DRI_IMAGE_FOURCC_YVU420 }, 62}; 63 64static int 65get_fourcc_yuv(int native, int is_ycrcb, int chroma_step) 66{ 67 int i; 68 69 for (i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) 70 if (droid_yuv_formats[i].native == native && 71 droid_yuv_formats[i].is_ycrcb == is_ycrcb && 72 droid_yuv_formats[i].chroma_step == chroma_step) 73 return droid_yuv_formats[i].fourcc; 74 75 return -1; 76} 77 78static bool 79is_yuv(int native) 80{ 81 int i; 82 83 for (i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) 84 if (droid_yuv_formats[i].native == native) 85 return true; 86 87 return false; 88} 89 90static int 91get_format_bpp(int native) 92{ 93 int bpp; 94 95 switch (native) { 96 case HAL_PIXEL_FORMAT_RGBA_8888: 97 case HAL_PIXEL_FORMAT_RGBX_8888: 98 case HAL_PIXEL_FORMAT_BGRA_8888: 99 bpp = 4; 100 break; 101 case HAL_PIXEL_FORMAT_RGB_565: 102 bpp = 2; 103 break; 104 default: 105 bpp = 0; 106 break; 107 } 108 109 return bpp; 110} 111 112/* createImageFromFds requires fourcc format */ 113static int get_fourcc(int native) 114{ 115 switch (native) { 116 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FOURCC_RGB565; 117 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FOURCC_ARGB8888; 118 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FOURCC_ABGR8888; 119 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FOURCC_XBGR8888; 120 default: 121 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native); 122 } 123 return -1; 124} 125 126static int get_format(int format) 127{ 128 switch (format) { 129 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888; 130 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565; 131 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888; 132 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888; 133 default: 134 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format); 135 } 136 return -1; 137} 138 139static int 140get_native_buffer_fd(struct ANativeWindowBuffer *buf) 141{ 142 native_handle_t *handle = (native_handle_t *)buf->handle; 143 /* 144 * Various gralloc implementations exist, but the dma-buf fd tends 145 * to be first. Access it directly to avoid a dependency on specific 146 * gralloc versions. 147 */ 148 return (handle && handle->numFds) ? handle->data[0] : -1; 149} 150 151static int 152get_native_buffer_name(struct ANativeWindowBuffer *buf) 153{ 154 return gralloc_drm_get_gem_handle(buf->handle); 155} 156 157static EGLBoolean 158droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) 159{ 160 int fence_fd; 161 162 if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer, 163 &fence_fd)) 164 return EGL_FALSE; 165 166 /* If access to the buffer is controlled by a sync fence, then block on the 167 * fence. 168 * 169 * It may be more performant to postpone blocking until there is an 170 * immediate need to write to the buffer. But doing so would require adding 171 * hooks to the DRI2 loader. 172 * 173 * From the ANativeWindow::dequeueBuffer documentation: 174 * 175 * The libsync fence file descriptor returned in the int pointed to by 176 * the fenceFd argument will refer to the fence that must signal 177 * before the dequeued buffer may be written to. A value of -1 178 * indicates that the caller may access the buffer immediately without 179 * waiting on a fence. If a valid file descriptor is returned (i.e. 180 * any value except -1) then the caller is responsible for closing the 181 * file descriptor. 182 */ 183 if (fence_fd >= 0) { 184 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>: 185 * 186 * Waits indefinitely if timeout < 0. 187 */ 188 int timeout = -1; 189 sync_wait(fence_fd, timeout); 190 close(fence_fd); 191 } 192 193 dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common); 194 195 return EGL_TRUE; 196} 197 198static EGLBoolean 199droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf) 200{ 201 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 202 203 /* To avoid blocking other EGL calls, release the display mutex before 204 * we enter droid_window_enqueue_buffer() and re-acquire the mutex upon 205 * return. 206 */ 207 mtx_unlock(&disp->Mutex); 208 209 /* Queue the buffer without a sync fence. This informs the ANativeWindow 210 * that it may access the buffer immediately. 211 * 212 * From ANativeWindow::dequeueBuffer: 213 * 214 * The fenceFd argument specifies a libsync fence file descriptor for 215 * a fence that must signal before the buffer can be accessed. If 216 * the buffer can be accessed immediately then a value of -1 should 217 * be used. The caller must not use the file descriptor after it 218 * is passed to queueBuffer, and the ANativeWindow implementation 219 * is responsible for closing it. 220 */ 221 int fence_fd = -1; 222 dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer, 223 fence_fd); 224 225 dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common); 226 dri2_surf->buffer = NULL; 227 228 mtx_lock(&disp->Mutex); 229 230 if (dri2_surf->dri_image_back) { 231 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back); 232 dri2_surf->dri_image_back = NULL; 233 } 234 235 return EGL_TRUE; 236} 237 238static void 239droid_window_cancel_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf) 240{ 241 /* no cancel buffer? */ 242 droid_window_enqueue_buffer(disp, dri2_surf); 243} 244 245static __DRIbuffer * 246droid_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 247 unsigned int att, unsigned int format) 248{ 249 struct dri2_egl_display *dri2_dpy = 250 dri2_egl_display(dri2_surf->base.Resource.Display); 251 252 if (att >= ARRAY_SIZE(dri2_surf->local_buffers)) 253 return NULL; 254 255 if (!dri2_surf->local_buffers[att]) { 256 dri2_surf->local_buffers[att] = 257 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format, 258 dri2_surf->base.Width, dri2_surf->base.Height); 259 } 260 261 return dri2_surf->local_buffers[att]; 262} 263 264static void 265droid_free_local_buffers(struct dri2_egl_surface *dri2_surf) 266{ 267 struct dri2_egl_display *dri2_dpy = 268 dri2_egl_display(dri2_surf->base.Resource.Display); 269 int i; 270 271 for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) { 272 if (dri2_surf->local_buffers[i]) { 273 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 274 dri2_surf->local_buffers[i]); 275 dri2_surf->local_buffers[i] = NULL; 276 } 277 } 278} 279 280static _EGLSurface * 281droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, 282 _EGLConfig *conf, void *native_window, 283 const EGLint *attrib_list) 284{ 285 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 286 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 287 struct dri2_egl_surface *dri2_surf; 288 struct ANativeWindow *window = native_window; 289 const __DRIconfig *config; 290 291 dri2_surf = calloc(1, sizeof *dri2_surf); 292 if (!dri2_surf) { 293 _eglError(EGL_BAD_ALLOC, "droid_create_surface"); 294 return NULL; 295 } 296 297 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) 298 goto cleanup_surface; 299 300 if (type == EGL_WINDOW_BIT) { 301 int format; 302 303 if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { 304 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 305 goto cleanup_surface; 306 } 307 if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) { 308 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 309 goto cleanup_surface; 310 } 311 312 if (format != dri2_conf->base.NativeVisualID) { 313 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x", 314 format, dri2_conf->base.NativeVisualID); 315 } 316 317 window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width); 318 window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height); 319 } 320 321 config = dri2_get_dri_config(dri2_conf, type, 322 dri2_surf->base.GLColorspace); 323 if (!config) 324 goto cleanup_surface; 325 326 dri2_surf->dri_drawable = 327 dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config, 328 dri2_surf); 329 if (dri2_surf->dri_drawable == NULL) { 330 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); 331 goto cleanup_surface; 332 } 333 334 if (window) { 335 window->common.incRef(&window->common); 336 dri2_surf->window = window; 337 } 338 339 return &dri2_surf->base; 340 341cleanup_surface: 342 free(dri2_surf); 343 344 return NULL; 345} 346 347static _EGLSurface * 348droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 349 _EGLConfig *conf, void *native_window, 350 const EGLint *attrib_list) 351{ 352 return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf, 353 native_window, attrib_list); 354} 355 356static _EGLSurface * 357droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, 358 _EGLConfig *conf, const EGLint *attrib_list) 359{ 360 return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, 361 NULL, attrib_list); 362} 363 364static EGLBoolean 365droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 366{ 367 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 368 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 369 370 droid_free_local_buffers(dri2_surf); 371 372 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 373 if (dri2_surf->buffer) 374 droid_window_cancel_buffer(disp, dri2_surf); 375 376 dri2_surf->window->common.decRef(&dri2_surf->window->common); 377 } 378 379 if (dri2_surf->dri_image_back) { 380 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__); 381 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back); 382 dri2_surf->dri_image_back = NULL; 383 } 384 385 if (dri2_surf->dri_image_front) { 386 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__); 387 dri2_dpy->image->destroyImage(dri2_surf->dri_image_front); 388 dri2_surf->dri_image_front = NULL; 389 } 390 391 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 392 393 free(dri2_surf); 394 395 return EGL_TRUE; 396} 397 398static int 399update_buffers(struct dri2_egl_surface *dri2_surf) 400{ 401 if (dri2_surf->base.Type != EGL_WINDOW_BIT) 402 return 0; 403 404 /* try to dequeue the next back buffer */ 405 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) { 406 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window"); 407 return -1; 408 } 409 410 /* free outdated buffers and update the surface size */ 411 if (dri2_surf->base.Width != dri2_surf->buffer->width || 412 dri2_surf->base.Height != dri2_surf->buffer->height) { 413 droid_free_local_buffers(dri2_surf); 414 dri2_surf->base.Width = dri2_surf->buffer->width; 415 dri2_surf->base.Height = dri2_surf->buffer->height; 416 } 417 418 return 0; 419} 420 421static int 422get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format) 423{ 424 struct dri2_egl_display *dri2_dpy = 425 dri2_egl_display(dri2_surf->base.Resource.Display); 426 427 if (dri2_surf->dri_image_front) 428 return 0; 429 430 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 431 /* According current EGL spec, front buffer rendering 432 * for window surface is not supported now. 433 * and mesa doesn't have the implementation of this case. 434 * Add warning message, but not treat it as error. 435 */ 436 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface"); 437 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) { 438 dri2_surf->dri_image_front = 439 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 440 dri2_surf->base.Width, 441 dri2_surf->base.Height, 442 format, 443 0, 444 dri2_surf); 445 if (!dri2_surf->dri_image_front) { 446 _eglLog(_EGL_WARNING, "dri2_image_front allocation failed"); 447 return -1; 448 } 449 } 450 451 return 0; 452} 453 454static int 455get_back_bo(struct dri2_egl_surface *dri2_surf, unsigned int format) 456{ 457 struct dri2_egl_display *dri2_dpy = 458 dri2_egl_display(dri2_surf->base.Resource.Display); 459 int fourcc, pitch; 460 int offset = 0, fd; 461 462 if (dri2_surf->dri_image_back) 463 return 0; 464 465 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 466 if (!dri2_surf->buffer) { 467 _eglLog(_EGL_WARNING, "Could not get native buffer"); 468 return -1; 469 } 470 471 fd = get_native_buffer_fd(dri2_surf->buffer); 472 if (fd < 0) { 473 _eglLog(_EGL_WARNING, "Could not get native buffer FD"); 474 return -1; 475 } 476 477 fourcc = get_fourcc(dri2_surf->buffer->format); 478 479 pitch = dri2_surf->buffer->stride * 480 get_format_bpp(dri2_surf->buffer->format); 481 482 if (fourcc == -1 || pitch == 0) { 483 _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)", 484 fourcc, pitch); 485 return -1; 486 } 487 488 dri2_surf->dri_image_back = 489 dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, 490 dri2_surf->base.Width, 491 dri2_surf->base.Height, 492 fourcc, 493 &fd, 494 1, 495 &pitch, 496 &offset, 497 dri2_surf); 498 if (!dri2_surf->dri_image_back) { 499 _eglLog(_EGL_WARNING, "failed to create DRI image from FD"); 500 return -1; 501 } 502 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) { 503 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically, 504 * the spec states that they have a back buffer but no front buffer, in 505 * contrast to pixmaps, which have a front buffer but no back buffer. 506 * 507 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate 508 * from the spec, following the precedent of Mesa's EGL X11 platform. The 509 * X11 platform correctly assigns pbuffers to single-buffered configs, but 510 * assigns the pbuffer a front buffer instead of a back buffer. 511 * 512 * Pbuffers in the X11 platform mostly work today, so let's just copy its 513 * behavior instead of trying to fix (and hence potentially breaking) the 514 * world. 515 */ 516 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface"); 517 } 518 519 return 0; 520} 521 522/* Some drivers will pass multiple bits in buffer_mask. 523 * For such case, will go through all the bits, and 524 * will not return error when unsupported buffer is requested, only 525 * return error when the allocation for supported buffer failed. 526 */ 527static int 528droid_image_get_buffers(__DRIdrawable *driDrawable, 529 unsigned int format, 530 uint32_t *stamp, 531 void *loaderPrivate, 532 uint32_t buffer_mask, 533 struct __DRIimageList *images) 534{ 535 struct dri2_egl_surface *dri2_surf = loaderPrivate; 536 537 images->image_mask = 0; 538 images->front = NULL; 539 images->back = NULL; 540 541 if (update_buffers(dri2_surf) < 0) 542 return 0; 543 544 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) { 545 if (get_front_bo(dri2_surf, format) < 0) 546 return 0; 547 548 if (dri2_surf->dri_image_front) { 549 images->front = dri2_surf->dri_image_front; 550 images->image_mask |= __DRI_IMAGE_BUFFER_FRONT; 551 } 552 } 553 554 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) { 555 if (get_back_bo(dri2_surf, format) < 0) 556 return 0; 557 558 if (dri2_surf->dri_image_back) { 559 images->back = dri2_surf->dri_image_back; 560 images->image_mask |= __DRI_IMAGE_BUFFER_BACK; 561 } 562 } 563 564 return 1; 565} 566 567static EGLBoolean 568droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 569{ 570 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 571 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 572 573 if (dri2_surf->base.Type != EGL_WINDOW_BIT) 574 return EGL_TRUE; 575 576 dri2_flush_drawable_for_swapbuffers(disp, draw); 577 578 if (dri2_surf->buffer) 579 droid_window_enqueue_buffer(disp, dri2_surf); 580 581 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); 582 583 return EGL_TRUE; 584} 585 586static _EGLImage * 587droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx, 588 struct ANativeWindowBuffer *buf, int fd) 589{ 590 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 591 struct android_ycbcr ycbcr; 592 size_t offsets[3]; 593 size_t pitches[3]; 594 int is_ycrcb; 595 int fourcc; 596 int ret; 597 598 if (!dri2_dpy->gralloc->lock_ycbcr) { 599 _eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr"); 600 return NULL; 601 } 602 603 memset(&ycbcr, 0, sizeof(ycbcr)); 604 ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle, 605 0, 0, 0, 0, 0, &ycbcr); 606 if (ret) { 607 _eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret); 608 return NULL; 609 } 610 dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle); 611 612 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags 613 * it will return the .y/.cb/.cr pointers based on a NULL pointer, 614 * so they can be interpreted as offsets. */ 615 offsets[0] = (size_t)ycbcr.y; 616 /* We assume here that all the planes are located in one DMA-buf. */ 617 is_ycrcb = (size_t)ycbcr.cr < (size_t)ycbcr.cb; 618 if (is_ycrcb) { 619 offsets[1] = (size_t)ycbcr.cr; 620 offsets[2] = (size_t)ycbcr.cb; 621 } else { 622 offsets[1] = (size_t)ycbcr.cb; 623 offsets[2] = (size_t)ycbcr.cr; 624 } 625 626 /* .ystride is the line length (in bytes) of the Y plane, 627 * .cstride is the line length (in bytes) of any of the remaining 628 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully 629 * planar formats. */ 630 pitches[0] = ycbcr.ystride; 631 pitches[1] = pitches[2] = ycbcr.cstride; 632 633 /* .chroma_step is the byte distance between the same chroma channel 634 * values of subsequent pixels, assumed to be the same for Cb and Cr. */ 635 fourcc = get_fourcc_yuv(buf->format, is_ycrcb, ycbcr.chroma_step); 636 if (fourcc == -1) { 637 _eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, is_ycrcb = %d, chroma_step = %d", 638 buf->format, is_ycrcb, ycbcr.chroma_step); 639 return NULL; 640 } 641 642 if (ycbcr.chroma_step == 2) { 643 /* Semi-planar Y + CbCr or Y + CbCr format. */ 644 const EGLint attr_list_2plane[] = { 645 EGL_WIDTH, buf->width, 646 EGL_HEIGHT, buf->height, 647 EGL_LINUX_DRM_FOURCC_EXT, fourcc, 648 EGL_DMA_BUF_PLANE0_FD_EXT, fd, 649 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0], 650 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0], 651 EGL_DMA_BUF_PLANE1_FD_EXT, fd, 652 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1], 653 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1], 654 EGL_NONE, 0 655 }; 656 657 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane); 658 } else { 659 /* Fully planar Y + Cb + Cr or Y + Cr + Cb format. */ 660 const EGLint attr_list_3plane[] = { 661 EGL_WIDTH, buf->width, 662 EGL_HEIGHT, buf->height, 663 EGL_LINUX_DRM_FOURCC_EXT, fourcc, 664 EGL_DMA_BUF_PLANE0_FD_EXT, fd, 665 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0], 666 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0], 667 EGL_DMA_BUF_PLANE1_FD_EXT, fd, 668 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1], 669 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1], 670 EGL_DMA_BUF_PLANE2_FD_EXT, fd, 671 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2], 672 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2], 673 EGL_NONE, 0 674 }; 675 676 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane); 677 } 678} 679 680static _EGLImage * 681droid_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx, 682 struct ANativeWindowBuffer *buf, int fd) 683{ 684 unsigned int pitch; 685 686 if (is_yuv(buf->format)) 687 return droid_create_image_from_prime_fd_yuv(disp, ctx, buf, fd); 688 689 const int fourcc = get_fourcc(buf->format); 690 if (fourcc == -1) { 691 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 692 return NULL; 693 } 694 695 pitch = buf->stride * get_format_bpp(buf->format); 696 if (pitch == 0) { 697 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 698 return NULL; 699 } 700 701 const EGLint attr_list[] = { 702 EGL_WIDTH, buf->width, 703 EGL_HEIGHT, buf->height, 704 EGL_LINUX_DRM_FOURCC_EXT, fourcc, 705 EGL_DMA_BUF_PLANE0_FD_EXT, fd, 706 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch, 707 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, 708 EGL_NONE, 0 709 }; 710 711 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list); 712} 713 714static _EGLImage * 715droid_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx, 716 struct ANativeWindowBuffer *buf) 717{ 718 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 719 struct dri2_egl_image *dri2_img; 720 int name; 721 int format; 722 723 name = get_native_buffer_name(buf); 724 if (!name) { 725 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 726 return NULL; 727 } 728 729 format = get_format(buf->format); 730 if (format == -1) 731 return NULL; 732 733 dri2_img = calloc(1, sizeof(*dri2_img)); 734 if (!dri2_img) { 735 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); 736 return NULL; 737 } 738 739 if (!_eglInitImage(&dri2_img->base, disp)) { 740 free(dri2_img); 741 return NULL; 742 } 743 744 dri2_img->dri_image = 745 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 746 buf->width, 747 buf->height, 748 format, 749 name, 750 buf->stride, 751 dri2_img); 752 if (!dri2_img->dri_image) { 753 free(dri2_img); 754 _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); 755 return NULL; 756 } 757 758 return &dri2_img->base; 759} 760 761static EGLBoolean 762droid_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 763 EGLint attribute, EGLint *value) 764{ 765 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 766 switch (attribute) { 767 case EGL_WIDTH: 768 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) { 769 dri2_surf->window->query(dri2_surf->window, 770 NATIVE_WINDOW_DEFAULT_WIDTH, value); 771 return EGL_TRUE; 772 } 773 break; 774 case EGL_HEIGHT: 775 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) { 776 dri2_surf->window->query(dri2_surf->window, 777 NATIVE_WINDOW_DEFAULT_HEIGHT, value); 778 return EGL_TRUE; 779 } 780 break; 781 default: 782 break; 783 } 784 return _eglQuerySurface(drv, dpy, surf, attribute, value); 785} 786 787static _EGLImage * 788dri2_create_image_android_native_buffer(_EGLDisplay *disp, 789 _EGLContext *ctx, 790 struct ANativeWindowBuffer *buf) 791{ 792 int fd; 793 794 if (ctx != NULL) { 795 /* From the EGL_ANDROID_image_native_buffer spec: 796 * 797 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not 798 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated. 799 */ 800 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for " 801 "EGL_NATIVE_BUFFER_ANDROID, the context must be " 802 "EGL_NO_CONTEXT"); 803 return NULL; 804 } 805 806 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || 807 buf->common.version != sizeof(*buf)) { 808 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 809 return NULL; 810 } 811 812 fd = get_native_buffer_fd(buf); 813 if (fd >= 0) 814 return droid_create_image_from_prime_fd(disp, ctx, buf, fd); 815 816 return droid_create_image_from_name(disp, ctx, buf); 817} 818 819static _EGLImage * 820droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 821 _EGLContext *ctx, EGLenum target, 822 EGLClientBuffer buffer, const EGLint *attr_list) 823{ 824 switch (target) { 825 case EGL_NATIVE_BUFFER_ANDROID: 826 return dri2_create_image_android_native_buffer(disp, ctx, 827 (struct ANativeWindowBuffer *) buffer); 828 default: 829 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); 830 } 831} 832 833static void 834droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 835{ 836} 837 838static int 839droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf, 840 unsigned int *attachments, int count) 841{ 842 int num_buffers = 0, i; 843 844 /* fill dri2_surf->buffers */ 845 for (i = 0; i < count * 2; i += 2) { 846 __DRIbuffer *buf, *local; 847 848 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers)); 849 buf = &dri2_surf->buffers[num_buffers]; 850 851 switch (attachments[i]) { 852 case __DRI_BUFFER_BACK_LEFT: 853 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 854 buf->attachment = attachments[i]; 855 buf->name = get_native_buffer_name(dri2_surf->buffer); 856 buf->cpp = get_format_bpp(dri2_surf->buffer->format); 857 buf->pitch = dri2_surf->buffer->stride * buf->cpp; 858 buf->flags = 0; 859 860 if (buf->name) 861 num_buffers++; 862 863 break; 864 } 865 /* fall through for pbuffers */ 866 case __DRI_BUFFER_DEPTH: 867 case __DRI_BUFFER_STENCIL: 868 case __DRI_BUFFER_ACCUM: 869 case __DRI_BUFFER_DEPTH_STENCIL: 870 case __DRI_BUFFER_HIZ: 871 local = droid_alloc_local_buffer(dri2_surf, 872 attachments[i], attachments[i + 1]); 873 874 if (local) { 875 *buf = *local; 876 num_buffers++; 877 } 878 break; 879 case __DRI_BUFFER_FRONT_LEFT: 880 case __DRI_BUFFER_FRONT_RIGHT: 881 case __DRI_BUFFER_FAKE_FRONT_LEFT: 882 case __DRI_BUFFER_FAKE_FRONT_RIGHT: 883 case __DRI_BUFFER_BACK_RIGHT: 884 default: 885 /* no front or right buffers */ 886 break; 887 } 888 } 889 890 return num_buffers; 891} 892 893static __DRIbuffer * 894droid_get_buffers_with_format(__DRIdrawable * driDrawable, 895 int *width, int *height, 896 unsigned int *attachments, int count, 897 int *out_count, void *loaderPrivate) 898{ 899 struct dri2_egl_surface *dri2_surf = loaderPrivate; 900 901 if (update_buffers(dri2_surf) < 0) 902 return NULL; 903 904 dri2_surf->buffer_count = 905 droid_get_buffers_parse_attachments(dri2_surf, attachments, count); 906 907 if (width) 908 *width = dri2_surf->base.Width; 909 if (height) 910 *height = dri2_surf->base.Height; 911 912 *out_count = dri2_surf->buffer_count; 913 914 return dri2_surf->buffers; 915} 916 917static EGLBoolean 918droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy) 919{ 920 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 921 static const struct { 922 int format; 923 unsigned int rgba_masks[4]; 924 } visuals[] = { 925 { HAL_PIXEL_FORMAT_RGBA_8888, { 0xff, 0xff00, 0xff0000, 0xff000000 } }, 926 { HAL_PIXEL_FORMAT_RGBX_8888, { 0xff, 0xff00, 0xff0000, 0x0 } }, 927 { HAL_PIXEL_FORMAT_RGB_565, { 0xf800, 0x7e0, 0x1f, 0x0 } }, 928 { HAL_PIXEL_FORMAT_BGRA_8888, { 0xff0000, 0xff00, 0xff, 0xff000000 } }, 929 }; 930 EGLint config_attrs[] = { 931 EGL_NATIVE_VISUAL_ID, 0, 932 EGL_NATIVE_VISUAL_TYPE, 0, 933 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE, 934 EGL_RECORDABLE_ANDROID, EGL_TRUE, 935 EGL_NONE 936 }; 937 unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 }; 938 int count, i, j; 939 940 count = 0; 941 for (i = 0; dri2_dpy->driver_configs[i]; i++) { 942 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; 943 struct dri2_egl_config *dri2_conf; 944 945 for (j = 0; j < ARRAY_SIZE(visuals); j++) { 946 config_attrs[1] = visuals[j].format; 947 config_attrs[3] = visuals[j].format; 948 949 dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[i], 950 count + 1, surface_type, config_attrs, visuals[j].rgba_masks); 951 if (dri2_conf) { 952 count++; 953 format_count[j]++; 954 } 955 } 956 } 957 958 for (i = 0; i < ARRAY_SIZE(format_count); i++) { 959 if (!format_count[i]) { 960 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x", 961 visuals[i].format); 962 } 963 } 964 965 return (count != 0); 966} 967 968static int 969droid_open_device(struct dri2_egl_display *dri2_dpy) 970{ 971 int fd = -1, err = -EINVAL; 972 973 if (dri2_dpy->gralloc->perform) 974 err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc, 975 GRALLOC_MODULE_PERFORM_GET_DRM_FD, 976 &fd); 977 if (err || fd < 0) { 978 _eglLog(_EGL_DEBUG, "fail to get drm fd"); 979 fd = -1; 980 } 981 982 return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1; 983} 984 985#define DRM_RENDER_DEV_NAME "%s/renderD%d" 986 987static int 988droid_probe_device(_EGLDisplay *dpy) 989{ 990 struct dri2_egl_display *dri2_dpy = dpy->DriverData; 991 const int limit = 64; 992 const int base = 128; 993 int fd; 994 int i; 995 996 for (i = 0; i < limit; ++i) { 997 char *card_path; 998 if (asprintf(&card_path, DRM_RENDER_DEV_NAME, DRM_DIR_NAME, base + i) < 0) 999 continue; 1000 1001 fd = loader_open_device(card_path); 1002 free(card_path); 1003 if (fd < 0) 1004 continue; 1005 1006 dri2_dpy->driver_name = loader_get_driver_for_fd(fd); 1007 if (!dri2_dpy->driver_name) { 1008 close(fd); 1009 continue; 1010 } 1011 1012 dri2_dpy->fd = fd; 1013 if (dri2_load_driver(dpy)) 1014 return 0; 1015 1016 close(fd); 1017 dri2_dpy->fd = -1; 1018 free(dri2_dpy->driver_name); 1019 dri2_dpy->driver_name = NULL; 1020 } 1021 1022 return -1; 1023} 1024 1025/* support versions < JellyBean */ 1026#ifndef ALOGW 1027#define ALOGW LOGW 1028#endif 1029#ifndef ALOGD 1030#define ALOGD LOGD 1031#endif 1032#ifndef ALOGI 1033#define ALOGI LOGI 1034#endif 1035 1036static void 1037droid_log(EGLint level, const char *msg) 1038{ 1039 switch (level) { 1040 case _EGL_DEBUG: 1041 ALOGD("%s", msg); 1042 break; 1043 case _EGL_INFO: 1044 ALOGI("%s", msg); 1045 break; 1046 case _EGL_WARNING: 1047 ALOGW("%s", msg); 1048 break; 1049 case _EGL_FATAL: 1050 LOG_FATAL("%s", msg); 1051 break; 1052 default: 1053 break; 1054 } 1055} 1056 1057static struct dri2_egl_display_vtbl droid_display_vtbl = { 1058 .authenticate = NULL, 1059 .create_window_surface = droid_create_window_surface, 1060 .create_pixmap_surface = dri2_fallback_create_pixmap_surface, 1061 .create_pbuffer_surface = droid_create_pbuffer_surface, 1062 .destroy_surface = droid_destroy_surface, 1063 .create_image = droid_create_image_khr, 1064 .swap_interval = dri2_fallback_swap_interval, 1065 .swap_buffers = droid_swap_buffers, 1066 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, 1067 .swap_buffers_region = dri2_fallback_swap_buffers_region, 1068 .post_sub_buffer = dri2_fallback_post_sub_buffer, 1069 .copy_buffers = dri2_fallback_copy_buffers, 1070 .query_buffer_age = dri2_fallback_query_buffer_age, 1071 .query_surface = droid_query_surface, 1072 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, 1073 .get_sync_values = dri2_fallback_get_sync_values, 1074 .get_dri_drawable = dri2_surface_get_dri_drawable, 1075}; 1076 1077static const __DRIdri2LoaderExtension droid_dri2_loader_extension = { 1078 .base = { __DRI_DRI2_LOADER, 3 }, 1079 1080 .getBuffers = NULL, 1081 .flushFrontBuffer = droid_flush_front_buffer, 1082 .getBuffersWithFormat = droid_get_buffers_with_format, 1083}; 1084 1085static const __DRIimageLoaderExtension droid_image_loader_extension = { 1086 .base = { __DRI_IMAGE_LOADER, 1 }, 1087 1088 .getBuffers = droid_image_get_buffers, 1089 .flushFrontBuffer = droid_flush_front_buffer, 1090}; 1091 1092static const __DRIextension *droid_dri2_loader_extensions[] = { 1093 &droid_dri2_loader_extension.base, 1094 &image_lookup_extension.base, 1095 &use_invalidate.base, 1096 NULL, 1097}; 1098 1099static const __DRIextension *droid_image_loader_extensions[] = { 1100 &droid_image_loader_extension.base, 1101 &image_lookup_extension.base, 1102 &use_invalidate.base, 1103 NULL, 1104}; 1105 1106EGLBoolean 1107dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy) 1108{ 1109 struct dri2_egl_display *dri2_dpy; 1110 const char *err; 1111 int ret; 1112 1113 _eglSetLogProc(droid_log); 1114 1115 loader_set_logger(_eglLog); 1116 1117 dri2_dpy = calloc(1, sizeof(*dri2_dpy)); 1118 if (!dri2_dpy) 1119 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 1120 1121 ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, 1122 (const hw_module_t **)&dri2_dpy->gralloc); 1123 if (ret) { 1124 err = "DRI2: failed to get gralloc module"; 1125 goto cleanup_display; 1126 } 1127 1128 dpy->DriverData = (void *) dri2_dpy; 1129 1130 dri2_dpy->fd = droid_open_device(dri2_dpy); 1131 if (dri2_dpy->fd >= 0) { 1132 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); 1133 if (dri2_dpy->driver_name == NULL) { 1134 err = "DRI2: failed to get driver name"; 1135 goto cleanup_device; 1136 } 1137 1138 if (!dri2_load_driver(dpy)) { 1139 err = "DRI2: failed to load driver"; 1140 goto cleanup_driver_name; 1141 } 1142 } else if (droid_probe_device(dpy) < 0) { 1143 err = "DRI2: failed to open device"; 1144 goto cleanup_display; 1145 } 1146 1147 dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; 1148 1149 /* render nodes cannot use Gem names, and thus do not support 1150 * the __DRI_DRI2_LOADER extension */ 1151 if (!dri2_dpy->is_render_node) 1152 dri2_dpy->loader_extensions = droid_dri2_loader_extensions; 1153 else 1154 dri2_dpy->loader_extensions = droid_image_loader_extensions; 1155 1156 if (!dri2_create_screen(dpy)) { 1157 err = "DRI2: failed to create screen"; 1158 goto cleanup_driver; 1159 } 1160 1161 if (!droid_add_configs_for_visuals(drv, dpy)) { 1162 err = "DRI2: failed to add configs"; 1163 goto cleanup_screen; 1164 } 1165 1166 dpy->Extensions.ANDROID_framebuffer_target = EGL_TRUE; 1167 dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; 1168 dpy->Extensions.ANDROID_recordable = EGL_TRUE; 1169 1170 /* Fill vtbl last to prevent accidentally calling virtual function during 1171 * initialization. 1172 */ 1173 dri2_dpy->vtbl = &droid_display_vtbl; 1174 1175 return EGL_TRUE; 1176 1177cleanup_screen: 1178 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 1179cleanup_driver: 1180 dlclose(dri2_dpy->driver); 1181cleanup_driver_name: 1182 free(dri2_dpy->driver_name); 1183cleanup_device: 1184 close(dri2_dpy->fd); 1185cleanup_display: 1186 free(dri2_dpy); 1187 dpy->DriverData = NULL; 1188 1189 return _eglError(EGL_NOT_INITIALIZED, err); 1190} 1191