Path: blob/21.2-virgl/src/egl/drivers/dri2/platform_android.c
4570 views
/*1* Mesa 3-D graphics library2*3* Copyright (C) 2010-2011 Chia-I Wu <[email protected]>4* Copyright (C) 2010-2011 LunarG Inc.5*6* Based on platform_x11, which has7*8* Copyright © 2011 Intel Corporation9*10* Permission is hereby granted, free of charge, to any person obtaining a11* copy of this software and associated documentation files (the "Software"),12* to deal in the Software without restriction, including without limitation13* the rights to use, copy, modify, merge, publish, distribute, sublicense,14* and/or sell copies of the Software, and to permit persons to whom the15* Software is furnished to do so, subject to the following conditions:16*17* The above copyright notice and this permission notice shall be included18* in all copies or substantial portions of the Software.19*20* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR21* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,22* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL23* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER24* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING25* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER26* DEALINGS IN THE SOFTWARE.27*/2829#include <cutils/properties.h>30#include <errno.h>31#include <dirent.h>32#include <dlfcn.h>33#include <fcntl.h>34#include <xf86drm.h>35#include <stdbool.h>36#include <stdio.h>37#include <sync/sync.h>38#include <sys/types.h>39#include <drm-uapi/drm_fourcc.h>4041#include "util/compiler.h"42#include "util/os_file.h"4344#include "loader.h"45#include "egl_dri2.h"46#include "platform_android.h"4748#ifdef HAVE_DRM_GRALLOC49#include <gralloc_drm_handle.h>50#include "gralloc_drm.h"51#endif /* HAVE_DRM_GRALLOC */5253#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))5455enum chroma_order {56YCbCr,57YCrCb,58};5960struct droid_yuv_format {61/* Lookup keys */62int native; /* HAL_PIXEL_FORMAT_ */63enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */64int chroma_step; /* Distance in bytes between subsequent chroma pixels. */6566/* Result */67int fourcc; /* DRM_FORMAT_ */68};6970/* The following table is used to look up a DRI image FourCC based71* on native format and information contained in android_ycbcr struct. */72static const struct droid_yuv_format droid_yuv_formats[] = {73/* Native format, YCrCb, Chroma step, DRI image FourCC */74{ HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12 },75{ HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420 },76{ HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420 },77{ HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420 },78/* HACK: See droid_create_image_from_prime_fds() and79* https://issuetracker.google.com/32077885. */80{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12 },81{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420 },82{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420 },83{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV },84{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888 },85};8687static int88get_fourcc_yuv(int native, enum chroma_order chroma_order, int chroma_step)89{90for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)91if (droid_yuv_formats[i].native == native &&92droid_yuv_formats[i].chroma_order == chroma_order &&93droid_yuv_formats[i].chroma_step == chroma_step)94return droid_yuv_formats[i].fourcc;9596return -1;97}9899static bool100is_yuv(int native)101{102for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)103if (droid_yuv_formats[i].native == native)104return true;105106return false;107}108109static int110get_format_bpp(int native)111{112int bpp;113114switch (native) {115case HAL_PIXEL_FORMAT_RGBA_FP16:116bpp = 8;117break;118case HAL_PIXEL_FORMAT_RGBA_8888:119case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:120/*121* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.122* TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.123*/124case HAL_PIXEL_FORMAT_RGBX_8888:125case HAL_PIXEL_FORMAT_BGRA_8888:126case HAL_PIXEL_FORMAT_RGBA_1010102:127bpp = 4;128break;129case HAL_PIXEL_FORMAT_RGB_565:130bpp = 2;131break;132default:133bpp = 0;134break;135}136137return bpp;138}139140/* createImageFromFds requires fourcc format */141static int get_fourcc(int native)142{143switch (native) {144case HAL_PIXEL_FORMAT_RGB_565: return DRM_FORMAT_RGB565;145case HAL_PIXEL_FORMAT_BGRA_8888: return DRM_FORMAT_ARGB8888;146case HAL_PIXEL_FORMAT_RGBA_8888: return DRM_FORMAT_ABGR8888;147case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:148/*149* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.150* TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.151*/152case HAL_PIXEL_FORMAT_RGBX_8888: return DRM_FORMAT_XBGR8888;153case HAL_PIXEL_FORMAT_RGBA_FP16: return DRM_FORMAT_ABGR16161616F;154case HAL_PIXEL_FORMAT_RGBA_1010102: return DRM_FORMAT_ABGR2101010;155default:156_eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native);157}158return -1;159}160161/* returns # of fds, and by reference the actual fds */162static unsigned163get_native_buffer_fds(struct ANativeWindowBuffer *buf, int fds[3])164{165native_handle_t *handle = (native_handle_t *)buf->handle;166167if (!handle)168return 0;169170/*171* Various gralloc implementations exist, but the dma-buf fd tends172* to be first. Access it directly to avoid a dependency on specific173* gralloc versions.174*/175for (int i = 0; i < handle->numFds; i++)176fds[i] = handle->data[i];177178return handle->numFds;179}180181#ifdef HAVE_DRM_GRALLOC182static int183get_native_buffer_name(struct ANativeWindowBuffer *buf)184{185return gralloc_drm_get_gem_handle(buf->handle);186}187#endif /* HAVE_DRM_GRALLOC */188189static int190get_yuv_buffer_info(struct dri2_egl_display *dri2_dpy,191struct ANativeWindowBuffer *buf,192struct buffer_info *out_buf_info)193{194struct android_ycbcr ycbcr;195enum chroma_order chroma_order;196int drm_fourcc = 0;197int num_fds = 0;198int fds[3];199int ret;200201num_fds = get_native_buffer_fds(buf, fds);202if (num_fds == 0)203return -EINVAL;204205if (!dri2_dpy->gralloc->lock_ycbcr) {206_eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr");207return -EINVAL;208}209210memset(&ycbcr, 0, sizeof(ycbcr));211ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle,2120, 0, 0, 0, 0, &ycbcr);213if (ret) {214/* HACK: See native_window_buffer_get_buffer_info() and215* https://issuetracker.google.com/32077885.*/216if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)217return -EAGAIN;218219_eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret);220return -EINVAL;221}222dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle);223224chroma_order = ((size_t)ycbcr.cr < (size_t)ycbcr.cb) ? YCrCb : YCbCr;225226/* .chroma_step is the byte distance between the same chroma channel227* values of subsequent pixels, assumed to be the same for Cb and Cr. */228drm_fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step);229if (drm_fourcc == -1) {230_eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = %d",231buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", ycbcr.chroma_step);232return -EINVAL;233}234235*out_buf_info = (struct buffer_info){236.width = buf->width,237.height = buf->height,238.drm_fourcc = drm_fourcc,239.num_planes = ycbcr.chroma_step == 2 ? 2 : 3,240.fds = { -1, -1, -1, -1 },241.modifier = DRM_FORMAT_MOD_INVALID,242.yuv_color_space = EGL_ITU_REC601_EXT,243.sample_range = EGL_YUV_NARROW_RANGE_EXT,244.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,245.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,246};247248/* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags249* it will return the .y/.cb/.cr pointers based on a NULL pointer,250* so they can be interpreted as offsets. */251out_buf_info->offsets[0] = (size_t)ycbcr.y;252/* We assume here that all the planes are located in one DMA-buf. */253if (chroma_order == YCrCb) {254out_buf_info->offsets[1] = (size_t)ycbcr.cr;255out_buf_info->offsets[2] = (size_t)ycbcr.cb;256} else {257out_buf_info->offsets[1] = (size_t)ycbcr.cb;258out_buf_info->offsets[2] = (size_t)ycbcr.cr;259}260261/* .ystride is the line length (in bytes) of the Y plane,262* .cstride is the line length (in bytes) of any of the remaining263* Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully264* planar formats. */265out_buf_info->pitches[0] = ycbcr.ystride;266out_buf_info->pitches[1] = out_buf_info->pitches[2] = ycbcr.cstride;267268/*269* Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that270* the single-fd case cannot happen. So handle eithe single271* fd or fd-per-plane case:272*/273if (num_fds == 1) {274out_buf_info->fds[1] = out_buf_info->fds[0] = fds[0];275if (out_buf_info->num_planes == 3)276out_buf_info->fds[2] = fds[0];277} else {278assert(num_fds == out_buf_info->num_planes);279out_buf_info->fds[0] = fds[0];280out_buf_info->fds[1] = fds[1];281out_buf_info->fds[2] = fds[2];282}283284return 0;285}286287static int288native_window_buffer_get_buffer_info(struct dri2_egl_display *dri2_dpy,289struct ANativeWindowBuffer *buf,290struct buffer_info *out_buf_info)291{292int num_planes = 0;293int drm_fourcc = 0;294int pitch = 0;295int fds[3];296297if (is_yuv(buf->format)) {298int ret = get_yuv_buffer_info(dri2_dpy, buf, out_buf_info);299/*300* HACK: https://issuetracker.google.com/32077885301* There is no API available to properly query the IMPLEMENTATION_DEFINED302* format. As a workaround we rely here on gralloc allocating either303* an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized304* by lock_ycbcr failing.305*/306if (ret != -EAGAIN)307return ret;308}309310/*311* Non-YUV formats could *also* have multiple planes, such as ancillary312* color compression state buffer, but the rest of the code isn't ready313* yet to deal with modifiers:314*/315num_planes = get_native_buffer_fds(buf, fds);316if (num_planes == 0)317return -EINVAL;318319assert(num_planes == 1);320321drm_fourcc = get_fourcc(buf->format);322if (drm_fourcc == -1) {323_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");324return -EINVAL;325}326327pitch = buf->stride * get_format_bpp(buf->format);328if (pitch == 0) {329_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");330return -EINVAL;331}332333*out_buf_info = (struct buffer_info){334.width = buf->width,335.height = buf->height,336.drm_fourcc = drm_fourcc,337.num_planes = num_planes,338.fds = { fds[0], -1, -1, -1 },339.modifier = DRM_FORMAT_MOD_INVALID,340.offsets = { 0, 0, 0, 0 },341.pitches = { pitch, 0, 0, 0 },342.yuv_color_space = EGL_ITU_REC601_EXT,343.sample_range = EGL_YUV_NARROW_RANGE_EXT,344.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,345.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,346};347348return 0;349}350351/* More recent CrOS gralloc has a perform op that fills out the struct below352* with canonical information about the buffer and its modifier, planes,353* offsets and strides. If we have this, we can skip straight to354* createImageFromDmaBufs2() and avoid all the guessing and recalculations.355* This also gives us the modifier and plane offsets/strides for multiplanar356* compressed buffers (eg Intel CCS buffers) in order to make that work in Android.357*/358359static const char cros_gralloc_module_name[] = "CrOS Gralloc";360361#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4362#define CROS_GRALLOC_DRM_GET_USAGE 5363#define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1364365struct cros_gralloc0_buffer_info {366uint32_t drm_fourcc;367int num_fds;368int fds[4];369uint64_t modifier;370int offset[4];371int stride[4];372};373374static int375cros_get_buffer_info(struct dri2_egl_display *dri2_dpy,376struct ANativeWindowBuffer *buf,377struct buffer_info *out_buf_info)378{379struct cros_gralloc0_buffer_info info;380381if (strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) == 0 &&382dri2_dpy->gralloc->perform &&383dri2_dpy->gralloc->perform(dri2_dpy->gralloc,384CROS_GRALLOC_DRM_GET_BUFFER_INFO,385buf->handle, &info) == 0) {386*out_buf_info = (struct buffer_info){387.width = buf->width,388.height = buf->height,389.drm_fourcc = info.drm_fourcc,390.num_planes = info.num_fds,391.fds = { -1, -1, -1, -1 },392.modifier = info.modifier,393.yuv_color_space = EGL_ITU_REC601_EXT,394.sample_range = EGL_YUV_NARROW_RANGE_EXT,395.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,396.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,397};398for (int i = 0; i < out_buf_info->num_planes; i++) {399out_buf_info->fds[i] = info.fds[i];400out_buf_info->offsets[i] = info.offset[i];401out_buf_info->pitches[i] = info.stride[i];402}403404return 0;405}406407return -EINVAL;408}409410static __DRIimage *411droid_create_image_from_buffer_info(struct dri2_egl_display *dri2_dpy,412struct buffer_info *buf_info,413void *priv)414{415unsigned error;416417if (dri2_dpy->image->base.version >= 15 &&418dri2_dpy->image->createImageFromDmaBufs2 != NULL) {419return dri2_dpy->image->createImageFromDmaBufs2(420dri2_dpy->dri_screen, buf_info->width, buf_info->height,421buf_info->drm_fourcc, buf_info->modifier, buf_info->fds,422buf_info->num_planes, buf_info->pitches, buf_info->offsets,423buf_info->yuv_color_space, buf_info->sample_range,424buf_info->horizontal_siting, buf_info->vertical_siting, &error,425priv);426}427428return dri2_dpy->image->createImageFromDmaBufs(429dri2_dpy->dri_screen, buf_info->width, buf_info->height,430buf_info->drm_fourcc, buf_info->fds, buf_info->num_planes,431buf_info->pitches, buf_info->offsets, buf_info->yuv_color_space,432buf_info->sample_range, buf_info->horizontal_siting,433buf_info->vertical_siting, &error, priv);434}435436static __DRIimage *437droid_create_image_from_native_buffer(_EGLDisplay *disp,438struct ANativeWindowBuffer *buf,439void *priv)440{441struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);442struct buffer_info buf_info;443__DRIimage *img = NULL;444445/* If dri driver is gallium virgl, real modifier info queried back from446* CrOS info (and potentially mapper metadata if integrated later) cannot447* get resolved and the buffer import will fail. Thus the fallback behavior448* is preserved down to native_window_buffer_get_buffer_info() so that the449* buffer can be imported without modifier info as a last resort.450*/451if (!img && !mapper_metadata_get_buffer_info(buf, &buf_info))452img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);453454if (!img && !cros_get_buffer_info(dri2_dpy, buf, &buf_info))455img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);456457if (!img && !native_window_buffer_get_buffer_info(dri2_dpy, buf, &buf_info))458img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);459460return img;461}462463static EGLBoolean464droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)465{466int fence_fd;467468if (ANativeWindow_dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,469&fence_fd))470return EGL_FALSE;471472/* If access to the buffer is controlled by a sync fence, then block on the473* fence.474*475* It may be more performant to postpone blocking until there is an476* immediate need to write to the buffer. But doing so would require adding477* hooks to the DRI2 loader.478*479* From the ANativeWindow_dequeueBuffer documentation:480*481* The libsync fence file descriptor returned in the int pointed to by482* the fenceFd argument will refer to the fence that must signal483* before the dequeued buffer may be written to. A value of -1484* indicates that the caller may access the buffer immediately without485* waiting on a fence. If a valid file descriptor is returned (i.e.486* any value except -1) then the caller is responsible for closing the487* file descriptor.488*/489if (fence_fd >= 0) {490/* From the SYNC_IOC_WAIT documentation in <linux/sync.h>:491*492* Waits indefinitely if timeout < 0.493*/494int timeout = -1;495sync_wait(fence_fd, timeout);496close(fence_fd);497}498499/* Record all the buffers created by ANativeWindow and update back buffer500* for updating buffer's age in swap_buffers.501*/502EGLBoolean updated = EGL_FALSE;503for (int i = 0; i < dri2_surf->color_buffers_count; i++) {504if (!dri2_surf->color_buffers[i].buffer) {505dri2_surf->color_buffers[i].buffer = dri2_surf->buffer;506}507if (dri2_surf->color_buffers[i].buffer == dri2_surf->buffer) {508dri2_surf->back = &dri2_surf->color_buffers[i];509updated = EGL_TRUE;510break;511}512}513514if (!updated) {515/* In case of all the buffers were recreated by ANativeWindow, reset516* the color_buffers517*/518for (int i = 0; i < dri2_surf->color_buffers_count; i++) {519dri2_surf->color_buffers[i].buffer = NULL;520dri2_surf->color_buffers[i].age = 0;521}522dri2_surf->color_buffers[0].buffer = dri2_surf->buffer;523dri2_surf->back = &dri2_surf->color_buffers[0];524}525526return EGL_TRUE;527}528529static EGLBoolean530droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)531{532struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);533534/* To avoid blocking other EGL calls, release the display mutex before535* we enter droid_window_enqueue_buffer() and re-acquire the mutex upon536* return.537*/538mtx_unlock(&disp->Mutex);539540/* Queue the buffer with stored out fence fd. The ANativeWindow or buffer541* consumer may choose to wait for the fence to signal before accessing542* it. If fence fd value is -1, buffer can be accessed by consumer543* immediately. Consumer or application shouldn't rely on timestamp544* associated with fence if the fence fd is -1.545*546* Ownership of fd is transferred to consumer after queueBuffer and the547* consumer is responsible for closing it. Caller must not use the fd548* after passing it to queueBuffer.549*/550int fence_fd = dri2_surf->out_fence_fd;551dri2_surf->out_fence_fd = -1;552ANativeWindow_queueBuffer(dri2_surf->window, dri2_surf->buffer, fence_fd);553554dri2_surf->buffer = NULL;555dri2_surf->back = NULL;556557mtx_lock(&disp->Mutex);558559if (dri2_surf->dri_image_back) {560dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);561dri2_surf->dri_image_back = NULL;562}563564return EGL_TRUE;565}566567static void568droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)569{570int ret;571int fence_fd = dri2_surf->out_fence_fd;572573dri2_surf->out_fence_fd = -1;574ret = ANativeWindow_cancelBuffer(dri2_surf->window, dri2_surf->buffer,575fence_fd);576dri2_surf->buffer = NULL;577if (ret < 0) {578_eglLog(_EGL_WARNING, "ANativeWindow_cancelBuffer failed");579dri2_surf->base.Lost = EGL_TRUE;580}581}582583static bool584droid_set_shared_buffer_mode(_EGLDisplay *disp, _EGLSurface *surf, bool mode)585{586#if ANDROID_API_LEVEL >= 24587struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);588struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);589struct ANativeWindow *window = dri2_surf->window;590591assert(surf->Type == EGL_WINDOW_BIT);592assert(_eglSurfaceHasMutableRenderBuffer(&dri2_surf->base));593594_eglLog(_EGL_DEBUG, "%s: mode=%d", __func__, mode);595596if (ANativeWindow_setSharedBufferMode(window, mode)) {597_eglLog(_EGL_WARNING, "failed ANativeWindow_setSharedBufferMode"598"(window=%p, mode=%d)", window, mode);599return false;600}601602if (mode)603dri2_surf->gralloc_usage |= dri2_dpy->front_rendering_usage;604else605dri2_surf->gralloc_usage &= ~dri2_dpy->front_rendering_usage;606607if (ANativeWindow_setUsage(window, dri2_surf->gralloc_usage)) {608_eglLog(_EGL_WARNING,609"failed ANativeWindow_setUsage(window=%p, usage=%u)", window,610dri2_surf->gralloc_usage);611return false;612}613614return true;615#else616_eglLog(_EGL_FATAL, "%s:%d: internal error: unreachable", __FILE__, __LINE__);617return false;618#endif619}620621static _EGLSurface *622droid_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,623void *native_window, const EGLint *attrib_list)624{625struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);626struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);627struct dri2_egl_surface *dri2_surf;628struct ANativeWindow *window = native_window;629const __DRIconfig *config;630631dri2_surf = calloc(1, sizeof *dri2_surf);632if (!dri2_surf) {633_eglError(EGL_BAD_ALLOC, "droid_create_surface");634return NULL;635}636637if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,638true, native_window))639goto cleanup_surface;640641if (type == EGL_WINDOW_BIT) {642int format;643int buffer_count;644int min_undequeued_buffers;645646format = ANativeWindow_getFormat(window);647if (format < 0) {648_eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");649goto cleanup_surface;650}651652/* Query ANativeWindow for MIN_UNDEQUEUED_BUFFER, minimum amount653* of undequeued buffers.654*/655if (ANativeWindow_query(window,656ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS,657&min_undequeued_buffers)) {658_eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");659goto cleanup_surface;660}661662/* Required buffer caching slots. */663buffer_count = min_undequeued_buffers + 2;664665dri2_surf->color_buffers = calloc(buffer_count,666sizeof(*dri2_surf->color_buffers));667if (!dri2_surf->color_buffers) {668_eglError(EGL_BAD_ALLOC, "droid_create_surface");669goto cleanup_surface;670}671dri2_surf->color_buffers_count = buffer_count;672673if (format != dri2_conf->base.NativeVisualID) {674_eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",675format, dri2_conf->base.NativeVisualID);676}677678ANativeWindow_query(window, ANATIVEWINDOW_QUERY_DEFAULT_WIDTH,679&dri2_surf->base.Width);680ANativeWindow_query(window, ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT,681&dri2_surf->base.Height);682683dri2_surf->gralloc_usage =684strcmp(dri2_dpy->driver_name, "kms_swrast") == 0685? GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN686: GRALLOC_USAGE_HW_RENDER;687688if (dri2_surf->base.ActiveRenderBuffer == EGL_SINGLE_BUFFER)689dri2_surf->gralloc_usage |= dri2_dpy->front_rendering_usage;690691if (ANativeWindow_setUsage(window, dri2_surf->gralloc_usage)) {692_eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");693goto cleanup_surface;694}695}696697config = dri2_get_dri_config(dri2_conf, type,698dri2_surf->base.GLColorspace);699if (!config) {700_eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");701goto cleanup_surface;702}703704if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))705goto cleanup_surface;706707if (window) {708ANativeWindow_acquire(window);709dri2_surf->window = window;710}711712return &dri2_surf->base;713714cleanup_surface:715if (dri2_surf->color_buffers_count)716free(dri2_surf->color_buffers);717free(dri2_surf);718719return NULL;720}721722static _EGLSurface *723droid_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,724void *native_window, const EGLint *attrib_list)725{726return droid_create_surface(disp, EGL_WINDOW_BIT, conf,727native_window, attrib_list);728}729730static _EGLSurface *731droid_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,732const EGLint *attrib_list)733{734return droid_create_surface(disp, EGL_PBUFFER_BIT, conf,735NULL, attrib_list);736}737738static EGLBoolean739droid_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)740{741struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);742struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);743744dri2_egl_surface_free_local_buffers(dri2_surf);745746if (dri2_surf->base.Type == EGL_WINDOW_BIT) {747if (dri2_surf->buffer)748droid_window_cancel_buffer(dri2_surf);749750ANativeWindow_release(dri2_surf->window);751}752753if (dri2_surf->dri_image_back) {754_eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);755dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);756dri2_surf->dri_image_back = NULL;757}758759if (dri2_surf->dri_image_front) {760_eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);761dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);762dri2_surf->dri_image_front = NULL;763}764765dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);766767dri2_fini_surface(surf);768free(dri2_surf->color_buffers);769free(dri2_surf);770771return EGL_TRUE;772}773774static EGLBoolean775droid_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)776{777struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);778struct ANativeWindow *window = dri2_surf->window;779780if (ANativeWindow_setSwapInterval(window, interval))781return EGL_FALSE;782783surf->SwapInterval = interval;784return EGL_TRUE;785}786787static int788update_buffers(struct dri2_egl_surface *dri2_surf)789{790if (dri2_surf->base.Lost)791return -1;792793if (dri2_surf->base.Type != EGL_WINDOW_BIT)794return 0;795796/* try to dequeue the next back buffer */797if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) {798_eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");799dri2_surf->base.Lost = EGL_TRUE;800return -1;801}802803/* free outdated buffers and update the surface size */804if (dri2_surf->base.Width != dri2_surf->buffer->width ||805dri2_surf->base.Height != dri2_surf->buffer->height) {806dri2_egl_surface_free_local_buffers(dri2_surf);807dri2_surf->base.Width = dri2_surf->buffer->width;808dri2_surf->base.Height = dri2_surf->buffer->height;809}810811return 0;812}813814static int815get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)816{817struct dri2_egl_display *dri2_dpy =818dri2_egl_display(dri2_surf->base.Resource.Display);819820if (dri2_surf->dri_image_front)821return 0;822823if (dri2_surf->base.Type == EGL_WINDOW_BIT) {824/* According current EGL spec, front buffer rendering825* for window surface is not supported now.826* and mesa doesn't have the implementation of this case.827* Add warning message, but not treat it as error.828*/829_eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface");830} else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {831dri2_surf->dri_image_front =832dri2_dpy->image->createImage(dri2_dpy->dri_screen,833dri2_surf->base.Width,834dri2_surf->base.Height,835format,8360,837NULL);838if (!dri2_surf->dri_image_front) {839_eglLog(_EGL_WARNING, "dri2_image_front allocation failed");840return -1;841}842}843844return 0;845}846847static int848get_back_bo(struct dri2_egl_surface *dri2_surf)849{850_EGLDisplay *disp = dri2_surf->base.Resource.Display;851852if (dri2_surf->dri_image_back)853return 0;854855if (dri2_surf->base.Type == EGL_WINDOW_BIT) {856if (!dri2_surf->buffer) {857_eglLog(_EGL_WARNING, "Could not get native buffer");858return -1;859}860861dri2_surf->dri_image_back =862droid_create_image_from_native_buffer(disp, dri2_surf->buffer, NULL);863if (!dri2_surf->dri_image_back) {864_eglLog(_EGL_WARNING, "failed to create DRI image from FD");865return -1;866}867} else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {868/* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,869* the spec states that they have a back buffer but no front buffer, in870* contrast to pixmaps, which have a front buffer but no back buffer.871*872* Single-buffered surfaces with no front buffer confuse Mesa; so we deviate873* from the spec, following the precedent of Mesa's EGL X11 platform. The874* X11 platform correctly assigns pbuffers to single-buffered configs, but875* assigns the pbuffer a front buffer instead of a back buffer.876*877* Pbuffers in the X11 platform mostly work today, so let's just copy its878* behavior instead of trying to fix (and hence potentially breaking) the879* world.880*/881_eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface");882}883884return 0;885}886887/* Some drivers will pass multiple bits in buffer_mask.888* For such case, will go through all the bits, and889* will not return error when unsupported buffer is requested, only890* return error when the allocation for supported buffer failed.891*/892static int893droid_image_get_buffers(__DRIdrawable *driDrawable,894unsigned int format,895uint32_t *stamp,896void *loaderPrivate,897uint32_t buffer_mask,898struct __DRIimageList *images)899{900struct dri2_egl_surface *dri2_surf = loaderPrivate;901902images->image_mask = 0;903images->front = NULL;904images->back = NULL;905906if (update_buffers(dri2_surf) < 0)907return 0;908909if (_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {910if (get_back_bo(dri2_surf) < 0)911return 0;912913/* We have dri_image_back because this is a window surface and914* get_back_bo() succeeded.915*/916assert(dri2_surf->dri_image_back);917images->back = dri2_surf->dri_image_back;918images->image_mask |= __DRI_IMAGE_BUFFER_SHARED;919920/* There exists no accompanying back nor front buffer. */921return 1;922}923924if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {925if (get_front_bo(dri2_surf, format) < 0)926return 0;927928if (dri2_surf->dri_image_front) {929images->front = dri2_surf->dri_image_front;930images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;931}932}933934if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {935if (get_back_bo(dri2_surf) < 0)936return 0;937938if (dri2_surf->dri_image_back) {939images->back = dri2_surf->dri_image_back;940images->image_mask |= __DRI_IMAGE_BUFFER_BACK;941}942}943944return 1;945}946947static EGLint948droid_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)949{950struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);951952if (update_buffers(dri2_surf) < 0) {953_eglError(EGL_BAD_ALLOC, "droid_query_buffer_age");954return -1;955}956957return dri2_surf->back ? dri2_surf->back->age : 0;958}959960static EGLBoolean961droid_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)962{963struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);964struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);965const bool has_mutable_rb = _eglSurfaceHasMutableRenderBuffer(draw);966967/* From the EGL_KHR_mutable_render_buffer spec (v12):968*969* If surface is a single-buffered window, pixmap, or pbuffer surface970* for which there is no pending change to the EGL_RENDER_BUFFER971* attribute, eglSwapBuffers has no effect.972*/973if (has_mutable_rb &&974draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER &&975draw->ActiveRenderBuffer == EGL_SINGLE_BUFFER) {976_eglLog(_EGL_DEBUG, "%s: remain in shared buffer mode", __func__);977return EGL_TRUE;978}979980for (int i = 0; i < dri2_surf->color_buffers_count; i++) {981if (dri2_surf->color_buffers[i].age > 0)982dri2_surf->color_buffers[i].age++;983}984985/* "XXX: we don't use get_back_bo() since it causes regressions in986* several dEQP tests.987*/988if (dri2_surf->back)989dri2_surf->back->age = 1;990991dri2_flush_drawable_for_swapbuffers(disp, draw);992993/* dri2_surf->buffer can be null even when no error has occured. For994* example, if the user has called no GL rendering commands since the995* previous eglSwapBuffers, then the driver may have not triggered996* a callback to ANativeWindow_dequeueBuffer, in which case997* dri2_surf->buffer remains null.998*/999if (dri2_surf->buffer)1000droid_window_enqueue_buffer(disp, dri2_surf);10011002dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);10031004/* Update the shared buffer mode */1005if (has_mutable_rb &&1006draw->ActiveRenderBuffer != draw->RequestedRenderBuffer) {1007bool mode = (draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER);1008_eglLog(_EGL_DEBUG, "%s: change to shared buffer mode %d",1009__func__, mode);10101011if (!droid_set_shared_buffer_mode(disp, draw, mode))1012return EGL_FALSE;1013draw->ActiveRenderBuffer = draw->RequestedRenderBuffer;1014}10151016return EGL_TRUE;1017}10181019#ifdef HAVE_DRM_GRALLOC1020static int get_format(int format)1021{1022switch (format) {1023case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888;1024case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565;1025case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888;1026case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:1027/*1028* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.1029* TODO: Revert this once https://issuetracker.google.com/32077885 is fixed.1030*/1031case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888;1032case HAL_PIXEL_FORMAT_RGBA_FP16: return __DRI_IMAGE_FORMAT_ABGR16161616F;1033case HAL_PIXEL_FORMAT_RGBA_1010102: return __DRI_IMAGE_FORMAT_ABGR2101010;1034default:1035_eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);1036}1037return -1;1038}10391040static __DRIimage *1041droid_create_image_from_name(_EGLDisplay *disp,1042struct ANativeWindowBuffer *buf,1043void *priv)1044{1045struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);1046int name;1047int format;10481049name = get_native_buffer_name(buf);1050if (!name) {1051_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");1052return NULL;1053}10541055format = get_format(buf->format);1056if (format == -1)1057return NULL;10581059return1060dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,1061buf->width,1062buf->height,1063format,1064name,1065buf->stride,1066priv);1067}1068#endif /* HAVE_DRM_GRALLOC */10691070static EGLBoolean1071droid_query_surface(_EGLDisplay *disp, _EGLSurface *surf,1072EGLint attribute, EGLint *value)1073{1074struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);1075switch (attribute) {1076case EGL_WIDTH:1077if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {1078ANativeWindow_query(dri2_surf->window,1079ANATIVEWINDOW_QUERY_DEFAULT_WIDTH, value);1080return EGL_TRUE;1081}1082break;1083case EGL_HEIGHT:1084if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {1085ANativeWindow_query(dri2_surf->window,1086ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT, value);1087return EGL_TRUE;1088}1089break;1090default:1091break;1092}1093return _eglQuerySurface(disp, surf, attribute, value);1094}10951096static _EGLImage *1097dri2_create_image_android_native_buffer(_EGLDisplay *disp,1098_EGLContext *ctx,1099struct ANativeWindowBuffer *buf)1100{1101if (ctx != NULL) {1102/* From the EGL_ANDROID_image_native_buffer spec:1103*1104* * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not1105* EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.1106*/1107_eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "1108"EGL_NATIVE_BUFFER_ANDROID, the context must be "1109"EGL_NO_CONTEXT");1110return NULL;1111}11121113if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||1114buf->common.version != sizeof(*buf)) {1115_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");1116return NULL;1117}11181119__DRIimage *dri_image =1120droid_create_image_from_native_buffer(disp, buf, buf);11211122#ifdef HAVE_DRM_GRALLOC1123if (dri_image == NULL)1124dri_image = droid_create_image_from_name(disp, buf, buf);1125#endif11261127if (dri_image) {1128#if ANDROID_API_LEVEL >= 261129AHardwareBuffer_acquire(ANativeWindowBuffer_getHardwareBuffer(buf));1130#endif1131return dri2_create_image_from_dri(disp, dri_image);1132}11331134return NULL;1135}11361137static _EGLImage *1138droid_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,1139EGLClientBuffer buffer, const EGLint *attr_list)1140{1141switch (target) {1142case EGL_NATIVE_BUFFER_ANDROID:1143return dri2_create_image_android_native_buffer(disp, ctx,1144(struct ANativeWindowBuffer *) buffer);1145default:1146return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);1147}1148}11491150static void1151droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)1152{1153}11541155#ifdef HAVE_DRM_GRALLOC1156static int1157droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,1158unsigned int *attachments, int count)1159{1160int num_buffers = 0;11611162/* fill dri2_surf->buffers */1163for (int i = 0; i < count * 2; i += 2) {1164__DRIbuffer *buf, *local;11651166assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));1167buf = &dri2_surf->buffers[num_buffers];11681169switch (attachments[i]) {1170case __DRI_BUFFER_BACK_LEFT:1171if (dri2_surf->base.Type == EGL_WINDOW_BIT) {1172buf->attachment = attachments[i];1173buf->name = get_native_buffer_name(dri2_surf->buffer);1174buf->cpp = get_format_bpp(dri2_surf->buffer->format);1175buf->pitch = dri2_surf->buffer->stride * buf->cpp;1176buf->flags = 0;11771178if (buf->name)1179num_buffers++;11801181break;1182}1183FALLTHROUGH; /* for pbuffers */1184case __DRI_BUFFER_DEPTH:1185case __DRI_BUFFER_STENCIL:1186case __DRI_BUFFER_ACCUM:1187case __DRI_BUFFER_DEPTH_STENCIL:1188case __DRI_BUFFER_HIZ:1189local = dri2_egl_surface_alloc_local_buffer(dri2_surf,1190attachments[i], attachments[i + 1]);11911192if (local) {1193*buf = *local;1194num_buffers++;1195}1196break;1197case __DRI_BUFFER_FRONT_LEFT:1198case __DRI_BUFFER_FRONT_RIGHT:1199case __DRI_BUFFER_FAKE_FRONT_LEFT:1200case __DRI_BUFFER_FAKE_FRONT_RIGHT:1201case __DRI_BUFFER_BACK_RIGHT:1202default:1203/* no front or right buffers */1204break;1205}1206}12071208return num_buffers;1209}12101211static __DRIbuffer *1212droid_get_buffers_with_format(__DRIdrawable * driDrawable,1213int *width, int *height,1214unsigned int *attachments, int count,1215int *out_count, void *loaderPrivate)1216{1217struct dri2_egl_surface *dri2_surf = loaderPrivate;12181219if (update_buffers(dri2_surf) < 0)1220return NULL;12211222*out_count = droid_get_buffers_parse_attachments(dri2_surf, attachments, count);12231224if (width)1225*width = dri2_surf->base.Width;1226if (height)1227*height = dri2_surf->base.Height;12281229return dri2_surf->buffers;1230}1231#endif /* HAVE_DRM_GRALLOC */12321233static unsigned1234droid_get_capability(void *loaderPrivate, enum dri_loader_cap cap)1235{1236/* Note: loaderPrivate is _EGLDisplay* */1237switch (cap) {1238case DRI_LOADER_CAP_RGBA_ORDERING:1239return 1;1240default:1241return 0;1242}1243}12441245static void1246droid_destroy_loader_image_state(void *loaderPrivate)1247{1248#if ANDROID_API_LEVEL >= 261249if (loaderPrivate) {1250AHardwareBuffer_release(1251ANativeWindowBuffer_getHardwareBuffer(loaderPrivate));1252}1253#endif1254}12551256static EGLBoolean1257droid_add_configs_for_visuals(_EGLDisplay *disp)1258{1259struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);1260static const struct {1261int format;1262int rgba_shifts[4];1263unsigned int rgba_sizes[4];1264} visuals[] = {1265{ HAL_PIXEL_FORMAT_RGBA_8888, { 0, 8, 16, 24 }, { 8, 8, 8, 8 } },1266{ HAL_PIXEL_FORMAT_RGBX_8888, { 0, 8, 16, -1 }, { 8, 8, 8, 0 } },1267{ HAL_PIXEL_FORMAT_RGB_565, { 11, 5, 0, -1 }, { 5, 6, 5, 0 } },1268/* This must be after HAL_PIXEL_FORMAT_RGBA_8888, we only keep BGRA1269* visual if it turns out RGBA visual is not available.1270*/1271{ HAL_PIXEL_FORMAT_BGRA_8888, { 16, 8, 0, 24 }, { 8, 8, 8, 8 } },1272};12731274unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 };1275int config_count = 0;12761277/* The nesting of loops is significant here. Also significant is the order1278* of the HAL pixel formats. Many Android apps (such as Google's official1279* NDK GLES2 example app), and even portions the core framework code (such1280* as SystemServiceManager in Nougat), incorrectly choose their EGLConfig.1281* They neglect to match the EGLConfig's EGL_NATIVE_VISUAL_ID against the1282* window's native format, and instead choose the first EGLConfig whose1283* channel sizes match those of the native window format while ignoring the1284* channel *ordering*.1285*1286* We can detect such buggy clients in logcat when they call1287* eglCreateSurface, by detecting the mismatch between the EGLConfig's1288* format and the window's format.1289*1290* As a workaround, we generate EGLConfigs such that all EGLConfigs for HAL1291* pixel format i precede those for HAL pixel format i+1. In my1292* (chadversary) testing on Android Nougat, this was good enough to pacify1293* the buggy clients.1294*/1295bool has_rgba = false;1296for (int i = 0; i < ARRAY_SIZE(visuals); i++) {1297/* Only enable BGRA configs when RGBA is not available. BGRA configs are1298* buggy on stock Android.1299*/1300if (visuals[i].format == HAL_PIXEL_FORMAT_BGRA_8888 && has_rgba)1301continue;1302for (int j = 0; dri2_dpy->driver_configs[j]; j++) {1303const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;13041305const EGLint config_attrs[] = {1306EGL_NATIVE_VISUAL_ID, visuals[i].format,1307EGL_NATIVE_VISUAL_TYPE, visuals[i].format,1308EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,1309EGL_RECORDABLE_ANDROID, EGL_TRUE,1310EGL_NONE1311};13121313struct dri2_egl_config *dri2_conf =1314dri2_add_config(disp, dri2_dpy->driver_configs[j],1315config_count + 1, surface_type, config_attrs,1316visuals[i].rgba_shifts, visuals[i].rgba_sizes);1317if (dri2_conf) {1318if (dri2_conf->base.ConfigID == config_count + 1)1319config_count++;1320format_count[i]++;1321}1322}1323if (visuals[i].format == HAL_PIXEL_FORMAT_RGBA_8888 && format_count[i])1324has_rgba = true;1325}13261327for (int i = 0; i < ARRAY_SIZE(format_count); i++) {1328if (!format_count[i]) {1329_eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",1330visuals[i].format);1331}1332}13331334return (config_count != 0);1335}13361337static const struct dri2_egl_display_vtbl droid_display_vtbl = {1338.authenticate = NULL,1339.create_window_surface = droid_create_window_surface,1340.create_pbuffer_surface = droid_create_pbuffer_surface,1341.destroy_surface = droid_destroy_surface,1342.create_image = droid_create_image_khr,1343.swap_buffers = droid_swap_buffers,1344.swap_interval = droid_swap_interval,1345.query_buffer_age = droid_query_buffer_age,1346.query_surface = droid_query_surface,1347.get_dri_drawable = dri2_surface_get_dri_drawable,1348.set_shared_buffer_mode = droid_set_shared_buffer_mode,1349};13501351#ifdef HAVE_DRM_GRALLOC1352static const __DRIdri2LoaderExtension droid_dri2_loader_extension = {1353.base = { __DRI_DRI2_LOADER, 5 },13541355.getBuffers = NULL,1356.flushFrontBuffer = droid_flush_front_buffer,1357.getBuffersWithFormat = droid_get_buffers_with_format,1358.getCapability = droid_get_capability,1359.destroyLoaderImageState = droid_destroy_loader_image_state,1360};13611362static const __DRIextension *droid_dri2_loader_extensions[] = {1363&droid_dri2_loader_extension.base,1364&image_lookup_extension.base,1365&use_invalidate.base,1366/* No __DRI_MUTABLE_RENDER_BUFFER_LOADER because it requires1367* __DRI_IMAGE_LOADER.1368*/1369NULL,1370};1371#endif /* HAVE_DRM_GRALLOC */13721373static const __DRIimageLoaderExtension droid_image_loader_extension = {1374.base = { __DRI_IMAGE_LOADER, 4 },13751376.getBuffers = droid_image_get_buffers,1377.flushFrontBuffer = droid_flush_front_buffer,1378.getCapability = droid_get_capability,1379.flushSwapBuffers = NULL,1380.destroyLoaderImageState = droid_destroy_loader_image_state,1381};13821383static void1384droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd,1385void *loaderPrivate)1386{1387struct dri2_egl_surface *dri2_surf = loaderPrivate;1388struct ANativeWindowBuffer *old_buffer UNUSED = dri2_surf->buffer;13891390if (!_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {1391_eglLog(_EGL_WARNING, "%s: internal error: buffer is not shared",1392__func__);1393return;1394}13951396if (fence_fd >= 0) {1397/* The driver's fence is more recent than the surface's out fence, if it1398* exists at all. So use the driver's fence.1399*/1400if (dri2_surf->out_fence_fd >= 0) {1401close(dri2_surf->out_fence_fd);1402dri2_surf->out_fence_fd = -1;1403}1404} else if (dri2_surf->out_fence_fd >= 0) {1405fence_fd = dri2_surf->out_fence_fd;1406dri2_surf->out_fence_fd = -1;1407}14081409if (ANativeWindow_queueBuffer(dri2_surf->window, dri2_surf->buffer,1410fence_fd)) {1411_eglLog(_EGL_WARNING, "%s: ANativeWindow_queueBuffer failed", __func__);1412close(fence_fd);1413return;1414}14151416fence_fd = -1;14171418if (ANativeWindow_dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,1419&fence_fd)) {1420/* Tear down the surface because it no longer has a back buffer. */1421struct dri2_egl_display *dri2_dpy =1422dri2_egl_display(dri2_surf->base.Resource.Display);14231424_eglLog(_EGL_WARNING, "%s: ANativeWindow_dequeueBuffer failed", __func__);14251426dri2_surf->base.Lost = true;1427dri2_surf->buffer = NULL;1428dri2_surf->back = NULL;14291430if (dri2_surf->dri_image_back) {1431dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);1432dri2_surf->dri_image_back = NULL;1433}14341435dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);1436return;1437}14381439if (fence_fd < 0)1440return;14411442/* Access to the buffer is controlled by a sync fence. Block on it.1443*1444* Ideally, we would submit the fence to the driver, and the driver would1445* postpone command execution until it signalled. But DRI lacks API for1446* that (as of 2018-04-11).1447*1448* SYNC_IOC_WAIT waits forever if timeout < 01449*/1450sync_wait(fence_fd, -1);1451close(fence_fd);1452}14531454static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = {1455.base = { __DRI_MUTABLE_RENDER_BUFFER_LOADER, 1 },1456.displaySharedBuffer = droid_display_shared_buffer,1457};14581459static const __DRIextension *droid_image_loader_extensions[] = {1460&droid_image_loader_extension.base,1461&image_lookup_extension.base,1462&use_invalidate.base,1463&droid_mutable_render_buffer_extension.base,1464NULL,1465};14661467static EGLBoolean1468droid_load_driver(_EGLDisplay *disp, bool swrast)1469{1470struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);14711472dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);1473if (dri2_dpy->driver_name == NULL)1474return false;14751476#ifdef HAVE_DRM_GRALLOC1477/* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names1478* for backwards compatibility with drm_gralloc. (Do not use on new1479* systems.) */1480dri2_dpy->loader_extensions = droid_dri2_loader_extensions;1481if (!dri2_load_driver(disp)) {1482goto error;1483}1484#else1485if (swrast) {1486/* Use kms swrast only with vgem / virtio_gpu.1487* virtio-gpu fallbacks to software rendering when 3D features1488* are unavailable since 6c5ab.1489*/1490if (strcmp(dri2_dpy->driver_name, "vgem") == 0 ||1491strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0) {1492free(dri2_dpy->driver_name);1493dri2_dpy->driver_name = strdup("kms_swrast");1494} else {1495goto error;1496}1497}14981499dri2_dpy->loader_extensions = droid_image_loader_extensions;1500if (!dri2_load_driver_dri3(disp)) {1501goto error;1502}1503#endif15041505return true;15061507error:1508free(dri2_dpy->driver_name);1509dri2_dpy->driver_name = NULL;1510return false;1511}15121513static void1514droid_unload_driver(_EGLDisplay *disp)1515{1516struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);15171518dlclose(dri2_dpy->driver);1519dri2_dpy->driver = NULL;1520free(dri2_dpy->driver_name);1521dri2_dpy->driver_name = NULL;1522}15231524static int1525droid_filter_device(_EGLDisplay *disp, int fd, const char *vendor)1526{1527drmVersionPtr ver = drmGetVersion(fd);1528if (!ver)1529return -1;15301531if (strcmp(vendor, ver->name) != 0) {1532drmFreeVersion(ver);1533return -1;1534}15351536drmFreeVersion(ver);1537return 0;1538}15391540static EGLBoolean1541droid_probe_device(_EGLDisplay *disp, bool swrast)1542{1543/* Check that the device is supported, by attempting to:1544* - load the dri module1545* - and, create a screen1546*/1547if (!droid_load_driver(disp, swrast))1548return EGL_FALSE;15491550if (!dri2_create_screen(disp)) {1551_eglLog(_EGL_WARNING, "DRI2: failed to create screen");1552droid_unload_driver(disp);1553return EGL_FALSE;1554}1555return EGL_TRUE;1556}15571558#ifdef HAVE_DRM_GRALLOC1559static EGLBoolean1560droid_open_device(_EGLDisplay *disp, bool swrast)1561{1562struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);1563int fd = -1, err = -EINVAL;15641565if (swrast)1566return EGL_FALSE;15671568if (dri2_dpy->gralloc->perform)1569err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,1570GRALLOC_MODULE_PERFORM_GET_DRM_FD,1571&fd);1572if (err || fd < 0) {1573_eglLog(_EGL_WARNING, "fail to get drm fd");1574return EGL_FALSE;1575}15761577dri2_dpy->fd = os_dupfd_cloexec(fd);1578if (dri2_dpy->fd < 0)1579return EGL_FALSE;15801581if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER)1582return EGL_FALSE;15831584return droid_probe_device(disp, swrast);1585}1586#else1587static EGLBoolean1588droid_open_device(_EGLDisplay *disp, bool swrast)1589{1590#define MAX_DRM_DEVICES 641591struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);1592drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL };1593int num_devices;15941595char *vendor_name = NULL;1596char vendor_buf[PROPERTY_VALUE_MAX];15971598#ifdef EGL_FORCE_RENDERNODE1599const unsigned node_type = DRM_NODE_RENDER;1600#else1601const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER;1602#endif16031604if (property_get("drm.gpu.vendor_name", vendor_buf, NULL) > 0)1605vendor_name = vendor_buf;16061607num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));1608if (num_devices < 0)1609return EGL_FALSE;16101611for (int i = 0; i < num_devices; i++) {1612device = devices[i];16131614if (!(device->available_nodes & (1 << node_type)))1615continue;16161617dri2_dpy->fd = loader_open_device(device->nodes[node_type]);1618if (dri2_dpy->fd < 0) {1619_eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s",1620__func__, device->nodes[node_type]);1621continue;1622}16231624/* If a vendor is explicitly provided, we use only that.1625* Otherwise we fall-back the first device that is supported.1626*/1627if (vendor_name) {1628if (droid_filter_device(disp, dri2_dpy->fd, vendor_name)) {1629/* Device does not match - try next device */1630close(dri2_dpy->fd);1631dri2_dpy->fd = -1;1632continue;1633}1634/* If the requested device matches - use it. Regardless if1635* init fails, do not fall-back to any other device.1636*/1637if (!droid_probe_device(disp, false)) {1638close(dri2_dpy->fd);1639dri2_dpy->fd = -1;1640}16411642break;1643}1644if (droid_probe_device(disp, swrast))1645break;16461647/* No explicit request - attempt the next device */1648close(dri2_dpy->fd);1649dri2_dpy->fd = -1;1650}1651drmFreeDevices(devices, num_devices);16521653if (dri2_dpy->fd < 0) {1654_eglLog(_EGL_WARNING, "Failed to open %s DRM device",1655vendor_name ? "desired": "any");1656return EGL_FALSE;1657}16581659return EGL_TRUE;1660#undef MAX_DRM_DEVICES1661}16621663#endif16641665EGLBoolean1666dri2_initialize_android(_EGLDisplay *disp)1667{1668_EGLDevice *dev;1669bool device_opened = false;1670struct dri2_egl_display *dri2_dpy;1671const char *err;1672int ret;16731674dri2_dpy = calloc(1, sizeof(*dri2_dpy));1675if (!dri2_dpy)1676return _eglError(EGL_BAD_ALLOC, "eglInitialize");16771678dri2_dpy->fd = -1;1679ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,1680(const hw_module_t **)&dri2_dpy->gralloc);1681if (ret) {1682err = "DRI2: failed to get gralloc module";1683goto cleanup;1684}16851686disp->DriverData = (void *) dri2_dpy;1687device_opened = droid_open_device(disp, disp->Options.ForceSoftware);16881689if (!device_opened) {1690err = "DRI2: failed to open device";1691goto cleanup;1692}16931694dev = _eglAddDevice(dri2_dpy->fd, false);1695if (!dev) {1696err = "DRI2: failed to find EGLDevice";1697goto cleanup;1698}16991700disp->Device = dev;17011702if (!dri2_setup_extensions(disp)) {1703err = "DRI2: failed to setup extensions";1704goto cleanup;1705}17061707dri2_setup_screen(disp);17081709/* We set the maximum swap interval as 1 for Android platform, since it is1710* the maximum value supported by Android according to the value of1711* ANativeWindow::maxSwapInterval.1712*/1713dri2_setup_swap_interval(disp, 1);17141715disp->Extensions.ANDROID_framebuffer_target = EGL_TRUE;1716disp->Extensions.ANDROID_image_native_buffer = EGL_TRUE;1717disp->Extensions.ANDROID_recordable = EGL_TRUE;17181719/* Querying buffer age requires a buffer to be dequeued. Without1720* EGL_ANDROID_native_fence_sync, dequeue might call eglClientWaitSync and1721* result in a deadlock (the lock is already held by eglQuerySurface).1722*/1723if (disp->Extensions.ANDROID_native_fence_sync) {1724disp->Extensions.EXT_buffer_age = EGL_TRUE;1725} else {1726/* disable KHR_partial_update that might have been enabled in1727* dri2_setup_screen1728*/1729disp->Extensions.KHR_partial_update = EGL_FALSE;1730}17311732disp->Extensions.KHR_image = EGL_TRUE;17331734dri2_dpy->front_rendering_usage = 0;1735#if ANDROID_API_LEVEL >= 241736if (dri2_dpy->mutable_render_buffer &&1737dri2_dpy->loader_extensions == droid_image_loader_extensions &&1738/* In big GL, front rendering is done at the core API level by directly1739* rendering on the front buffer. However, in ES, the front buffer is1740* completely inaccessible through the core ES API.1741*1742* EGL_KHR_mutable_render_buffer is Android's attempt to re-introduce1743* front rendering into ES by squeezing into EGL. Unlike big GL, this1744* extension redirects GL_BACK used by ES for front rendering. Thus we1745* restrict the enabling of this extension to ES only.1746*/1747(disp->ClientAPIs & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT |1748EGL_OPENGL_ES3_BIT_KHR)) == 0) {1749/* For cros gralloc, if the front rendering query is supported, then all1750* available window surface configs support front rendering because:1751*1752* 1) EGL queries cros gralloc for the front rendering usage bit here1753* 2) EGL combines the front rendering usage bit with the existing usage1754* if the window surface requests mutable render buffer1755* 3) EGL sets the combined usage onto the ANativeWindow and the next1756* dequeueBuffer will ask gralloc for an allocation/re-allocation with1757* the new combined usage1758* 4) cros gralloc(on top of minigbm) resolves the front rendering usage1759* bit into either BO_USE_FRONT_RENDERING or BO_USE_LINEAR based on1760* the format support checking.1761*1762* So at least we can force BO_USE_LINEAR as the fallback.1763*/1764uint32_t front_rendering_usage = 0;1765if (!strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) &&1766dri2_dpy->gralloc->perform &&1767dri2_dpy->gralloc->perform(1768dri2_dpy->gralloc, CROS_GRALLOC_DRM_GET_USAGE,1769CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT,1770&front_rendering_usage) == 0) {1771dri2_dpy->front_rendering_usage = front_rendering_usage;1772disp->Extensions.KHR_mutable_render_buffer = EGL_TRUE;1773}1774}1775#endif17761777/* Create configs *after* enabling extensions because presence of DRI1778* driver extensions can affect the capabilities of EGLConfigs.1779*/1780if (!droid_add_configs_for_visuals(disp)) {1781err = "DRI2: failed to add configs";1782goto cleanup;1783}17841785/* Fill vtbl last to prevent accidentally calling virtual function during1786* initialization.1787*/1788dri2_dpy->vtbl = &droid_display_vtbl;17891790return EGL_TRUE;17911792cleanup:1793dri2_display_destroy(disp);1794return _eglError(EGL_NOT_INITIALIZED, err);1795}179617971798