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 <cutils/properties.h> 31#include <errno.h> 32#include <dirent.h> 33#include <dlfcn.h> 34#include <fcntl.h> 35#include <xf86drm.h> 36#include <stdbool.h> 37#include <stdio.h> 38#include <sync/sync.h> 39#include <sys/types.h> 40#include <drm-uapi/drm_fourcc.h> 41 42#include "util/compiler.h" 43#include "util/os_file.h" 44 45#include "loader.h" 46#include "egl_dri2.h" 47#include "platform_android.h" 48 49#ifdef HAVE_DRM_GRALLOC 50#include <gralloc_drm_handle.h> 51#include "gralloc_drm.h" 52#endif /* HAVE_DRM_GRALLOC */ 53 54#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1)) 55 56enum chroma_order { 57 YCbCr, 58 YCrCb, 59}; 60 61struct droid_yuv_format { 62 /* Lookup keys */ 63 int native; /* HAL_PIXEL_FORMAT_ */ 64 enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */ 65 int chroma_step; /* Distance in bytes between subsequent chroma pixels. */ 66 67 /* Result */ 68 int fourcc; /* DRM_FORMAT_ */ 69}; 70 71/* The following table is used to look up a DRI image FourCC based 72 * on native format and information contained in android_ycbcr struct. */ 73static const struct droid_yuv_format droid_yuv_formats[] = { 74 /* Native format, YCrCb, Chroma step, DRI image FourCC */ 75 { HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12 }, 76 { HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420 }, 77 { HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420 }, 78 { HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420 }, 79 /* HACK: See droid_create_image_from_prime_fds() and 80 * https://issuetracker.google.com/32077885. */ 81 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12 }, 82 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420 }, 83 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420 }, 84 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV }, 85 { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888 }, 86}; 87 88static int 89get_fourcc_yuv(int native, enum chroma_order chroma_order, int chroma_step) 90{ 91 for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) 92 if (droid_yuv_formats[i].native == native && 93 droid_yuv_formats[i].chroma_order == chroma_order && 94 droid_yuv_formats[i].chroma_step == chroma_step) 95 return droid_yuv_formats[i].fourcc; 96 97 return -1; 98} 99 100static bool 101is_yuv(int native) 102{ 103 for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) 104 if (droid_yuv_formats[i].native == native) 105 return true; 106 107 return false; 108} 109 110static int 111get_format_bpp(int native) 112{ 113 int bpp; 114 115 switch (native) { 116 case HAL_PIXEL_FORMAT_RGBA_FP16: 117 bpp = 8; 118 break; 119 case HAL_PIXEL_FORMAT_RGBA_8888: 120 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 121 /* 122 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack. 123 * TODO: Remove this once https://issuetracker.google.com/32077885 is fixed. 124 */ 125 case HAL_PIXEL_FORMAT_RGBX_8888: 126 case HAL_PIXEL_FORMAT_BGRA_8888: 127 case HAL_PIXEL_FORMAT_RGBA_1010102: 128 bpp = 4; 129 break; 130 case HAL_PIXEL_FORMAT_RGB_565: 131 bpp = 2; 132 break; 133 default: 134 bpp = 0; 135 break; 136 } 137 138 return bpp; 139} 140 141/* createImageFromFds requires fourcc format */ 142static int get_fourcc(int native) 143{ 144 switch (native) { 145 case HAL_PIXEL_FORMAT_RGB_565: return DRM_FORMAT_RGB565; 146 case HAL_PIXEL_FORMAT_BGRA_8888: return DRM_FORMAT_ARGB8888; 147 case HAL_PIXEL_FORMAT_RGBA_8888: return DRM_FORMAT_ABGR8888; 148 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 149 /* 150 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack. 151 * TODO: Remove this once https://issuetracker.google.com/32077885 is fixed. 152 */ 153 case HAL_PIXEL_FORMAT_RGBX_8888: return DRM_FORMAT_XBGR8888; 154 case HAL_PIXEL_FORMAT_RGBA_FP16: return DRM_FORMAT_ABGR16161616F; 155 case HAL_PIXEL_FORMAT_RGBA_1010102: return DRM_FORMAT_ABGR2101010; 156 default: 157 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native); 158 } 159 return -1; 160} 161 162/* returns # of fds, and by reference the actual fds */ 163static unsigned 164get_native_buffer_fds(struct ANativeWindowBuffer *buf, int fds[3]) 165{ 166 native_handle_t *handle = (native_handle_t *)buf->handle; 167 168 if (!handle) 169 return 0; 170 171 /* 172 * Various gralloc implementations exist, but the dma-buf fd tends 173 * to be first. Access it directly to avoid a dependency on specific 174 * gralloc versions. 175 */ 176 for (int i = 0; i < handle->numFds; i++) 177 fds[i] = handle->data[i]; 178 179 return handle->numFds; 180} 181 182#ifdef HAVE_DRM_GRALLOC 183static int 184get_native_buffer_name(struct ANativeWindowBuffer *buf) 185{ 186 return gralloc_drm_get_gem_handle(buf->handle); 187} 188#endif /* HAVE_DRM_GRALLOC */ 189 190static int 191get_yuv_buffer_info(struct dri2_egl_display *dri2_dpy, 192 struct ANativeWindowBuffer *buf, 193 struct buffer_info *out_buf_info) 194{ 195 struct android_ycbcr ycbcr; 196 enum chroma_order chroma_order; 197 int drm_fourcc = 0; 198 int num_fds = 0; 199 int fds[3]; 200 int ret; 201 202 num_fds = get_native_buffer_fds(buf, fds); 203 if (num_fds == 0) 204 return -EINVAL; 205 206 if (!dri2_dpy->gralloc->lock_ycbcr) { 207 _eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr"); 208 return -EINVAL; 209 } 210 211 memset(&ycbcr, 0, sizeof(ycbcr)); 212 ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle, 213 0, 0, 0, 0, 0, &ycbcr); 214 if (ret) { 215 /* HACK: See native_window_buffer_get_buffer_info() and 216 * https://issuetracker.google.com/32077885.*/ 217 if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) 218 return -EAGAIN; 219 220 _eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret); 221 return -EINVAL; 222 } 223 dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle); 224 225 chroma_order = ((size_t)ycbcr.cr < (size_t)ycbcr.cb) ? YCrCb : YCbCr; 226 227 /* .chroma_step is the byte distance between the same chroma channel 228 * values of subsequent pixels, assumed to be the same for Cb and Cr. */ 229 drm_fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step); 230 if (drm_fourcc == -1) { 231 _eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = %d", 232 buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", ycbcr.chroma_step); 233 return -EINVAL; 234 } 235 236 *out_buf_info = (struct buffer_info){ 237 .width = buf->width, 238 .height = buf->height, 239 .drm_fourcc = drm_fourcc, 240 .num_planes = ycbcr.chroma_step == 2 ? 2 : 3, 241 .fds = { -1, -1, -1, -1 }, 242 .modifier = DRM_FORMAT_MOD_INVALID, 243 .yuv_color_space = EGL_ITU_REC601_EXT, 244 .sample_range = EGL_YUV_NARROW_RANGE_EXT, 245 .horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT, 246 .vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT, 247 }; 248 249 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags 250 * it will return the .y/.cb/.cr pointers based on a NULL pointer, 251 * so they can be interpreted as offsets. */ 252 out_buf_info->offsets[0] = (size_t)ycbcr.y; 253 /* We assume here that all the planes are located in one DMA-buf. */ 254 if (chroma_order == YCrCb) { 255 out_buf_info->offsets[1] = (size_t)ycbcr.cr; 256 out_buf_info->offsets[2] = (size_t)ycbcr.cb; 257 } else { 258 out_buf_info->offsets[1] = (size_t)ycbcr.cb; 259 out_buf_info->offsets[2] = (size_t)ycbcr.cr; 260 } 261 262 /* .ystride is the line length (in bytes) of the Y plane, 263 * .cstride is the line length (in bytes) of any of the remaining 264 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully 265 * planar formats. */ 266 out_buf_info->pitches[0] = ycbcr.ystride; 267 out_buf_info->pitches[1] = out_buf_info->pitches[2] = ycbcr.cstride; 268 269 /* 270 * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that 271 * the single-fd case cannot happen. So handle eithe single 272 * fd or fd-per-plane case: 273 */ 274 if (num_fds == 1) { 275 out_buf_info->fds[1] = out_buf_info->fds[0] = fds[0]; 276 if (out_buf_info->num_planes == 3) 277 out_buf_info->fds[2] = fds[0]; 278 } else { 279 assert(num_fds == out_buf_info->num_planes); 280 out_buf_info->fds[0] = fds[0]; 281 out_buf_info->fds[1] = fds[1]; 282 out_buf_info->fds[2] = fds[2]; 283 } 284 285 return 0; 286} 287 288static int 289native_window_buffer_get_buffer_info(struct dri2_egl_display *dri2_dpy, 290 struct ANativeWindowBuffer *buf, 291 struct buffer_info *out_buf_info) 292{ 293 int num_planes = 0; 294 int drm_fourcc = 0; 295 int pitch = 0; 296 int fds[3]; 297 298 if (is_yuv(buf->format)) { 299 int ret = get_yuv_buffer_info(dri2_dpy, buf, out_buf_info); 300 /* 301 * HACK: https://issuetracker.google.com/32077885 302 * There is no API available to properly query the IMPLEMENTATION_DEFINED 303 * format. As a workaround we rely here on gralloc allocating either 304 * an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized 305 * by lock_ycbcr failing. 306 */ 307 if (ret != -EAGAIN) 308 return ret; 309 } 310 311 /* 312 * Non-YUV formats could *also* have multiple planes, such as ancillary 313 * color compression state buffer, but the rest of the code isn't ready 314 * yet to deal with modifiers: 315 */ 316 num_planes = get_native_buffer_fds(buf, fds); 317 if (num_planes == 0) 318 return -EINVAL; 319 320 assert(num_planes == 1); 321 322 drm_fourcc = get_fourcc(buf->format); 323 if (drm_fourcc == -1) { 324 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 325 return -EINVAL; 326 } 327 328 pitch = buf->stride * get_format_bpp(buf->format); 329 if (pitch == 0) { 330 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 331 return -EINVAL; 332 } 333 334 *out_buf_info = (struct buffer_info){ 335 .width = buf->width, 336 .height = buf->height, 337 .drm_fourcc = drm_fourcc, 338 .num_planes = num_planes, 339 .fds = { fds[0], -1, -1, -1 }, 340 .modifier = DRM_FORMAT_MOD_INVALID, 341 .offsets = { 0, 0, 0, 0 }, 342 .pitches = { pitch, 0, 0, 0 }, 343 .yuv_color_space = EGL_ITU_REC601_EXT, 344 .sample_range = EGL_YUV_NARROW_RANGE_EXT, 345 .horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT, 346 .vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT, 347 }; 348 349 return 0; 350} 351 352/* More recent CrOS gralloc has a perform op that fills out the struct below 353 * with canonical information about the buffer and its modifier, planes, 354 * offsets and strides. If we have this, we can skip straight to 355 * createImageFromDmaBufs2() and avoid all the guessing and recalculations. 356 * This also gives us the modifier and plane offsets/strides for multiplanar 357 * compressed buffers (eg Intel CCS buffers) in order to make that work in Android. 358 */ 359 360static const char cros_gralloc_module_name[] = "CrOS Gralloc"; 361 362#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4 363#define CROS_GRALLOC_DRM_GET_USAGE 5 364#define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1 365 366struct cros_gralloc0_buffer_info { 367 uint32_t drm_fourcc; 368 int num_fds; 369 int fds[4]; 370 uint64_t modifier; 371 int offset[4]; 372 int stride[4]; 373}; 374 375static int 376cros_get_buffer_info(struct dri2_egl_display *dri2_dpy, 377 struct ANativeWindowBuffer *buf, 378 struct buffer_info *out_buf_info) 379{ 380 struct cros_gralloc0_buffer_info info; 381 382 if (strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) == 0 && 383 dri2_dpy->gralloc->perform && 384 dri2_dpy->gralloc->perform(dri2_dpy->gralloc, 385 CROS_GRALLOC_DRM_GET_BUFFER_INFO, 386 buf->handle, &info) == 0) { 387 *out_buf_info = (struct buffer_info){ 388 .width = buf->width, 389 .height = buf->height, 390 .drm_fourcc = info.drm_fourcc, 391 .num_planes = info.num_fds, 392 .fds = { -1, -1, -1, -1 }, 393 .modifier = info.modifier, 394 .yuv_color_space = EGL_ITU_REC601_EXT, 395 .sample_range = EGL_YUV_NARROW_RANGE_EXT, 396 .horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT, 397 .vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT, 398 }; 399 for (int i = 0; i < out_buf_info->num_planes; i++) { 400 out_buf_info->fds[i] = info.fds[i]; 401 out_buf_info->offsets[i] = info.offset[i]; 402 out_buf_info->pitches[i] = info.stride[i]; 403 } 404 405 return 0; 406 } 407 408 return -EINVAL; 409} 410 411static __DRIimage * 412droid_create_image_from_buffer_info(struct dri2_egl_display *dri2_dpy, 413 struct buffer_info *buf_info, 414 void *priv) 415{ 416 unsigned error; 417 418 if (dri2_dpy->image->base.version >= 15 && 419 dri2_dpy->image->createImageFromDmaBufs2 != NULL) { 420 return dri2_dpy->image->createImageFromDmaBufs2( 421 dri2_dpy->dri_screen, buf_info->width, buf_info->height, 422 buf_info->drm_fourcc, buf_info->modifier, buf_info->fds, 423 buf_info->num_planes, buf_info->pitches, buf_info->offsets, 424 buf_info->yuv_color_space, buf_info->sample_range, 425 buf_info->horizontal_siting, buf_info->vertical_siting, &error, 426 priv); 427 } 428 429 return dri2_dpy->image->createImageFromDmaBufs( 430 dri2_dpy->dri_screen, buf_info->width, buf_info->height, 431 buf_info->drm_fourcc, buf_info->fds, buf_info->num_planes, 432 buf_info->pitches, buf_info->offsets, buf_info->yuv_color_space, 433 buf_info->sample_range, buf_info->horizontal_siting, 434 buf_info->vertical_siting, &error, priv); 435} 436 437static __DRIimage * 438droid_create_image_from_native_buffer(_EGLDisplay *disp, 439 struct ANativeWindowBuffer *buf, 440 void *priv) 441{ 442 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 443 struct buffer_info buf_info; 444 __DRIimage *img = NULL; 445 446 /* If dri driver is gallium virgl, real modifier info queried back from 447 * CrOS info (and potentially mapper metadata if integrated later) cannot 448 * get resolved and the buffer import will fail. Thus the fallback behavior 449 * is preserved down to native_window_buffer_get_buffer_info() so that the 450 * buffer can be imported without modifier info as a last resort. 451 */ 452 if (!img && !mapper_metadata_get_buffer_info(buf, &buf_info)) 453 img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv); 454 455 if (!img && !cros_get_buffer_info(dri2_dpy, buf, &buf_info)) 456 img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv); 457 458 if (!img && !native_window_buffer_get_buffer_info(dri2_dpy, buf, &buf_info)) 459 img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv); 460 461 return img; 462} 463 464static EGLBoolean 465droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) 466{ 467 int fence_fd; 468 469 if (ANativeWindow_dequeueBuffer(dri2_surf->window, &dri2_surf->buffer, 470 &fence_fd)) 471 return EGL_FALSE; 472 473 /* If access to the buffer is controlled by a sync fence, then block on the 474 * fence. 475 * 476 * It may be more performant to postpone blocking until there is an 477 * immediate need to write to the buffer. But doing so would require adding 478 * hooks to the DRI2 loader. 479 * 480 * From the ANativeWindow_dequeueBuffer documentation: 481 * 482 * The libsync fence file descriptor returned in the int pointed to by 483 * the fenceFd argument will refer to the fence that must signal 484 * before the dequeued buffer may be written to. A value of -1 485 * indicates that the caller may access the buffer immediately without 486 * waiting on a fence. If a valid file descriptor is returned (i.e. 487 * any value except -1) then the caller is responsible for closing the 488 * file descriptor. 489 */ 490 if (fence_fd >= 0) { 491 /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>: 492 * 493 * Waits indefinitely if timeout < 0. 494 */ 495 int timeout = -1; 496 sync_wait(fence_fd, timeout); 497 close(fence_fd); 498 } 499 500 /* Record all the buffers created by ANativeWindow and update back buffer 501 * for updating buffer's age in swap_buffers. 502 */ 503 EGLBoolean updated = EGL_FALSE; 504 for (int i = 0; i < dri2_surf->color_buffers_count; i++) { 505 if (!dri2_surf->color_buffers[i].buffer) { 506 dri2_surf->color_buffers[i].buffer = dri2_surf->buffer; 507 } 508 if (dri2_surf->color_buffers[i].buffer == dri2_surf->buffer) { 509 dri2_surf->back = &dri2_surf->color_buffers[i]; 510 updated = EGL_TRUE; 511 break; 512 } 513 } 514 515 if (!updated) { 516 /* In case of all the buffers were recreated by ANativeWindow, reset 517 * the color_buffers 518 */ 519 for (int i = 0; i < dri2_surf->color_buffers_count; i++) { 520 dri2_surf->color_buffers[i].buffer = NULL; 521 dri2_surf->color_buffers[i].age = 0; 522 } 523 dri2_surf->color_buffers[0].buffer = dri2_surf->buffer; 524 dri2_surf->back = &dri2_surf->color_buffers[0]; 525 } 526 527 return EGL_TRUE; 528} 529 530static EGLBoolean 531droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf) 532{ 533 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 534 535 /* To avoid blocking other EGL calls, release the display mutex before 536 * we enter droid_window_enqueue_buffer() and re-acquire the mutex upon 537 * return. 538 */ 539 mtx_unlock(&disp->Mutex); 540 541 /* Queue the buffer with stored out fence fd. The ANativeWindow or buffer 542 * consumer may choose to wait for the fence to signal before accessing 543 * it. If fence fd value is -1, buffer can be accessed by consumer 544 * immediately. Consumer or application shouldn't rely on timestamp 545 * associated with fence if the fence fd is -1. 546 * 547 * Ownership of fd is transferred to consumer after queueBuffer and the 548 * consumer is responsible for closing it. Caller must not use the fd 549 * after passing it to queueBuffer. 550 */ 551 int fence_fd = dri2_surf->out_fence_fd; 552 dri2_surf->out_fence_fd = -1; 553 ANativeWindow_queueBuffer(dri2_surf->window, dri2_surf->buffer, fence_fd); 554 555 dri2_surf->buffer = NULL; 556 dri2_surf->back = NULL; 557 558 mtx_lock(&disp->Mutex); 559 560 if (dri2_surf->dri_image_back) { 561 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back); 562 dri2_surf->dri_image_back = NULL; 563 } 564 565 return EGL_TRUE; 566} 567 568static void 569droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf) 570{ 571 int ret; 572 int fence_fd = dri2_surf->out_fence_fd; 573 574 dri2_surf->out_fence_fd = -1; 575 ret = ANativeWindow_cancelBuffer(dri2_surf->window, dri2_surf->buffer, 576 fence_fd); 577 dri2_surf->buffer = NULL; 578 if (ret < 0) { 579 _eglLog(_EGL_WARNING, "ANativeWindow_cancelBuffer failed"); 580 dri2_surf->base.Lost = EGL_TRUE; 581 } 582} 583 584static bool 585droid_set_shared_buffer_mode(_EGLDisplay *disp, _EGLSurface *surf, bool mode) 586{ 587#if ANDROID_API_LEVEL >= 24 588 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 589 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 590 struct ANativeWindow *window = dri2_surf->window; 591 592 assert(surf->Type == EGL_WINDOW_BIT); 593 assert(_eglSurfaceHasMutableRenderBuffer(&dri2_surf->base)); 594 595 _eglLog(_EGL_DEBUG, "%s: mode=%d", __func__, mode); 596 597 if (ANativeWindow_setSharedBufferMode(window, mode)) { 598 _eglLog(_EGL_WARNING, "failed ANativeWindow_setSharedBufferMode" 599 "(window=%p, mode=%d)", window, mode); 600 return false; 601 } 602 603 if (mode) 604 dri2_surf->gralloc_usage |= dri2_dpy->front_rendering_usage; 605 else 606 dri2_surf->gralloc_usage &= ~dri2_dpy->front_rendering_usage; 607 608 if (ANativeWindow_setUsage(window, dri2_surf->gralloc_usage)) { 609 _eglLog(_EGL_WARNING, 610 "failed ANativeWindow_setUsage(window=%p, usage=%u)", window, 611 dri2_surf->gralloc_usage); 612 return false; 613 } 614 615 return true; 616#else 617 _eglLog(_EGL_FATAL, "%s:%d: internal error: unreachable", __FILE__, __LINE__); 618 return false; 619#endif 620} 621 622static _EGLSurface * 623droid_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf, 624 void *native_window, const EGLint *attrib_list) 625{ 626 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 627 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 628 struct dri2_egl_surface *dri2_surf; 629 struct ANativeWindow *window = native_window; 630 const __DRIconfig *config; 631 632 dri2_surf = calloc(1, sizeof *dri2_surf); 633 if (!dri2_surf) { 634 _eglError(EGL_BAD_ALLOC, "droid_create_surface"); 635 return NULL; 636 } 637 638 if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, 639 true, native_window)) 640 goto cleanup_surface; 641 642 if (type == EGL_WINDOW_BIT) { 643 int format; 644 int buffer_count; 645 int min_undequeued_buffers; 646 647 format = ANativeWindow_getFormat(window); 648 if (format < 0) { 649 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 650 goto cleanup_surface; 651 } 652 653 /* Query ANativeWindow for MIN_UNDEQUEUED_BUFFER, minimum amount 654 * of undequeued buffers. 655 */ 656 if (ANativeWindow_query(window, 657 ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS, 658 &min_undequeued_buffers)) { 659 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 660 goto cleanup_surface; 661 } 662 663 /* Required buffer caching slots. */ 664 buffer_count = min_undequeued_buffers + 2; 665 666 dri2_surf->color_buffers = calloc(buffer_count, 667 sizeof(*dri2_surf->color_buffers)); 668 if (!dri2_surf->color_buffers) { 669 _eglError(EGL_BAD_ALLOC, "droid_create_surface"); 670 goto cleanup_surface; 671 } 672 dri2_surf->color_buffers_count = buffer_count; 673 674 if (format != dri2_conf->base.NativeVisualID) { 675 _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x", 676 format, dri2_conf->base.NativeVisualID); 677 } 678 679 ANativeWindow_query(window, ANATIVEWINDOW_QUERY_DEFAULT_WIDTH, 680 &dri2_surf->base.Width); 681 ANativeWindow_query(window, ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT, 682 &dri2_surf->base.Height); 683 684 dri2_surf->gralloc_usage = 685 strcmp(dri2_dpy->driver_name, "kms_swrast") == 0 686 ? GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN 687 : GRALLOC_USAGE_HW_RENDER; 688 689 if (dri2_surf->base.ActiveRenderBuffer == EGL_SINGLE_BUFFER) 690 dri2_surf->gralloc_usage |= dri2_dpy->front_rendering_usage; 691 692 if (ANativeWindow_setUsage(window, dri2_surf->gralloc_usage)) { 693 _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); 694 goto cleanup_surface; 695 } 696 } 697 698 config = dri2_get_dri_config(dri2_conf, type, 699 dri2_surf->base.GLColorspace); 700 if (!config) { 701 _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); 702 goto cleanup_surface; 703 } 704 705 if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) 706 goto cleanup_surface; 707 708 if (window) { 709 ANativeWindow_acquire(window); 710 dri2_surf->window = window; 711 } 712 713 return &dri2_surf->base; 714 715cleanup_surface: 716 if (dri2_surf->color_buffers_count) 717 free(dri2_surf->color_buffers); 718 free(dri2_surf); 719 720 return NULL; 721} 722 723static _EGLSurface * 724droid_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, 725 void *native_window, const EGLint *attrib_list) 726{ 727 return droid_create_surface(disp, EGL_WINDOW_BIT, conf, 728 native_window, attrib_list); 729} 730 731static _EGLSurface * 732droid_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf, 733 const EGLint *attrib_list) 734{ 735 return droid_create_surface(disp, EGL_PBUFFER_BIT, conf, 736 NULL, attrib_list); 737} 738 739static EGLBoolean 740droid_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 741{ 742 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 743 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 744 745 dri2_egl_surface_free_local_buffers(dri2_surf); 746 747 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 748 if (dri2_surf->buffer) 749 droid_window_cancel_buffer(dri2_surf); 750 751 ANativeWindow_release(dri2_surf->window); 752 } 753 754 if (dri2_surf->dri_image_back) { 755 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__); 756 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back); 757 dri2_surf->dri_image_back = NULL; 758 } 759 760 if (dri2_surf->dri_image_front) { 761 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__); 762 dri2_dpy->image->destroyImage(dri2_surf->dri_image_front); 763 dri2_surf->dri_image_front = NULL; 764 } 765 766 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 767 768 dri2_fini_surface(surf); 769 free(dri2_surf->color_buffers); 770 free(dri2_surf); 771 772 return EGL_TRUE; 773} 774 775static EGLBoolean 776droid_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval) 777{ 778 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 779 struct ANativeWindow *window = dri2_surf->window; 780 781 if (ANativeWindow_setSwapInterval(window, interval)) 782 return EGL_FALSE; 783 784 surf->SwapInterval = interval; 785 return EGL_TRUE; 786} 787 788static int 789update_buffers(struct dri2_egl_surface *dri2_surf) 790{ 791 if (dri2_surf->base.Lost) 792 return -1; 793 794 if (dri2_surf->base.Type != EGL_WINDOW_BIT) 795 return 0; 796 797 /* try to dequeue the next back buffer */ 798 if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) { 799 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window"); 800 dri2_surf->base.Lost = EGL_TRUE; 801 return -1; 802 } 803 804 /* free outdated buffers and update the surface size */ 805 if (dri2_surf->base.Width != dri2_surf->buffer->width || 806 dri2_surf->base.Height != dri2_surf->buffer->height) { 807 dri2_egl_surface_free_local_buffers(dri2_surf); 808 dri2_surf->base.Width = dri2_surf->buffer->width; 809 dri2_surf->base.Height = dri2_surf->buffer->height; 810 } 811 812 return 0; 813} 814 815static int 816get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format) 817{ 818 struct dri2_egl_display *dri2_dpy = 819 dri2_egl_display(dri2_surf->base.Resource.Display); 820 821 if (dri2_surf->dri_image_front) 822 return 0; 823 824 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 825 /* According current EGL spec, front buffer rendering 826 * for window surface is not supported now. 827 * and mesa doesn't have the implementation of this case. 828 * Add warning message, but not treat it as error. 829 */ 830 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface"); 831 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) { 832 dri2_surf->dri_image_front = 833 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 834 dri2_surf->base.Width, 835 dri2_surf->base.Height, 836 format, 837 0, 838 NULL); 839 if (!dri2_surf->dri_image_front) { 840 _eglLog(_EGL_WARNING, "dri2_image_front allocation failed"); 841 return -1; 842 } 843 } 844 845 return 0; 846} 847 848static int 849get_back_bo(struct dri2_egl_surface *dri2_surf) 850{ 851 _EGLDisplay *disp = dri2_surf->base.Resource.Display; 852 853 if (dri2_surf->dri_image_back) 854 return 0; 855 856 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 857 if (!dri2_surf->buffer) { 858 _eglLog(_EGL_WARNING, "Could not get native buffer"); 859 return -1; 860 } 861 862 dri2_surf->dri_image_back = 863 droid_create_image_from_native_buffer(disp, dri2_surf->buffer, NULL); 864 if (!dri2_surf->dri_image_back) { 865 _eglLog(_EGL_WARNING, "failed to create DRI image from FD"); 866 return -1; 867 } 868 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) { 869 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically, 870 * the spec states that they have a back buffer but no front buffer, in 871 * contrast to pixmaps, which have a front buffer but no back buffer. 872 * 873 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate 874 * from the spec, following the precedent of Mesa's EGL X11 platform. The 875 * X11 platform correctly assigns pbuffers to single-buffered configs, but 876 * assigns the pbuffer a front buffer instead of a back buffer. 877 * 878 * Pbuffers in the X11 platform mostly work today, so let's just copy its 879 * behavior instead of trying to fix (and hence potentially breaking) the 880 * world. 881 */ 882 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface"); 883 } 884 885 return 0; 886} 887 888/* Some drivers will pass multiple bits in buffer_mask. 889 * For such case, will go through all the bits, and 890 * will not return error when unsupported buffer is requested, only 891 * return error when the allocation for supported buffer failed. 892 */ 893static int 894droid_image_get_buffers(__DRIdrawable *driDrawable, 895 unsigned int format, 896 uint32_t *stamp, 897 void *loaderPrivate, 898 uint32_t buffer_mask, 899 struct __DRIimageList *images) 900{ 901 struct dri2_egl_surface *dri2_surf = loaderPrivate; 902 903 images->image_mask = 0; 904 images->front = NULL; 905 images->back = NULL; 906 907 if (update_buffers(dri2_surf) < 0) 908 return 0; 909 910 if (_eglSurfaceInSharedBufferMode(&dri2_surf->base)) { 911 if (get_back_bo(dri2_surf) < 0) 912 return 0; 913 914 /* We have dri_image_back because this is a window surface and 915 * get_back_bo() succeeded. 916 */ 917 assert(dri2_surf->dri_image_back); 918 images->back = dri2_surf->dri_image_back; 919 images->image_mask |= __DRI_IMAGE_BUFFER_SHARED; 920 921 /* There exists no accompanying back nor front buffer. */ 922 return 1; 923 } 924 925 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) { 926 if (get_front_bo(dri2_surf, format) < 0) 927 return 0; 928 929 if (dri2_surf->dri_image_front) { 930 images->front = dri2_surf->dri_image_front; 931 images->image_mask |= __DRI_IMAGE_BUFFER_FRONT; 932 } 933 } 934 935 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) { 936 if (get_back_bo(dri2_surf) < 0) 937 return 0; 938 939 if (dri2_surf->dri_image_back) { 940 images->back = dri2_surf->dri_image_back; 941 images->image_mask |= __DRI_IMAGE_BUFFER_BACK; 942 } 943 } 944 945 return 1; 946} 947 948static EGLint 949droid_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface) 950{ 951 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface); 952 953 if (update_buffers(dri2_surf) < 0) { 954 _eglError(EGL_BAD_ALLOC, "droid_query_buffer_age"); 955 return -1; 956 } 957 958 return dri2_surf->back ? dri2_surf->back->age : 0; 959} 960 961static EGLBoolean 962droid_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) 963{ 964 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 965 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 966 const bool has_mutable_rb = _eglSurfaceHasMutableRenderBuffer(draw); 967 968 /* From the EGL_KHR_mutable_render_buffer spec (v12): 969 * 970 * If surface is a single-buffered window, pixmap, or pbuffer surface 971 * for which there is no pending change to the EGL_RENDER_BUFFER 972 * attribute, eglSwapBuffers has no effect. 973 */ 974 if (has_mutable_rb && 975 draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER && 976 draw->ActiveRenderBuffer == EGL_SINGLE_BUFFER) { 977 _eglLog(_EGL_DEBUG, "%s: remain in shared buffer mode", __func__); 978 return EGL_TRUE; 979 } 980 981 for (int i = 0; i < dri2_surf->color_buffers_count; i++) { 982 if (dri2_surf->color_buffers[i].age > 0) 983 dri2_surf->color_buffers[i].age++; 984 } 985 986 /* "XXX: we don't use get_back_bo() since it causes regressions in 987 * several dEQP tests. 988 */ 989 if (dri2_surf->back) 990 dri2_surf->back->age = 1; 991 992 dri2_flush_drawable_for_swapbuffers(disp, draw); 993 994 /* dri2_surf->buffer can be null even when no error has occured. For 995 * example, if the user has called no GL rendering commands since the 996 * previous eglSwapBuffers, then the driver may have not triggered 997 * a callback to ANativeWindow_dequeueBuffer, in which case 998 * dri2_surf->buffer remains null. 999 */ 1000 if (dri2_surf->buffer) 1001 droid_window_enqueue_buffer(disp, dri2_surf); 1002 1003 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); 1004 1005 /* Update the shared buffer mode */ 1006 if (has_mutable_rb && 1007 draw->ActiveRenderBuffer != draw->RequestedRenderBuffer) { 1008 bool mode = (draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER); 1009 _eglLog(_EGL_DEBUG, "%s: change to shared buffer mode %d", 1010 __func__, mode); 1011 1012 if (!droid_set_shared_buffer_mode(disp, draw, mode)) 1013 return EGL_FALSE; 1014 draw->ActiveRenderBuffer = draw->RequestedRenderBuffer; 1015 } 1016 1017 return EGL_TRUE; 1018} 1019 1020#ifdef HAVE_DRM_GRALLOC 1021static int get_format(int format) 1022{ 1023 switch (format) { 1024 case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888; 1025 case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565; 1026 case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888; 1027 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 1028 /* 1029 * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack. 1030 * TODO: Revert this once https://issuetracker.google.com/32077885 is fixed. 1031 */ 1032 case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888; 1033 case HAL_PIXEL_FORMAT_RGBA_FP16: return __DRI_IMAGE_FORMAT_ABGR16161616F; 1034 case HAL_PIXEL_FORMAT_RGBA_1010102: return __DRI_IMAGE_FORMAT_ABGR2101010; 1035 default: 1036 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format); 1037 } 1038 return -1; 1039} 1040 1041static __DRIimage * 1042droid_create_image_from_name(_EGLDisplay *disp, 1043 struct ANativeWindowBuffer *buf, 1044 void *priv) 1045{ 1046 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1047 int name; 1048 int format; 1049 1050 name = get_native_buffer_name(buf); 1051 if (!name) { 1052 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 1053 return NULL; 1054 } 1055 1056 format = get_format(buf->format); 1057 if (format == -1) 1058 return NULL; 1059 1060 return 1061 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1062 buf->width, 1063 buf->height, 1064 format, 1065 name, 1066 buf->stride, 1067 priv); 1068} 1069#endif /* HAVE_DRM_GRALLOC */ 1070 1071static EGLBoolean 1072droid_query_surface(_EGLDisplay *disp, _EGLSurface *surf, 1073 EGLint attribute, EGLint *value) 1074{ 1075 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1076 switch (attribute) { 1077 case EGL_WIDTH: 1078 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) { 1079 ANativeWindow_query(dri2_surf->window, 1080 ANATIVEWINDOW_QUERY_DEFAULT_WIDTH, value); 1081 return EGL_TRUE; 1082 } 1083 break; 1084 case EGL_HEIGHT: 1085 if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) { 1086 ANativeWindow_query(dri2_surf->window, 1087 ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT, value); 1088 return EGL_TRUE; 1089 } 1090 break; 1091 default: 1092 break; 1093 } 1094 return _eglQuerySurface(disp, surf, attribute, value); 1095} 1096 1097static _EGLImage * 1098dri2_create_image_android_native_buffer(_EGLDisplay *disp, 1099 _EGLContext *ctx, 1100 struct ANativeWindowBuffer *buf) 1101{ 1102 if (ctx != NULL) { 1103 /* From the EGL_ANDROID_image_native_buffer spec: 1104 * 1105 * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not 1106 * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated. 1107 */ 1108 _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for " 1109 "EGL_NATIVE_BUFFER_ANDROID, the context must be " 1110 "EGL_NO_CONTEXT"); 1111 return NULL; 1112 } 1113 1114 if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || 1115 buf->common.version != sizeof(*buf)) { 1116 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); 1117 return NULL; 1118 } 1119 1120 __DRIimage *dri_image = 1121 droid_create_image_from_native_buffer(disp, buf, buf); 1122 1123#ifdef HAVE_DRM_GRALLOC 1124 if (dri_image == NULL) 1125 dri_image = droid_create_image_from_name(disp, buf, buf); 1126#endif 1127 1128 if (dri_image) { 1129#if ANDROID_API_LEVEL >= 26 1130 AHardwareBuffer_acquire(ANativeWindowBuffer_getHardwareBuffer(buf)); 1131#endif 1132 return dri2_create_image_from_dri(disp, dri_image); 1133 } 1134 1135 return NULL; 1136} 1137 1138static _EGLImage * 1139droid_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 1140 EGLClientBuffer buffer, const EGLint *attr_list) 1141{ 1142 switch (target) { 1143 case EGL_NATIVE_BUFFER_ANDROID: 1144 return dri2_create_image_android_native_buffer(disp, ctx, 1145 (struct ANativeWindowBuffer *) buffer); 1146 default: 1147 return dri2_create_image_khr(disp, ctx, target, buffer, attr_list); 1148 } 1149} 1150 1151static void 1152droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 1153{ 1154} 1155 1156#ifdef HAVE_DRM_GRALLOC 1157static int 1158droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf, 1159 unsigned int *attachments, int count) 1160{ 1161 int num_buffers = 0; 1162 1163 /* fill dri2_surf->buffers */ 1164 for (int i = 0; i < count * 2; i += 2) { 1165 __DRIbuffer *buf, *local; 1166 1167 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers)); 1168 buf = &dri2_surf->buffers[num_buffers]; 1169 1170 switch (attachments[i]) { 1171 case __DRI_BUFFER_BACK_LEFT: 1172 if (dri2_surf->base.Type == EGL_WINDOW_BIT) { 1173 buf->attachment = attachments[i]; 1174 buf->name = get_native_buffer_name(dri2_surf->buffer); 1175 buf->cpp = get_format_bpp(dri2_surf->buffer->format); 1176 buf->pitch = dri2_surf->buffer->stride * buf->cpp; 1177 buf->flags = 0; 1178 1179 if (buf->name) 1180 num_buffers++; 1181 1182 break; 1183 } 1184 FALLTHROUGH; /* for pbuffers */ 1185 case __DRI_BUFFER_DEPTH: 1186 case __DRI_BUFFER_STENCIL: 1187 case __DRI_BUFFER_ACCUM: 1188 case __DRI_BUFFER_DEPTH_STENCIL: 1189 case __DRI_BUFFER_HIZ: 1190 local = dri2_egl_surface_alloc_local_buffer(dri2_surf, 1191 attachments[i], attachments[i + 1]); 1192 1193 if (local) { 1194 *buf = *local; 1195 num_buffers++; 1196 } 1197 break; 1198 case __DRI_BUFFER_FRONT_LEFT: 1199 case __DRI_BUFFER_FRONT_RIGHT: 1200 case __DRI_BUFFER_FAKE_FRONT_LEFT: 1201 case __DRI_BUFFER_FAKE_FRONT_RIGHT: 1202 case __DRI_BUFFER_BACK_RIGHT: 1203 default: 1204 /* no front or right buffers */ 1205 break; 1206 } 1207 } 1208 1209 return num_buffers; 1210} 1211 1212static __DRIbuffer * 1213droid_get_buffers_with_format(__DRIdrawable * driDrawable, 1214 int *width, int *height, 1215 unsigned int *attachments, int count, 1216 int *out_count, void *loaderPrivate) 1217{ 1218 struct dri2_egl_surface *dri2_surf = loaderPrivate; 1219 1220 if (update_buffers(dri2_surf) < 0) 1221 return NULL; 1222 1223 *out_count = droid_get_buffers_parse_attachments(dri2_surf, attachments, count); 1224 1225 if (width) 1226 *width = dri2_surf->base.Width; 1227 if (height) 1228 *height = dri2_surf->base.Height; 1229 1230 return dri2_surf->buffers; 1231} 1232#endif /* HAVE_DRM_GRALLOC */ 1233 1234static unsigned 1235droid_get_capability(void *loaderPrivate, enum dri_loader_cap cap) 1236{ 1237 /* Note: loaderPrivate is _EGLDisplay* */ 1238 switch (cap) { 1239 case DRI_LOADER_CAP_RGBA_ORDERING: 1240 return 1; 1241 default: 1242 return 0; 1243 } 1244} 1245 1246static void 1247droid_destroy_loader_image_state(void *loaderPrivate) 1248{ 1249#if ANDROID_API_LEVEL >= 26 1250 if (loaderPrivate) { 1251 AHardwareBuffer_release( 1252 ANativeWindowBuffer_getHardwareBuffer(loaderPrivate)); 1253 } 1254#endif 1255} 1256 1257static EGLBoolean 1258droid_add_configs_for_visuals(_EGLDisplay *disp) 1259{ 1260 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1261 static const struct { 1262 int format; 1263 int rgba_shifts[4]; 1264 unsigned int rgba_sizes[4]; 1265 } visuals[] = { 1266 { HAL_PIXEL_FORMAT_RGBA_8888, { 0, 8, 16, 24 }, { 8, 8, 8, 8 } }, 1267 { HAL_PIXEL_FORMAT_RGBX_8888, { 0, 8, 16, -1 }, { 8, 8, 8, 0 } }, 1268 { HAL_PIXEL_FORMAT_RGB_565, { 11, 5, 0, -1 }, { 5, 6, 5, 0 } }, 1269 /* This must be after HAL_PIXEL_FORMAT_RGBA_8888, we only keep BGRA 1270 * visual if it turns out RGBA visual is not available. 1271 */ 1272 { HAL_PIXEL_FORMAT_BGRA_8888, { 16, 8, 0, 24 }, { 8, 8, 8, 8 } }, 1273 }; 1274 1275 unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 }; 1276 int config_count = 0; 1277 1278 /* The nesting of loops is significant here. Also significant is the order 1279 * of the HAL pixel formats. Many Android apps (such as Google's official 1280 * NDK GLES2 example app), and even portions the core framework code (such 1281 * as SystemServiceManager in Nougat), incorrectly choose their EGLConfig. 1282 * They neglect to match the EGLConfig's EGL_NATIVE_VISUAL_ID against the 1283 * window's native format, and instead choose the first EGLConfig whose 1284 * channel sizes match those of the native window format while ignoring the 1285 * channel *ordering*. 1286 * 1287 * We can detect such buggy clients in logcat when they call 1288 * eglCreateSurface, by detecting the mismatch between the EGLConfig's 1289 * format and the window's format. 1290 * 1291 * As a workaround, we generate EGLConfigs such that all EGLConfigs for HAL 1292 * pixel format i precede those for HAL pixel format i+1. In my 1293 * (chadversary) testing on Android Nougat, this was good enough to pacify 1294 * the buggy clients. 1295 */ 1296 bool has_rgba = false; 1297 for (int i = 0; i < ARRAY_SIZE(visuals); i++) { 1298 /* Only enable BGRA configs when RGBA is not available. BGRA configs are 1299 * buggy on stock Android. 1300 */ 1301 if (visuals[i].format == HAL_PIXEL_FORMAT_BGRA_8888 && has_rgba) 1302 continue; 1303 for (int j = 0; dri2_dpy->driver_configs[j]; j++) { 1304 const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; 1305 1306 const EGLint config_attrs[] = { 1307 EGL_NATIVE_VISUAL_ID, visuals[i].format, 1308 EGL_NATIVE_VISUAL_TYPE, visuals[i].format, 1309 EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE, 1310 EGL_RECORDABLE_ANDROID, EGL_TRUE, 1311 EGL_NONE 1312 }; 1313 1314 struct dri2_egl_config *dri2_conf = 1315 dri2_add_config(disp, dri2_dpy->driver_configs[j], 1316 config_count + 1, surface_type, config_attrs, 1317 visuals[i].rgba_shifts, visuals[i].rgba_sizes); 1318 if (dri2_conf) { 1319 if (dri2_conf->base.ConfigID == config_count + 1) 1320 config_count++; 1321 format_count[i]++; 1322 } 1323 } 1324 if (visuals[i].format == HAL_PIXEL_FORMAT_RGBA_8888 && format_count[i]) 1325 has_rgba = true; 1326 } 1327 1328 for (int i = 0; i < ARRAY_SIZE(format_count); i++) { 1329 if (!format_count[i]) { 1330 _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x", 1331 visuals[i].format); 1332 } 1333 } 1334 1335 return (config_count != 0); 1336} 1337 1338static const struct dri2_egl_display_vtbl droid_display_vtbl = { 1339 .authenticate = NULL, 1340 .create_window_surface = droid_create_window_surface, 1341 .create_pbuffer_surface = droid_create_pbuffer_surface, 1342 .destroy_surface = droid_destroy_surface, 1343 .create_image = droid_create_image_khr, 1344 .swap_buffers = droid_swap_buffers, 1345 .swap_interval = droid_swap_interval, 1346 .query_buffer_age = droid_query_buffer_age, 1347 .query_surface = droid_query_surface, 1348 .get_dri_drawable = dri2_surface_get_dri_drawable, 1349 .set_shared_buffer_mode = droid_set_shared_buffer_mode, 1350}; 1351 1352#ifdef HAVE_DRM_GRALLOC 1353static const __DRIdri2LoaderExtension droid_dri2_loader_extension = { 1354 .base = { __DRI_DRI2_LOADER, 5 }, 1355 1356 .getBuffers = NULL, 1357 .flushFrontBuffer = droid_flush_front_buffer, 1358 .getBuffersWithFormat = droid_get_buffers_with_format, 1359 .getCapability = droid_get_capability, 1360 .destroyLoaderImageState = droid_destroy_loader_image_state, 1361}; 1362 1363static const __DRIextension *droid_dri2_loader_extensions[] = { 1364 &droid_dri2_loader_extension.base, 1365 &image_lookup_extension.base, 1366 &use_invalidate.base, 1367 /* No __DRI_MUTABLE_RENDER_BUFFER_LOADER because it requires 1368 * __DRI_IMAGE_LOADER. 1369 */ 1370 NULL, 1371}; 1372#endif /* HAVE_DRM_GRALLOC */ 1373 1374static const __DRIimageLoaderExtension droid_image_loader_extension = { 1375 .base = { __DRI_IMAGE_LOADER, 4 }, 1376 1377 .getBuffers = droid_image_get_buffers, 1378 .flushFrontBuffer = droid_flush_front_buffer, 1379 .getCapability = droid_get_capability, 1380 .flushSwapBuffers = NULL, 1381 .destroyLoaderImageState = droid_destroy_loader_image_state, 1382}; 1383 1384static void 1385droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd, 1386 void *loaderPrivate) 1387{ 1388 struct dri2_egl_surface *dri2_surf = loaderPrivate; 1389 struct ANativeWindowBuffer *old_buffer UNUSED = dri2_surf->buffer; 1390 1391 if (!_eglSurfaceInSharedBufferMode(&dri2_surf->base)) { 1392 _eglLog(_EGL_WARNING, "%s: internal error: buffer is not shared", 1393 __func__); 1394 return; 1395 } 1396 1397 if (fence_fd >= 0) { 1398 /* The driver's fence is more recent than the surface's out fence, if it 1399 * exists at all. So use the driver's fence. 1400 */ 1401 if (dri2_surf->out_fence_fd >= 0) { 1402 close(dri2_surf->out_fence_fd); 1403 dri2_surf->out_fence_fd = -1; 1404 } 1405 } else if (dri2_surf->out_fence_fd >= 0) { 1406 fence_fd = dri2_surf->out_fence_fd; 1407 dri2_surf->out_fence_fd = -1; 1408 } 1409 1410 if (ANativeWindow_queueBuffer(dri2_surf->window, dri2_surf->buffer, 1411 fence_fd)) { 1412 _eglLog(_EGL_WARNING, "%s: ANativeWindow_queueBuffer failed", __func__); 1413 close(fence_fd); 1414 return; 1415 } 1416 1417 fence_fd = -1; 1418 1419 if (ANativeWindow_dequeueBuffer(dri2_surf->window, &dri2_surf->buffer, 1420 &fence_fd)) { 1421 /* Tear down the surface because it no longer has a back buffer. */ 1422 struct dri2_egl_display *dri2_dpy = 1423 dri2_egl_display(dri2_surf->base.Resource.Display); 1424 1425 _eglLog(_EGL_WARNING, "%s: ANativeWindow_dequeueBuffer failed", __func__); 1426 1427 dri2_surf->base.Lost = true; 1428 dri2_surf->buffer = NULL; 1429 dri2_surf->back = NULL; 1430 1431 if (dri2_surf->dri_image_back) { 1432 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back); 1433 dri2_surf->dri_image_back = NULL; 1434 } 1435 1436 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); 1437 return; 1438 } 1439 1440 if (fence_fd < 0) 1441 return; 1442 1443 /* Access to the buffer is controlled by a sync fence. Block on it. 1444 * 1445 * Ideally, we would submit the fence to the driver, and the driver would 1446 * postpone command execution until it signalled. But DRI lacks API for 1447 * that (as of 2018-04-11). 1448 * 1449 * SYNC_IOC_WAIT waits forever if timeout < 0 1450 */ 1451 sync_wait(fence_fd, -1); 1452 close(fence_fd); 1453} 1454 1455static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = { 1456 .base = { __DRI_MUTABLE_RENDER_BUFFER_LOADER, 1 }, 1457 .displaySharedBuffer = droid_display_shared_buffer, 1458}; 1459 1460static const __DRIextension *droid_image_loader_extensions[] = { 1461 &droid_image_loader_extension.base, 1462 &image_lookup_extension.base, 1463 &use_invalidate.base, 1464 &droid_mutable_render_buffer_extension.base, 1465 NULL, 1466}; 1467 1468static EGLBoolean 1469droid_load_driver(_EGLDisplay *disp, bool swrast) 1470{ 1471 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1472 1473 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); 1474 if (dri2_dpy->driver_name == NULL) 1475 return false; 1476 1477#ifdef HAVE_DRM_GRALLOC 1478 /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names 1479 * for backwards compatibility with drm_gralloc. (Do not use on new 1480 * systems.) */ 1481 dri2_dpy->loader_extensions = droid_dri2_loader_extensions; 1482 if (!dri2_load_driver(disp)) { 1483 goto error; 1484 } 1485#else 1486 if (swrast) { 1487 /* Use kms swrast only with vgem / virtio_gpu. 1488 * virtio-gpu fallbacks to software rendering when 3D features 1489 * are unavailable since 6c5ab. 1490 */ 1491 if (strcmp(dri2_dpy->driver_name, "vgem") == 0 || 1492 strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0) { 1493 free(dri2_dpy->driver_name); 1494 dri2_dpy->driver_name = strdup("kms_swrast"); 1495 } else { 1496 goto error; 1497 } 1498 } 1499 1500 dri2_dpy->loader_extensions = droid_image_loader_extensions; 1501 if (!dri2_load_driver_dri3(disp)) { 1502 goto error; 1503 } 1504#endif 1505 1506 return true; 1507 1508error: 1509 free(dri2_dpy->driver_name); 1510 dri2_dpy->driver_name = NULL; 1511 return false; 1512} 1513 1514static void 1515droid_unload_driver(_EGLDisplay *disp) 1516{ 1517 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1518 1519 dlclose(dri2_dpy->driver); 1520 dri2_dpy->driver = NULL; 1521 free(dri2_dpy->driver_name); 1522 dri2_dpy->driver_name = NULL; 1523} 1524 1525static int 1526droid_filter_device(_EGLDisplay *disp, int fd, const char *vendor) 1527{ 1528 drmVersionPtr ver = drmGetVersion(fd); 1529 if (!ver) 1530 return -1; 1531 1532 if (strcmp(vendor, ver->name) != 0) { 1533 drmFreeVersion(ver); 1534 return -1; 1535 } 1536 1537 drmFreeVersion(ver); 1538 return 0; 1539} 1540 1541static EGLBoolean 1542droid_probe_device(_EGLDisplay *disp, bool swrast) 1543{ 1544 /* Check that the device is supported, by attempting to: 1545 * - load the dri module 1546 * - and, create a screen 1547 */ 1548 if (!droid_load_driver(disp, swrast)) 1549 return EGL_FALSE; 1550 1551 if (!dri2_create_screen(disp)) { 1552 _eglLog(_EGL_WARNING, "DRI2: failed to create screen"); 1553 droid_unload_driver(disp); 1554 return EGL_FALSE; 1555 } 1556 return EGL_TRUE; 1557} 1558 1559#ifdef HAVE_DRM_GRALLOC 1560static EGLBoolean 1561droid_open_device(_EGLDisplay *disp, bool swrast) 1562{ 1563 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1564 int fd = -1, err = -EINVAL; 1565 1566 if (swrast) 1567 return EGL_FALSE; 1568 1569 if (dri2_dpy->gralloc->perform) 1570 err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc, 1571 GRALLOC_MODULE_PERFORM_GET_DRM_FD, 1572 &fd); 1573 if (err || fd < 0) { 1574 _eglLog(_EGL_WARNING, "fail to get drm fd"); 1575 return EGL_FALSE; 1576 } 1577 1578 dri2_dpy->fd = os_dupfd_cloexec(fd); 1579 if (dri2_dpy->fd < 0) 1580 return EGL_FALSE; 1581 1582 if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER) 1583 return EGL_FALSE; 1584 1585 return droid_probe_device(disp, swrast); 1586} 1587#else 1588static EGLBoolean 1589droid_open_device(_EGLDisplay *disp, bool swrast) 1590{ 1591#define MAX_DRM_DEVICES 64 1592 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1593 drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL }; 1594 int num_devices; 1595 1596 char *vendor_name = NULL; 1597 char vendor_buf[PROPERTY_VALUE_MAX]; 1598 1599#ifdef EGL_FORCE_RENDERNODE 1600 const unsigned node_type = DRM_NODE_RENDER; 1601#else 1602 const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER; 1603#endif 1604 1605 if (property_get("drm.gpu.vendor_name", vendor_buf, NULL) > 0) 1606 vendor_name = vendor_buf; 1607 1608 num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); 1609 if (num_devices < 0) 1610 return EGL_FALSE; 1611 1612 for (int i = 0; i < num_devices; i++) { 1613 device = devices[i]; 1614 1615 if (!(device->available_nodes & (1 << node_type))) 1616 continue; 1617 1618 dri2_dpy->fd = loader_open_device(device->nodes[node_type]); 1619 if (dri2_dpy->fd < 0) { 1620 _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s", 1621 __func__, device->nodes[node_type]); 1622 continue; 1623 } 1624 1625 /* If a vendor is explicitly provided, we use only that. 1626 * Otherwise we fall-back the first device that is supported. 1627 */ 1628 if (vendor_name) { 1629 if (droid_filter_device(disp, dri2_dpy->fd, vendor_name)) { 1630 /* Device does not match - try next device */ 1631 close(dri2_dpy->fd); 1632 dri2_dpy->fd = -1; 1633 continue; 1634 } 1635 /* If the requested device matches - use it. Regardless if 1636 * init fails, do not fall-back to any other device. 1637 */ 1638 if (!droid_probe_device(disp, false)) { 1639 close(dri2_dpy->fd); 1640 dri2_dpy->fd = -1; 1641 } 1642 1643 break; 1644 } 1645 if (droid_probe_device(disp, swrast)) 1646 break; 1647 1648 /* No explicit request - attempt the next device */ 1649 close(dri2_dpy->fd); 1650 dri2_dpy->fd = -1; 1651 } 1652 drmFreeDevices(devices, num_devices); 1653 1654 if (dri2_dpy->fd < 0) { 1655 _eglLog(_EGL_WARNING, "Failed to open %s DRM device", 1656 vendor_name ? "desired": "any"); 1657 return EGL_FALSE; 1658 } 1659 1660 return EGL_TRUE; 1661#undef MAX_DRM_DEVICES 1662} 1663 1664#endif 1665 1666EGLBoolean 1667dri2_initialize_android(_EGLDisplay *disp) 1668{ 1669 _EGLDevice *dev; 1670 bool device_opened = false; 1671 struct dri2_egl_display *dri2_dpy; 1672 const char *err; 1673 int ret; 1674 1675 dri2_dpy = calloc(1, sizeof(*dri2_dpy)); 1676 if (!dri2_dpy) 1677 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 1678 1679 dri2_dpy->fd = -1; 1680 ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, 1681 (const hw_module_t **)&dri2_dpy->gralloc); 1682 if (ret) { 1683 err = "DRI2: failed to get gralloc module"; 1684 goto cleanup; 1685 } 1686 1687 disp->DriverData = (void *) dri2_dpy; 1688 device_opened = droid_open_device(disp, disp->Options.ForceSoftware); 1689 1690 if (!device_opened) { 1691 err = "DRI2: failed to open device"; 1692 goto cleanup; 1693 } 1694 1695 dev = _eglAddDevice(dri2_dpy->fd, false); 1696 if (!dev) { 1697 err = "DRI2: failed to find EGLDevice"; 1698 goto cleanup; 1699 } 1700 1701 disp->Device = dev; 1702 1703 if (!dri2_setup_extensions(disp)) { 1704 err = "DRI2: failed to setup extensions"; 1705 goto cleanup; 1706 } 1707 1708 dri2_setup_screen(disp); 1709 1710 /* We set the maximum swap interval as 1 for Android platform, since it is 1711 * the maximum value supported by Android according to the value of 1712 * ANativeWindow::maxSwapInterval. 1713 */ 1714 dri2_setup_swap_interval(disp, 1); 1715 1716 disp->Extensions.ANDROID_framebuffer_target = EGL_TRUE; 1717 disp->Extensions.ANDROID_image_native_buffer = EGL_TRUE; 1718 disp->Extensions.ANDROID_recordable = EGL_TRUE; 1719 1720 /* Querying buffer age requires a buffer to be dequeued. Without 1721 * EGL_ANDROID_native_fence_sync, dequeue might call eglClientWaitSync and 1722 * result in a deadlock (the lock is already held by eglQuerySurface). 1723 */ 1724 if (disp->Extensions.ANDROID_native_fence_sync) { 1725 disp->Extensions.EXT_buffer_age = EGL_TRUE; 1726 } else { 1727 /* disable KHR_partial_update that might have been enabled in 1728 * dri2_setup_screen 1729 */ 1730 disp->Extensions.KHR_partial_update = EGL_FALSE; 1731 } 1732 1733 disp->Extensions.KHR_image = EGL_TRUE; 1734 1735 dri2_dpy->front_rendering_usage = 0; 1736#if ANDROID_API_LEVEL >= 24 1737 if (dri2_dpy->mutable_render_buffer && 1738 dri2_dpy->loader_extensions == droid_image_loader_extensions && 1739 /* In big GL, front rendering is done at the core API level by directly 1740 * rendering on the front buffer. However, in ES, the front buffer is 1741 * completely inaccessible through the core ES API. 1742 * 1743 * EGL_KHR_mutable_render_buffer is Android's attempt to re-introduce 1744 * front rendering into ES by squeezing into EGL. Unlike big GL, this 1745 * extension redirects GL_BACK used by ES for front rendering. Thus we 1746 * restrict the enabling of this extension to ES only. 1747 */ 1748 (disp->ClientAPIs & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | 1749 EGL_OPENGL_ES3_BIT_KHR)) == 0) { 1750 /* For cros gralloc, if the front rendering query is supported, then all 1751 * available window surface configs support front rendering because: 1752 * 1753 * 1) EGL queries cros gralloc for the front rendering usage bit here 1754 * 2) EGL combines the front rendering usage bit with the existing usage 1755 * if the window surface requests mutable render buffer 1756 * 3) EGL sets the combined usage onto the ANativeWindow and the next 1757 * dequeueBuffer will ask gralloc for an allocation/re-allocation with 1758 * the new combined usage 1759 * 4) cros gralloc(on top of minigbm) resolves the front rendering usage 1760 * bit into either BO_USE_FRONT_RENDERING or BO_USE_LINEAR based on 1761 * the format support checking. 1762 * 1763 * So at least we can force BO_USE_LINEAR as the fallback. 1764 */ 1765 uint32_t front_rendering_usage = 0; 1766 if (!strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) && 1767 dri2_dpy->gralloc->perform && 1768 dri2_dpy->gralloc->perform( 1769 dri2_dpy->gralloc, CROS_GRALLOC_DRM_GET_USAGE, 1770 CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT, 1771 &front_rendering_usage) == 0) { 1772 dri2_dpy->front_rendering_usage = front_rendering_usage; 1773 disp->Extensions.KHR_mutable_render_buffer = EGL_TRUE; 1774 } 1775 } 1776#endif 1777 1778 /* Create configs *after* enabling extensions because presence of DRI 1779 * driver extensions can affect the capabilities of EGLConfigs. 1780 */ 1781 if (!droid_add_configs_for_visuals(disp)) { 1782 err = "DRI2: failed to add configs"; 1783 goto cleanup; 1784 } 1785 1786 /* Fill vtbl last to prevent accidentally calling virtual function during 1787 * initialization. 1788 */ 1789 dri2_dpy->vtbl = &droid_display_vtbl; 1790 1791 return EGL_TRUE; 1792 1793cleanup: 1794 dri2_display_destroy(disp); 1795 return _eglError(EGL_NOT_INITIALIZED, err); 1796} 1797