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