2
* Mesa 3-D graphics library
4
* Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
5
* Copyright (C) 2010-2011 LunarG Inc.
7
* Based on platform_x11, which has
9
* Copyright © 2011 Intel Corporation
11
* Permission is hereby granted, free of charge, to any person obtaining a
12
* copy of this software and associated documentation files (the "Software"),
13
* to deal in the Software without restriction, including without limitation
14
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
* and/or sell copies of the Software, and to permit persons to whom the
16
* Software is furnished to do so, subject to the following conditions:
18
* The above copyright notice and this permission notice shall be included
19
* in all copies or substantial portions of the Software.
21
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
* DEALINGS IN THE SOFTWARE.
30
#include <cutils/properties.h>
38
#include <sync/sync.h>
39
#include <sys/types.h>
40
#include <drm-uapi/drm_fourcc.h>
42
#include "util/compiler.h"
43
#include "util/os_file.h"
44
#include "util/libsync.h"
48
#include "platform_android.h"
50
#ifdef HAVE_DRM_GRALLOC
51
#include <gralloc_drm_handle.h>
52
#include "gralloc_drm.h"
53
#endif /* HAVE_DRM_GRALLOC */
55
#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
62
struct droid_yuv_format {
64
int native; /* HAL_PIXEL_FORMAT_ */
65
enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
66
int chroma_step; /* Distance in bytes between subsequent chroma pixels. */
69
int fourcc; /* DRM_FORMAT_ */
72
/* The following table is used to look up a DRI image FourCC based
73
* on native format and information contained in android_ycbcr struct. */
74
static const struct droid_yuv_format droid_yuv_formats[] = {
75
/* Native format, YCrCb, Chroma step, DRI image FourCC */
76
{ HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12 },
77
{ HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420 },
78
{ HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420 },
79
{ HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420 },
80
/* HACK: See droid_create_image_from_prime_fds() and
81
* https://issuetracker.google.com/32077885. */
82
{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12 },
83
{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420 },
84
{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420 },
85
{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV },
86
{ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888 },
90
get_fourcc_yuv(int native, enum chroma_order chroma_order, int chroma_step)
92
for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
93
if (droid_yuv_formats[i].native == native &&
94
droid_yuv_formats[i].chroma_order == chroma_order &&
95
droid_yuv_formats[i].chroma_step == chroma_step)
96
return droid_yuv_formats[i].fourcc;
104
for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
105
if (droid_yuv_formats[i].native == native)
112
get_format_bpp(int native)
117
case HAL_PIXEL_FORMAT_RGBA_FP16:
120
case HAL_PIXEL_FORMAT_RGBA_8888:
121
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
123
* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
124
* TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.
126
case HAL_PIXEL_FORMAT_RGBX_8888:
127
case HAL_PIXEL_FORMAT_BGRA_8888:
128
case HAL_PIXEL_FORMAT_RGBA_1010102:
131
case HAL_PIXEL_FORMAT_RGB_565:
142
/* createImageFromFds requires fourcc format */
143
static int get_fourcc(int native)
146
case HAL_PIXEL_FORMAT_RGB_565: return DRM_FORMAT_RGB565;
147
case HAL_PIXEL_FORMAT_BGRA_8888: return DRM_FORMAT_ARGB8888;
148
case HAL_PIXEL_FORMAT_RGBA_8888: return DRM_FORMAT_ABGR8888;
149
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
151
* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
152
* TODO: Remove this once https://issuetracker.google.com/32077885 is fixed.
154
case HAL_PIXEL_FORMAT_RGBX_8888: return DRM_FORMAT_XBGR8888;
155
case HAL_PIXEL_FORMAT_RGBA_FP16: return DRM_FORMAT_ABGR16161616F;
156
case HAL_PIXEL_FORMAT_RGBA_1010102: return DRM_FORMAT_ABGR2101010;
158
_eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native);
163
/* returns # of fds, and by reference the actual fds */
165
get_native_buffer_fds(struct ANativeWindowBuffer *buf, int fds[3])
167
native_handle_t *handle = (native_handle_t *)buf->handle;
173
* Various gralloc implementations exist, but the dma-buf fd tends
174
* to be first. Access it directly to avoid a dependency on specific
177
for (int i = 0; i < handle->numFds; i++)
178
fds[i] = handle->data[i];
180
return handle->numFds;
183
#ifdef HAVE_DRM_GRALLOC
185
get_native_buffer_name(struct ANativeWindowBuffer *buf)
187
return gralloc_drm_get_gem_handle(buf->handle);
189
#endif /* HAVE_DRM_GRALLOC */
192
get_yuv_buffer_info(struct dri2_egl_display *dri2_dpy,
193
struct ANativeWindowBuffer *buf,
194
struct buffer_info *out_buf_info)
196
struct android_ycbcr ycbcr;
197
enum chroma_order chroma_order;
203
num_fds = get_native_buffer_fds(buf, fds);
207
if (!dri2_dpy->gralloc->lock_ycbcr) {
208
_eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr");
212
memset(&ycbcr, 0, sizeof(ycbcr));
213
ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle,
214
0, 0, 0, 0, 0, &ycbcr);
216
/* HACK: See native_window_buffer_get_buffer_info() and
217
* https://issuetracker.google.com/32077885.*/
218
if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
221
_eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret);
224
dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle);
226
chroma_order = ((size_t)ycbcr.cr < (size_t)ycbcr.cb) ? YCrCb : YCbCr;
228
/* .chroma_step is the byte distance between the same chroma channel
229
* values of subsequent pixels, assumed to be the same for Cb and Cr. */
230
drm_fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step);
231
if (drm_fourcc == -1) {
232
_eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = %d",
233
buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", ycbcr.chroma_step);
237
*out_buf_info = (struct buffer_info){
239
.height = buf->height,
240
.drm_fourcc = drm_fourcc,
241
.num_planes = ycbcr.chroma_step == 2 ? 2 : 3,
242
.fds = { -1, -1, -1, -1 },
243
.modifier = DRM_FORMAT_MOD_INVALID,
244
.yuv_color_space = EGL_ITU_REC601_EXT,
245
.sample_range = EGL_YUV_NARROW_RANGE_EXT,
246
.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,
247
.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,
250
/* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
251
* it will return the .y/.cb/.cr pointers based on a NULL pointer,
252
* so they can be interpreted as offsets. */
253
out_buf_info->offsets[0] = (size_t)ycbcr.y;
254
/* We assume here that all the planes are located in one DMA-buf. */
255
if (chroma_order == YCrCb) {
256
out_buf_info->offsets[1] = (size_t)ycbcr.cr;
257
out_buf_info->offsets[2] = (size_t)ycbcr.cb;
259
out_buf_info->offsets[1] = (size_t)ycbcr.cb;
260
out_buf_info->offsets[2] = (size_t)ycbcr.cr;
263
/* .ystride is the line length (in bytes) of the Y plane,
264
* .cstride is the line length (in bytes) of any of the remaining
265
* Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
267
out_buf_info->pitches[0] = ycbcr.ystride;
268
out_buf_info->pitches[1] = out_buf_info->pitches[2] = ycbcr.cstride;
271
* Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
272
* the single-fd case cannot happen. So handle eithe single
273
* fd or fd-per-plane case:
276
out_buf_info->fds[1] = out_buf_info->fds[0] = fds[0];
277
if (out_buf_info->num_planes == 3)
278
out_buf_info->fds[2] = fds[0];
280
assert(num_fds == out_buf_info->num_planes);
281
out_buf_info->fds[0] = fds[0];
282
out_buf_info->fds[1] = fds[1];
283
out_buf_info->fds[2] = fds[2];
290
native_window_buffer_get_buffer_info(struct dri2_egl_display *dri2_dpy,
291
struct ANativeWindowBuffer *buf,
292
struct buffer_info *out_buf_info)
299
if (is_yuv(buf->format)) {
300
int ret = get_yuv_buffer_info(dri2_dpy, buf, out_buf_info);
302
* HACK: https://issuetracker.google.com/32077885
303
* There is no API available to properly query the IMPLEMENTATION_DEFINED
304
* format. As a workaround we rely here on gralloc allocating either
305
* an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized
306
* by lock_ycbcr failing.
313
* Non-YUV formats could *also* have multiple planes, such as ancillary
314
* color compression state buffer, but the rest of the code isn't ready
315
* yet to deal with modifiers:
317
num_planes = get_native_buffer_fds(buf, fds);
321
assert(num_planes == 1);
323
drm_fourcc = get_fourcc(buf->format);
324
if (drm_fourcc == -1) {
325
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
329
pitch = buf->stride * get_format_bpp(buf->format);
331
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
335
*out_buf_info = (struct buffer_info){
337
.height = buf->height,
338
.drm_fourcc = drm_fourcc,
339
.num_planes = num_planes,
340
.fds = { fds[0], -1, -1, -1 },
341
.modifier = DRM_FORMAT_MOD_INVALID,
342
.offsets = { 0, 0, 0, 0 },
343
.pitches = { pitch, 0, 0, 0 },
344
.yuv_color_space = EGL_ITU_REC601_EXT,
345
.sample_range = EGL_YUV_NARROW_RANGE_EXT,
346
.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,
347
.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,
353
/* More recent CrOS gralloc has a perform op that fills out the struct below
354
* with canonical information about the buffer and its modifier, planes,
355
* offsets and strides. If we have this, we can skip straight to
356
* createImageFromDmaBufs2() and avoid all the guessing and recalculations.
357
* This also gives us the modifier and plane offsets/strides for multiplanar
358
* compressed buffers (eg Intel CCS buffers) in order to make that work in Android.
361
static const char cros_gralloc_module_name[] = "CrOS Gralloc";
363
#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4
364
#define CROS_GRALLOC_DRM_GET_USAGE 5
365
#define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1
367
struct cros_gralloc0_buffer_info {
377
cros_get_buffer_info(struct dri2_egl_display *dri2_dpy,
378
struct ANativeWindowBuffer *buf,
379
struct buffer_info *out_buf_info)
381
struct cros_gralloc0_buffer_info info;
383
if (strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) == 0 &&
384
dri2_dpy->gralloc->perform &&
385
dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
386
CROS_GRALLOC_DRM_GET_BUFFER_INFO,
387
buf->handle, &info) == 0) {
388
*out_buf_info = (struct buffer_info){
390
.height = buf->height,
391
.drm_fourcc = info.drm_fourcc,
392
.num_planes = info.num_fds,
393
.fds = { -1, -1, -1, -1 },
394
.modifier = info.modifier,
395
.yuv_color_space = EGL_ITU_REC601_EXT,
396
.sample_range = EGL_YUV_NARROW_RANGE_EXT,
397
.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,
398
.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,
400
for (int i = 0; i < out_buf_info->num_planes; i++) {
401
out_buf_info->fds[i] = info.fds[i];
402
out_buf_info->offsets[i] = info.offset[i];
403
out_buf_info->pitches[i] = info.stride[i];
413
droid_create_image_from_buffer_info(struct dri2_egl_display *dri2_dpy,
414
struct buffer_info *buf_info,
419
if (dri2_dpy->image->base.version >= 15 &&
420
dri2_dpy->image->createImageFromDmaBufs2 != NULL) {
421
return dri2_dpy->image->createImageFromDmaBufs2(
422
dri2_dpy->dri_screen, buf_info->width, buf_info->height,
423
buf_info->drm_fourcc, buf_info->modifier, buf_info->fds,
424
buf_info->num_planes, buf_info->pitches, buf_info->offsets,
425
buf_info->yuv_color_space, buf_info->sample_range,
426
buf_info->horizontal_siting, buf_info->vertical_siting, &error,
430
return dri2_dpy->image->createImageFromDmaBufs(
431
dri2_dpy->dri_screen, buf_info->width, buf_info->height,
432
buf_info->drm_fourcc, buf_info->fds, buf_info->num_planes,
433
buf_info->pitches, buf_info->offsets, buf_info->yuv_color_space,
434
buf_info->sample_range, buf_info->horizontal_siting,
435
buf_info->vertical_siting, &error, priv);
439
droid_create_image_from_native_buffer(_EGLDisplay *disp,
440
struct ANativeWindowBuffer *buf,
443
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
444
struct buffer_info buf_info;
445
__DRIimage *img = NULL;
447
/* If dri driver is gallium virgl, real modifier info queried back from
448
* CrOS info (and potentially mapper metadata if integrated later) cannot
449
* get resolved and the buffer import will fail. Thus the fallback behavior
450
* is preserved down to native_window_buffer_get_buffer_info() so that the
451
* buffer can be imported without modifier info as a last resort.
453
if (!img && !mapper_metadata_get_buffer_info(buf, &buf_info))
454
img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);
456
if (!img && !cros_get_buffer_info(dri2_dpy, buf, &buf_info))
457
img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);
459
if (!img && !native_window_buffer_get_buffer_info(dri2_dpy, buf, &buf_info))
460
img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);
466
handle_in_fence_fd(struct dri2_egl_surface *dri2_surf, __DRIimage *img)
468
_EGLDisplay *disp = dri2_surf->base.Resource.Display;
469
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
471
if (dri2_surf->in_fence_fd < 0)
474
validate_fence_fd(dri2_surf->in_fence_fd);
476
if (dri2_dpy->image->base.version >= 21 &&
477
dri2_dpy->image->setInFenceFd != NULL) {
478
dri2_dpy->image->setInFenceFd(img, dri2_surf->in_fence_fd);
480
sync_wait(dri2_surf->in_fence_fd, -1);
485
close_in_fence_fd(struct dri2_egl_surface *dri2_surf)
487
validate_fence_fd(dri2_surf->in_fence_fd);
488
if (dri2_surf->in_fence_fd >= 0)
489
close(dri2_surf->in_fence_fd);
490
dri2_surf->in_fence_fd = -1;
494
droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
498
if (ANativeWindow_dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
502
close_in_fence_fd(dri2_surf);
504
validate_fence_fd(fence_fd);
506
dri2_surf->in_fence_fd = fence_fd;
508
/* Record all the buffers created by ANativeWindow and update back buffer
509
* for updating buffer's age in swap_buffers.
511
EGLBoolean updated = EGL_FALSE;
512
for (int i = 0; i < dri2_surf->color_buffers_count; i++) {
513
if (!dri2_surf->color_buffers[i].buffer) {
514
dri2_surf->color_buffers[i].buffer = dri2_surf->buffer;
516
if (dri2_surf->color_buffers[i].buffer == dri2_surf->buffer) {
517
dri2_surf->back = &dri2_surf->color_buffers[i];
524
/* In case of all the buffers were recreated by ANativeWindow, reset
527
for (int i = 0; i < dri2_surf->color_buffers_count; i++) {
528
dri2_surf->color_buffers[i].buffer = NULL;
529
dri2_surf->color_buffers[i].age = 0;
531
dri2_surf->color_buffers[0].buffer = dri2_surf->buffer;
532
dri2_surf->back = &dri2_surf->color_buffers[0];
539
droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
541
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
543
/* To avoid blocking other EGL calls, release the display mutex before
544
* we enter droid_window_enqueue_buffer() and re-acquire the mutex upon
547
mtx_unlock(&disp->Mutex);
549
/* Queue the buffer with stored out fence fd. The ANativeWindow or buffer
550
* consumer may choose to wait for the fence to signal before accessing
551
* it. If fence fd value is -1, buffer can be accessed by consumer
552
* immediately. Consumer or application shouldn't rely on timestamp
553
* associated with fence if the fence fd is -1.
555
* Ownership of fd is transferred to consumer after queueBuffer and the
556
* consumer is responsible for closing it. Caller must not use the fd
557
* after passing it to queueBuffer.
559
int fence_fd = dri2_surf->out_fence_fd;
560
dri2_surf->out_fence_fd = -1;
561
ANativeWindow_queueBuffer(dri2_surf->window, dri2_surf->buffer, fence_fd);
563
dri2_surf->buffer = NULL;
564
dri2_surf->back = NULL;
566
mtx_lock(&disp->Mutex);
568
if (dri2_surf->dri_image_back) {
569
dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
570
dri2_surf->dri_image_back = NULL;
577
droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
580
int fence_fd = dri2_surf->out_fence_fd;
582
dri2_surf->out_fence_fd = -1;
583
ret = ANativeWindow_cancelBuffer(dri2_surf->window, dri2_surf->buffer,
585
dri2_surf->buffer = NULL;
587
_eglLog(_EGL_WARNING, "ANativeWindow_cancelBuffer failed");
588
dri2_surf->base.Lost = EGL_TRUE;
591
close_in_fence_fd(dri2_surf);
595
droid_set_shared_buffer_mode(_EGLDisplay *disp, _EGLSurface *surf, bool mode)
597
#if ANDROID_API_LEVEL >= 24
598
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
599
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
600
struct ANativeWindow *window = dri2_surf->window;
602
assert(surf->Type == EGL_WINDOW_BIT);
603
assert(_eglSurfaceHasMutableRenderBuffer(&dri2_surf->base));
605
_eglLog(_EGL_DEBUG, "%s: mode=%d", __func__, mode);
607
if (ANativeWindow_setSharedBufferMode(window, mode)) {
608
_eglLog(_EGL_WARNING, "failed ANativeWindow_setSharedBufferMode"
609
"(window=%p, mode=%d)", window, mode);
614
dri2_surf->gralloc_usage |= dri2_dpy->front_rendering_usage;
616
dri2_surf->gralloc_usage &= ~dri2_dpy->front_rendering_usage;
618
if (ANativeWindow_setUsage(window, dri2_surf->gralloc_usage)) {
619
_eglLog(_EGL_WARNING,
620
"failed ANativeWindow_setUsage(window=%p, usage=%u)", window,
621
dri2_surf->gralloc_usage);
627
_eglLog(_EGL_FATAL, "%s:%d: internal error: unreachable", __FILE__, __LINE__);
633
droid_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
634
void *native_window, const EGLint *attrib_list)
636
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
637
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
638
struct dri2_egl_surface *dri2_surf;
639
struct ANativeWindow *window = native_window;
640
const __DRIconfig *config;
642
dri2_surf = calloc(1, sizeof *dri2_surf);
644
_eglError(EGL_BAD_ALLOC, "droid_create_surface");
648
dri2_surf->in_fence_fd = -1;
650
if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
651
true, native_window))
652
goto cleanup_surface;
654
if (type == EGL_WINDOW_BIT) {
657
int min_undequeued_buffers;
659
format = ANativeWindow_getFormat(window);
661
_eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
662
goto cleanup_surface;
665
/* Query ANativeWindow for MIN_UNDEQUEUED_BUFFER, minimum amount
666
* of undequeued buffers.
668
if (ANativeWindow_query(window,
669
ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS,
670
&min_undequeued_buffers)) {
671
_eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
672
goto cleanup_surface;
675
/* Required buffer caching slots. */
676
buffer_count = min_undequeued_buffers + 2;
678
dri2_surf->color_buffers = calloc(buffer_count,
679
sizeof(*dri2_surf->color_buffers));
680
if (!dri2_surf->color_buffers) {
681
_eglError(EGL_BAD_ALLOC, "droid_create_surface");
682
goto cleanup_surface;
684
dri2_surf->color_buffers_count = buffer_count;
686
if (format != dri2_conf->base.NativeVisualID) {
687
_eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
688
format, dri2_conf->base.NativeVisualID);
691
ANativeWindow_query(window, ANATIVEWINDOW_QUERY_DEFAULT_WIDTH,
692
&dri2_surf->base.Width);
693
ANativeWindow_query(window, ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT,
694
&dri2_surf->base.Height);
696
dri2_surf->gralloc_usage =
697
strcmp(dri2_dpy->driver_name, "kms_swrast") == 0
698
? GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN
699
: GRALLOC_USAGE_HW_RENDER;
701
if (dri2_surf->base.ActiveRenderBuffer == EGL_SINGLE_BUFFER)
702
dri2_surf->gralloc_usage |= dri2_dpy->front_rendering_usage;
704
if (ANativeWindow_setUsage(window, dri2_surf->gralloc_usage)) {
705
_eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
706
goto cleanup_surface;
710
config = dri2_get_dri_config(dri2_conf, type,
711
dri2_surf->base.GLColorspace);
713
_eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
714
goto cleanup_surface;
717
if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
718
goto cleanup_surface;
721
ANativeWindow_acquire(window);
722
dri2_surf->window = window;
725
return &dri2_surf->base;
728
if (dri2_surf->color_buffers_count)
729
free(dri2_surf->color_buffers);
736
droid_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
737
void *native_window, const EGLint *attrib_list)
739
return droid_create_surface(disp, EGL_WINDOW_BIT, conf,
740
native_window, attrib_list);
744
droid_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
745
const EGLint *attrib_list)
747
return droid_create_surface(disp, EGL_PBUFFER_BIT, conf,
752
droid_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
754
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
755
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
757
dri2_egl_surface_free_local_buffers(dri2_surf);
759
if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
760
if (dri2_surf->buffer)
761
droid_window_cancel_buffer(dri2_surf);
763
ANativeWindow_release(dri2_surf->window);
766
if (dri2_surf->dri_image_back) {
767
_eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);
768
dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
769
dri2_surf->dri_image_back = NULL;
772
if (dri2_surf->dri_image_front) {
773
_eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);
774
dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);
775
dri2_surf->dri_image_front = NULL;
778
dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
780
close_in_fence_fd(dri2_surf);
781
dri2_fini_surface(surf);
782
free(dri2_surf->color_buffers);
789
droid_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
791
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
792
struct ANativeWindow *window = dri2_surf->window;
794
if (ANativeWindow_setSwapInterval(window, interval))
797
surf->SwapInterval = interval;
802
update_buffers(struct dri2_egl_surface *dri2_surf)
804
if (dri2_surf->base.Lost)
807
if (dri2_surf->base.Type != EGL_WINDOW_BIT)
810
/* try to dequeue the next back buffer */
811
if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) {
812
_eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");
813
dri2_surf->base.Lost = EGL_TRUE;
817
/* free outdated buffers and update the surface size */
818
if (dri2_surf->base.Width != dri2_surf->buffer->width ||
819
dri2_surf->base.Height != dri2_surf->buffer->height) {
820
dri2_egl_surface_free_local_buffers(dri2_surf);
821
dri2_surf->base.Width = dri2_surf->buffer->width;
822
dri2_surf->base.Height = dri2_surf->buffer->height;
829
get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
831
struct dri2_egl_display *dri2_dpy =
832
dri2_egl_display(dri2_surf->base.Resource.Display);
834
if (dri2_surf->dri_image_front)
837
if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
838
/* According current EGL spec, front buffer rendering
839
* for window surface is not supported now.
840
* and mesa doesn't have the implementation of this case.
841
* Add warning message, but not treat it as error.
843
_eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface");
844
} else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
845
dri2_surf->dri_image_front =
846
dri2_dpy->image->createImage(dri2_dpy->dri_screen,
847
dri2_surf->base.Width,
848
dri2_surf->base.Height,
852
if (!dri2_surf->dri_image_front) {
853
_eglLog(_EGL_WARNING, "dri2_image_front allocation failed");
862
get_back_bo(struct dri2_egl_surface *dri2_surf)
864
_EGLDisplay *disp = dri2_surf->base.Resource.Display;
866
if (dri2_surf->dri_image_back)
869
if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
870
if (!dri2_surf->buffer) {
871
_eglLog(_EGL_WARNING, "Could not get native buffer");
875
dri2_surf->dri_image_back =
876
droid_create_image_from_native_buffer(disp, dri2_surf->buffer, NULL);
877
if (!dri2_surf->dri_image_back) {
878
_eglLog(_EGL_WARNING, "failed to create DRI image from FD");
882
handle_in_fence_fd(dri2_surf, dri2_surf->dri_image_back);
884
} else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
885
/* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
886
* the spec states that they have a back buffer but no front buffer, in
887
* contrast to pixmaps, which have a front buffer but no back buffer.
889
* Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
890
* from the spec, following the precedent of Mesa's EGL X11 platform. The
891
* X11 platform correctly assigns pbuffers to single-buffered configs, but
892
* assigns the pbuffer a front buffer instead of a back buffer.
894
* Pbuffers in the X11 platform mostly work today, so let's just copy its
895
* behavior instead of trying to fix (and hence potentially breaking) the
898
_eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface");
904
/* Some drivers will pass multiple bits in buffer_mask.
905
* For such case, will go through all the bits, and
906
* will not return error when unsupported buffer is requested, only
907
* return error when the allocation for supported buffer failed.
910
droid_image_get_buffers(__DRIdrawable *driDrawable,
914
uint32_t buffer_mask,
915
struct __DRIimageList *images)
917
struct dri2_egl_surface *dri2_surf = loaderPrivate;
919
images->image_mask = 0;
920
images->front = NULL;
923
if (update_buffers(dri2_surf) < 0)
926
if (_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {
927
if (get_back_bo(dri2_surf) < 0)
930
/* We have dri_image_back because this is a window surface and
931
* get_back_bo() succeeded.
933
assert(dri2_surf->dri_image_back);
934
images->back = dri2_surf->dri_image_back;
935
images->image_mask |= __DRI_IMAGE_BUFFER_SHARED;
937
/* There exists no accompanying back nor front buffer. */
941
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
942
if (get_front_bo(dri2_surf, format) < 0)
945
if (dri2_surf->dri_image_front) {
946
images->front = dri2_surf->dri_image_front;
947
images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
951
if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
952
if (get_back_bo(dri2_surf) < 0)
955
if (dri2_surf->dri_image_back) {
956
images->back = dri2_surf->dri_image_back;
957
images->image_mask |= __DRI_IMAGE_BUFFER_BACK;
965
droid_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
967
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
969
if (update_buffers(dri2_surf) < 0) {
970
_eglError(EGL_BAD_ALLOC, "droid_query_buffer_age");
974
return dri2_surf->back ? dri2_surf->back->age : 0;
978
droid_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
980
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
981
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
982
const bool has_mutable_rb = _eglSurfaceHasMutableRenderBuffer(draw);
984
/* From the EGL_KHR_mutable_render_buffer spec (v12):
986
* If surface is a single-buffered window, pixmap, or pbuffer surface
987
* for which there is no pending change to the EGL_RENDER_BUFFER
988
* attribute, eglSwapBuffers has no effect.
990
if (has_mutable_rb &&
991
draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER &&
992
draw->ActiveRenderBuffer == EGL_SINGLE_BUFFER) {
993
_eglLog(_EGL_DEBUG, "%s: remain in shared buffer mode", __func__);
997
for (int i = 0; i < dri2_surf->color_buffers_count; i++) {
998
if (dri2_surf->color_buffers[i].age > 0)
999
dri2_surf->color_buffers[i].age++;
1002
/* "XXX: we don't use get_back_bo() since it causes regressions in
1003
* several dEQP tests.
1005
if (dri2_surf->back)
1006
dri2_surf->back->age = 1;
1008
dri2_flush_drawable_for_swapbuffers(disp, draw);
1010
/* dri2_surf->buffer can be null even when no error has occured. For
1011
* example, if the user has called no GL rendering commands since the
1012
* previous eglSwapBuffers, then the driver may have not triggered
1013
* a callback to ANativeWindow_dequeueBuffer, in which case
1014
* dri2_surf->buffer remains null.
1016
if (dri2_surf->buffer)
1017
droid_window_enqueue_buffer(disp, dri2_surf);
1019
dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
1021
/* Update the shared buffer mode */
1022
if (has_mutable_rb &&
1023
draw->ActiveRenderBuffer != draw->RequestedRenderBuffer) {
1024
bool mode = (draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER);
1025
_eglLog(_EGL_DEBUG, "%s: change to shared buffer mode %d",
1028
if (!droid_set_shared_buffer_mode(disp, draw, mode))
1030
draw->ActiveRenderBuffer = draw->RequestedRenderBuffer;
1036
#ifdef HAVE_DRM_GRALLOC
1037
static int get_format(int format)
1040
case HAL_PIXEL_FORMAT_BGRA_8888: return __DRI_IMAGE_FORMAT_ARGB8888;
1041
case HAL_PIXEL_FORMAT_RGB_565: return __DRI_IMAGE_FORMAT_RGB565;
1042
case HAL_PIXEL_FORMAT_RGBA_8888: return __DRI_IMAGE_FORMAT_ABGR8888;
1043
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1045
* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
1046
* TODO: Revert this once https://issuetracker.google.com/32077885 is fixed.
1048
case HAL_PIXEL_FORMAT_RGBX_8888: return __DRI_IMAGE_FORMAT_XBGR8888;
1049
case HAL_PIXEL_FORMAT_RGBA_FP16: return __DRI_IMAGE_FORMAT_ABGR16161616F;
1050
case HAL_PIXEL_FORMAT_RGBA_1010102: return __DRI_IMAGE_FORMAT_ABGR2101010;
1052
_eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
1058
droid_create_image_from_name(_EGLDisplay *disp,
1059
struct ANativeWindowBuffer *buf,
1062
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1066
name = get_native_buffer_name(buf);
1068
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1072
format = get_format(buf->format);
1077
dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1085
#endif /* HAVE_DRM_GRALLOC */
1088
droid_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
1089
EGLint attribute, EGLint *value)
1091
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1092
switch (attribute) {
1094
if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
1095
ANativeWindow_query(dri2_surf->window,
1096
ANATIVEWINDOW_QUERY_DEFAULT_WIDTH, value);
1101
if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->window) {
1102
ANativeWindow_query(dri2_surf->window,
1103
ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT, value);
1110
return _eglQuerySurface(disp, surf, attribute, value);
1114
dri2_create_image_android_native_buffer(_EGLDisplay *disp,
1116
struct ANativeWindowBuffer *buf)
1119
/* From the EGL_ANDROID_image_native_buffer spec:
1121
* * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not
1122
* EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
1124
_eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
1125
"EGL_NATIVE_BUFFER_ANDROID, the context must be "
1130
if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
1131
buf->common.version != sizeof(*buf)) {
1132
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1136
__DRIimage *dri_image =
1137
droid_create_image_from_native_buffer(disp, buf, buf);
1139
#ifdef HAVE_DRM_GRALLOC
1140
if (dri_image == NULL)
1141
dri_image = droid_create_image_from_name(disp, buf, buf);
1145
#if ANDROID_API_LEVEL >= 26
1146
AHardwareBuffer_acquire(ANativeWindowBuffer_getHardwareBuffer(buf));
1148
return dri2_create_image_from_dri(disp, dri_image);
1155
droid_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
1156
EGLClientBuffer buffer, const EGLint *attr_list)
1159
case EGL_NATIVE_BUFFER_ANDROID:
1160
return dri2_create_image_android_native_buffer(disp, ctx,
1161
(struct ANativeWindowBuffer *) buffer);
1163
return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
1168
droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
1172
#ifdef HAVE_DRM_GRALLOC
1174
droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
1175
unsigned int *attachments, int count)
1177
int num_buffers = 0;
1179
/* fill dri2_surf->buffers */
1180
for (int i = 0; i < count * 2; i += 2) {
1181
__DRIbuffer *buf, *local;
1183
assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
1184
buf = &dri2_surf->buffers[num_buffers];
1186
switch (attachments[i]) {
1187
case __DRI_BUFFER_BACK_LEFT:
1188
if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1189
buf->attachment = attachments[i];
1190
buf->name = get_native_buffer_name(dri2_surf->buffer);
1191
buf->cpp = get_format_bpp(dri2_surf->buffer->format);
1192
buf->pitch = dri2_surf->buffer->stride * buf->cpp;
1200
FALLTHROUGH; /* for pbuffers */
1201
case __DRI_BUFFER_DEPTH:
1202
case __DRI_BUFFER_STENCIL:
1203
case __DRI_BUFFER_ACCUM:
1204
case __DRI_BUFFER_DEPTH_STENCIL:
1205
case __DRI_BUFFER_HIZ:
1206
local = dri2_egl_surface_alloc_local_buffer(dri2_surf,
1207
attachments[i], attachments[i + 1]);
1214
case __DRI_BUFFER_FRONT_LEFT:
1215
case __DRI_BUFFER_FRONT_RIGHT:
1216
case __DRI_BUFFER_FAKE_FRONT_LEFT:
1217
case __DRI_BUFFER_FAKE_FRONT_RIGHT:
1218
case __DRI_BUFFER_BACK_RIGHT:
1220
/* no front or right buffers */
1228
static __DRIbuffer *
1229
droid_get_buffers_with_format(__DRIdrawable * driDrawable,
1230
int *width, int *height,
1231
unsigned int *attachments, int count,
1232
int *out_count, void *loaderPrivate)
1234
struct dri2_egl_surface *dri2_surf = loaderPrivate;
1236
if (update_buffers(dri2_surf) < 0)
1239
*out_count = droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
1242
*width = dri2_surf->base.Width;
1244
*height = dri2_surf->base.Height;
1246
return dri2_surf->buffers;
1248
#endif /* HAVE_DRM_GRALLOC */
1251
droid_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
1253
/* Note: loaderPrivate is _EGLDisplay* */
1255
case DRI_LOADER_CAP_RGBA_ORDERING:
1263
droid_destroy_loader_image_state(void *loaderPrivate)
1265
#if ANDROID_API_LEVEL >= 26
1266
if (loaderPrivate) {
1267
AHardwareBuffer_release(
1268
ANativeWindowBuffer_getHardwareBuffer(loaderPrivate));
1274
droid_add_configs_for_visuals(_EGLDisplay *disp)
1276
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1277
static const struct {
1280
unsigned int rgba_sizes[4];
1282
{ HAL_PIXEL_FORMAT_RGBA_8888, { 0, 8, 16, 24 }, { 8, 8, 8, 8 } },
1283
{ HAL_PIXEL_FORMAT_RGBX_8888, { 0, 8, 16, -1 }, { 8, 8, 8, 0 } },
1284
{ HAL_PIXEL_FORMAT_RGB_565, { 11, 5, 0, -1 }, { 5, 6, 5, 0 } },
1285
/* This must be after HAL_PIXEL_FORMAT_RGBA_8888, we only keep BGRA
1286
* visual if it turns out RGBA visual is not available.
1288
{ HAL_PIXEL_FORMAT_BGRA_8888, { 16, 8, 0, 24 }, { 8, 8, 8, 8 } },
1291
unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 };
1292
int config_count = 0;
1294
/* The nesting of loops is significant here. Also significant is the order
1295
* of the HAL pixel formats. Many Android apps (such as Google's official
1296
* NDK GLES2 example app), and even portions the core framework code (such
1297
* as SystemServiceManager in Nougat), incorrectly choose their EGLConfig.
1298
* They neglect to match the EGLConfig's EGL_NATIVE_VISUAL_ID against the
1299
* window's native format, and instead choose the first EGLConfig whose
1300
* channel sizes match those of the native window format while ignoring the
1301
* channel *ordering*.
1303
* We can detect such buggy clients in logcat when they call
1304
* eglCreateSurface, by detecting the mismatch between the EGLConfig's
1305
* format and the window's format.
1307
* As a workaround, we generate EGLConfigs such that all EGLConfigs for HAL
1308
* pixel format i precede those for HAL pixel format i+1. In my
1309
* (chadversary) testing on Android Nougat, this was good enough to pacify
1310
* the buggy clients.
1312
bool has_rgba = false;
1313
for (int i = 0; i < ARRAY_SIZE(visuals); i++) {
1314
/* Only enable BGRA configs when RGBA is not available. BGRA configs are
1315
* buggy on stock Android.
1317
if (visuals[i].format == HAL_PIXEL_FORMAT_BGRA_8888 && has_rgba)
1319
for (int j = 0; dri2_dpy->driver_configs[j]; j++) {
1320
const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
1322
const EGLint config_attrs[] = {
1323
EGL_NATIVE_VISUAL_ID, visuals[i].format,
1324
EGL_NATIVE_VISUAL_TYPE, visuals[i].format,
1325
EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,
1326
EGL_RECORDABLE_ANDROID, EGL_TRUE,
1330
struct dri2_egl_config *dri2_conf =
1331
dri2_add_config(disp, dri2_dpy->driver_configs[j],
1332
config_count + 1, surface_type, config_attrs,
1333
visuals[i].rgba_shifts, visuals[i].rgba_sizes);
1335
if (dri2_conf->base.ConfigID == config_count + 1)
1340
if (visuals[i].format == HAL_PIXEL_FORMAT_RGBA_8888 && format_count[i])
1344
for (int i = 0; i < ARRAY_SIZE(format_count); i++) {
1345
if (!format_count[i]) {
1346
_eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
1351
return (config_count != 0);
1354
static const struct dri2_egl_display_vtbl droid_display_vtbl = {
1355
.authenticate = NULL,
1356
.create_window_surface = droid_create_window_surface,
1357
.create_pbuffer_surface = droid_create_pbuffer_surface,
1358
.destroy_surface = droid_destroy_surface,
1359
.create_image = droid_create_image_khr,
1360
.swap_buffers = droid_swap_buffers,
1361
.swap_interval = droid_swap_interval,
1362
.query_buffer_age = droid_query_buffer_age,
1363
.query_surface = droid_query_surface,
1364
.get_dri_drawable = dri2_surface_get_dri_drawable,
1365
.set_shared_buffer_mode = droid_set_shared_buffer_mode,
1368
#ifdef HAVE_DRM_GRALLOC
1369
static const __DRIdri2LoaderExtension droid_dri2_loader_extension = {
1370
.base = { __DRI_DRI2_LOADER, 5 },
1373
.flushFrontBuffer = droid_flush_front_buffer,
1374
.getBuffersWithFormat = droid_get_buffers_with_format,
1375
.getCapability = droid_get_capability,
1376
.destroyLoaderImageState = droid_destroy_loader_image_state,
1379
static const __DRIextension *droid_dri2_loader_extensions[] = {
1380
&droid_dri2_loader_extension.base,
1381
&image_lookup_extension.base,
1382
&use_invalidate.base,
1383
/* No __DRI_MUTABLE_RENDER_BUFFER_LOADER because it requires
1384
* __DRI_IMAGE_LOADER.
1388
#endif /* HAVE_DRM_GRALLOC */
1390
static const __DRIimageLoaderExtension droid_image_loader_extension = {
1391
.base = { __DRI_IMAGE_LOADER, 4 },
1393
.getBuffers = droid_image_get_buffers,
1394
.flushFrontBuffer = droid_flush_front_buffer,
1395
.getCapability = droid_get_capability,
1396
.flushSwapBuffers = NULL,
1397
.destroyLoaderImageState = droid_destroy_loader_image_state,
1401
droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd,
1402
void *loaderPrivate)
1404
struct dri2_egl_surface *dri2_surf = loaderPrivate;
1405
struct ANativeWindowBuffer *old_buffer UNUSED = dri2_surf->buffer;
1407
if (!_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {
1408
_eglLog(_EGL_WARNING, "%s: internal error: buffer is not shared",
1413
if (fence_fd >= 0) {
1414
/* The driver's fence is more recent than the surface's out fence, if it
1415
* exists at all. So use the driver's fence.
1417
if (dri2_surf->out_fence_fd >= 0) {
1418
close(dri2_surf->out_fence_fd);
1419
dri2_surf->out_fence_fd = -1;
1421
} else if (dri2_surf->out_fence_fd >= 0) {
1422
fence_fd = dri2_surf->out_fence_fd;
1423
dri2_surf->out_fence_fd = -1;
1426
if (ANativeWindow_queueBuffer(dri2_surf->window, dri2_surf->buffer,
1428
_eglLog(_EGL_WARNING, "%s: ANativeWindow_queueBuffer failed", __func__);
1435
if (ANativeWindow_dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
1437
/* Tear down the surface because it no longer has a back buffer. */
1438
struct dri2_egl_display *dri2_dpy =
1439
dri2_egl_display(dri2_surf->base.Resource.Display);
1441
_eglLog(_EGL_WARNING, "%s: ANativeWindow_dequeueBuffer failed", __func__);
1443
dri2_surf->base.Lost = true;
1444
dri2_surf->buffer = NULL;
1445
dri2_surf->back = NULL;
1447
if (dri2_surf->dri_image_back) {
1448
dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
1449
dri2_surf->dri_image_back = NULL;
1452
dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
1456
close_in_fence_fd(dri2_surf);
1457
validate_fence_fd(fence_fd);
1458
dri2_surf->in_fence_fd = fence_fd;
1459
handle_in_fence_fd(dri2_surf, dri2_surf->dri_image_back);
1462
static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = {
1463
.base = { __DRI_MUTABLE_RENDER_BUFFER_LOADER, 1 },
1464
.displaySharedBuffer = droid_display_shared_buffer,
1467
static const __DRIextension *droid_image_loader_extensions[] = {
1468
&droid_image_loader_extension.base,
1469
&image_lookup_extension.base,
1470
&use_invalidate.base,
1471
&droid_mutable_render_buffer_extension.base,
1476
droid_load_driver(_EGLDisplay *disp, bool swrast)
1478
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1480
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
1481
if (dri2_dpy->driver_name == NULL)
1484
#ifdef HAVE_DRM_GRALLOC
1485
/* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names
1486
* for backwards compatibility with drm_gralloc. (Do not use on new
1488
dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
1489
if (!dri2_load_driver(disp)) {
1494
/* Use kms swrast only with vgem / virtio_gpu.
1495
* virtio-gpu fallbacks to software rendering when 3D features
1496
* are unavailable since 6c5ab.
1498
if (strcmp(dri2_dpy->driver_name, "vgem") == 0 ||
1499
strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0) {
1500
free(dri2_dpy->driver_name);
1501
dri2_dpy->driver_name = strdup("kms_swrast");
1507
dri2_dpy->loader_extensions = droid_image_loader_extensions;
1508
if (!dri2_load_driver_dri3(disp)) {
1516
free(dri2_dpy->driver_name);
1517
dri2_dpy->driver_name = NULL;
1522
droid_unload_driver(_EGLDisplay *disp)
1524
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1526
dlclose(dri2_dpy->driver);
1527
dri2_dpy->driver = NULL;
1528
free(dri2_dpy->driver_name);
1529
dri2_dpy->driver_name = NULL;
1533
droid_filter_device(_EGLDisplay *disp, int fd, const char *vendor)
1535
drmVersionPtr ver = drmGetVersion(fd);
1539
if (strcmp(vendor, ver->name) != 0) {
1540
drmFreeVersion(ver);
1544
drmFreeVersion(ver);
1549
droid_probe_device(_EGLDisplay *disp, bool swrast)
1551
/* Check that the device is supported, by attempting to:
1552
* - load the dri module
1553
* - and, create a screen
1555
if (!droid_load_driver(disp, swrast))
1558
if (!dri2_create_screen(disp)) {
1559
_eglLog(_EGL_WARNING, "DRI2: failed to create screen");
1560
droid_unload_driver(disp);
1566
#ifdef HAVE_DRM_GRALLOC
1568
droid_open_device(_EGLDisplay *disp, bool swrast)
1570
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1571
int fd = -1, err = -EINVAL;
1576
if (dri2_dpy->gralloc->perform)
1577
err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
1578
GRALLOC_MODULE_PERFORM_GET_DRM_FD,
1580
if (err || fd < 0) {
1581
_eglLog(_EGL_WARNING, "fail to get drm fd");
1585
dri2_dpy->fd = os_dupfd_cloexec(fd);
1586
if (dri2_dpy->fd < 0)
1589
if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER)
1592
return droid_probe_device(disp, swrast);
1596
droid_open_device(_EGLDisplay *disp, bool swrast)
1598
#define MAX_DRM_DEVICES 64
1599
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1600
drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL };
1603
char *vendor_name = NULL;
1604
char vendor_buf[PROPERTY_VALUE_MAX];
1606
#ifdef EGL_FORCE_RENDERNODE
1607
const unsigned node_type = DRM_NODE_RENDER;
1609
const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER;
1612
if (property_get("drm.gpu.vendor_name", vendor_buf, NULL) > 0)
1613
vendor_name = vendor_buf;
1615
num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
1616
if (num_devices < 0)
1619
for (int i = 0; i < num_devices; i++) {
1620
device = devices[i];
1622
if (!(device->available_nodes & (1 << node_type)))
1625
dri2_dpy->fd = loader_open_device(device->nodes[node_type]);
1626
if (dri2_dpy->fd < 0) {
1627
_eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s",
1628
__func__, device->nodes[node_type]);
1632
/* If a vendor is explicitly provided, we use only that.
1633
* Otherwise we fall-back the first device that is supported.
1636
if (droid_filter_device(disp, dri2_dpy->fd, vendor_name)) {
1637
/* Device does not match - try next device */
1638
close(dri2_dpy->fd);
1642
/* If the requested device matches - use it. Regardless if
1643
* init fails, do not fall-back to any other device.
1645
if (!droid_probe_device(disp, false)) {
1646
close(dri2_dpy->fd);
1652
if (droid_probe_device(disp, swrast))
1655
/* No explicit request - attempt the next device */
1656
close(dri2_dpy->fd);
1659
drmFreeDevices(devices, num_devices);
1661
if (dri2_dpy->fd < 0) {
1662
_eglLog(_EGL_WARNING, "Failed to open %s DRM device",
1663
vendor_name ? "desired": "any");
1668
#undef MAX_DRM_DEVICES
1674
dri2_initialize_android(_EGLDisplay *disp)
1677
bool device_opened = false;
1678
struct dri2_egl_display *dri2_dpy;
1682
dri2_dpy = calloc(1, sizeof(*dri2_dpy));
1684
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1687
ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
1688
(const hw_module_t **)&dri2_dpy->gralloc);
1690
err = "DRI2: failed to get gralloc module";
1694
disp->DriverData = (void *) dri2_dpy;
1695
device_opened = droid_open_device(disp, disp->Options.ForceSoftware);
1697
if (!device_opened) {
1698
err = "DRI2: failed to open device";
1702
dev = _eglAddDevice(dri2_dpy->fd, false);
1704
err = "DRI2: failed to find EGLDevice";
1710
if (!dri2_setup_extensions(disp)) {
1711
err = "DRI2: failed to setup extensions";
1715
dri2_setup_screen(disp);
1717
/* We set the maximum swap interval as 1 for Android platform, since it is
1718
* the maximum value supported by Android according to the value of
1719
* ANativeWindow::maxSwapInterval.
1721
dri2_setup_swap_interval(disp, 1);
1723
disp->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
1724
disp->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
1725
disp->Extensions.ANDROID_recordable = EGL_TRUE;
1727
/* Querying buffer age requires a buffer to be dequeued. Without
1728
* EGL_ANDROID_native_fence_sync, dequeue might call eglClientWaitSync and
1729
* result in a deadlock (the lock is already held by eglQuerySurface).
1731
if (disp->Extensions.ANDROID_native_fence_sync) {
1732
disp->Extensions.EXT_buffer_age = EGL_TRUE;
1734
/* disable KHR_partial_update that might have been enabled in
1737
disp->Extensions.KHR_partial_update = EGL_FALSE;
1740
disp->Extensions.KHR_image = EGL_TRUE;
1742
dri2_dpy->front_rendering_usage = 0;
1743
#if ANDROID_API_LEVEL >= 24
1744
if (dri2_dpy->mutable_render_buffer &&
1745
dri2_dpy->loader_extensions == droid_image_loader_extensions &&
1746
/* In big GL, front rendering is done at the core API level by directly
1747
* rendering on the front buffer. However, in ES, the front buffer is
1748
* completely inaccessible through the core ES API.
1750
* EGL_KHR_mutable_render_buffer is Android's attempt to re-introduce
1751
* front rendering into ES by squeezing into EGL. Unlike big GL, this
1752
* extension redirects GL_BACK used by ES for front rendering. Thus we
1753
* restrict the enabling of this extension to ES only.
1755
(disp->ClientAPIs & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT |
1756
EGL_OPENGL_ES3_BIT_KHR)) == 0) {
1757
/* For cros gralloc, if the front rendering query is supported, then all
1758
* available window surface configs support front rendering because:
1760
* 1) EGL queries cros gralloc for the front rendering usage bit here
1761
* 2) EGL combines the front rendering usage bit with the existing usage
1762
* if the window surface requests mutable render buffer
1763
* 3) EGL sets the combined usage onto the ANativeWindow and the next
1764
* dequeueBuffer will ask gralloc for an allocation/re-allocation with
1765
* the new combined usage
1766
* 4) cros gralloc(on top of minigbm) resolves the front rendering usage
1767
* bit into either BO_USE_FRONT_RENDERING or BO_USE_LINEAR based on
1768
* the format support checking.
1770
* So at least we can force BO_USE_LINEAR as the fallback.
1772
uint32_t front_rendering_usage = 0;
1773
if (!strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) &&
1774
dri2_dpy->gralloc->perform &&
1775
dri2_dpy->gralloc->perform(
1776
dri2_dpy->gralloc, CROS_GRALLOC_DRM_GET_USAGE,
1777
CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT,
1778
&front_rendering_usage) == 0) {
1779
dri2_dpy->front_rendering_usage = front_rendering_usage;
1780
disp->Extensions.KHR_mutable_render_buffer = EGL_TRUE;
1785
/* Create configs *after* enabling extensions because presence of DRI
1786
* driver extensions can affect the capabilities of EGLConfigs.
1788
if (!droid_add_configs_for_visuals(disp)) {
1789
err = "DRI2: failed to add configs";
1793
/* Fill vtbl last to prevent accidentally calling virtual function during
1796
dri2_dpy->vtbl = &droid_display_vtbl;
1801
dri2_display_destroy(disp);
1802
return _eglError(EGL_NOT_INITIALIZED, err);