mesa-pvr: add patches from visionfive2 buildroot

This is a simply copy/paste of all existing patches from the VisionFive2
buildroot configuration.
This commit is contained in:
Andreas Cord-Landwehr
2023-01-09 20:48:01 +01:00
committed by Khem Raj
parent 0c9bf7388f
commit 235a2c600a
68 changed files with 20353 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
From 184d3da84d449bc05511cb857cc843285dde4b63 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Wed, 17 Jun 2015 15:37:18 +0100
Subject: [PATCH 02/67] Force Mesa to use the PVR driver for platform devices
For platform devices, Mesa uses the DRM driver name to determine which DRI
driver to load. This doesn't work in the multi-DRM driver model where there
are separate DRM drivers for the display and GPU. This is because we normally
want Mesa to deal with the display driver and the name of this won't match
that of the DRI driver. For the time being, take the easy approach and just
force it to use the PVR DRI driver.
---
src/loader/loader.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/loader/loader.c b/src/loader/loader.c
index 08eeb61504b..c7e561ef2e4 100644
--- a/src/loader/loader.c
+++ b/src/loader/loader.c
@@ -436,7 +436,11 @@ loader_get_pci_driver(int fd)
char *driver = NULL;
if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id))
+#if 1
+ return strdup("pvr");
+#else
return NULL;
+#endif
for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
if (vendor_id != driver_map[i].vendor_id)
--
2.25.1

View File

@@ -0,0 +1,80 @@
From fec4f46f7cedb6b3e90bf88c3efc3cd5da0d9131 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Thu, 5 Jun 2014 12:07:01 +0100
Subject: [PATCH 03/67] dri: Add some new DRI formats and fourccs
Add ARGB4444 DRI format and fourcc.
Add YVU444_PACK10_IMG DRI format and fourcc.
Add BGR888 DRI format and fourcc.
---
include/GL/internal/dri_interface.h | 4 ++++
include/drm-uapi/drm_fourcc.h | 1 +
src/egl/drivers/dri2/egl_dri2.c | 1 +
src/mesa/drivers/dri/common/dri_util.c | 5 +++++
4 files changed, 11 insertions(+)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 66dc0927cb7..510289403d2 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1367,6 +1367,9 @@ struct __DRIdri2ExtensionRec {
#define __DRI_IMAGE_FORMAT_ABGR16161616F 0x1015
#define __DRI_IMAGE_FORMAT_SXRGB8 0x1016
#define __DRI_IMAGE_FORMAT_ABGR16161616 0x1017
+#define __DRI_IMAGE_FORMAT_ARGB4444 0x1018
+#define __DRI_IMAGE_FORMAT_YVU444_PACK10_IMG 0x1019
+#define __DRI_IMAGE_FORMAT_BGR888 0x101a
#define __DRI_IMAGE_USE_SHARE 0x0001
#define __DRI_IMAGE_USE_SCANOUT 0x0002
@@ -1397,6 +1400,7 @@ struct __DRIdri2ExtensionRec {
#define __DRI_IMAGE_FOURCC_SABGR8888 0x84324258
#define __DRI_IMAGE_FOURCC_SXRGB8888 0x85324258
#define __DRI_IMAGE_FOURCC_RGBA16161616 0x38344152 /* fourcc_code('R', 'A', '4', '8' ) */
+#define __DRI_IMAGE_FOURCC_SBGR888 0xff324742
/**
* Queryable on images created by createImageFromNames.
diff --git a/include/drm-uapi/drm_fourcc.h b/include/drm-uapi/drm_fourcc.h
index cd3ce8a8c60..57657592a38 100644
--- a/include/drm-uapi/drm_fourcc.h
+++ b/include/drm-uapi/drm_fourcc.h
@@ -344,6 +344,7 @@ extern "C" {
#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YVU444_PACK10_IMG fourcc_code('I', 'M', 'G', '2')
/*
* Format Modifiers:
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 9e5a55a287c..eee28eb4726 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -2652,6 +2652,7 @@ dri2_num_fourcc_format_planes(EGLint format)
case DRM_FORMAT_Y410:
case DRM_FORMAT_Y412:
case DRM_FORMAT_Y416:
+ case DRM_FORMAT_YVU444_PACK10_IMG:
return 1;
case DRM_FORMAT_NV12:
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index e2a11240dea..caed5fa6a68 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -904,6 +904,11 @@ static const struct {
.mesa_format = MESA_FORMAT_B5G5R5A1_UNORM,
.internal_format = GL_RGB5_A1,
},
+ {
+ .image_format = __DRI_IMAGE_FORMAT_ARGB4444,
+ .mesa_format = MESA_FORMAT_B4G4R4A4_UNORM,
+ .internal_format = GL_RGBA4,
+ },
{
.image_format = __DRI_IMAGE_FORMAT_XRGB8888,
.mesa_format = MESA_FORMAT_B8G8R8X8_UNORM,
--
2.25.1

View File

@@ -0,0 +1,104 @@
From e66cd64b65e86a23807260a9a0c73f1355715314 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Wed, 12 Aug 2015 09:11:51 +0100
Subject: [PATCH 04/67] GL_EXT_sparse_texture entry points
---
src/mapi/glapi/gen/EXT_sparse_texture.xml | 56 +++++++++++++++++++++++
src/mapi/glapi/gen/es_EXT.xml | 3 ++
src/mapi/glapi/gen/static_data.py | 2 +
3 files changed, 61 insertions(+)
create mode 100644 src/mapi/glapi/gen/EXT_sparse_texture.xml
diff --git a/src/mapi/glapi/gen/EXT_sparse_texture.xml b/src/mapi/glapi/gen/EXT_sparse_texture.xml
new file mode 100644
index 00000000000..48d03e7b9c0
--- /dev/null
+++ b/src/mapi/glapi/gen/EXT_sparse_texture.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="EXT_sparse_texture" number="240">
+
+ <enum name="TEXTURE_SPARSE_EXT" value="0x91A6"/>
+ <enum name="VIRTUAL_PAGE_SIZE_INDEX_EXT" value="0x91A7"/>
+
+ <enum name="NUM_SPARSE_LEVELS_EXT" value="0x91AA"/>
+
+ <enum name="NUM_VIRTUAL_PAGE_SIZES_EXT" value="0x91A8"/>
+
+ <enum name="VIRTUAL_PAGE_SIZE_X_EXT" value="0x9195"/>
+ <enum name="VIRTUAL_PAGE_SIZE_Y_EXT" value="0x9196"/>
+ <enum name="VIRTUAL_PAGE_SIZE_Z_EXT" value="0x9197"/>
+
+ <enum name="TEXTURE_2D" value="0x0DE1"/>
+ <enum name="TEXTURE_2D_ARRAY" value="0x8C1A"/>
+ <enum name="TEXTURE_CUBE_MAP" value="0x8513"/>
+ <enum name="TEXTURE_CUBE_MAP_ARRAY_OES" value="0x9009"/>
+ <enum name="TEXTURE_3D" value="0x806F"/>
+
+ <enum name="MAX_SPARSE_TEXTURE_SIZE_EXT" value="0x9198"/>
+ <enum name="MAX_SPARSE_3D_TEXTURE_SIZE_EXT" value="0x9199"/>
+ <enum name="MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT" value="0x919A"/>
+ <enum name="SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT" value="0x91A9"/>
+
+ <function name="TexPageCommitmentEXT" es2="3.1" exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="commit" type="GLboolean"/>
+ </function>
+
+ <function name="TexturePageCommitmentEXT" es2="3.1" exec="dynamic">
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="commit" type="GLboolean"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml
index 929b40bbd4a..962170bc58e 100644
--- a/src/mapi/glapi/gen/es_EXT.xml
+++ b/src/mapi/glapi/gen/es_EXT.xml
@@ -1433,6 +1433,9 @@
</category>
+<!-- 240. EXT_sparse_texture -->
+<xi:include href="EXT_sparse_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
<category name="GL_OES_viewport_array" number="267">
<function name="ViewportArrayvOES" es2="3.1" alias="ViewportArrayv">
<param name="first" type="GLuint"/>
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index 6accff1b231..d063930bd81 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1689,6 +1689,8 @@ offsets = {
"VertexAttribs2hvNV": 1653,
"VertexAttribs3hvNV": 1654,
"VertexAttribs4hvNV": 1655,
+ "TexPageCommitmentEXT": 1656,
+ "TexturePageCommitmentEXT" : 1657,
}
functions = [
--
2.25.1

View File

@@ -0,0 +1,106 @@
From 4a1be491de2ea78be95dc4cf08af4b1da5e16d91 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 10 Mar 2014 12:27:03 +0000
Subject: [PATCH 05/67] Add support for various GLES extensions
Add support for:
EXT_occlusion_query_boolean
IMG_multisampled_render_to_texture
OES_matrix_palette
---
src/mapi/glapi/gen/es_EXT.xml | 41 ++++++++++++++++++++++++-------
src/mapi/glapi/gen/static_data.py | 6 +++++
2 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml
index 962170bc58e..e586b0ec19b 100644
--- a/src/mapi/glapi/gen/es_EXT.xml
+++ b/src/mapi/glapi/gen/es_EXT.xml
@@ -285,28 +285,25 @@
<enum name="WEIGHT_ARRAY_BUFFER_BINDING_OES" value="0x889E"/>
<enum name="MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES" value="0x8B9E"/>
- <function name="CurrentPaletteMatrixOES" alias="CurrentPaletteMatrixARB"
- exec="skip">
+ <function name="CurrentPaletteMatrixOES" es1="1.0" exec="dynamic">
<param name="matrixpaletteindex" type="GLuint"/>
</function>
- <!-- no offset -->
- <function name="LoadPaletteFromModelViewMatrixOES" exec="skip">
+ <function name="LoadPaletteFromModelViewMatrixOES" es1="1.0" exec="dynamic">
</function>
- <function name="MatrixIndexPointerOES" alias="MatrixIndexPointerARB"
- exec="skip">
+ <function name="MatrixIndexPointerOES" es1="1.0" exec="dynamic">
<param name="size" type="GLint"/>
<param name="type" type="GLenum"/>
<param name="stride" type="GLsizei"/>
- <param name="pointer" type="const GLvoid *"/>
+ <param name="pointer" type="GLvoid *"/>
</function>
- <function name="WeightPointerOES" alias="WeightPointerARB" exec="skip">
+ <function name="WeightPointerOES" es1="1.0" exec="dynamic">
<param name="size" type="GLint"/>
<param name="type" type="GLenum"/>
<param name="stride" type="GLsizei"/>
- <param name="pointer" type="const GLvoid *"/>
+ <param name="pointer" type="GLvoid *"/>
</function>
</category>
@@ -680,6 +677,32 @@
</enum>
</category>
+<!-- 74. GL_IMG_multisampled_render_to_texture -->
+<category name="GL_IMG_multisampled_render_to_texture" number="74">
+ <enum name="RENDERBUFFER_SAMPLES_IMG" value="0x9133"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG" value="0x9134"/>
+ <enum name="MAX_SAMPLES_IMG" value="0x9135"/>
+ <enum name="TEXTURE_SAMPLES_IMG" value="0x9136"/>
+
+ <function name="RenderbufferStorageMultisampleIMG" es2="2.0" exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="samples" type="GLsizei"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ </function>
+
+ <function name="FramebufferTexture2DMultisampleIMG" es2="2.0"
+ exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="samples" type="GLsizei"/>
+ </function>
+</category>
+
<!-- 87. GL_OES_EGL_image_external -->
<category name="GL_OES_EGL_image_external" number="87">
<enum name="TEXTURE_EXTERNAL_OES" value="0x8D65"/>
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index d063930bd81..79b8f19cb75 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1691,6 +1691,12 @@ offsets = {
"VertexAttribs4hvNV": 1655,
"TexPageCommitmentEXT": 1656,
"TexturePageCommitmentEXT" : 1657,
+ "CurrentPaletteMatrixOES" : 1658,
+ "LoadPaletteFromModelViewMatrixOES" : 1659,
+ "MatrixIndexPointerOES" : 1660,
+ "WeightPointerOES" : 1661,
+ "RenderbufferStorageMultisampleIMG" : 1662,
+ "FramebufferTexture2DMultisampleIMG" : 1663,
}
functions = [
--
2.25.1

View File

@@ -0,0 +1,187 @@
From 7fdeb8bf25be01f122a7cb55dbe2b0e67e4a24a2 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 11 Mar 2014 11:50:53 +0000
Subject: [PATCH 06/67] Add EGL_IMG_cl_image extension
Add support for the experimental EGL_IMG_cl_image extension to EGL, and
the DRI2 EGL driver.
---
include/EGL/eglmesaext.h | 5 +++
include/GL/internal/dri_interface.h | 13 +++++++
src/egl/drivers/dri2/egl_dri2.c | 60 +++++++++++++++++++++++++----
src/egl/main/eglapi.c | 1 +
src/egl/main/egldisplay.h | 2 +
5 files changed, 73 insertions(+), 8 deletions(-)
diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index f0395a8a58c..5d11f3e488e 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -49,6 +49,11 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EG
#define EGL_DRM_BUFFER_FORMAT_RGB565_MESA 0x3292
#endif /* EGL_MESA_drm_image_formats */
+#ifndef EGL_IMG_cl_image
+#define EGL_IMG_cl_image 1
+#define EGL_CL_IMAGE_IMG 0x6010
+#endif /* Experimental eglCreateImageKHR target */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 510289403d2..b197092939f 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1831,6 +1831,19 @@ struct __DRIimageExtensionRec {
const unsigned int modifier_count,
unsigned int use,
void *loaderPrivate);
+
+ /**
+ * Support for experimental EGL_CL_IMAGE_IMG.
+ * Like createImageFromTexture, but from a buffer, the contents
+ * of which depend on the target.
+ *
+ * \since 8
+ */
+ __DRIimage *(*createImageFromBuffer)(__DRIcontext *context,
+ int target,
+ void *buffer,
+ unsigned *error,
+ void *loaderPrivate);
};
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index eee28eb4726..dea5899b3a8 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -995,6 +995,10 @@ dri2_setup_screen(_EGLDisplay *disp)
disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE;
}
#endif
+ if (dri2_dpy->image->base.version >= 8 &&
+ dri2_dpy->image->createImageFromBuffer) {
+ disp->Extensions.IMG_cl_image = EGL_TRUE;
+ }
}
if (dri2_dpy->flush_control)
@@ -2360,17 +2364,13 @@ dri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf,
return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc);
}
-/**
- * Set the error code after a call to
- * dri2_egl_image::dri_image::createImageFromTexture.
- */
static void
-dri2_create_image_khr_texture_error(int dri_error)
+dri2_create_image_khr_error(int dri_error)
{
EGLint egl_error = egl_error_from_dri_image_error(dri_error);
if (egl_error != EGL_SUCCESS)
- _eglError(egl_error, "dri2_create_image_khr_texture");
+ _eglError(egl_error, "dri2_create_image_khr");
}
static _EGLImage *
@@ -2449,7 +2449,49 @@ dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
attrs.GLTextureLevel,
&error,
NULL);
- dri2_create_image_khr_texture_error(error);
+ dri2_create_image_khr_error(error);
+
+ if (!dri2_img->dri_image) {
+ free(dri2_img);
+ return EGL_NO_IMAGE_KHR;
+ }
+ return &dri2_img->base;
+}
+
+static _EGLImage *
+dri2_create_image_img_buffer(_EGLDisplay *disp, _EGLContext *ctx,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint *attr_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
+ struct dri2_egl_image *dri2_img;
+ unsigned error;
+
+ switch (target) {
+ case EGL_CL_IMAGE_IMG:
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ dri2_img = malloc(sizeof *dri2_img);
+ if (!dri2_img) {
+ _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ _eglInitImage(&dri2_img->base, disp);
+
+ dri2_img->dri_image =
+ dri2_dpy->image->createImageFromBuffer(dri2_ctx->dri_context,
+ target,
+ buffer,
+ &error,
+ NULL);
+ dri2_create_image_khr_error(error);
if (!dri2_img->dri_image) {
free(dri2_img);
@@ -2916,7 +2958,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
&error,
NULL);
}
- dri2_create_image_khr_texture_error(error);
+ dri2_create_image_khr_error(error);
if (!dri_image)
return EGL_NO_IMAGE_KHR;
@@ -3152,6 +3194,8 @@ dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
case EGL_WAYLAND_BUFFER_WL:
return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
#endif
+ case EGL_CL_IMAGE_IMG:
+ return dri2_create_image_img_buffer(disp, ctx, target, buffer, attr_list);
default:
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
return EGL_NO_IMAGE_KHR;
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 17e36af22e1..6ffcff8b2cc 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -549,6 +549,7 @@ _eglCreateExtensionsString(_EGLDisplay *disp)
_EGL_CHECK_EXTENSION(WL_bind_wayland_display);
_EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
+ _EGL_CHECK_EXTENSION(IMG_cl_image);
#undef _EGL_CHECK_EXTENSION
}
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 4d2afbc712e..5b05dcc1e6d 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -150,6 +150,8 @@ struct _egl_extensions
EGLBoolean WL_bind_wayland_display;
EGLBoolean WL_create_wayland_buffer_from_image;
+
+ EGLBoolean IMG_cl_image;
};
struct _egl_display
--
2.25.1

View File

@@ -0,0 +1,51 @@
From fa57726f60bc6fc6e7094f16300cdc41b44ff4f3 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Wed, 18 Jun 2014 17:10:28 +0100
Subject: [PATCH 07/67] egl: Be stricter when making a context current without
any surfaces
The EGL_KHR_surfaceless_context extension spec states for eglMakeCurrent:
"If <ctx> does not support being bound without read and draw
surfaces, and both <draw> and <read> are EGL_NO_SURFACE, an
EGL_BAD_MATCH error is generated."
Only OpenGLES contexts support this, via the GL_OES_surfaceless_context,
so if EGL_KHR_surfaceless_context is supported and the context isn't an
OpenGLES context then set the EGL error to EGL_BAD_MATCH.
NOTE: This patch can't be upstreamed as is because we set the error to
EGL_BAD_MATCH if we have an OpenGLES 1.x context but the
GL_OES_surfaceless_context extension spec says:
"This extension is written against the OpenGL ES 2.0 Specification
but can apply to OpenGL ES 1.1 with the GL_OES_framebuffer_object
extension."
All Mesa OpenGLES drivers support GL_OES_framebuffer_object, but we
don't, so there would never be a reason to check whether or not this
extension is supported.
In order to upstream this patch the check would need to be changed
to set the error to EGL_BAD_MATCH if EGL_KHR_surfaceless_context is
supported and the context API isn't OpenGLES or the OpenGLES version
is 1.0.
---
src/egl/main/eglapi.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 6ffcff8b2cc..3cd69b96a0f 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -888,6 +888,9 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
if (draw_surf || read_surf)
RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
+ if (disp->Extensions.KHR_surfaceless_context && context &&
+ (context->ClientAPI != EGL_OPENGL_ES_API || context->ClientMajorVersion == 1))
+ RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
}
/* If a native window underlying either draw or read is no longer valid,
--
2.25.1

View File

@@ -0,0 +1,46 @@
From f556292d5811750d119acea6c7dc0c5ebd3e1af6 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Tue, 15 Sep 2015 14:15:31 +0100
Subject: [PATCH 08/67] egl: optimise eglMakeCurrent for the case where nothing
has changed
When an application calls eglMakeCurrent with a context, draw surface and
read surface that match those that are currently bound to the calling
thread don't perform a flush as this is an expensive operation.
---
src/egl/main/eglapi.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 3cd69b96a0f..234449adf64 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -853,6 +853,7 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
EGLContext ctx)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLContext *current_context = _eglGetCurrentContext();
_EGLContext *context = _eglLookupContext(ctx, disp);
_EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
_EGLSurface *read_surf = _eglLookupSurface(read, disp);
@@ -909,7 +910,16 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
draw_surf && !draw_surf->ProtectedContent)
RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
- ret = disp->Driver->MakeCurrent(disp, draw_surf, read_surf, context);
+ /* As an optimisation don't do anything unless something has changed */
+ if (context != current_context ||
+ (current_context &&
+ (draw_surf != current_context->DrawSurface ||
+ read_surf != current_context->ReadSurface)) ||
+ (!current_context && (draw_surf || read_surf))) {
+ ret = disp->Driver->MakeCurrent(disp, draw_surf, read_surf, context);
+ } else {
+ ret = EGL_TRUE;
+ }
RETURN_EGL_EVAL(disp, ret);
}
--
2.25.1

View File

@@ -0,0 +1,84 @@
From 13e925af5ba3bd763eb4c9e5d0781f92981550f6 Mon Sep 17 00:00:00 2001
From: Rufus Hamade <rufus.hamade@imgtec.com>
Date: Thu, 4 Feb 2016 14:09:26 +0000
Subject: [PATCH 09/67] GL_EXT_shader_pixel_local_storage2 entry points
---
.../gen/EXT_shader_pixel_local_storage2.xml | 35 +++++++++++++++++++
src/mapi/glapi/gen/es_EXT.xml | 3 ++
src/mapi/glapi/gen/static_data.py | 3 ++
3 files changed, 41 insertions(+)
create mode 100644 src/mapi/glapi/gen/EXT_shader_pixel_local_storage2.xml
diff --git a/src/mapi/glapi/gen/EXT_shader_pixel_local_storage2.xml b/src/mapi/glapi/gen/EXT_shader_pixel_local_storage2.xml
new file mode 100644
index 00000000000..20e186c0f0d
--- /dev/null
+++ b/src/mapi/glapi/gen/EXT_shader_pixel_local_storage2.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="EXT_shader_pixel_local_storage2" number="240">
+
+ <enum name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT" value="0x8F63"/>
+ <enum name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT" value="0x8F67"/>
+ <enum name="GL_SHADER_PIXEL_LOCAL_STORAGE_EXT" value="0x8F64"/>
+ <enum name="GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT" value="0x9650"/>
+ <enum name="GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT" value="0x9651"/>
+ <enum name="GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT" value="0x9652"/>
+
+ <function name="ClearPixelLocalStorageuiEXT" es2="3.1" exec="dynamic">
+ <param name="offset" type="GLsizei"/>
+ <param name="n" type="GLsizei"/>
+ <param name="values" type="const GLuint *"/>
+ </function>
+
+ <function name="FramebufferPixelLocalStorageSizeEXT" es2="3.1"
+ exec="dynamic">
+ <param name="target" type="GLuint"/>
+ <param name="size" type="GLsizei"/>
+ </function>
+
+ <function name="GetFramebufferPixelLocalStorageSizeEXT" es2="3.1"
+ exec="dynamic">
+ <param name="target" type="GLuint"/>
+ <return type="GLsizei"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml
index e586b0ec19b..a3bfe86a888 100644
--- a/src/mapi/glapi/gen/es_EXT.xml
+++ b/src/mapi/glapi/gen/es_EXT.xml
@@ -1459,6 +1459,9 @@
<!-- 240. EXT_sparse_texture -->
<xi:include href="EXT_sparse_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<!-- 253. GL_EXT_shader_pixel_local_storage2 -->
+<xi:include href="EXT_shader_pixel_local_storage2.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
<category name="GL_OES_viewport_array" number="267">
<function name="ViewportArrayvOES" es2="3.1" alias="ViewportArrayv">
<param name="first" type="GLuint"/>
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index 79b8f19cb75..99729e21b7f 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1697,6 +1697,9 @@ offsets = {
"WeightPointerOES" : 1661,
"RenderbufferStorageMultisampleIMG" : 1662,
"FramebufferTexture2DMultisampleIMG" : 1663,
+ "ClearPixelLocalStorageuiEXT" : 1664,
+ "FramebufferPixelLocalStorageSizeEXT" : 1665,
+ "GetFramebufferPixelLocalStorageSizeEXT" : 1666,
}
functions = [
--
2.25.1

View File

@@ -0,0 +1,85 @@
From f43a3258b8f4859ff3e0e3d3d356b319dd6a5435 Mon Sep 17 00:00:00 2001
From: Rufus Hamade <rufus.hamade@imgtec.com>
Date: Thu, 4 Feb 2016 14:09:26 +0000
Subject: [PATCH 10/67] GL_IMG_framebuffer_downsample entry points
---
.../glapi/gen/IMG_framebuffer_downsample.xml | 37 +++++++++++++++++++
src/mapi/glapi/gen/es_EXT.xml | 3 ++
src/mapi/glapi/gen/static_data.py | 2 +
3 files changed, 42 insertions(+)
create mode 100644 src/mapi/glapi/gen/IMG_framebuffer_downsample.xml
diff --git a/src/mapi/glapi/gen/IMG_framebuffer_downsample.xml b/src/mapi/glapi/gen/IMG_framebuffer_downsample.xml
new file mode 100644
index 00000000000..b5ce77dfb08
--- /dev/null
+++ b/src/mapi/glapi/gen/IMG_framebuffer_downsample.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_IMG_framebuffer_downsample" number="255">
+
+ <enum name="FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG" value="0x913C"/>
+ <enum name="NUM_DOWNSAMPLE_SCALES_IMG" value="0x913D"/>
+ <enum name="DOWNSAMPLE_SCALES_IMG" value="0x913E"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG" value="0x913F"/>
+
+ <function name="FramebufferTexture2DDownsampleIMG" es1="1.0" es2="2.0"
+ exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="xscale" type="GLint"/>
+ <param name="yscale" type="GLint"/>
+ </function>
+
+ <function name="FramebufferTextureLayerDownsampleIMG" es1="1.0" es2="2.0"
+ exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="layer" type="GLint"/>
+ <param name="xscale" type="GLint"/>
+ <param name="yscale" type="GLint"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml
index a3bfe86a888..b3432820ba6 100644
--- a/src/mapi/glapi/gen/es_EXT.xml
+++ b/src/mapi/glapi/gen/es_EXT.xml
@@ -1462,6 +1462,9 @@
<!-- 253. GL_EXT_shader_pixel_local_storage2 -->
<xi:include href="EXT_shader_pixel_local_storage2.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<!-- 255. GL_IMG_framebuffer_downsample -->
+<xi:include href="IMG_framebuffer_downsample.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
<category name="GL_OES_viewport_array" number="267">
<function name="ViewportArrayvOES" es2="3.1" alias="ViewportArrayv">
<param name="first" type="GLuint"/>
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index 99729e21b7f..c723cb3fab8 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1700,6 +1700,8 @@ offsets = {
"ClearPixelLocalStorageuiEXT" : 1664,
"FramebufferPixelLocalStorageSizeEXT" : 1665,
"GetFramebufferPixelLocalStorageSizeEXT" : 1666,
+ "FramebufferTexture2DDownsampleIMG" : 1667,
+ "FramebufferTextureLayerDownsampleIMG" : 1668,
}
functions = [
--
2.25.1

View File

@@ -0,0 +1,53 @@
From cbc7a7501ea4ceffd55ca389deb55d12ff9ceb3f Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 11 Jul 2016 12:45:30 +0100
Subject: [PATCH 11/67] GL_OVR_multiview entry points
---
src/mapi/glapi/gen/gl_API.xml | 17 +++++++++++++++++
src/mapi/glapi/gen/static_data.py | 1 +
2 files changed, 18 insertions(+)
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index cf5a0f0a0c0..4e35de0f4ea 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -13125,6 +13125,23 @@
</function>
</category>
+<category name="GL_OVR_multiview" number="478">
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR" value="0x9630" />
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR" value="0x9632" />
+ <enum name="MAX_VIEWS_OVR" value="0x9631">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR" value="0x9633" />
+ <function name="FramebufferTextureMultiviewOVR" es2="3.0" exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="baseViewIndex" type="GLint"/>
+ <param name="numViews" type="GLsizei"/>
+ </function>
+</category>
+
<xi:include href="EXT_window_rectangles.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<!-- 520. GL_EXT_shader_framebuffer_fetch -->
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index c723cb3fab8..73625c7fe41 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1702,6 +1702,7 @@ offsets = {
"GetFramebufferPixelLocalStorageSizeEXT" : 1666,
"FramebufferTexture2DDownsampleIMG" : 1667,
"FramebufferTextureLayerDownsampleIMG" : 1668,
+ "FramebufferTextureMultiviewOVR" : 1669,
}
functions = [
--
2.25.1

View File

@@ -0,0 +1,68 @@
From 91ea37486db99fd403654ebff2a0a8401f7cd600 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 11 Jul 2016 13:29:51 +0100
Subject: [PATCH 12/67] Add OVR_multiview_multisampled_render_to_texture
---
...ltiview_multisampled_render_to_texture.xml | 21 +++++++++++++++++++
src/mapi/glapi/gen/es_EXT.xml | 3 +++
src/mapi/glapi/gen/static_data.py | 1 +
3 files changed, 25 insertions(+)
create mode 100644 src/mapi/glapi/gen/OVR_multiview_multisampled_render_to_texture.xml
diff --git a/src/mapi/glapi/gen/OVR_multiview_multisampled_render_to_texture.xml b/src/mapi/glapi/gen/OVR_multiview_multisampled_render_to_texture.xml
new file mode 100644
index 00000000000..86bebc728e9
--- /dev/null
+++ b/src/mapi/glapi/gen/OVR_multiview_multisampled_render_to_texture.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_OVR_multiview_multisampled_render_to_texture" number="250">
+
+ <function name="FramebufferTextureMultisampleMultiviewOVR" es2="3.0"
+ exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="samples" type="GLsizei"/>
+ <param name="baseViewIndex" type="GLint"/>
+ <param name="numViews" type="GLsizei"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml
index b3432820ba6..fe8f27e1e6f 100644
--- a/src/mapi/glapi/gen/es_EXT.xml
+++ b/src/mapi/glapi/gen/es_EXT.xml
@@ -1459,6 +1459,9 @@
<!-- 240. EXT_sparse_texture -->
<xi:include href="EXT_sparse_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<!-- 250. GL_OVR_multiview_multisampled_render_to_texture -->
+<xi:include href="OVR_multiview_multisampled_render_to_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
<!-- 253. GL_EXT_shader_pixel_local_storage2 -->
<xi:include href="EXT_shader_pixel_local_storage2.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index 73625c7fe41..dc6bdc9dcce 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1703,6 +1703,7 @@ offsets = {
"FramebufferTexture2DDownsampleIMG" : 1667,
"FramebufferTextureLayerDownsampleIMG" : 1668,
"FramebufferTextureMultiviewOVR" : 1669,
+ "FramebufferTextureMultisampleMultiviewOVR" : 1670,
}
functions = [
--
2.25.1

View File

@@ -0,0 +1,57 @@
From b38c4118c7a3a060ef1c8b8477200f5a73305397 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Thu, 18 Aug 2016 15:52:28 +0100
Subject: [PATCH 13/67] wayland-drm: install wayland-drm.xml to the configured
pkgdatadir
Add a pkg-config file as well so that it can be located without hardcoding the
path.
---
src/egl/wayland/wayland-drm/meson.build | 15 +++++++++++++++
src/egl/wayland/wayland-drm/wayland-drm.pc.in | 7 +++++++
2 files changed, 22 insertions(+)
create mode 100644 src/egl/wayland/wayland-drm/wayland-drm.pc.in
diff --git a/src/egl/wayland/wayland-drm/meson.build b/src/egl/wayland/wayland-drm/meson.build
index b4782a013c9..f291ef9f55e 100644
--- a/src/egl/wayland/wayland-drm/meson.build
+++ b/src/egl/wayland/wayland-drm/meson.build
@@ -49,6 +49,21 @@ libwayland_drm = static_library(
build_by_default : false,
)
+install_data('wayland-drm.xml')
+
+pkg.generate(
+ filebase : 'wayland-drm',
+ name : 'Mesa Wayland Protocols',
+ description : 'Mesa Wayland protocol files',
+ version : meson.project_version(),
+ variables : [
+ 'datarootdir=${prefix}/' + get_option('datadir'),
+ 'pkgdatadir=${pc_sysrootdir}${datarootdir}/' + meson.project_name(),
+ ],
+ install_dir : '@0@/@1@/pkgconfig'.format(get_option('prefix'),
+ get_option('datadir')),
+)
+
# linux-dmabuf isn't part of wayland-drm, but this happens to be the only
# place which is a) guaranteed to be built when building either or both
# of EGL and Vulkan WSI, and b) guaranteed to be included before both,
diff --git a/src/egl/wayland/wayland-drm/wayland-drm.pc.in b/src/egl/wayland/wayland-drm/wayland-drm.pc.in
new file mode 100644
index 00000000000..d08ccdaf6ce
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/wayland-drm.pc.in
@@ -0,0 +1,7 @@
+prefix=@prefix@
+datarootdir=@datarootdir@
+pkgdatadir=${pc_sysrootdir}@datadir@/@PACKAGE@
+
+Name: @PACKAGE_NAME@ Wayland Protocols
+Description: @PACKAGE_NAME@ Wayland protocol files
+Version: @PACKAGE_VERSION@
\ No newline at end of file
--
2.25.1

View File

@@ -0,0 +1,27 @@
From b80c78b05ebb661e7f088d0a369b0f0d2990afca Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Wed, 26 Oct 2016 16:24:28 +0100
Subject: [PATCH 14/67] Enable buffer sharing in the kms_swrast driver
Enable buffer sharing, so that a DRI driver can be loaded by a
Wayland client when kms_swrast is being used by the compositor.
---
src/gallium/frontends/dri/dri2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c
index ebc18a73c86..09f4b02e758 100644
--- a/src/gallium/frontends/dri/dri2.c
+++ b/src/gallium/frontends/dri/dri2.c
@@ -2400,7 +2400,7 @@ dri_kms_init_screen(__DRIscreen * sPriv)
if (!configs)
goto destroy_screen;
- screen->can_share_buffer = false;
+ screen->can_share_buffer = true;
screen->auto_fake_front = dri_with_format(sPriv);
screen->broken_invalidate = !sPriv->dri2.useInvalidate;
screen->lookup_egl_image = dri2_lookup_egl_image;
--
2.25.1

View File

@@ -0,0 +1,46 @@
From 55a15a019dd792477e39f6225f2b4e50a1359b66 Mon Sep 17 00:00:00 2001
From: James Glanville <James.Glanville@imgtec.com>
Date: Tue, 28 Feb 2017 16:08:47 +0000
Subject: [PATCH 15/67] egl/wayland: add support for RGB565 back buffers
---
src/egl/drivers/dri2/platform_wayland.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index cfff0ade90e..c18edc0de4e 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -633,18 +633,27 @@ back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
__DRIimage *image;
- int name, pitch;
+ int name, pitch, format;
image = dri2_surf->back->dri_image;
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
buffer->attachment = __DRI_BUFFER_BACK_LEFT;
buffer->name = name;
buffer->pitch = pitch;
- buffer->cpp = 4;
buffer->flags = 0;
+
+ switch (format) {
+ case __DRI_IMAGE_FORMAT_RGB565:
+ buffer->cpp = 2;
+ break;
+ default:
+ buffer->cpp = 4;
+ break;
+ }
}
static int
--
2.25.1

View File

@@ -0,0 +1,49 @@
From 03f4f18f9edb4090c6aeca16e6f4de602aea68bf Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 13 Apr 2017 10:12:40 +0100
Subject: [PATCH 16/67] egl/dri3: fix segfault in eglCopyBuffers
The loader_dri3_copy_drawable function expected the drawable to have
a fake front buffer, resulting in a segfault if there wasn't one,
when dri3_fence_reset was called.
If there is no fake front buffer, but there are back buffers, use the
current back buffer.
---
src/loader/loader_dri3_helper.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index 6e825f9a898..ff6d1ffc660 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -863,15 +863,24 @@ loader_dri3_copy_drawable(struct loader_dri3_drawable *draw,
xcb_drawable_t dest,
xcb_drawable_t src)
{
+ struct loader_dri3_buffer *buffer;
+
+ if (draw->have_fake_front)
+ buffer = dri3_fake_front_buffer(draw);
+ else if (draw->have_back)
+ buffer = dri3_back_buffer(draw);
+ else
+ return;
+
loader_dri3_flush(draw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_COPYSUBBUFFER);
- dri3_fence_reset(draw->conn, dri3_fake_front_buffer(draw));
+ dri3_fence_reset(draw->conn, buffer);
dri3_copy_area(draw->conn,
src, dest,
dri3_drawable_gc(draw),
0, 0, 0, 0, draw->width, draw->height);
- dri3_fence_trigger(draw->conn, dri3_fake_front_buffer(draw));
- dri3_fence_await(draw->conn, draw, dri3_fake_front_buffer(draw));
+ dri3_fence_trigger(draw->conn, buffer);
+ dri3_fence_await(draw->conn, draw, buffer);
}
void
--
2.25.1

View File

@@ -0,0 +1,78 @@
From d98cd46b5841ecb785a801a977a1b341d98d08c4 Mon Sep 17 00:00:00 2001
From: Iosif Antochi <iosif.antochi@imgtec.com>
Date: Wed, 14 Jun 2017 14:49:55 +0100
Subject: [PATCH 17/67] egl: automatically call eglReleaseThread on thread
termination
EGL thread cleanup conformance tests could run out of memory as the contexts
were not freed even though the application requested to have them deleted.
This was caused by the fact that the contexts were still current on their
threads when delete was called and (in order not to block any potential
pending renders) they were just marked for delete.
Fix this by calling eglReleaseThread on thread termination. This is safe to
do even if this was already called by the application since, according to the
EGL 1.5 spec, eglReleaseThread can be called multiple times without error.
Fixes:
dEQP-EGL.functional.thread_cleanup.multi_context_*
dEQP-EGL.functional.robustness.create_context.query_robust_access
---
src/egl/main/eglcurrent.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c
index 11277d3e4c0..c87eac0d007 100644
--- a/src/egl/main/eglcurrent.c
+++ b/src/egl/main/eglcurrent.c
@@ -44,6 +44,7 @@ static mtx_t _egl_TSDMutex = _MTX_INITIALIZER_NP;
static EGLBoolean _egl_TSDInitialized;
static tss_t _egl_TSD;
static void _eglDestroyThreadInfo(_EGLThreadInfo *t);
+static void _eglDestroyThreadInfoCallback(_EGLThreadInfo *t);
#ifdef USE_ELF_TLS
static __THREAD_INITIAL_EXEC const _EGLThreadInfo *_egl_TLS;
@@ -86,7 +87,7 @@ static inline EGLBoolean _eglInitTSD()
/* check again after acquiring lock */
if (!_egl_TSDInitialized) {
- if (tss_create(&_egl_TSD, (void (*)(void *)) _eglDestroyThreadInfo) != thrd_success) {
+ if (tss_create(&_egl_TSD, (void (*)(void *)) _eglDestroyThreadInfoCallback) != thrd_success) {
mtx_unlock(&_egl_TSDMutex);
return EGL_FALSE;
}
@@ -135,6 +136,30 @@ _eglDestroyThreadInfo(_EGLThreadInfo *t)
}
+/**
+ * Delete/free a _EGLThreadInfo object.
+ */
+static void
+_eglDestroyThreadInfoCallback(_EGLThreadInfo *t)
+{
+ /* If this callback is called on thread termination then try to also give a
+ * chance to cleanup to the client drivers. If called for module termination
+ * then just release the thread information as calling eglReleaseThread
+ * would result in a deadlock.
+ */
+ if (_egl_TSDInitialized) {
+ /* The callback handler has replaced the TLS entry, which is passed in as
+ * 't', with NULL. Restore it here so that the release thread finds it in
+ * the TLS entry.
+ */
+ _eglSetTSD(t);
+ eglReleaseThread();
+ } else {
+ _eglDestroyThreadInfo(t);
+ }
+}
+
+
/**
* Make sure TSD is initialized and return current value.
*/
--
2.25.1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,231 @@
From 230a8cb550dc23a46a96b1852720c262bb244665 Mon Sep 17 00:00:00 2001
From: Eric Engestrom <eric.engestrom@imgtec.com>
Date: Mon, 6 Feb 2017 15:54:00 +0000
Subject: [PATCH 19/67] egl: add support for EGL_TIZEN_image_native_surface
---
src/egl/drivers/dri2/egl_dri2.c | 127 ++++++++++++++++++++------
src/egl/drivers/dri2/platform_tizen.c | 1 +
src/egl/main/eglapi.c | 2 +
src/egl/main/egldisplay.h | 2 +
4 files changed, 102 insertions(+), 30 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 6d34395d65d..eaa0baed066 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -58,6 +58,10 @@
#include "X11/Xlibint.h"
#endif
+#ifdef HAVE_TIZEN_PLATFORM
+#include <tpl.h>
+#endif
+
#include "egldefines.h"
#include "egl_dri2.h"
#include "GL/mesa_glinterop.h"
@@ -2311,28 +2315,115 @@ dri2_fourcc_from_tbm_format(tbm_format format)
switch (format) {
case TBM_FORMAT_ARGB8888:
return DRM_FORMAT_ARGB8888;
+ case TBM_FORMAT_ABGR8888:
+ return DRM_FORMAT_ABGR8888;
case TBM_FORMAT_XRGB8888:
return DRM_FORMAT_XRGB8888;
+ case TBM_FORMAT_XBGR8888:
+ return DRM_FORMAT_XBGR8888;
+ case TBM_FORMAT_ARGB4444:
+ return DRM_FORMAT_ARGB4444;
+ case TBM_FORMAT_ARGB1555:
+ return DRM_FORMAT_ARGB1555;
case TBM_FORMAT_RGB565:
return DRM_FORMAT_RGB565;
+ case TBM_FORMAT_YUV420:
+ return DRM_FORMAT_YUV420;
+ case TBM_FORMAT_YVU420:
+ return DRM_FORMAT_YVU420;
+ case TBM_FORMAT_NV12:
+ return DRM_FORMAT_NV12;
+ case TBM_FORMAT_NV21:
+ return DRM_FORMAT_NV21;
default:
_eglLog(_EGL_DEBUG, "%s: unsupported tbm format %#x", __func__, format);
return 0;
}
}
+static _EGLImage *
+dri2_create_image_tbm_surface(_EGLDisplay *disp, _EGLContext *ctx,
+ tbm_surface_h tbm_surf)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ __DRIimage *dri_image;
+ tbm_surface_info_s info;
+ int fd[TBM_SURF_PLANE_MAX], pitch[TBM_SURF_PLANE_MAX], offset[TBM_SURF_PLANE_MAX];
+ int fourcc;
+ int i;
+
+ if (tbm_surface_get_info(tbm_surf, &info)) {
+ _eglError(EGL_BAD_PARAMETER, "tbm_surface_get_info");
+ return NULL;
+ }
+
+ fourcc = dri2_fourcc_from_tbm_format(info.format);
+ if (!fourcc) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_fourcc_from_tbm_format");
+ return NULL;
+ }
+
+ for (i = 0; i < info.num_planes; i++) {
+ tbm_bo tbm_buf;
+
+ tbm_buf = tbm_surface_internal_get_bo(tbm_surf, i);
+ if (!tbm_buf) {
+ _eglError(EGL_BAD_PARAMETER, "tbm_surface_internal_get_bo");
+ goto fail_close;
+ }
+
+ pitch[i] = info.planes[i].stride;
+ offset[i] = info.planes[i].offset;
+ fd[i] = tbm_bo_export_fd(tbm_buf);
+ }
+
+ dri_image = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
+ info.width,
+ info.height,
+ fourcc,
+ &fd[0],
+ info.num_planes,
+ &pitch[0],
+ &offset[0],
+ tbm_surf);
+ for (i = 0; i < info.num_planes; i++) {
+ close(fd[i]);
+ fd[i] = -1;
+ }
+
+ if (!dri_image) {
+ _eglError(EGL_BAD_PARAMETER, "createImageFromFds");
+ return NULL;
+ }
+
+ return dri2_create_image_from_dri(disp, dri_image);
+
+fail_close:
+ while (i--)
+ close(fd[i]);
+
+ return NULL;
+}
+
+static _EGLImage *
+dri2_create_image_tizen(_EGLDisplay *disp, _EGLContext *ctx,
+ EGLClientBuffer _buffer,
+ const EGLint *attr_list)
+{
+ tbm_surface_h tbm_surf = (tbm_surface_h)_buffer;
+
+ return dri2_create_image_tbm_surface(disp, ctx, tbm_surf);
+}
+
static _EGLImage *
dri2_create_image_wayland_wl_buffer_tizen(_EGLDisplay *disp, _EGLContext *ctx,
EGLClientBuffer _buffer,
const EGLint *attr_list)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- __DRIimage *dri_image;
_EGLImageAttribs attrs;
tbm_surface_h tbm_surf;
- tbm_bo tbm_buf;
tbm_surface_info_s info;
- int fourcc, fd, pitch, offset;
tbm_surf = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_dpy,
(tpl_handle_t) _buffer);
@@ -2363,33 +2454,7 @@ dri2_create_image_wayland_wl_buffer_tizen(_EGLDisplay *disp, _EGLContext *ctx,
return NULL;
}
- tbm_buf = tbm_surface_internal_get_bo(tbm_surf, attrs.PlaneWL);
- if (!tbm_buf) {
- _eglError(EGL_BAD_PARAMETER, "tbm_surface_internal_get_bo");
- return NULL;
- }
-
- fourcc = dri2_fourcc_from_tbm_format(info.format);
- pitch = info.planes[attrs.PlaneWL].stride;
- offset = info.planes[attrs.PlaneWL].offset;
- fd = tbm_bo_export_fd(tbm_buf);
-
- dri_image = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
- info.width,
- info.height,
- fourcc,
- &fd,
- 1,
- &pitch,
- &offset,
- tbm_surf);
- close(fd);
- if (dri_image == NULL) {
- _eglError(EGL_BAD_PARAMETER, "createImageFromFds");
- return NULL;
- }
-
- return dri2_create_image_from_dri(disp, dri_image);
+ return dri2_create_image_tbm_surface(disp, ctx, tbm_surf);
}
#endif
@@ -3296,6 +3361,8 @@ dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
#ifdef HAVE_TIZEN_PLATFORM
case EGL_WAYLAND_BUFFER_WL:
return dri2_create_image_wayland_wl_buffer_tizen(disp, ctx, buffer, attr_list);
+ case EGL_NATIVE_SURFACE_TIZEN:
+ return dri2_create_image_tizen(disp, ctx, buffer, attr_list);
#endif
case EGL_CL_IMAGE_IMG:
return dri2_create_image_img_buffer(disp, ctx, target, buffer, attr_list);
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index a08bc8c07bf..ad75c115d7e 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -965,6 +965,7 @@ dri2_initialize_tizen(_EGLDisplay *dpy)
dpy->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE;
dpy->Extensions.KHR_image_base = EGL_TRUE;
dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
+ dpy->Extensions.TIZEN_image_native_surface = EGL_TRUE;
/*
* Fill vtbl last to prevent accidentally calling virtual function during
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 43c7b917909..e2a7797d73e 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -553,6 +553,8 @@ _eglCreateExtensionsString(_EGLDisplay *disp)
_EGL_CHECK_EXTENSION(NV_post_sub_buffer);
+ _EGL_CHECK_EXTENSION(TIZEN_image_native_surface);
+
_EGL_CHECK_EXTENSION(WL_bind_wayland_display);
_EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index cbb098331bf..0a7366b7c07 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -149,6 +149,8 @@ struct _egl_extensions
EGLBoolean NV_post_sub_buffer;
+ EGLBoolean TIZEN_image_native_surface;
+
EGLBoolean WL_bind_wayland_display;
EGLBoolean WL_create_wayland_buffer_from_image;
--
2.25.1

View File

@@ -0,0 +1,33 @@
From 54d08798efca8f8929744a238e2b8b2851083317 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Wed, 8 Nov 2017 15:15:20 +0000
Subject: [PATCH 20/67] egl/wayland: post maximum damage when blitting
When blitting, as part of the "is_different_gpu" case when swapping
buffers, the blit is done using the full surface dimensions, ignoring
the damage region. This results in corruption of the non damaged region
on screen. Workaround this by posting maximum damage when blitting.
A better fix would be to limit the blit to the damaged region, at least
when the number of damage rectangles is 1.
---
src/egl/drivers/dri2/platform_wayland.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index c18edc0de4e..c2e428769fe 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -1112,7 +1112,8 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
/* If the compositor doesn't support damage_buffer, we deliberately
* ignore the damage region and post maximum damage, due to
* https://bugs.freedesktop.org/78190 */
- if (!n_rects || !try_damage_buffer(dri2_surf, rects, n_rects))
+ if (dri2_dpy->is_different_gpu ||
+ !n_rects || !try_damage_buffer(dri2_surf, rects, n_rects))
wl_surface_damage(dri2_surf->wl_surface_wrapper,
0, 0, INT32_MAX, INT32_MAX);
--
2.25.1

View File

@@ -0,0 +1,46 @@
From a6aa5c866c25f7f334afbbcc3835467d50eb8965 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Wed, 8 Nov 2017 15:26:25 +0000
Subject: [PATCH 21/67] egl/wayland: flush the drawable before blitting
Flush the drawable before blitting in the "is_different_gpu" case when
swapping buffers, and pass the flush flag to the blitImage call. The
change brings the code into line with the way the DRI3 GLX code works.
For the PowerVR driver, the drawable parameters that will be used in
the flush have been obtained previously, including any native fence
associated with the blit source. The blit will result in a new native
fence for the source, and make the one in the drawable parameters
invalid.
---
src/egl/drivers/dri2/platform_wayland.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index c2e428769fe..811d28bd669 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -1117,6 +1117,8 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
wl_surface_damage(dri2_surf->wl_surface_wrapper,
0, 0, INT32_MAX, INT32_MAX);
+ dri2_flush_drawable_for_swapbuffers(disp, draw);
+
if (dri2_dpy->is_different_gpu) {
_EGLContext *ctx = _eglGetCurrentContext();
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
@@ -1126,10 +1128,9 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
0, 0, dri2_surf->base.Width,
dri2_surf->base.Height,
0, 0, dri2_surf->base.Width,
- dri2_surf->base.Height, 0);
+ dri2_surf->base.Height, __BLIT_FLAG_FLUSH);
}
- dri2_flush_drawable_for_swapbuffers(disp, draw);
dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
wl_surface_commit(dri2_surf->wl_surface_wrapper);
--
2.25.1

View File

@@ -0,0 +1,380 @@
From 404c0e915de381c2337c79657f80b0aa95c1c995 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Wed, 25 Oct 2017 18:15:00 +0100
Subject: [PATCH 22/67] egl/tizen: create an internal _EGLImage for each tbm
surface
Create an internal _EGLImage the first time a tbm surface is seen
by eglCreateImageKHR (with either the EGL_WAYLAND_BUFFER_WL or
EGL_NATIVE_SURFACE_TIZEN target) and return a copy of it to the
caller. This avoids some tbm surfaces being frequently mapped and
then unmapped from the GPU.
---
src/egl/drivers/dri2/egl_dri2.c | 236 +++++++++++++++++++++++++-
src/egl/drivers/dri2/egl_dri2.h | 12 ++
src/egl/drivers/dri2/platform_tizen.c | 6 +
3 files changed, 251 insertions(+), 3 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index eaa0baed066..db993f8f059 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1264,6 +1264,10 @@ dri2_display_destroy(_EGLDisplay *disp)
break;
#ifdef HAVE_TIZEN_PLATFORM
case _EGL_PLATFORM_TIZEN:
+ if (dri2_dpy->image_list_mutex_initialized) {
+ pthread_mutex_destroy(&dri2_dpy->image_list_mutex);
+ dri2_dpy->image_list_mutex_initialized = false;
+ }
if (dri2_dpy->tpl_dpy)
tpl_object_unreference((tpl_object_t *) dri2_dpy->tpl_dpy);
break;
@@ -1320,6 +1324,60 @@ dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf)
}
}
+static void
+dri2_display_release_resources_tizen(_EGLDisplay *disp)
+{
+#ifdef HAVE_TIZEN_PLATFORM
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ _EGLResource *image_elem;
+
+ /* Destroy _EGLImages in the image_list */
+ pthread_mutex_lock(&dri2_dpy->image_list_mutex);
+ image_elem = dri2_dpy->image_list;
+ dri2_dpy->image_list = NULL;
+ pthread_mutex_unlock(&dri2_dpy->image_list_mutex);
+
+ while (image_elem) {
+ _EGLImage *img = (_EGLImage *) image_elem;
+ struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+
+ image_elem = image_elem->Next;
+
+ /*
+ * Delete the tbm surface user data (_EGLImage), unless the tbm surface
+ * was destroyed since we started processing the image_list.
+ */
+ if (dri2_img->tbm_surf)
+ tbm_surface_internal_delete_user_data(dri2_img->tbm_surf,
+ (unsigned long) disp);
+
+ /*
+ * dri2_orphan_tbm_surf_egl_image won't be able to transfer the
+ * _EGLImage to the orphan_image_list once we have started processing
+ * the image_list so we must destroy it ourselves.
+ */
+ dri2_dpy->image->destroyImage(dri2_img->dri_image);
+ free(dri2_img);
+ }
+
+ /* Destroy _EGLimages in the orphan_image_list*/
+ pthread_mutex_lock(&dri2_dpy->image_list_mutex);
+ image_elem = dri2_dpy->orphan_image_list;
+ dri2_dpy->orphan_image_list = NULL;
+ pthread_mutex_unlock(&dri2_dpy->image_list_mutex);
+
+ while (image_elem) {
+ _EGLImage *img = (_EGLImage *) image_elem;
+ struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+
+ image_elem = image_elem->Next;
+
+ dri2_dpy->image->destroyImage(dri2_img->dri_image);
+ free(dri2_img);
+ }
+#endif
+}
+
/**
* Called via eglTerminate(), drv->Terminate().
*
@@ -1332,6 +1390,8 @@ dri2_terminate(_EGLDisplay *disp)
/* Release all non-current Context/Surfaces. */
_eglReleaseDisplayResources(disp);
+ dri2_display_release_resources_tizen(disp);
+
dri2_display_release(disp);
return EGL_TRUE;
@@ -2309,6 +2369,9 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
}
#ifdef HAVE_TIZEN_PLATFORM
+static EGLBoolean
+dri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image);
+
int
dri2_fourcc_from_tbm_format(tbm_format format)
{
@@ -2405,14 +2468,145 @@ fail_close:
return NULL;
}
+static void
+dri2_orphan_tbm_surf_egl_image(void *user_data)
+{
+ _EGLImage *img = user_data;
+ struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+ _EGLDisplay *disp = img->Resource.Display;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ /*
+ * Transfer the passed in _EGLImage from the image_list to the
+ * orphan_image_list so that it can be cleaned up at some later
+ * point. This is necessary as the disp->Mutex needs to be held
+ * in order destroy the _EGLImage and this could potentially cause
+ * a deadlock in the event that the tbm surface is destroyed.
+ */
+ pthread_mutex_lock(&dri2_dpy->image_list_mutex);
+ /*
+ * This may be NULL if called via dri2_terminate or if dri2_terminate is
+ * running in another thread.
+ */
+ if (dri2_dpy->image_list) {
+ _EGLResource *image_elem;
+
+ /* Remove the _EGLImage from the image_list */
+ image_elem = dri2_dpy->image_list;
+ if (image_elem != &img->Resource) {
+ while (image_elem) {
+ if (image_elem->Next == &img->Resource)
+ break;
+ image_elem = image_elem->Next;
+ }
+ image_elem->Next = img->Resource.Next;
+ } else {
+ dri2_dpy->image_list = img->Resource.Next;
+ }
+
+ /* Add the _EGLImage to the orphan_image_list */
+ img->Resource.Next = dri2_dpy->orphan_image_list;
+ dri2_dpy->orphan_image_list = &img->Resource;
+ }
+
+ /*
+ * This function may have been called via tbm_surface_destroy so tbm_surf
+ * may be invalid after this function returns.
+ */
+ dri2_img->tbm_surf = NULL;
+ pthread_mutex_unlock(&dri2_dpy->image_list_mutex);
+}
+
+static _EGLImage *
+dri2_get_tbm_surf_egl_image(_EGLDisplay *disp, _EGLContext *ctx,
+ tbm_surface_h tbm_surf)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_image *dri2_img;
+ _EGLImage *img;
+ int ret;
+
+ ret = tbm_surface_internal_get_user_data(tbm_surf, (unsigned long) disp,
+ (void **) &img);
+ if (ret)
+ return img;
+
+ img = dri2_create_image_tbm_surface(disp, ctx, tbm_surf);
+ if (!img) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_tbm_surface failed");
+ goto fail_exit;
+ }
+ dri2_img = dri2_egl_image(img);
+
+ /* Use 'disp' as the 'key' as the _EGLimage is tied to it */
+ ret = tbm_surface_internal_add_user_data(tbm_surf, (unsigned long) disp,
+ dri2_orphan_tbm_surf_egl_image);
+ if (!ret) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_get_tbm_surf_egl_image");
+ goto fail_destroy_image;
+ }
+
+ ret = tbm_surface_internal_set_user_data(tbm_surf, (unsigned long) disp, img);
+ if (!ret) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_get_tbm_surf_egl_image");
+ goto fail_delete_user_data;
+ }
+
+ /*
+ * Store the tbm surface so that the user data (_EGLImage) can be destroyed
+ * in dri2_terminate. We don't take a reference on the surface as this would
+ * prevent it from being destroyed until eglTerminate is called. This isn't
+ * an issue since it will be set to NULL, via dri2_orphan_tbm_surf_egl_image,
+ * once the surface is destroyed (although it's actually safe to call tbm
+ * surface functions with stale/NULL pointers).
+ */
+ dri2_img->tbm_surf = tbm_surf;
+
+ /*
+ * Add to the list of _EGLImages that are associated with tbm surfaces.
+ * This allows the _EGLImage to be destroyed if the application calls
+ * eglTerminate before the tbm surface is destroyed.
+ */
+ pthread_mutex_lock(&dri2_dpy->image_list_mutex);
+ img->Resource.Next = dri2_dpy->image_list;
+ dri2_dpy->image_list = &img->Resource;
+ pthread_mutex_unlock(&dri2_dpy->image_list_mutex);
+
+ return img;
+
+fail_delete_user_data:
+ tbm_surface_internal_delete_user_data(tbm_surf, (unsigned long) disp);
+fail_destroy_image:
+ dri2_destroy_image_khr(disp, img);
+fail_exit:
+ return NULL;
+}
+
static _EGLImage *
dri2_create_image_tizen(_EGLDisplay *disp, _EGLContext *ctx,
EGLClientBuffer _buffer,
const EGLint *attr_list)
{
- tbm_surface_h tbm_surf = (tbm_surface_h)_buffer;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ tbm_surface_h tbm_surf = (tbm_surface_h) _buffer;
+ _EGLImage *img;
+ struct dri2_egl_image *dri2_img;
+ __DRIimage *dri_image;
+
+ img = dri2_get_tbm_surf_egl_image(disp, ctx, tbm_surf);
+ if (!img) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_tizen");
+ return NULL;
+ }
+ dri2_img = dri2_egl_image(img);
+
+ dri_image = dri2_dpy->image->fromPlanar(dri2_img->dri_image, 0, NULL);
+ if (!dri_image) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_tizen");
+ return NULL;
+ }
- return dri2_create_image_tbm_surface(disp, ctx, tbm_surf);
+ return dri2_create_image_from_dri(disp, dri_image);
}
static _EGLImage *
@@ -2424,6 +2618,9 @@ dri2_create_image_wayland_wl_buffer_tizen(_EGLDisplay *disp, _EGLContext *ctx,
_EGLImageAttribs attrs;
tbm_surface_h tbm_surf;
tbm_surface_info_s info;
+ _EGLImage *img;
+ struct dri2_egl_image *dri2_img;
+ __DRIimage *dri_image;
tbm_surf = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_dpy,
(tpl_handle_t) _buffer);
@@ -2454,7 +2651,21 @@ dri2_create_image_wayland_wl_buffer_tizen(_EGLDisplay *disp, _EGLContext *ctx,
return NULL;
}
- return dri2_create_image_tbm_surface(disp, ctx, tbm_surf);
+ img = dri2_get_tbm_surf_egl_image(disp, ctx, tbm_surf);
+ if (!img) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer_tizen");
+ return NULL;
+ }
+ dri2_img = dri2_egl_image(img);
+
+ dri_image =
+ dri2_dpy->image->fromPlanar(dri2_img->dri_image, attrs.PlaneWL, NULL);
+ if (!dri_image) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer_tizen");
+ return NULL;
+ }
+
+ return dri2_create_image_from_dri(disp, dri_image);
}
#endif
@@ -3377,10 +3588,29 @@ dri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_image *dri2_img = dri2_egl_image(image);
+#ifdef HAVE_TIZEN_PLATFORM
+ _EGLResource *image_elem;
+#endif
dri2_dpy->image->destroyImage(dri2_img->dri_image);
free(dri2_img);
+#ifdef HAVE_TIZEN_PLATFORM
+ /* Take the opportunity to destroy orphaned tbm surface _EGLImages */
+ pthread_mutex_lock(&dri2_dpy->image_list_mutex);
+ image_elem = dri2_dpy->orphan_image_list;
+ dri2_dpy->orphan_image_list = NULL;
+ pthread_mutex_unlock(&dri2_dpy->image_list_mutex);
+
+ while (image_elem) {
+ dri2_img = dri2_egl_image((_EGLImage *) image_elem);
+ image_elem = image_elem->Next;
+
+ dri2_dpy->image->destroyImage(dri2_img->dri_image);
+ free(dri2_img);
+ }
+#endif
+
return EGL_TRUE;
}
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index a8bfe45b1f5..546bc0a0dbc 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -268,6 +268,15 @@ struct dri2_egl_display
#ifdef HAVE_TIZEN_PLATFORM
tpl_display_t *tpl_dpy;
+ /*
+ * The image_list_mutex protects the image_list and orphan_image_list. It
+ * should never be held while calling a libtbm function as this may result
+ * in a deadlock.
+ */
+ pthread_mutex_t image_list_mutex;
+ bool image_list_mutex_initialized;
+ _EGLResource *image_list;
+ _EGLResource *orphan_image_list;
#endif
};
@@ -413,6 +422,9 @@ struct dri2_egl_image
{
_EGLImage base;
__DRIimage *dri_image;
+#ifdef HAVE_TIZEN_PLATFORM
+ tbm_surface_h tbm_surf;
+#endif
};
struct dri2_egl_sync {
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index ad75c115d7e..49462152beb 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -891,6 +891,7 @@ dri2_initialize_tizen(_EGLDisplay *dpy)
{
struct dri2_egl_display *dri2_dpy;
int i;
+ int err;
dri2_dpy = calloc(1, sizeof(*dri2_dpy));
if (!dri2_dpy)
@@ -906,6 +907,11 @@ dri2_initialize_tizen(_EGLDisplay *dpy)
goto cleanup;
}
+ err = pthread_mutex_init(&dri2_dpy->image_list_mutex, NULL);
+ if (err)
+ goto cleanup;
+ dri2_dpy->image_list_mutex_initialized = true;
+
for (i = TIZEN_DRM_RENDER_MINOR_START; i <= TIZEN_DRM_RENDER_MINOR_MAX; i++) {
char *render_path;
--
2.25.1

View File

@@ -0,0 +1,54 @@
From 1f4a1a21384b00e28b8a9dd2c29f9c261f201c6f Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 23 Nov 2017 15:50:21 +0000
Subject: [PATCH 23/67] dri: use a supported API in driCreateNewContext
Don't assume the screen supports OpenGL when creating a new context,
use an API that the screen supports.
---
src/mesa/drivers/dri/common/dri_util.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index caed5fa6a68..6c45eb007fc 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -50,6 +50,7 @@
#include "main/debug_output.h"
#include "main/errors.h"
#include "main/macros.h"
+#include "util/bitscan.h"
driOptionDescription __dri2ConfigOptions[] = {
DRI_CONF_SECTION_DEBUG
@@ -332,7 +333,11 @@ driCreateContextAttribs(__DRIscreen *screen, int api,
mesa_api = API_OPENGLES;
break;
case __DRI_API_GLES2:
+ ctx_config.major_version = 2;
+ mesa_api = API_OPENGLES2;
+ break;
case __DRI_API_GLES3:
+ ctx_config.major_version = 3;
mesa_api = API_OPENGLES2;
break;
case __DRI_API_OPENGL_CORE:
@@ -515,7 +520,14 @@ static __DRIcontext *
driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
__DRIcontext *shared, void *data)
{
- return driCreateNewContextForAPI(screen, __DRI_API_OPENGL,
+ int apifs;
+
+ apifs = ffs(screen->api_mask);
+
+ if (!apifs)
+ return NULL;
+
+ return driCreateNewContextForAPI(screen, apifs - 1,
config, shared, data);
}
--
2.25.1

View File

@@ -0,0 +1,224 @@
From 0751612b949f1c90338a14453ff7fa4be8bfd016 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 28 Nov 2017 16:27:38 +0000
Subject: [PATCH 24/67] gbm: add gbm_bo_blit
For the GBM DRI backend, gbm_bo_blit is a wrapper around blitImage in
the DRI Image extension.
---
src/gbm/backends/dri/gbm_dri.c | 33 +++++++++++++++++++++++++++++++++
src/gbm/main/gbm.c | 31 +++++++++++++++++++++++++++++++
src/gbm/main/gbm.h | 21 +++++++++++++++++++++
src/gbm/main/gbm_abi_check.c | 20 +++++++++++++++++++-
src/gbm/main/gbm_backend_abi.h | 10 +++++++++-
5 files changed, 113 insertions(+), 2 deletions(-)
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index 96fa9217255..bd8a80cdecf 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -1355,6 +1355,37 @@ gbm_dri_surface_destroy(struct gbm_surface *_surf)
free(surf);
}
+static int
+gbm_dri_bo_blit(struct gbm_bo *_dst_bo, struct gbm_bo *_src_bo,
+ int dst_x0, int dst_y0, int dst_width, int dst_height,
+ int src_x0, int src_y0, int src_width, int src_height,
+ enum gbm_blit_flags flags)
+{
+ struct gbm_dri_device *dri = gbm_dri_device(_dst_bo->gbm);
+ struct gbm_dri_bo *dst_bo = gbm_dri_bo(_dst_bo);
+ struct gbm_dri_bo *src_bo = gbm_dri_bo(_src_bo);
+
+ if (!dri->image || dri->image->base.version < 9 || !dri->image->blitImage) {
+ errno = ENOSYS;
+ return 0;
+ }
+
+ mtx_lock(&dri->mutex);
+ if (!dri->context)
+ dri->context = dri->dri2->createNewContext(dri->screen, NULL,
+ NULL, NULL);
+ assert(dri->context);
+ mtx_unlock(&dri->mutex);
+
+ /* GBM flags and DRI flags are the same, so just pass them on */
+ dri->image->blitImage(dri->context, dst_bo->image, src_bo->image,
+ dst_x0, dst_y0, dst_width, dst_height,
+ src_x0, src_y0, src_width, src_height,
+ flags);
+
+ return 1;
+}
+
static void
dri_destroy(struct gbm_device *gbm)
{
@@ -1416,6 +1447,8 @@ dri_device_create(int fd, uint32_t gbm_backend_version)
dri->base.v0.name = "drm";
+ dri->base.v1.bo_blit = gbm_dri_bo_blit;
+
dri->visual_table = gbm_dri_visuals_table;
dri->num_visuals = ARRAY_SIZE(gbm_dri_visuals_table);
diff --git a/src/gbm/main/gbm.c b/src/gbm/main/gbm.c
index d81931a7483..e2351d34ad8 100644
--- a/src/gbm/main/gbm.c
+++ b/src/gbm/main/gbm.c
@@ -758,6 +758,37 @@ gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc)
return desc->name;
}
+/**
+ * Blit from one buffer object to another
+ *
+ * \param dst_bo The destination buffer object
+ * \param src_bo The source buffer object
+ * \param dst_x0 The X coordinate (top left origin) of the destination rectangle
+ * \param dst_y0 The Y coordinate (top left origin) of the destination rectangle
+ * \param dst_width The width of the destination rectangle
+ * \param dst_height The height of the destination rectangle
+ * \param src_x0 The X coordinate (top left origin) of the source rectangle
+ * \param src_y0 The Y coordinate (top left origin) of the source rectangle
+ * \param src_width The width of the source rectangle
+ * \param src_height The height of the source rectangle
+ * \param flags The flags for the blit
+ * \return 1 on success, 0 otherwise
+ */
+GBM_EXPORT int
+gbm_bo_blit(struct gbm_bo *dst_bo, struct gbm_bo *src_bo,
+ int dst_x0, int dst_y0, int dst_width, int dst_height,
+ int src_x0, int src_y0, int src_width, int src_height,
+ enum gbm_blit_flags flags)
+{
+ if (dst_bo->gbm->v0.backend_version >= 1)
+ return dst_bo->gbm->v1.bo_blit(dst_bo, src_bo,
+ dst_x0, dst_y0, dst_width, dst_height,
+ src_x0, src_y0, src_width, src_height,
+ flags);
+ else
+ return 0;
+}
+
/**
* A global table of functions and global variables defined in the core GBM
* code that need to be accessed directly by GBM backends.
diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h
index 3a0fe73faae..7c82cd661a3 100644
--- a/src/gbm/main/gbm.h
+++ b/src/gbm/main/gbm.h
@@ -246,6 +246,21 @@ enum gbm_bo_flags {
GBM_BO_USE_PROTECTED = (1 << 5),
};
+/**
+ * Flags to control the behaviour of a blit - these are passed to
+ * gbm_bo_blit().
+ */
+enum gbm_blit_flags {
+ /**
+ * Force blit execution in finite time
+ */
+ GBM_BLIT_FLAG_FLUSH = 0x0001,
+ /**
+ * Flush, and wait for the blit to complete
+ */
+ GBM_BLIT_FLAG_FINISH = 0x0002
+};
+
int
gbm_device_get_fd(struct gbm_device *gbm);
@@ -425,6 +440,12 @@ gbm_surface_destroy(struct gbm_surface *surface);
char *
gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc);
+int
+gbm_bo_blit(struct gbm_bo *dst_bo, struct gbm_bo *src_bo,
+ int dst_x0, int dst_y0, int dst_width, int dst_height,
+ int src_x0, int src_y0, int src_width, int src_height,
+ enum gbm_blit_flags flags);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gbm/main/gbm_abi_check.c b/src/gbm/main/gbm_abi_check.c
index f1137be7baf..02ce23b129e 100644
--- a/src/gbm/main/gbm_abi_check.c
+++ b/src/gbm/main/gbm_abi_check.c
@@ -101,6 +101,21 @@ struct gbm_device_abi0 {
struct gbm_device_v0_abi0 v0;
};
+#define GBM_BACKEND_ABI_VERSION_abi1 1
+struct gbm_device_v1_abi1 {
+ int (*bo_blit)(struct gbm_bo *dst_bo, struct gbm_bo *src_bo,
+ int dst_x0, int dst_y0, int dst_width, int dst_height,
+ int src_x0, int src_y0, int src_width, int src_height,
+ enum gbm_blit_flags flags);
+};
+
+struct gbm_device_abi1 {
+ /* Hack to make a gbm_device detectable by its first element. */
+ struct gbm_device *(*dummy)(int);
+ struct gbm_device_v0_abi0 v0;
+ struct gbm_device_v1_abi1 v1;
+};
+
/**
* GBM buffer object interface corresponding to GBM_BACKEND_ABI_VERSION = 0
*
@@ -359,8 +374,11 @@ int main(int argc, char **argv)
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_has_free_buffers);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_destroy);
+ CHECK_MEMBER_CURRENT(gbm_device_v1, _abi1, bo_blit);
+
/* Size of ABI-versioned substructures verified by above member checks */
- CHECK_SIZE_CURRENT (gbm_device, _abi0);
+ CHECK_SIZE (gbm_device, _abi0, _abi1);
+ CHECK_SIZE_CURRENT (gbm_device, _abi1);
/* Check current gbm_bo ABI against gbm_bo_abi0*/
diff --git a/src/gbm/main/gbm_backend_abi.h b/src/gbm/main/gbm_backend_abi.h
index 962ee74f003..3abf29faa92 100644
--- a/src/gbm/main/gbm_backend_abi.h
+++ b/src/gbm/main/gbm_backend_abi.h
@@ -72,7 +72,7 @@ struct gbm_backend_desc;
* Core ABI version: 4
* ABI version of a buffer object created by a device from the backend: 4
*/
-#define GBM_BACKEND_ABI_VERSION 0
+#define GBM_BACKEND_ABI_VERSION 1
/**
* GBM device interface corresponding to GBM_BACKEND_ABI_VERSION = 0
@@ -149,6 +149,13 @@ struct gbm_device_v0 {
void (*surface_destroy)(struct gbm_surface *surface);
};
+struct gbm_device_v1 {
+ int (*bo_blit)(struct gbm_bo *dst_bo, struct gbm_bo *src_bo,
+ int dst_x0, int dst_y0, int dst_width, int dst_height,
+ int src_x0, int src_y0, int src_width, int src_height,
+ enum gbm_blit_flags flags);
+};
+
/**
* The device used for the memory allocation.
*
@@ -161,6 +168,7 @@ struct gbm_device {
/* Hack to make a gbm_device detectable by its first element. */
struct gbm_device *(*dummy)(int);
struct gbm_device_v0 v0;
+ struct gbm_device_v1 v1;
};
/**
--
2.25.1

View File

@@ -0,0 +1,44 @@
From dbe611e4cb6f0dddc05ead03f0341274a6b018c8 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Fri, 1 Dec 2017 08:31:15 +0000
Subject: [PATCH 25/67] gbm: don't assert if DRI context creation fails
If the DRI backend fails to create a DRI context, return an error,
rather than asserting.
---
src/gbm/backends/dri/gbm_dri.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index bd8a80cdecf..2aa9c7c41ad 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -1245,8 +1245,11 @@ gbm_dri_bo_map(struct gbm_bo *_bo,
if (!dri->context)
dri->context = dri->dri2->createNewContext(dri->screen, NULL,
NULL, NULL);
- assert(dri->context);
mtx_unlock(&dri->mutex);
+ if (!dri->context) {
+ errno = ENOSYS;
+ return NULL;
+ }
/* GBM flags and DRI flags are the same, so just pass them on */
return dri->image->mapImage(dri->context, bo->image, x, y,
@@ -1374,8 +1377,11 @@ gbm_dri_bo_blit(struct gbm_bo *_dst_bo, struct gbm_bo *_src_bo,
if (!dri->context)
dri->context = dri->dri2->createNewContext(dri->screen, NULL,
NULL, NULL);
- assert(dri->context);
mtx_unlock(&dri->mutex);
+ if (!dri->context) {
+ errno = ENOSYS;
+ return 0;
+ }
/* GBM flags and DRI flags are the same, so just pass them on */
dri->image->blitImage(dri->context, dst_bo->image, src_bo->image,
--
2.25.1

View File

@@ -0,0 +1,471 @@
From f16ea577ee06375423198dced8231d04e94536af Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Fri, 17 Mar 2017 16:23:07 +0000
Subject: [PATCH 26/67] egl/wayland: add pbuffer support
The pbuffer code is based on that in the Surfaceless platform code.
---
src/egl/drivers/dri2/egl_dri2.h | 4 +
src/egl/drivers/dri2/platform_wayland.c | 270 ++++++++++++++++++++----
2 files changed, 236 insertions(+), 38 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 546bc0a0dbc..f41f32cd234 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -405,6 +405,10 @@ struct dri2_egl_surface
__DRIimage *front;
unsigned int visual;
+#ifdef HAVE_WAYLAND_PLATFORM
+ void *swrast_front;
+#endif
+
int out_fence_fd;
EGLBoolean enable_out_fence;
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 811d28bd669..a096d9500c1 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -427,6 +427,99 @@ dri2_wl_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
return NULL;
}
+static _EGLSurface *
+dri2_wl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
+ const EGLint *attrib_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
+ struct dri2_egl_surface *dri2_surf;
+ int visual_idx;
+ const __DRIconfig *config;
+
+ dri2_surf = calloc(1, sizeof *dri2_surf);
+ if (!dri2_surf) {
+ _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
+ return NULL;
+ }
+
+ if (!dri2_init_surface(&dri2_surf->base, disp, EGL_PBUFFER_BIT, conf,
+ attrib_list, false, NULL))
+ goto cleanup_surf;
+
+ config = dri2_get_dri_config(dri2_conf, EGL_PBUFFER_BIT,
+ dri2_surf->base.GLColorspace);
+ if (!config) {
+ _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
+ goto cleanup_surf;
+ }
+
+ visual_idx = dri2_wl_visual_idx_from_config(dri2_dpy, config);
+ assert(visual_idx != -1);
+
+ if (dri2_dpy->wl_dmabuf || dri2_dpy->wl_drm) {
+ dri2_surf->format = dri2_wl_visuals[visual_idx].wl_drm_format;
+ } else {
+ assert(dri2_dpy->wl_shm);
+ dri2_surf->format = dri2_wl_visuals[visual_idx].wl_shm_format;
+ }
+
+ if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
+ goto cleanup_surf;
+
+ return &dri2_surf->base;
+
+ cleanup_surf:
+ free(dri2_surf);
+
+ return NULL;
+}
+
+static int
+allocate_front_buffer(struct dri2_egl_display *dri2_dpy,
+ struct dri2_egl_surface *dri2_surf,
+ EGLBoolean need_name)
+{
+ int use_flags = need_name ? __DRI_IMAGE_USE_SHARE : 0;
+ int visual_idx;
+ unsigned int dri_image_format;
+
+ visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
+ assert(visual_idx != -1);
+ dri_image_format = dri2_wl_visuals[visual_idx].dri_image_format;
+
+ if (!dri2_surf->front)
+ dri2_surf->front = dri2_dpy->image->createImage(dri2_dpy->dri_screen,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ dri_image_format,
+ use_flags,
+ NULL);
+ if (!dri2_surf->front) {
+ _eglError(EGL_BAD_ALLOC, "failed to allocate front buffer");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+free_front_buffer(struct dri2_egl_display *dri2_dpy,
+ struct dri2_egl_surface *dri2_surf)
+{
+ if (dri2_surf->front) {
+ dri2_dpy->image->destroyImage(dri2_surf->front);
+ dri2_surf->front = NULL;
+ }
+}
+
+static void
+swrast_free_front_buffer(struct dri2_egl_surface *dri2_surf)
+{
+ free(dri2_surf->swrast_front);
+ dri2_surf->swrast_front = NULL;
+}
+
/**
* Called via eglDestroySurface(), drv->DestroySurface().
*/
@@ -453,6 +546,9 @@ dri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
if (dri2_dpy->dri2)
dri2_egl_surface_free_local_buffers(dri2_surf);
+ free_front_buffer(dri2_dpy, dri2_surf);
+ swrast_free_front_buffer(dri2_surf);
+
if (dri2_surf->throttle_callback)
wl_callback_destroy(dri2_surf->throttle_callback);
@@ -462,11 +558,14 @@ dri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
dri2_surf->wl_win->destroy_window_callback = NULL;
}
- wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
- wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
+ if (dri2_surf->wl_surface_wrapper)
+ wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
+ if (dri2_surf->wl_dpy_wrapper)
+ wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
if (dri2_surf->wl_drm_wrapper)
wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper);
- wl_event_queue_destroy(dri2_surf->wl_queue);
+ if (dri2_surf->wl_queue)
+ wl_event_queue_destroy(dri2_surf->wl_queue);
dri2_fini_surface(surf);
free(surf);
@@ -628,20 +727,16 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
static void
-back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
+bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy, unsigned int attachment,
+ __DRIimage *image, __DRIbuffer *buffer)
{
- struct dri2_egl_display *dri2_dpy =
- dri2_egl_display(dri2_surf->base.Resource.Display);
- __DRIimage *image;
int name, pitch, format;
- image = dri2_surf->back->dri_image;
-
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
- buffer->attachment = __DRI_BUFFER_BACK_LEFT;
+ buffer->attachment = attachment;
buffer->name = name;
buffer->pitch = pitch;
buffer->flags = 0;
@@ -656,12 +751,28 @@ back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
}
}
-static int
-update_buffers(struct dri2_egl_surface *dri2_surf)
+static void
+back_bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy,
+ struct dri2_egl_surface *dri2_surf,
+ __DRIbuffer *buffer)
{
- struct dri2_egl_display *dri2_dpy =
- dri2_egl_display(dri2_surf->base.Resource.Display);
+ bo_to_dri_buffer(dri2_dpy, __DRI_BUFFER_BACK_LEFT,
+ dri2_surf->back->dri_image, buffer);
+}
+
+static void
+front_bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy,
+ struct dri2_egl_surface *dri2_surf,
+ __DRIbuffer *buffer)
+{
+ bo_to_dri_buffer(dri2_dpy, __DRI_BUFFER_FRONT_LEFT,
+ dri2_surf->front, buffer);
+}
+static int
+update_buffers(struct dri2_egl_display *dri2_dpy,
+ struct dri2_egl_surface *dri2_surf)
+{
if (dri2_surf->wl_win &&
(dri2_surf->base.Width != dri2_surf->wl_win->width ||
dri2_surf->base.Height != dri2_surf->wl_win->height)) {
@@ -703,12 +814,13 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
}
static int
-update_buffers_if_needed(struct dri2_egl_surface *dri2_surf)
+update_buffers_if_needed(struct dri2_egl_display *dri2_dpy,
+ struct dri2_egl_surface *dri2_surf)
{
if (dri2_surf->back != NULL)
return 0;
- return update_buffers(dri2_surf);
+ return update_buffers(dri2_dpy, dri2_surf);
}
static __DRIbuffer *
@@ -718,17 +830,25 @@ dri2_wl_get_buffers_with_format(__DRIdrawable * driDrawable,
int *out_count, void *loaderPrivate)
{
struct dri2_egl_surface *dri2_surf = loaderPrivate;
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
int i, j;
- if (update_buffers(dri2_surf) < 0)
- return NULL;
-
for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
__DRIbuffer *local;
switch (attachments[i]) {
case __DRI_BUFFER_BACK_LEFT:
- back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
+ if (update_buffers(dri2_dpy, dri2_surf) < 0)
+ return NULL;
+
+ back_bo_to_dri_buffer(dri2_dpy, dri2_surf, &dri2_surf->buffers[j]);
+ break;
+ case __DRI_BUFFER_FRONT_LEFT:
+ if (allocate_front_buffer(dri2_dpy, dri2_surf, EGL_TRUE) < 0)
+ return NULL;
+
+ front_bo_to_dri_buffer(dri2_dpy, dri2_surf, &dri2_surf->buffers[j]);
break;
default:
local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i],
@@ -798,12 +918,30 @@ image_get_buffers(__DRIdrawable *driDrawable,
struct __DRIimageList *buffers)
{
struct dri2_egl_surface *dri2_surf = loaderPrivate;
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
- if (update_buffers(dri2_surf) < 0)
- return 0;
+ buffers->image_mask = 0;
+ buffers->front = NULL;
+ buffers->back = NULL;
+
+ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK)
+ {
+ if (update_buffers(dri2_dpy, dri2_surf) < 0)
+ return 0;
- buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
- buffers->back = dri2_surf->back->dri_image;
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
+ buffers->back = dri2_surf->back->dri_image;
+ }
+
+ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT)
+ {
+ if (allocate_front_buffer(dri2_dpy, dri2_surf, EGL_FALSE) < 0)
+ return 0;
+
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
+ buffers->front = dri2_surf->front;
+ }
return 1;
}
@@ -1054,6 +1192,9 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+ if (draw->Type != EGL_WINDOW_BIT)
+ return EGL_TRUE;
+
if (!dri2_surf->wl_win)
return _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_swap_buffers");
@@ -1068,7 +1209,7 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
/* Make sure we have a back buffer in case we're swapping without ever
* rendering. */
- if (update_buffers_if_needed(dri2_surf) < 0)
+ if (update_buffers_if_needed(dri2_dpy, dri2_surf) < 0)
return _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
if (draw->SwapInterval > 0) {
@@ -1153,9 +1294,13 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
static EGLint
dri2_wl_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
- if (update_buffers_if_needed(dri2_surf) < 0) {
+ if (surface->Type != EGL_WINDOW_BIT)
+ return 0;
+
+ if (update_buffers_if_needed(dri2_dpy, dri2_surf) < 0) {
_eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
return -1;
}
@@ -1376,6 +1521,7 @@ static const struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
.authenticate = dri2_wl_authenticate,
.create_window_surface = dri2_wl_create_window_surface,
.create_pixmap_surface = dri2_wl_create_pixmap_surface,
+ .create_pbuffer_surface = dri2_wl_create_pbuffer_surface,
.destroy_surface = dri2_wl_destroy_surface,
.create_image = dri2_create_image_khr,
.swap_buffers = dri2_wl_swap_buffers,
@@ -1418,7 +1564,7 @@ dri2_wl_add_configs_for_visuals(_EGLDisplay *disp)
continue;
dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
- count + 1, EGL_WINDOW_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
+ count + 1, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
if (dri2_conf) {
if (dri2_conf->base.ConfigID == count + 1)
count++;
@@ -1654,6 +1800,23 @@ dri2_wl_swrast_get_stride_for_format(int format, int w)
return w * (dri2_wl_visuals[visual_idx].bpp / 8);
}
+static EGLBoolean
+swrast_allocate_local_buffer(int format, int w, int h, void **data)
+{
+ int stride, size_map;
+ void *data_map;
+
+ stride = dri2_wl_swrast_get_stride_for_format(format, w);
+ size_map = h * stride;
+
+ data_map = malloc(size_map);
+ if (!data_map)
+ return EGL_FALSE;
+
+ *data = data_map;
+ return EGL_TRUE;
+}
+
static EGLBoolean
dri2_wl_swrast_allocate_buffer(struct dri2_egl_surface *dri2_surf,
int format, int w, int h,
@@ -1775,8 +1938,24 @@ swrast_update_buffers(struct dri2_egl_surface *dri2_surf)
return 0;
}
+static int
+swrast_allocate_front_buffer(struct dri2_egl_surface *dri2_surf)
+{
+ if (!dri2_surf->swrast_front) {
+ if (!swrast_allocate_local_buffer(dri2_surf->format,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ &dri2_surf->swrast_front)) {
+ _eglError(EGL_BAD_ALLOC, "failed to allocate front buffer");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static void*
-dri2_wl_swrast_get_frontbuffer_data(struct dri2_egl_surface *dri2_surf)
+dri2_wl_swrast_get_currentbuffer_data(struct dri2_egl_surface *dri2_surf)
{
/* if there has been a resize: */
if (!dri2_surf->current)
@@ -1846,7 +2025,9 @@ dri2_wl_swrast_get_drawable_info(__DRIdrawable * draw,
{
struct dri2_egl_surface *dri2_surf = loaderPrivate;
- (void) swrast_update_buffers(dri2_surf);
+ if (dri2_surf->base.Type == EGL_WINDOW_BIT)
+ (void) swrast_update_buffers(dri2_surf);
+
*x = 0;
*y = 0;
*w = dri2_surf->base.Width;
@@ -1865,7 +2046,11 @@ dri2_wl_swrast_get_image(__DRIdrawable * read,
int dst_stride = copy_width;
char *src, *dst;
- src = dri2_wl_swrast_get_frontbuffer_data(dri2_surf);
+ if (dri2_surf->base.Type == EGL_WINDOW_BIT)
+ src = dri2_wl_swrast_get_currentbuffer_data(dri2_surf);
+ else
+ src = dri2_surf->swrast_front;
+
if (!src) {
memset(data, 0, copy_width * h);
return;
@@ -1903,14 +2088,20 @@ dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
assert(copy_width <= stride);
- (void) swrast_update_buffers(dri2_surf);
- dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
+ if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
+ (void) swrast_update_buffers(dri2_surf);
+ dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
- /* partial copy, copy old content */
- if (copy_width < dst_stride)
- dri2_wl_swrast_get_image(draw, 0, 0,
- dri2_surf->base.Width, dri2_surf->base.Height,
- dst, loaderPrivate);
+ /* partial copy, copy old content */
+ if (copy_width < dst_stride)
+ dri2_wl_swrast_get_image(draw, 0, 0,
+ dri2_surf->base.Width, dri2_surf->base.Height,
+ dst, loaderPrivate);
+ } else {
+ (void) swrast_allocate_front_buffer(dri2_surf);
+ dst = dri2_surf->swrast_front;
+ assert(dst);
+ }
dst += x_offset;
dst += y * dst_stride;
@@ -1928,7 +2119,9 @@ dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
src += stride;
dst += dst_stride;
}
- dri2_wl_swrast_commit_backbuffer(dri2_surf);
+
+ if (dri2_surf->base.Type == EGL_WINDOW_BIT)
+ dri2_wl_swrast_commit_backbuffer(dri2_surf);
}
static void
@@ -1996,6 +2189,7 @@ static const struct dri2_egl_display_vtbl dri2_wl_swrast_display_vtbl = {
.authenticate = NULL,
.create_window_surface = dri2_wl_create_window_surface,
.create_pixmap_surface = dri2_wl_create_pixmap_surface,
+ .create_pbuffer_surface = dri2_wl_create_pbuffer_surface,
.destroy_surface = dri2_wl_destroy_surface,
.create_image = dri2_create_image_khr,
.swap_buffers = dri2_wl_swrast_swap_buffers,
--
2.25.1

View File

@@ -0,0 +1,121 @@
From 48fe256681d8d7d3892393b102bf0a3ebc697c51 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Mon, 18 Dec 2017 19:22:50 +0000
Subject: [PATCH 27/67] egl/tizen: support DRI driver handling of swap preserve
This adds a new flag (__DRI_IMAGE_BUFFER_PREV) to the __DRIimageBufferMask
enum that allows a DRI driver to request the previous back buffer. This
will only be returned if the swap behaviour is EGL_BUFFER_PRESERVED and
should result in the DRI driver preserving the previous content instead of
this being done in the platform code. For hardware that supports it, this
should avoid a blit being performed every frame, although this will still
be necessary under certain conditions, e.g. an empty swap.
---
include/GL/internal/dri_interface.h | 3 +++
src/egl/drivers/dri2/platform_tizen.c | 29 +++++++++++++++++++++------
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index b197092939f..16cc095ea29 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -2073,12 +2073,15 @@ enum __DRIimageBufferMask {
* OpenGL ES API and little change to the SurfaceFlinger API.
*/
__DRI_IMAGE_BUFFER_SHARED = (1 << 2),
+#define DRI_IMAGE_HAS_BUFFER_PREV
+ __DRI_IMAGE_BUFFER_PREV = (1 << 31),
};
struct __DRIimageList {
uint32_t image_mask;
__DRIimage *back;
__DRIimage *front;
+ __DRIimage *prev;
};
#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index 49462152beb..2bc9b3e7c64 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -147,7 +147,8 @@ create_image_from_native(struct dri2_egl_surface *dri2_surf,
}
static int
-get_back_bo(struct dri2_egl_surface *dri2_surf, bool allow_update)
+get_back_bo(struct dri2_egl_surface *dri2_surf, bool allow_update,
+ bool allow_preserve)
{
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
@@ -277,7 +278,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, bool allow_update)
dri2_surf->back->locked = true;
if (dri2_surf->base.SwapBehavior == EGL_BUFFER_PRESERVED &&
- dri2_surf->current) {
+ allow_preserve && dri2_surf->current) {
_EGLContext *ctx = _eglGetCurrentContext();
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
@@ -609,7 +610,7 @@ dri2_tizen_swap_buffers_with_damage(_EGLDisplay *dpy, _EGLSurface *draw,
* Make sure we have a back buffer in case we're swapping without ever
* rendering.
*/
- if (get_back_bo(dri2_surf, false) < 0) {
+ if (get_back_bo(dri2_surf, false, true) < 0) {
_eglError(EGL_BAD_ALLOC, "DRI2: failed to get back buffer");
return EGL_FALSE;
}
@@ -673,7 +674,7 @@ dri2_tizen_query_buffer_age(_EGLDisplay *dpy, _EGLSurface *surface)
{
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
- if (get_back_bo(dri2_surf, false) < 0) {
+ if (get_back_bo(dri2_surf, false, true) < 0) {
_eglError(EGL_BAD_ALLOC, "DRI2: failed to get back buffer");
return -1;
}
@@ -748,14 +749,22 @@ dri2_tizen_get_buffers(__DRIdrawable *driDrawable,
buffers->image_mask = 0;
buffers->front = NULL;
buffers->back = NULL;
+ buffers->prev = NULL;
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT)
if (get_front_bo(dri2_surf) < 0)
return 0;
- if (buffer_mask & __DRI_IMAGE_BUFFER_BACK)
- if (get_back_bo(dri2_surf, true) < 0)
+ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
+ /*
+ * The DRI driver has requested the previous buffer so it will take care
+ * of preserving the previous content.
+ */
+ bool allow_preserve = !(buffer_mask & __DRI_IMAGE_BUFFER_PREV);
+
+ if (get_back_bo(dri2_surf, true, allow_preserve) < 0)
return 0;
+ }
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
buffers->front = dri2_surf->front;
@@ -767,6 +776,14 @@ dri2_tizen_get_buffers(__DRIdrawable *driDrawable,
buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
}
+ if (buffer_mask & __DRI_IMAGE_BUFFER_PREV) {
+ if (dri2_surf->base.SwapBehavior == EGL_BUFFER_PRESERVED &&
+ dri2_surf->current) {
+ buffers->prev = dri2_surf->current->dri_image;
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_PREV;
+ }
+ }
+
return 1;
}
--
2.25.1

View File

@@ -0,0 +1,29 @@
From 90c87ad050dd7a4deda3ee1609e6cc27ea7dd616 Mon Sep 17 00:00:00 2001
From: Eric Engestrom <eric.engestrom@imgtec.com>
Date: Mon, 25 Sep 2017 15:58:49 +0100
Subject: [PATCH 28/67] egl: eglBindAPI workaround for dEQP bug
dEQP relies on eglBindAPI to only return true if the API can
successfully be used to create contexts, which the spec does not
require.
Until dEQP is fixed, just disable GL on non-X11 platforms.
---
src/egl/main/eglcurrent.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h
index d9a4a90174e..32570970947 100644
--- a/src/egl/main/eglcurrent.h
+++ b/src/egl/main/eglcurrent.h
@@ -71,7 +71,7 @@ struct _egl_thread_info
static inline EGLBoolean
_eglIsApiValid(EGLenum api)
{
-#ifdef ANDROID
+#ifndef HAVE_X11_PLATFORM
/* OpenGL is not a valid/supported API on Android */
return api == EGL_OPENGL_ES_API;
#else
--
2.25.1

View File

@@ -0,0 +1,56 @@
From a763c01172ee21a26f4c9dbb6055093f78d06fb2 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 30 Jan 2018 10:25:11 +0000
Subject: [PATCH 29/67] GL_EXT_multi_draw_indirect entry points
---
src/mapi/glapi/gen/es_EXT.xml | 19 +++++++++++++++++++
src/mapi/glapi/gen/static_data.py | 2 ++
2 files changed, 21 insertions(+)
diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml
index fe8f27e1e6f..e0d60faa9d2 100644
--- a/src/mapi/glapi/gen/es_EXT.xml
+++ b/src/mapi/glapi/gen/es_EXT.xml
@@ -1140,6 +1140,25 @@
</category>
+<category name="GL_EXT_multi_draw_indirect" number="205">
+
+ <function name="MultiDrawArraysIndirectEXT" es2="3.1" exec="dynamic">
+ <param name="mode" type="GLenum"/>
+ <param name="indirect" type="const GLvoid *"/>
+ <param name="drawcount" type="GLsizei"/>
+ <param name="stride" type="GLsizei"/>
+ </function>
+
+ <function name="MultiDrawElementsIndirectEXT" es2="3.1" exec="dynamic">
+ <param name="mode" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="indirect" type="const GLvoid *"/>
+ <param name="drawcount" type="GLsizei"/>
+ <param name="stride" type="GLsizei"/>
+ </function>
+
+</category>
+
<category name="GL_EXT_copy_image" number="208">
<function name="CopyImageSubDataEXT" alias="CopyImageSubData" es2="3.0">
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index dc6bdc9dcce..e231c176264 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1704,6 +1704,8 @@ offsets = {
"FramebufferTextureLayerDownsampleIMG" : 1668,
"FramebufferTextureMultiviewOVR" : 1669,
"FramebufferTextureMultisampleMultiviewOVR" : 1670,
+ "MultiDrawArraysIndirectEXT" : 1671,
+ "MultiDrawElementsIndirectEXT" : 1672,
}
functions = [
--
2.25.1

View File

@@ -0,0 +1,494 @@
From 389e1a41360160bf56182a87cc52b5df9dc1265d Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Fri, 22 Dec 2017 17:17:50 +0000
Subject: [PATCH 30/67] dri: add support for YUV DRI config
This is prerequisite for adding support for EGL_EXT_yuv_surface.
This also adds support for NV12 and NV21 EGL configs.
---
include/GL/internal/dri_interface.h | 42 ++++++++-
src/gallium/frontends/dri/dri_screen.c | 8 +-
src/gallium/include/pipe/p_format.h | 2 +
src/mesa/drivers/dri/common/utils.c | 88 +++++++++++++++++--
src/mesa/drivers/dri/common/utils.h | 3 +-
src/mesa/drivers/dri/i915/intel_screen.c | 8 +-
src/mesa/drivers/dri/i965/brw_screen.c | 12 ++-
src/mesa/drivers/dri/nouveau/nouveau_screen.c | 4 +-
src/mesa/drivers/dri/radeon/radeon_screen.c | 4 +-
src/mesa/main/format_info.py | 2 +-
src/mesa/main/formats.c | 9 ++
src/mesa/main/formats.csv | 2 +
src/mesa/main/formats.h | 7 ++
src/mesa/main/mtypes.h | 9 ++
14 files changed, 181 insertions(+), 19 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 16cc095ea29..4d5a1874dc2 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -826,7 +826,13 @@ struct __DRIuseInvalidateExtensionRec {
#define __DRI_ATTRIB_GREEN_SHIFT 51
#define __DRI_ATTRIB_BLUE_SHIFT 52
#define __DRI_ATTRIB_ALPHA_SHIFT 53
-#define __DRI_ATTRIB_MAX 54
+#define __DRI_ATTRIB_YUV_ORDER 54
+#define __DRI_ATTRIB_YUV_NUMBER_OF_PLANES 55
+#define __DRI_ATTRIB_YUV_SUBSAMPLE 56
+#define __DRI_ATTRIB_YUV_DEPTH_RANGE 57
+#define __DRI_ATTRIB_YUV_CSC_STANDARD 58
+#define __DRI_ATTRIB_YUV_PLANE_BPP 59
+#define __DRI_ATTRIB_MAX 60
/* __DRI_ATTRIB_RENDER_TYPE */
#define __DRI_ATTRIB_RGBA_BIT 0x01
@@ -834,6 +840,7 @@ struct __DRIuseInvalidateExtensionRec {
#define __DRI_ATTRIB_LUMINANCE_BIT 0x04
#define __DRI_ATTRIB_FLOAT_BIT 0x08
#define __DRI_ATTRIB_UNSIGNED_FLOAT_BIT 0x10
+#define __DRI_ATTRIB_YUV_BIT 0x20
/* __DRI_ATTRIB_CONFIG_CAVEAT */
#define __DRI_ATTRIB_SLOW_BIT 0x01
@@ -860,6 +867,39 @@ struct __DRIuseInvalidateExtensionRec {
#define __DRI_ATTRIB_SWAP_COPY 0x8062
#define __DRI_ATTRIB_SWAP_UNDEFINED 0x8063
+/* __DRI_ATTRIB_YUV_ORDER */
+#define __DRI_ATTRIB_YUV_ORDER_NONE 0x0
+#define __DRI_ATTRIB_YUV_ORDER_YUV_BIT 0x1
+#define __DRI_ATTRIB_YUV_ORDER_YVU_BIT 0x2
+#define __DRI_ATTRIB_YUV_ORDER_YUYV_BIT 0x4
+#define __DRI_ATTRIB_YUV_ORDER_UYVY_BIT 0x8
+#define __DRI_ATTRIB_YUV_ORDER_YVYU_BIT 0x10
+#define __DRI_ATTRIB_YUV_ORDER_VYUY_BIT 0x20
+#define __DRI_ATTRIB_YUV_ORDER_AYUV_BIT 0x40
+
+/* __DRI_ATTRIB_YUV_SUBSAMPLE */
+#define __DRI_ATTRIB_YUV_SUBSAMPLE_NONE 0x0
+#define __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT 0x1
+#define __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_2_BIT 0x2
+#define __DRI_ATTRIB_YUV_SUBSAMPLE_4_4_4_BIT 0x4
+
+/* __DRI_ATTRIB_YUV_DEPTH_RANGE */
+#define __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE 0x0
+#define __DRI_ATTRIB_YUV_DEPTH_RANGE_LIMITED_BIT 0x1
+#define __DRI_ATTRIB_YUV_DEPTH_RANGE_FULL_BIT 0x2
+
+/* __DRI_ATTRIB_YUV_CSC_STANDARD */
+#define __DRI_ATTRIB_YUV_CSC_STANDARD_NONE 0x0
+#define __DRI_ATTRIB_YUV_CSC_STANDARD_601_BIT 0x1
+#define __DRI_ATTRIB_YUV_CSC_STANDARD_709_BIT 0x2
+#define __DRI_ATTRIB_YUV_CSC_STANDARD_2020_BIT 0x4
+
+/* __DRI_ATTRIB_YUV_PLANE_BPP */
+#define __DRI_ATTRIB_YUV_PLANE_BPP_NONE 0x0
+#define __DRI_ATTRIB_YUV_PLANE_BPP_0_BIT 0x1
+#define __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT 0x2
+#define __DRI_ATTRIB_YUV_PLANE_BPP_10_BIT 0x4
+
/**
* This extension defines the core DRI functionality.
*
diff --git a/src/gallium/frontends/dri/dri_screen.c b/src/gallium/frontends/dri/dri_screen.c
index b565a1fe8ec..37a0d4add0c 100644
--- a/src/gallium/frontends/dri/dri_screen.c
+++ b/src/gallium/frontends/dri/dri_screen.c
@@ -324,7 +324,9 @@ dri_fill_in_modes(struct dri_screen *screen)
depth_buffer_factor, back_buffer_modes,
ARRAY_SIZE(back_buffer_modes),
msaa_modes, 1,
- GL_TRUE, !mixed_color_depth);
+ GL_TRUE, !mixed_color_depth,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
/* Multi-sample configs without an accumulation buffer. */
@@ -334,7 +336,9 @@ dri_fill_in_modes(struct dri_screen *screen)
depth_buffer_factor, back_buffer_modes,
ARRAY_SIZE(back_buffer_modes),
msaa_modes+1, num_msaa_modes-1,
- GL_FALSE, !mixed_color_depth);
+ GL_FALSE, !mixed_color_depth,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
}
}
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
index 0c93d7df6e2..fd653379b7a 100644
--- a/src/gallium/include/pipe/p_format.h
+++ b/src/gallium/include/pipe/p_format.h
@@ -513,6 +513,8 @@ enum pipe_format {
PIPE_FORMAT_R4G4B4X4_UNORM,
PIPE_FORMAT_B10G10R10X2_SNORM,
PIPE_FORMAT_R5G6B5_SRGB,
+ PIPE_FORMAT_YUV420_2PLANE,
+ PIPE_FORMAT_YVU420_2PLANE,
PIPE_FORMAT_COUNT
};
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
index a3f2bc57f46..d268dc41fbb 100644
--- a/src/mesa/drivers/dri/common/utils.c
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -163,6 +163,21 @@ driGetRendererString( char * buffer, const char * hardware_name,
* This forces 32-bit color to have 24-bit depth, and
* 16-bit color to have 16-bit depth.
*
+ * \param yuv_depth_range YUV pixel depth range. For non-YUV pixel formats this
+ * should be \c __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE.
+ * Otherwise valid values are
+ * \c __DRI_ATTRIB_YUV_DEPTH_RANGE_LIMITED_BIT and
+ * \c __DRI_ATTRIB_YUV_DEPTH_RANGE_FULL_BIT. See the
+ * EGL_EXT_yuv_surface extension spec for more details.
+ * \param yuv_csc_standard YUV color conversion standard. For non-YUV pixel
+ * formats this should be
+ * \c __DRI_ATTRIB_YUV_CSC_STANDARD_NONE. Otherwise
+ * valid values are
+ * \c __DRI_ATTRIB_YUV_CSC_STANDARD_601_BIT,
+ * \c __DRI_ATTRIB_YUV_CSC_STANDARD_709_BIT and
+ * \c __DRI_ATTRIB_YUV_CSC_STANDARD_2020_BIT. See the
+ * EGL_EXT_yuv_surface extension spec for more details.
+ *
* \returns
* Pointer to any array of pointers to the \c __DRIconfig structures created
* for the specified formats. If there is an error, \c NULL is returned.
@@ -175,7 +190,8 @@ driCreateConfigs(mesa_format format,
unsigned num_depth_stencil_bits,
const GLenum * db_modes, unsigned num_db_modes,
const uint8_t * msaa_samples, unsigned num_msaa_modes,
- GLboolean enable_accum, GLboolean color_depth_match)
+ GLboolean enable_accum, GLboolean color_depth_match,
+ GLint yuv_depth_range, GLint yuv_csc_standard)
{
static const struct {
uint32_t masks[4];
@@ -214,6 +230,9 @@ driCreateConfigs(mesa_format format,
/* MESA_FORMAT_RGBA_FLOAT16 */
{{ 0, 0, 0, 0},
{ 0, 16, 32, 48 }},
+ /* Mesa YUV formats */
+ {{ 0, 0, 0, 0 },
+ { -1, -1, -1, -1}},
};
const uint32_t * masks;
@@ -227,6 +246,11 @@ driCreateConfigs(mesa_format format,
int green_bits;
int blue_bits;
int alpha_bits;
+ int yuv_order = __DRI_ATTRIB_YUV_ORDER_NONE;
+ int yuv_num_planes = 0;
+ int yuv_subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_NONE;
+ int yuv_plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_NONE;
+ bool is_yuv = false;
bool is_srgb;
bool is_float;
@@ -279,6 +303,33 @@ driCreateConfigs(mesa_format format,
masks = format_table[8].masks;
shifts = format_table[8].shifts;
break;
+ case MESA_FORMAT_YCBCR:
+ masks = format_table[11].masks;
+ shifts = format_table[11].shifts;
+ is_yuv = true; /* FIXME: This should come from formats_info.py */
+ yuv_order = __DRI_ATTRIB_YUV_ORDER_YUYV_BIT;
+ yuv_num_planes = 1;
+ yuv_subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_2_BIT;
+ yuv_plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT;
+ break;
+ case MESA_FORMAT_YUV420_2PLANE:
+ masks = format_table[11].masks;
+ shifts = format_table[11].shifts;
+ is_yuv = true; /* FIXME: This should come from formats_info.py */
+ yuv_order = __DRI_ATTRIB_YUV_ORDER_YUV_BIT;
+ yuv_num_planes = 2;
+ yuv_subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT;
+ yuv_plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT;
+ break;
+ case MESA_FORMAT_YVU420_2PLANE:
+ masks = format_table[11].masks;
+ shifts = format_table[11].shifts;
+ is_yuv = true; /* FIXME: This should come from formats_info.py */
+ yuv_order = __DRI_ATTRIB_YUV_ORDER_YVU_BIT;
+ yuv_num_planes = 2;
+ yuv_subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT;
+ yuv_plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT;
+ break;
default:
fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n",
__func__, __LINE__,
@@ -334,8 +385,12 @@ driCreateConfigs(mesa_format format,
modes->greenShift = shifts[1];
modes->blueShift = shifts[2];
modes->alphaShift = shifts[3];
- modes->rgbBits = modes->redBits + modes->greenBits
- + modes->blueBits + modes->alphaBits;
+
+ if (is_yuv)
+ modes->rgbBits = 8;
+ else
+ modes->rgbBits = modes->redBits + modes->greenBits
+ + modes->blueBits + modes->alphaBits;
modes->accumRedBits = 16 * j;
modes->accumGreenBits = 16 * j;
@@ -345,6 +400,8 @@ driCreateConfigs(mesa_format format,
modes->stencilBits = stencil_bits[k];
modes->depthBits = depth_bits[k];
+ modes->rgbMode = !is_yuv;
+
if (db_modes[i] == __DRI_ATTRIB_SWAP_NONE) {
modes->doubleBufferMode = GL_FALSE;
modes->swapMethod = __DRI_ATTRIB_SWAP_UNDEFINED;
@@ -357,6 +414,13 @@ driCreateConfigs(mesa_format format,
modes->samples = msaa_samples[h];
modes->sRGBCapable = is_srgb;
+
+ modes->YUVOrder = yuv_order;
+ modes->YUVNumberOfPlanes = yuv_num_planes;
+ modes->YUVSubsample = yuv_subsample;
+ modes->YUVDepthRange = yuv_depth_range;
+ modes->YUVCSCStandard = yuv_csc_standard;
+ modes->YUVPlaneBPP = yuv_plane_bpp;
}
}
}
@@ -436,10 +500,14 @@ driGetConfigAttribIndex(const __DRIconfig *config,
break;
__ATTRIB(__DRI_ATTRIB_SAMPLES, samples);
case __DRI_ATTRIB_RENDER_TYPE:
- /* no support for color index mode */
- *value = __DRI_ATTRIB_RGBA_BIT;
- if (config->modes.floatMode)
- *value |= __DRI_ATTRIB_FLOAT_BIT;
+ /* no support for color index mode */
+ if (config->modes.rgbMode)
+ *value = __DRI_ATTRIB_RGBA_BIT;
+ else
+ *value = __DRI_ATTRIB_YUV_BIT;
+
+ if (config->modes.floatMode)
+ *value |= __DRI_ATTRIB_FLOAT_BIT;
break;
case __DRI_ATTRIB_CONFIG_CAVEAT:
if (config->modes.accumRedBits != 0)
@@ -505,6 +573,12 @@ driGetConfigAttribIndex(const __DRIconfig *config,
__ATTRIB(__DRI_ATTRIB_GREEN_SHIFT, greenShift);
__ATTRIB(__DRI_ATTRIB_BLUE_SHIFT, blueShift);
__ATTRIB(__DRI_ATTRIB_ALPHA_SHIFT, alphaShift);
+ __ATTRIB(__DRI_ATTRIB_YUV_ORDER, YUVOrder);
+ __ATTRIB(__DRI_ATTRIB_YUV_NUMBER_OF_PLANES, YUVNumberOfPlanes);
+ __ATTRIB(__DRI_ATTRIB_YUV_SUBSAMPLE, YUVSubsample);
+ __ATTRIB(__DRI_ATTRIB_YUV_DEPTH_RANGE, YUVDepthRange);
+ __ATTRIB(__DRI_ATTRIB_YUV_CSC_STANDARD, YUVCSCStandard);
+ __ATTRIB(__DRI_ATTRIB_YUV_PLANE_BPP, YUVPlaneBPP);
default:
/* XXX log an error or smth */
return GL_FALSE;
diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h
index 7be0465c261..ebd98d9dc33 100644
--- a/src/mesa/drivers/dri/common/utils.h
+++ b/src/mesa/drivers/dri/common/utils.h
@@ -45,7 +45,8 @@ driCreateConfigs(mesa_format format,
unsigned num_depth_stencil_bits,
const GLenum * db_modes, unsigned num_db_modes,
const uint8_t * msaa_samples, unsigned num_msaa_modes,
- GLboolean enable_accum, GLboolean color_depth_match);
+ GLboolean enable_accum, GLboolean color_depth_match,
+ GLint yuv_depth_range, GLint yuv_csc_standards);
__DRIconfig **driConcatConfigs(__DRIconfig **a,
__DRIconfig **b);
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 6135357c2a0..a94c6de0a06 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -1083,7 +1083,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
num_depth_stencil_bits,
back_buffer_modes, 2,
singlesample_samples, 1,
- false, false);
+ false, false,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
}
@@ -1105,7 +1107,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
depth_bits, stencil_bits, 1,
back_buffer_modes, 1,
singlesample_samples, 1,
- true, false);
+ true, false,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
}
diff --git a/src/mesa/drivers/dri/i965/brw_screen.c b/src/mesa/drivers/dri/i965/brw_screen.c
index 56811110567..c450bae1054 100644
--- a/src/mesa/drivers/dri/i965/brw_screen.c
+++ b/src/mesa/drivers/dri/i965/brw_screen.c
@@ -2292,7 +2292,9 @@ brw_screen_make_configs(__DRIscreen *dri_screen)
num_depth_stencil_bits,
back_buffer_modes, 2,
singlesample_samples, 1,
- false, false);
+ false, false,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
}
@@ -2325,7 +2327,9 @@ brw_screen_make_configs(__DRIscreen *dri_screen)
depth_bits, stencil_bits, 1,
back_buffer_modes, 1,
singlesample_samples, 1,
- true, false);
+ true, false,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
}
@@ -2390,7 +2394,9 @@ brw_screen_make_configs(__DRIscreen *dri_screen)
back_buffer_modes, 1,
multisample_samples,
num_msaa_modes,
- false, false);
+ false, false,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
index c92efcd7b20..fc87d5eb395 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
@@ -79,7 +79,9 @@ nouveau_get_configs(uint32_t chipset)
ARRAY_SIZE(back_buffer_modes),
msaa_samples,
ARRAY_SIZE(msaa_samples),
- GL_TRUE, chipset < 0x10);
+ GL_TRUE, chipset < 0x10,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
assert(config);
configs = driConcatConfigs(configs, config);
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 3764a5d6538..f7628555b8f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -838,7 +838,9 @@ __DRIconfig **radeonInitScreen2(__DRIscreen *psp)
ARRAY_SIZE(back_buffer_modes),
msaa_samples_array,
ARRAY_SIZE(msaa_samples_array),
- GL_TRUE, GL_FALSE);
+ GL_TRUE, GL_FALSE,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE,
+ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE);
configs = driConcatConfigs(configs, new_configs);
}
diff --git a/src/mesa/main/format_info.py b/src/mesa/main/format_info.py
index edc0324e60b..d58403ea85e 100644
--- a/src/mesa/main/format_info.py
+++ b/src/mesa/main/format_info.py
@@ -29,7 +29,7 @@ import sys
def get_gl_base_format(fmat):
if fmat.name == 'MESA_FORMAT_NONE':
return 'GL_NONE'
- elif fmat.name in ['MESA_FORMAT_YCBCR', 'MESA_FORMAT_YCBCR_REV']:
+ elif fmat.name in ['MESA_FORMAT_YCBCR', 'MESA_FORMAT_YCBCR_REV', 'MESA_FORMAT_YUV420_2PLANE', 'MESA_FORMAT_YVU420_2PLANE']:
return 'GL_YCBCR_MESA'
elif fmat.has_channel('r'):
if fmat.has_channel('g'):
diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
index 9cd026f7507..f81caeceff4 100644
--- a/src/mesa/main/formats.c
+++ b/src/mesa/main/formats.c
@@ -1452,6 +1452,15 @@ _mesa_format_matches_format_and_type(mesa_format mformat,
if (error)
*error = GL_NO_ERROR;
+ switch (mformat) {
+ case MESA_FORMAT_YUV420_2PLANE:
+ case MESA_FORMAT_YVU420_2PLANE:
+ return false;
+
+ default:
+ break;
+ }
+
if (_mesa_is_format_compressed(mformat)) {
if (error)
*error = GL_INVALID_ENUM;
diff --git a/src/mesa/main/formats.csv b/src/mesa/main/formats.csv
index 21cdea26e08..b2d476577e0 100644
--- a/src/mesa/main/formats.csv
+++ b/src/mesa/main/formats.csv
@@ -92,6 +92,8 @@ MESA_FORMAT_A2R10G10B10_UNORM , packed, 1, 1, 1, un2 , un10, un10, u
MESA_FORMAT_YCBCR , other , 1, 1, 1, x16 , , , , xyzw, yuv
MESA_FORMAT_YCBCR_REV , other , 1, 1, 1, x16 , , , , xyzw, yuv
+MESA_FORMAT_YUV420_2PLANE , other , 1, 1, 1, x8 , , , , y___, yuv
+MESA_FORMAT_YVU420_2PLANE , other , 1, 1, 1, x8 , , , , y___, yuv
MESA_FORMAT_RG_RB_UNORM8 , other , 2, 1, 1, x16 , , , , xyz1, rgb
MESA_FORMAT_GR_BR_UNORM8 , other , 2, 1, 1, x16 , , , , xyz1, rgb
diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
index 508c9c342d2..0e778d64467 100644
--- a/src/mesa/main/formats.h
+++ b/src/mesa/main/formats.h
@@ -617,6 +617,13 @@ typedef enum pipe_format mesa_format;
#define MESA_FORMAT_ATC_RGB PIPE_FORMAT_ATC_RGB
#define MESA_FORMAT_ATC_RGBA_EXPLICIT PIPE_FORMAT_ATC_RGBA_EXPLICIT
#define MESA_FORMAT_ATC_RGBA_INTERPOLATED PIPE_FORMAT_ATC_RGBA_INTERPOLATED
+
+#define HAVE_MESA_FORMAT_YUV420_2PLANE
+#define MESA_FORMAT_YUV420_2PLANE PIPE_FORMAT_YUV420_2PLANE
+
+#define HAVE_MESA_FORMAT_YVU420_2PLANE
+#define MESA_FORMAT_YVU420_2PLANE PIPE_FORMAT_YVU420_2PLANE
+
#define MESA_FORMAT_COUNT PIPE_FORMAT_COUNT
/* Packed to array format adapters */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 32528a5f16b..8f77d4c58dd 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -158,6 +158,7 @@ _mesa_varying_slot_in_fs(gl_varying_slot slot)
*/
struct gl_config
{
+ GLboolean rgbMode;
GLboolean floatMode;
GLuint doubleBufferMode;
GLuint stereoMode;
@@ -179,6 +180,14 @@ struct gl_config
/* EXT_framebuffer_sRGB */
GLint sRGBCapable;
+
+ /* EXT_yuv_surface */
+ GLint YUVOrder;
+ GLint YUVNumberOfPlanes;
+ GLint YUVSubsample;
+ GLint YUVDepthRange;
+ GLint YUVCSCStandard;
+ GLint YUVPlaneBPP;
};
--
2.25.1

View File

@@ -0,0 +1,541 @@
From 4e65ae659b775259b4f703eb563feffc623c17b7 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Wed, 20 Dec 2017 17:41:38 +0000
Subject: [PATCH 31/67] egl: add support for EXT_yuv_surface
This implements EXT_yuv_surface but doesn't expose it for any platform.
---
include/GL/internal/dri_interface.h | 1 +
src/egl/drivers/dri2/egl_dri2.c | 83 +++++++++
src/egl/main/eglapi.c | 1 +
src/egl/main/eglconfig.c | 255 +++++++++++++++++++++++++++-
src/egl/main/eglconfig.h | 12 ++
src/egl/main/egldisplay.h | 1 +
6 files changed, 348 insertions(+), 5 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 4d5a1874dc2..62517e4004a 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1154,6 +1154,7 @@ enum dri_loader_cap {
*/
DRI_LOADER_CAP_RGBA_ORDERING,
DRI_LOADER_CAP_FP16,
+ DRI_LOADER_CAP_YUV_SURFACE_IMG = 0x7001,
};
struct __DRIdri2LoaderExtensionRec {
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index db993f8f059..ee3bcda4d12 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -306,6 +306,7 @@ static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = {
[__DRI_ATTRIB_MAX_SWAP_INTERVAL] = EGL_MAX_SWAP_INTERVAL,
[__DRI_ATTRIB_MIN_SWAP_INTERVAL] = EGL_MIN_SWAP_INTERVAL,
[__DRI_ATTRIB_YINVERTED] = EGL_Y_INVERTED_NOK,
+ [__DRI_ATTRIB_YUV_NUMBER_OF_PLANES] = EGL_YUV_NUMBER_OF_PLANES_EXT,
};
const __DRIconfig *
@@ -432,6 +433,8 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
value = EGL_RGB_BUFFER;
else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
value = EGL_LUMINANCE_BUFFER;
+ else if (value & __DRI_ATTRIB_YUV_BIT)
+ value = EGL_YUV_BUFFER_EXT;
else
return NULL;
base.ColorBufferType = value;
@@ -536,6 +539,73 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
if (disp->Extensions.KHR_mutable_render_buffer)
surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
break;
+
+ case __DRI_ATTRIB_YUV_ORDER:
+ if (value & __DRI_ATTRIB_YUV_ORDER_YUV_BIT)
+ value = EGL_YUV_ORDER_YUV_EXT;
+ else if (value & __DRI_ATTRIB_YUV_ORDER_YVU_BIT)
+ value = EGL_YUV_ORDER_YVU_EXT;
+ else if (value & __DRI_ATTRIB_YUV_ORDER_YUYV_BIT)
+ value = EGL_YUV_ORDER_YUYV_EXT;
+ else if (value & __DRI_ATTRIB_YUV_ORDER_UYVY_BIT)
+ value = EGL_YUV_ORDER_UYVY_EXT;
+ else if (value & __DRI_ATTRIB_YUV_ORDER_YVYU_BIT)
+ value = EGL_YUV_ORDER_YVYU_EXT;
+ else if (value & __DRI_ATTRIB_YUV_ORDER_VYUY_BIT)
+ value = EGL_YUV_ORDER_VYUY_EXT;
+ else if (value & __DRI_ATTRIB_YUV_ORDER_AYUV_BIT)
+ value = EGL_YUV_ORDER_AYUV_EXT;
+ else
+ value = EGL_NONE;
+ _eglSetConfigKey(&base, EGL_YUV_ORDER_EXT, value);
+ break;
+
+ case __DRI_ATTRIB_YUV_SUBSAMPLE:
+ if (value & __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT)
+ value = EGL_YUV_SUBSAMPLE_4_2_0_EXT;
+ else if (value & __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_2_BIT)
+ value = EGL_YUV_SUBSAMPLE_4_2_2_EXT;
+ else if (value & __DRI_ATTRIB_YUV_SUBSAMPLE_4_4_4_BIT)
+ value = EGL_YUV_SUBSAMPLE_4_4_4_EXT;
+ else
+ value = EGL_NONE;
+ _eglSetConfigKey(&base, EGL_YUV_SUBSAMPLE_EXT, value);
+ break;
+
+ case __DRI_ATTRIB_YUV_DEPTH_RANGE:
+ if (value & __DRI_ATTRIB_YUV_DEPTH_RANGE_LIMITED_BIT)
+ value = EGL_YUV_DEPTH_RANGE_LIMITED_EXT;
+ else if (value & __DRI_ATTRIB_YUV_DEPTH_RANGE_FULL_BIT)
+ value = EGL_YUV_DEPTH_RANGE_FULL_EXT;
+ else
+ value = EGL_NONE;
+ _eglSetConfigKey(&base, EGL_YUV_DEPTH_RANGE_EXT, value);
+ break;
+
+ case __DRI_ATTRIB_YUV_CSC_STANDARD:
+ if (value & __DRI_ATTRIB_YUV_CSC_STANDARD_601_BIT)
+ value = EGL_YUV_CSC_STANDARD_601_EXT;
+ else if (value & __DRI_ATTRIB_YUV_CSC_STANDARD_709_BIT)
+ value = EGL_YUV_CSC_STANDARD_709_EXT;
+ else if (value & __DRI_ATTRIB_YUV_CSC_STANDARD_2020_BIT)
+ value = EGL_YUV_CSC_STANDARD_2020_EXT;
+ else
+ value = EGL_NONE;
+ _eglSetConfigKey(&base, EGL_YUV_CSC_STANDARD_EXT, value);
+ break;
+
+ case __DRI_ATTRIB_YUV_PLANE_BPP:
+ if (value & __DRI_ATTRIB_YUV_PLANE_BPP_0_BIT)
+ value = EGL_YUV_PLANE_BPP_0_EXT;
+ else if (value & __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT)
+ value = EGL_YUV_PLANE_BPP_8_EXT;
+ else if (value & __DRI_ATTRIB_YUV_PLANE_BPP_10_BIT)
+ value = EGL_YUV_PLANE_BPP_10_EXT;
+ else
+ value = EGL_NONE;
+ _eglSetConfigKey(&base, EGL_YUV_PLANE_BPP_EXT, value);
+ break;
+
default:
key = dri2_to_egl_attribute_map[attrib];
if (key != 0)
@@ -583,6 +653,17 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
base.RenderableType = disp->ClientAPIs;
base.Conformant = disp->ClientAPIs;
+ /*
+ * We assume that if dri_config is YUV then GL_EXT_YUV_target must be
+ * supported, which requires OpenGL ES 3.0.
+ */
+ if (base.ColorBufferType == EGL_YUV_BUFFER_EXT) {
+ base.RenderableType &= EGL_OPENGL_ES3_BIT;
+ base.Conformant &= EGL_OPENGL_ES3_BIT;
+ }
+ if (!base.RenderableType)
+ return NULL;
+
base.MinSwapInterval = dri2_dpy->min_swap_interval;
base.MaxSwapInterval = dri2_dpy->max_swap_interval;
@@ -1014,6 +1095,8 @@ dri2_setup_screen(_EGLDisplay *disp)
disp->Extensions.EXT_protected_surface =
dri2_renderer_query_integer(dri2_dpy,
__DRI2_RENDERER_HAS_PROTECTED_CONTENT);
+
+ disp->Extensions.EXT_yuv_surface = EGL_TRUE;
}
void
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index e2a7797d73e..6d7f62c6851 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -512,6 +512,7 @@ _eglCreateExtensionsString(_EGLDisplay *disp)
_EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata);
_EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata);
_EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
+ _EGL_CHECK_EXTENSION(EXT_yuv_surface);
_EGL_CHECK_EXTENSION(IMG_context_priority);
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index 17d8f3555d4..5e56948ab72 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -258,6 +258,24 @@ static const struct {
{ EGL_COLOR_COMPONENT_TYPE_EXT, ATTRIB_TYPE_ENUM,
ATTRIB_CRITERION_EXACT,
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT },
+ { EGL_YUV_ORDER_EXT, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_YUV_NUMBER_OF_PLANES_EXT, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_YUV_SUBSAMPLE_EXT, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_YUV_DEPTH_RANGE_EXT, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_YUV_CSC_STANDARD_EXT, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_YUV_PLANE_BPP_EXT, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
};
@@ -296,6 +314,28 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
if (val > 1 || val < 0)
valid = EGL_FALSE;
break;
+ case EGL_YUV_NUMBER_OF_PLANES_EXT:
+ /* From the EGL_EXT_yuv_surface spec (v9):
+ *
+ * The allowed values for EGL_YUV_NUMBER_OF_PLANES_EXT must
+ * be greater than zero and not more than three.
+ *
+ * However, it also says:
+ *
+ * Attribute Default Selection Sort Sort
+ * Criteria Order Priority
+ * ---------------------------- ------- --------- ----- --------
+ * EGL_YUV_NUMBER_OF_PLANES_EXT 0 At least None
+ *
+ * This means that we need to allow the value 0 when doing config
+ * matching (where it's essentially treated as EGL_DONT_CARE).
+ * Furthermore, this attribute isn't applicable to non-YUV EGL
+ * color buffer types. Allow 0 through here and then do further
+ * validation later on.
+ */
+ if (val < 0 || val > 3)
+ valid = EGL_FALSE;
+ break;
default:
if (val < 0)
valid = EGL_FALSE;
@@ -318,7 +358,43 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
valid = EGL_FALSE;
break;
case EGL_COLOR_BUFFER_TYPE:
- if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
+ if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER &&
+ val != EGL_YUV_BUFFER_EXT)
+ valid = EGL_FALSE;
+ break;
+ case EGL_YUV_ORDER_EXT:
+ if (val != EGL_NONE &&
+ val != EGL_YUV_ORDER_YUV_EXT && val != EGL_YUV_ORDER_YVU_EXT &&
+ val != EGL_YUV_ORDER_YUYV_EXT && val != EGL_YUV_ORDER_UYVY_EXT &&
+ val != EGL_YUV_ORDER_YVYU_EXT && val != EGL_YUV_ORDER_VYUY_EXT &&
+ val != EGL_YUV_ORDER_AYUV_EXT)
+ valid = EGL_FALSE;
+ break;
+ case EGL_YUV_SUBSAMPLE_EXT:
+ if (val != EGL_NONE &&
+ val != EGL_YUV_SUBSAMPLE_4_2_0_EXT &&
+ val != EGL_YUV_SUBSAMPLE_4_2_2_EXT &&
+ val != EGL_YUV_SUBSAMPLE_4_4_4_EXT)
+ valid = EGL_FALSE;
+ break;
+ case EGL_YUV_DEPTH_RANGE_EXT:
+ if (val != EGL_NONE &&
+ val != EGL_YUV_DEPTH_RANGE_LIMITED_EXT &&
+ val != EGL_YUV_DEPTH_RANGE_FULL_EXT)
+ valid = EGL_FALSE;
+ break;
+ case EGL_YUV_CSC_STANDARD_EXT:
+ if (val != EGL_NONE &&
+ val != EGL_YUV_CSC_STANDARD_601_EXT &&
+ val != EGL_YUV_CSC_STANDARD_709_EXT &&
+ val != EGL_YUV_CSC_STANDARD_2020_EXT)
+ valid = EGL_FALSE;
+ break;
+ case EGL_YUV_PLANE_BPP_EXT:
+ if (val != EGL_NONE &&
+ val != EGL_YUV_PLANE_BPP_0_EXT &&
+ val != EGL_YUV_PLANE_BPP_8_EXT &&
+ val != EGL_YUV_PLANE_BPP_10_EXT)
valid = EGL_FALSE;
break;
case EGL_COLOR_COMPONENT_TYPE_EXT:
@@ -404,6 +480,11 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize)
valid = EGL_FALSE;
break;
+ case EGL_YUV_BUFFER_EXT:
+ if (conf->RedSize || conf->GreenSize || conf->BlueSize ||
+ conf->AlphaSize || conf->LuminanceSize)
+ valid = EGL_FALSE;
+ break;
}
if (!valid) {
_eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
@@ -430,6 +511,88 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
return EGL_FALSE;
}
+ /* From the EGL_EXT_yuv_surface spec (v9):
+ *
+ * SUBSAMPLE_EXT NUMBER_OF_PLANES_EXT ORDER_EXT PLANE_BPP_EXT
+ * ------------------- -------------------- ----------------- ------------------
+ * SUBSAMPLE_4_2_0_EXT 2 or 3 ORDER_YUV_EXT or PLANE_BPP_8_EXT or
+ * ORDER_YVU_EXT PLANE_BPP_10_EXT
+ */
+ if (conf->YUVSubsampleEXT == EGL_YUV_SUBSAMPLE_4_2_0_EXT) {
+ if ((!for_matching || conf->YUVNumberOfPlanesEXT != 0) &&
+ conf->YUVNumberOfPlanesEXT != 2 &&
+ conf->YUVNumberOfPlanesEXT != 3)
+ valid = EGL_FALSE;
+ if (conf->YUVOrderEXT != EGL_DONT_CARE &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_YUV_EXT &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_YVU_EXT)
+ valid = EGL_FALSE;
+ if (conf->YUVPlaneBPPEXT != EGL_DONT_CARE &&
+ conf->YUVPlaneBPPEXT != EGL_YUV_PLANE_BPP_8_EXT &&
+ conf->YUVPlaneBPPEXT != EGL_YUV_PLANE_BPP_10_EXT)
+ valid = EGL_FALSE;
+ }
+ /* From the EGL_EXT_yuv_surface spec (v9):
+ *
+ * SUBSAMPLE_EXT NUMBER_OF_PLANES_EXT ORDER_EXT PLANE_BPP_EXT
+ * ------------------- -------------------- ----------------- ------------------
+ * SUBSAMPLE_4_2_2_EXT 1 ORDER_YUYV_EXT or PLANE_BPP_8_EXT or
+ * ORDER_YVYU_EXT or PLANE_BPP_10_EXT
+ * ORDER_UYVY_EXT or
+ * ORDER_VYUY_EXT
+ *
+ * SUBSAMPLE_4_2_2_EXT 2 or 3 ORDER_YUV_EXT or PLANE_BPP_8_EXT or
+ * ORDER_YVU_EXT PLANE_BPP_10_EXT
+ */
+ else if (conf->YUVSubsampleEXT == EGL_YUV_SUBSAMPLE_4_2_2_EXT) {
+ if ((!for_matching || conf->YUVNumberOfPlanesEXT != 0) &&
+ conf->YUVNumberOfPlanesEXT != 1 &&
+ conf->YUVNumberOfPlanesEXT != 2 &&
+ conf->YUVNumberOfPlanesEXT != 3)
+ valid = EGL_FALSE;
+ if (conf->YUVNumberOfPlanesEXT == 1) {
+ if (conf->YUVOrderEXT != EGL_DONT_CARE &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_YUYV_EXT &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_YVYU_EXT &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_UYVY_EXT &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_VYUY_EXT)
+ valid = EGL_FALSE;
+ } else if (conf->YUVNumberOfPlanesEXT == 2 ||
+ conf->YUVNumberOfPlanesEXT == 3) {
+ if (conf->YUVOrderEXT != EGL_DONT_CARE &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_YUV_EXT &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_YVU_EXT)
+ valid = EGL_FALSE;
+ }
+ if (conf->YUVPlaneBPPEXT != EGL_DONT_CARE &&
+ conf->YUVPlaneBPPEXT != EGL_YUV_PLANE_BPP_8_EXT &&
+ conf->YUVPlaneBPPEXT != EGL_YUV_PLANE_BPP_10_EXT)
+ valid = EGL_FALSE;
+ }
+ /* From the EGL_EXT_yuv_surface spec (v9):
+ *
+ * SUBSAMPLE_EXT NUMBER_OF_PLANES_EXT ORDER_EXT PLANE_BPP_EXT
+ * ------------------- -------------------- ----------------- ------------------
+ * SUBSAMPLE_4_4_4_EXT 1 ORDER_AYUV_EXT PLANE_BPP_8_EXT or
+ * PLANE_BPP_10_EXT
+ */
+ else if (conf->YUVSubsampleEXT == EGL_YUV_SUBSAMPLE_4_4_4_EXT) {
+ if ((!for_matching || conf->YUVNumberOfPlanesEXT != 0) &&
+ conf->YUVNumberOfPlanesEXT != 1)
+ valid = EGL_FALSE;
+ if (conf->YUVOrderEXT != EGL_DONT_CARE &&
+ conf->YUVOrderEXT != EGL_YUV_ORDER_AYUV_EXT)
+ valid = EGL_FALSE;
+ if (conf->YUVPlaneBPPEXT != EGL_DONT_CARE &&
+ conf->YUVPlaneBPPEXT != EGL_YUV_PLANE_BPP_8_EXT &&
+ conf->YUVPlaneBPPEXT != EGL_YUV_PLANE_BPP_10_EXT)
+ valid = EGL_FALSE;
+ }
+ if (!valid) {
+ _eglLog(_EGL_DEBUG, "invalid YUV subsample/num planes/order/bpp combination");
+ return EGL_FALSE;
+ }
+
return valid;
}
@@ -509,6 +672,28 @@ _eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
return conf->Display->Extensions.ANDROID_framebuffer_target;
case EGL_RECORDABLE_ANDROID:
return conf->Display->Extensions.ANDROID_recordable;
+ case EGL_YUV_ORDER_EXT:
+ case EGL_YUV_NUMBER_OF_PLANES_EXT:
+ case EGL_YUV_SUBSAMPLE_EXT:
+ case EGL_YUV_DEPTH_RANGE_EXT:
+ case EGL_YUV_CSC_STANDARD_EXT:
+ case EGL_YUV_PLANE_BPP_EXT:
+ return conf->Display->Extensions.EXT_yuv_surface;
+ default:
+ break;
+ }
+
+ return EGL_TRUE;
+}
+
+static inline EGLBoolean
+_eglIsConfigAttribValueValid(_EGLConfig *conf, EGLint attr, EGLint val)
+{
+ switch (attr) {
+ case EGL_COLOR_BUFFER_TYPE:
+ if (!conf->Display->Extensions.EXT_yuv_surface && val == EGL_YUV_BUFFER_EXT)
+ return EGL_FALSE;
+ break;
default:
break;
}
@@ -543,6 +728,9 @@ _eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *disp,
if (!_eglIsConfigAttribValid(conf, attr))
return EGL_FALSE;
+ if (!_eglIsConfigAttribValueValid(conf, attr, val))
+ return EGL_FALSE;
+
_eglSetConfigKey(conf, attr, val);
}
@@ -617,6 +805,7 @@ _eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
/* the enum values have the desired ordering */
STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
+ STATIC_ASSERT(EGL_LUMINANCE_BUFFER < EGL_YUV_BUFFER_EXT);
val1 = conf1->ColorBufferType - conf2->ColorBufferType;
if (val1)
return val1;
@@ -636,16 +825,42 @@ _eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
val1 += conf1->BlueSize;
val2 += conf2->BlueSize;
}
+ if (criteria->AlphaSize > 0) {
+ val1 += conf1->AlphaSize;
+ val2 += conf2->AlphaSize;
+ }
}
- else {
+ else if (conf1->ColorBufferType == EGL_LUMINANCE_BUFFER) {
if (criteria->LuminanceSize > 0) {
val1 += conf1->LuminanceSize;
val2 += conf2->LuminanceSize;
}
+ if (criteria->AlphaSize > 0) {
+ val1 += conf1->AlphaSize;
+ val2 += conf2->AlphaSize;
+ }
}
- if (criteria->AlphaSize > 0) {
- val1 += conf1->AlphaSize;
- val2 += conf2->AlphaSize;
+ else {
+ /* From the EGL_EXT_yuv_surface spec (v9):
+ *
+ * Special: by larger total number of color bits
+ * ...
+ * for YUV color buffers, this returns the integer value with
+ * respect to the enumeration provided for EGL_YUV_PLANE_BPP_EXT
+ *
+ * and:
+ *
+ * EGL_BUFFER_SIZE gives the total of the color component bits of
+ * the color buffer for EGL_RGB_BUFFER or for EGL_LUMINANCE_BUFFER.
+ * ...
+ * When EGL_COLOR_BUFFER_TYPE is of type EGL_YUV_BUFFER_EXT,
+ * this will reflect the enumeration provided as an integer)
+ * for EGL_YUV_PLANE_BPP_EXT, giving a value of 0, 8 or 10
+ */
+ if (criteria->BufferSize > 0) {
+ val1 = conf1->BufferSize;
+ val2 = conf2->BufferSize;
+ }
}
}
else {
@@ -664,6 +879,36 @@ _eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
return (val1 - val2);
}
+ if (conf1->YUVOrderEXT != conf2->YUVOrderEXT)
+ {
+ const EGLint yuv_order[] = {
+ EGL_NONE,
+ EGL_YUV_ORDER_YUV_EXT,
+ EGL_YUV_ORDER_YVU_EXT,
+ EGL_YUV_ORDER_YUYV_EXT,
+ EGL_YUV_ORDER_YVYU_EXT,
+ EGL_YUV_ORDER_UYVY_EXT,
+ EGL_YUV_ORDER_VYUY_EXT,
+ EGL_YUV_ORDER_AYUV_EXT,
+ };
+
+ val1 = val2 = 0;
+ for (i = 0; i < ARRAY_SIZE(yuv_order); i++) {
+ if (yuv_order[i] == conf1->YUVOrderEXT) {
+ val1 = i;
+ break;
+ }
+ }
+ for (i = 0; i < ARRAY_SIZE(yuv_order); i++) {
+ if (yuv_order[i] == conf2->YUVOrderEXT) {
+ val2 = i;
+ break;
+ }
+ }
+ if (val1 != val2)
+ return val1 - val2;
+ }
+
/* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0;
diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h
index 1f2a4008f12..d4a748970b5 100644
--- a/src/egl/main/eglconfig.h
+++ b/src/egl/main/eglconfig.h
@@ -89,6 +89,12 @@ struct _egl_config
EGLint FramebufferTargetAndroid;
EGLint RecordableAndroid;
EGLint ComponentType;
+ EGLint YUVOrderEXT;
+ EGLint YUVNumberOfPlanesEXT;
+ EGLint YUVSubsampleEXT;
+ EGLint YUVDepthRangeEXT;
+ EGLint YUVCSCStandardEXT;
+ EGLint YUVPlaneBPPEXT;
};
@@ -139,6 +145,12 @@ _eglOffsetOfConfig(EGLint attr)
ATTRIB_MAP(EGL_FRAMEBUFFER_TARGET_ANDROID, FramebufferTargetAndroid);
ATTRIB_MAP(EGL_RECORDABLE_ANDROID, RecordableAndroid);
ATTRIB_MAP(EGL_COLOR_COMPONENT_TYPE_EXT, ComponentType);
+ ATTRIB_MAP(EGL_YUV_ORDER_EXT, YUVOrderEXT);
+ ATTRIB_MAP(EGL_YUV_NUMBER_OF_PLANES_EXT, YUVNumberOfPlanesEXT);
+ ATTRIB_MAP(EGL_YUV_SUBSAMPLE_EXT, YUVSubsampleEXT);
+ ATTRIB_MAP(EGL_YUV_DEPTH_RANGE_EXT, YUVDepthRangeEXT);
+ ATTRIB_MAP(EGL_YUV_CSC_STANDARD_EXT, YUVCSCStandardEXT);
+ ATTRIB_MAP(EGL_YUV_PLANE_BPP_EXT, YUVPlaneBPPEXT);
#undef ATTRIB_MAP
default:
return -1;
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 0a7366b7c07..020529c57e2 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -112,6 +112,7 @@ struct _egl_extensions
EGLBoolean EXT_surface_CTA861_3_metadata;
EGLBoolean EXT_surface_SMPTE2086_metadata;
EGLBoolean EXT_swap_buffers_with_damage;
+ EGLBoolean EXT_yuv_surface;
unsigned int IMG_context_priority;
#define __EGL_CONTEXT_PRIORITY_LOW_BIT 0
--
2.25.1

View File

@@ -0,0 +1,35 @@
From 5a22280c13e98932ad45fa6a131217abdffd16b4 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Fri, 2 Feb 2018 16:59:52 +0000
Subject: [PATCH 32/67] dri: add missing __DRI_IMAGE_COMPONENTS define for
EGL_TEXTURE_EXTERNAL_WL
The __DRI_IMAGE_COMPONENTS defines have been re-ordered, to make it
less likely that new defines will be added with the same values as
existing ones.
---
include/GL/internal/dri_interface.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 62517e4004a..6490f6e80e2 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1461,11 +1461,12 @@ struct __DRIdri2ExtensionRec {
#define __DRI_IMAGE_COMPONENTS_Y_U_V 0x3003
#define __DRI_IMAGE_COMPONENTS_Y_UV 0x3004
#define __DRI_IMAGE_COMPONENTS_Y_XUXV 0x3005
+#define __DRI_IMAGE_COMPONENTS_R 0x3006
+#define __DRI_IMAGE_COMPONENTS_RG 0x3007
#define __DRI_IMAGE_COMPONENTS_Y_UXVX 0x3008
#define __DRI_IMAGE_COMPONENTS_AYUV 0x3009
#define __DRI_IMAGE_COMPONENTS_XYUV 0x300A
-#define __DRI_IMAGE_COMPONENTS_R 0x3006
-#define __DRI_IMAGE_COMPONENTS_RG 0x3007
+#define __DRI_IMAGE_COMPONENTS_EXTERNAL 0x300B
/**
--
2.25.1

View File

@@ -0,0 +1,74 @@
From 3d47285da42c76fe36ae67c62e8d0a0d76d18da0 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Thu, 11 Jan 2018 09:38:47 +0000
Subject: [PATCH 33/67] egl/wayland: expose EXT_yuv_surface support
This adds support for YUYV configs.
---
src/egl/drivers/dri2/egl_dri2.c | 1 +
src/egl/drivers/dri2/platform_wayland.c | 15 ++++++++++++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index ee3bcda4d12..d511d73f2ed 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -2769,6 +2769,7 @@ static const struct wl_drm_components_descriptor {
{ __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
{ __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
{ __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
+ { __DRI_IMAGE_COMPONENTS_EXTERNAL, EGL_TEXTURE_EXTERNAL_WL, 1 },
};
static _EGLImage *
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index a096d9500c1..72456d5d748 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -135,6 +135,13 @@ static const struct dri2_wl_visual {
{ 11, 5, 0, -1 },
{ 5, 6, 5, 0 },
},
+ {
+ "YUYV",
+ WL_DRM_FORMAT_YUYV, WL_SHM_FORMAT_YUYV,
+ __DRI_IMAGE_FORMAT_YUYV, __DRI_IMAGE_FORMAT_NONE, 32,
+ { -1, -1, -1, -1 },
+ { 0, 0, 0, 0 },
+ },
};
static_assert(ARRAY_SIZE(dri2_wl_visuals) <= EGL_DRI2_MAX_FORMATS,
@@ -958,6 +965,7 @@ dri2_wl_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
{
switch (cap) {
case DRI_LOADER_CAP_FP16:
+ case DRI_LOADER_CAP_YUV_SURFACE_IMG:
return 1;
default:
return 0;
@@ -1552,6 +1560,7 @@ dri2_wl_add_configs_for_visuals(_EGLDisplay *disp)
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
unsigned int format_count[ARRAY_SIZE(dri2_wl_visuals)] = { 0 };
unsigned int count = 0;
+ EGLint surface_type;
bool assigned;
for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
@@ -1563,8 +1572,12 @@ dri2_wl_add_configs_for_visuals(_EGLDisplay *disp)
if (!BITSET_TEST(dri2_dpy->formats, j))
continue;
+ surface_type = EGL_WINDOW_BIT;
+ if (dri2_wl_visuals[j].wl_drm_format != WL_DRM_FORMAT_YUYV)
+ surface_type |= EGL_PBUFFER_BIT;
+
dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
- count + 1, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
+ count + 1, surface_type, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
if (dri2_conf) {
if (dri2_conf->base.ConfigID == count + 1)
count++;
--
2.25.1

View File

@@ -0,0 +1,357 @@
From 40c0d03cfb2751279b24890d0f752fade968862e Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Tue, 13 Feb 2018 14:47:48 +0000
Subject: [PATCH 34/67] egl/tizen: expose EXT_yuv_surface support
This adds support for NV12 and NV21 configs.
---
src/egl/drivers/dri2/platform_tizen.c | 278 ++++++++++++++++++--------
1 file changed, 200 insertions(+), 78 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index 2bc9b3e7c64..b6478a1875b 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -100,37 +100,93 @@ create_image_from_native(struct dri2_egl_surface *dri2_surf,
{
_EGLSurface *surf = &dri2_surf->base;
struct dri2_egl_display *dri2_dpy = dri2_egl_display(surf->Resource.Display);
+ struct dri2_egl_config *dri2_conf = dri2_egl_config(surf->Config);
+ const __DRIconfig *config =
+ dri2_get_dri_config(dri2_conf, surf->Type, surf->GLColorspace);
tbm_bo tbm_buf;
tbm_surface_info_s info;
- int fd, fourcc, offset, pitch;
+ int fd[TBM_SURF_PLANE_MAX];
+ int offset[TBM_SURF_PLANE_MAX];
+ int pitch[TBM_SURF_PLANE_MAX];
+ int fourcc;
__DRIimage *dri_image;
-
- tbm_buf = tbm_surface_internal_get_bo(tbm_surf, 0);
- if (!tbm_buf) {
- _eglLog(_EGL_DEBUG, "%s: failed to get bo for tbm surface", __func__);
- return NULL;
- }
+ enum __DRIYUVColorSpace color_space;
+ enum __DRISampleRange sample_range;
+ unsigned csc_standard;
+ unsigned depth_range;
+ unsigned create_error;
if (tbm_surface_get_info(tbm_surf, &info)) {
_eglLog(_EGL_DEBUG, "%s: failed to get tbm surface info", __func__);
return NULL;
}
- fd = tbm_bo_export_fd(tbm_buf);
fourcc = dri2_fourcc_from_tbm_format(info.format);
- offset = info.planes[0].offset;
- pitch = info.planes[0].stride;
-
- dri_image = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
- info.width,
- info.height,
- fourcc,
- &fd,
- 1,
- &pitch,
- &offset,
- loaderPrivate);
- close(fd);
+
+ for (unsigned i = 0; i < info.num_planes; i++) {
+ int index = tbm_surface_internal_get_plane_bo_idx(tbm_surf, i);
+
+ tbm_buf = tbm_surface_internal_get_bo(tbm_surf, index);
+ if (!tbm_buf) {
+ while (i--)
+ close(fd[i]);
+ _eglLog(_EGL_DEBUG, "%s: failed to get bo %d for tbm surface",
+ __func__, i);
+ return NULL;
+ }
+
+ fd[i] = tbm_bo_export_fd(tbm_buf);
+ offset[i] = info.planes[i].offset;
+ pitch[i] = info.planes[i].stride;
+ }
+
+ dri2_dpy->core->getConfigAttrib(config,
+ __DRI_ATTRIB_YUV_CSC_STANDARD, &csc_standard);
+ switch (csc_standard) {
+ case __DRI_ATTRIB_YUV_CSC_STANDARD_601_BIT:
+ color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601;
+ break;
+ case __DRI_ATTRIB_YUV_CSC_STANDARD_709_BIT:
+ color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709;
+ break;
+ case __DRI_ATTRIB_YUV_CSC_STANDARD_2020_BIT:
+ color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020;
+ break;
+ default:
+ color_space = __DRI_YUV_COLOR_SPACE_UNDEFINED;
+ break;
+ }
+
+ dri2_dpy->core->getConfigAttrib(config,
+ __DRI_ATTRIB_YUV_DEPTH_RANGE, &depth_range);
+ switch (depth_range) {
+ case __DRI_ATTRIB_YUV_DEPTH_RANGE_LIMITED_BIT:
+ sample_range = __DRI_YUV_NARROW_RANGE;
+ break;
+ case __DRI_ATTRIB_YUV_DEPTH_RANGE_FULL_BIT:
+ sample_range = __DRI_YUV_FULL_RANGE;
+ break;
+ default:
+ sample_range = __DRI_YUV_RANGE_UNDEFINED;
+ break;
+ }
+
+ dri_image = dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
+ info.width,
+ info.height,
+ fourcc,
+ fd,
+ info.num_planes,
+ pitch,
+ offset,
+ color_space,
+ sample_range,
+ __DRI_YUV_CHROMA_SITING_UNDEFINED,
+ __DRI_YUV_CHROMA_SITING_UNDEFINED,
+ &create_error,
+ loaderPrivate);
+ for (unsigned i = 0; i < info.num_planes; i++)
+ close(fd[i]);
if (!dri_image) {
_eglLog(_EGL_DEBUG, "%s: failed to create dri image from tbm bo", __func__);
@@ -792,10 +848,22 @@ dri2_tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
{
}
+static unsigned
+dri2_tizen_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
+{
+ switch (cap) {
+ case DRI_LOADER_CAP_YUV_SURFACE_IMG:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static const __DRIimageLoaderExtension tizen_image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 1 },
+ .base = { __DRI_IMAGE_LOADER, 2 },
.getBuffers = dri2_tizen_get_buffers,
.flushFrontBuffer = dri2_tizen_flush_front_buffer,
+ .getCapability = dri2_tizen_get_capability,
};
static const __DRIextension *image_loader_extensions[] = {
@@ -804,6 +872,41 @@ static const __DRIextension *image_loader_extensions[] = {
NULL,
};
+static EGLBoolean
+derive_yuv_native_visual_from_config(struct dri2_egl_display *dri2_dpy,
+ const __DRIconfig *dri_config,
+ int *native_visual)
+{
+ unsigned order, subsample, num_planes, plane_bpp;
+
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_ORDER,
+ &order);
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_SUBSAMPLE,
+ &subsample);
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_NUMBER_OF_PLANES,
+ &num_planes);
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_PLANE_BPP,
+ &plane_bpp);
+
+ if ((plane_bpp & __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT) == 0)
+ return EGL_FALSE;
+
+ if (num_planes != 2)
+ return EGL_FALSE;
+
+ if (subsample & __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT) {
+ if (order & __DRI_ATTRIB_YUV_ORDER_YUV_BIT) {
+ *native_visual = TBM_FORMAT_NV12;
+ return EGL_TRUE;
+ } else if (order & __DRI_ATTRIB_YUV_ORDER_YVU_BIT) {
+ *native_visual = TBM_FORMAT_NV21;
+ return EGL_TRUE;
+ }
+ }
+
+ return EGL_FALSE;
+}
+
static EGLBoolean
dri2_tizen_add_configs(_EGLDisplay *dpy)
{
@@ -811,83 +914,102 @@ dri2_tizen_add_configs(_EGLDisplay *dpy)
int count = 0;
for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
- static const struct rgba_shifts_and_sizes pbuffer_sasa[] = {
- {
- /* ARGB8888 */
- { 16, 8, 0, 24 },
- { 8, 8, 8, 8 },
- },
- {
- /* RGB888 */
- { 16, 8, 0, -1 },
- { 8, 8, 8, 0 },
- },
- {
- /* RGB565 */
- { 11, 5, 0, -1 },
- { 5, 6, 5, 0 },
- },
- };
struct dri2_egl_config *dri2_cfg;
- int shifts[4];
- unsigned int sizes[4];
+ unsigned int render_type;
unsigned int caveat = 0;
int surface_type = 0;
- tpl_bool_t is_slow;
EGLint attr_list[] = {
EGL_NATIVE_VISUAL_ID, 0,
EGL_CONFIG_CAVEAT, EGL_NONE,
EGL_NONE,
};
- tpl_result_t res;
-
- dri2_get_shifts_and_sizes(dri2_dpy->core, dri2_dpy->driver_configs[i],
- shifts, sizes);
dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
- __DRI_ATTRIB_BUFFER_SIZE, &depth);
+ __DRI_ATTRIB_CONFIG_CAVEAT, &caveat);
dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
- __DRI_ATTRIB_CONFIG_CAVEAT, &caveat);
+ __DRI_ATTRIB_RENDER_TYPE, &render_type);
+
+ if (render_type & __DRI_ATTRIB_RGBA_BIT) {
+ static const struct rgba_shifts_and_sizes pbuffer_sasa[] = {
+ {
+ /* ARGB8888 */
+ { 16, 8, 0, 24 },
+ { 8, 8, 8, 8 },
+ },
+ {
+ /* RGB888 */
+ { 16, 8, 0, -1 },
+ { 8, 8, 8, 0 },
+ },
+ {
+ /* RGB565 */
+ { 11, 5, 0, -1 },
+ { 5, 6, 5, 0 },
+ },
+ };
+ int shifts[4];
+ unsigned int sizes[4];
+ unsigned int depth;
+ tpl_bool_t is_slow;
+ tpl_result_t res;
- res = tpl_display_query_config(dri2_dpy->tpl_dpy, TPL_SURFACE_TYPE_WINDOW,
- sizes[0], sizes[1], sizes[2], sizes[3],
- depth, &attr_list[1], &is_slow);
- if (res != TPL_ERROR_NONE)
- continue;
- surface_type |= EGL_WINDOW_BIT;
+ dri2_get_shifts_and_sizes(dri2_dpy->core, dri2_dpy->driver_configs[i],
+ shifts, sizes);
- if (is_slow)
- caveat |= __DRI_ATTRIB_SLOW_BIT;
+ dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
+ __DRI_ATTRIB_BUFFER_SIZE, &depth);
+
+ res = tpl_display_query_config(dri2_dpy->tpl_dpy,
+ TPL_SURFACE_TYPE_WINDOW,
+ sizes[0], sizes[1], sizes[2], sizes[3],
+ depth, &attr_list[1], &is_slow);
+ if (res != TPL_ERROR_NONE)
+ continue;
- res = tpl_display_query_config(dri2_dpy->tpl_dpy, TPL_SURFACE_TYPE_PIXMAP,
- sizes[0], sizes[1], sizes[2], sizes[3],
- depth, NULL, &is_slow);
- if (res == TPL_ERROR_NONE) {
- surface_type |= EGL_PIXMAP_BIT;
+ surface_type |= EGL_WINDOW_BIT;
if (is_slow)
caveat |= __DRI_ATTRIB_SLOW_BIT;
- }
- for (unsigned j = 0; j < ARRAY_SIZE(pbuffer_sasa); j++) {
- const struct rgba_shifts_and_sizes *pbuffer_sas = &pbuffer_sasa[j];
-
- if (shifts[0] == pbuffer_sas->shifts[0] &&
- shifts[1] == pbuffer_sas->shifts[1] &&
- shifts[2] == pbuffer_sas->shifts[2] &&
- shifts[3] == pbuffer_sas->shifts[3] &&
- sizes[0] == pbuffer_sas->sizes[0] &&
- sizes[1] == pbuffer_sas->sizes[1] &&
- sizes[2] == pbuffer_sas->sizes[2] &&
- sizes[3] == pbuffer_sas->sizes[3]) {
- surface_type |= EGL_PBUFFER_BIT;
- break;
+ res = tpl_display_query_config(dri2_dpy->tpl_dpy,
+ TPL_SURFACE_TYPE_PIXMAP,
+ sizes[0], sizes[1], sizes[2], sizes[3],
+ depth, NULL, &is_slow);
+ if (res == TPL_ERROR_NONE) {
+ surface_type |= EGL_PIXMAP_BIT;
+
+ if (is_slow)
+ caveat |= __DRI_ATTRIB_SLOW_BIT;
}
- }
- if (dri2_dpy->image->base.version >= 9 && dri2_dpy->image->blitImage)
- surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ for (unsigned j = 0; j < ARRAY_SIZE(pbuffer_sasa); j++) {
+ const struct rgba_shifts_and_sizes *pbuffer_sas = &pbuffer_sasa[j];
+
+ if (shifts[0] == pbuffer_sas->shifts[0] &&
+ shifts[1] == pbuffer_sas->shifts[1] &&
+ shifts[2] == pbuffer_sas->shifts[2] &&
+ shifts[3] == pbuffer_sas->shifts[3] &&
+ sizes[0] == pbuffer_sas->sizes[0] &&
+ sizes[1] == pbuffer_sas->sizes[1] &&
+ sizes[2] == pbuffer_sas->sizes[2] &&
+ sizes[3] == pbuffer_sas->sizes[3]) {
+ surface_type |= EGL_PBUFFER_BIT;
+ break;
+ }
+
+ }
+
+ if (dri2_dpy->image->base.version >= 9 && dri2_dpy->image->blitImage)
+ surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ } else if (render_type & __DRI_ATTRIB_YUV_BIT) {
+ if (!derive_yuv_native_visual_from_config(dri2_dpy,
+ dri2_dpy->driver_configs[i],
+ &attr_list[1]))
+ continue;
+ surface_type = EGL_WINDOW_BIT;
+ caveat = 0;
+ }
if (caveat & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
attr_list[3] = EGL_NON_CONFORMANT_CONFIG;
--
2.25.1

View File

@@ -0,0 +1,69 @@
From 5bd42e648dc9068392641436b70fc28a00689c8e Mon Sep 17 00:00:00 2001
From: Silvestrs Timofejevs <silvestrs.timofejevs@imgtec.com>
Date: Thu, 30 Aug 2018 13:48:53 +0100
Subject: [PATCH 35/67] gbm: add some new GBM formats
GBM_FORMAT_ARGB4444
GBM_FORMAT_BGR888
GBM_FORMAT_YUYV
GBM_FORMAT_YVU444_PACK10_IMG
---
src/gbm/backends/dri/gbm_dri.c | 16 ++++++++++++++++
src/gbm/main/gbm.h | 2 ++
2 files changed, 18 insertions(+)
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index 2aa9c7c41ad..5acb15b516f 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -514,11 +514,21 @@ static const struct gbm_dri_visual gbm_dri_visuals_table[] = {
{ 10, 5, 0, 11 },
{ 5, 5, 5, 1 },
},
+ {
+ GBM_FORMAT_ARGB4444, __DRI_IMAGE_FORMAT_ARGB4444,
+ { 8, 4, 0, 12 },
+ { 4, 4, 4, 4 },
+ },
{
GBM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565,
{ 11, 5, 0, -1 },
{ 5, 6, 5, 0 },
},
+ {
+ GBM_FORMAT_BGR888, __DRI_IMAGE_FORMAT_BGR888,
+ { 0, 8, 16, -1 },
+ { 8, 8, 8, 0 },
+ },
{
GBM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888,
{ 16, 8, 0, -1 },
@@ -571,6 +581,12 @@ static const struct gbm_dri_visual gbm_dri_visuals_table[] = {
{ 16, 16, 16, 16 },
true,
},
+ {
+ GBM_FORMAT_YUYV, __DRI_IMAGE_FORMAT_YUYV,
+ },
+ {
+ GBM_FORMAT_YVU444_PACK10_IMG, __DRI_IMAGE_FORMAT_YVU444_PACK10_IMG,
+ },
};
static int
diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h
index 7c82cd661a3..81308ab9745 100644
--- a/src/gbm/main/gbm.h
+++ b/src/gbm/main/gbm.h
@@ -167,6 +167,8 @@ enum gbm_bo_format {
#define GBM_FORMAT_AYUV __gbm_fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+#define GBM_FORMAT_YVU444_PACK10_IMG __gbm_fourcc_code('I', 'M', 'G', '2') /* [31:0] unused:Y:Cr:Cb 2:10:10:10 little endian */
+
/*
* 2 plane YCbCr
* index 0 = Y plane, [7:0] Y
--
2.25.1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,509 @@
From 02065d490a68d542be56c2ea23346b3fa19928cb Mon Sep 17 00:00:00 2001
From: Silvestrs Timofejevs <silvestrs.timofejevs@imgtec.com>
Date: Mon, 24 Sep 2018 14:14:25 +0100
Subject: [PATCH 37/67] egl: add config debug printout
Feature to print out EGL returned configs for debug purposes.
'eglChooseConfig' and 'eglGetConfigs' debug information printout is
enabled when the log level equals '_EGL_DEBUG'. The configs are
printed, and if any of them are "chosen" they are marked with their
index in the chosen configs array.
---
src/egl/main/eglconfig.c | 20 ++-
src/egl/main/eglconfigdebug.c | 321 ++++++++++++++++++++++++++++++++++
src/egl/main/eglconfigdebug.h | 55 ++++++
src/egl/main/egllog.c | 9 +
src/egl/main/egllog.h | 4 +
src/egl/meson.build | 2 +
6 files changed, 407 insertions(+), 4 deletions(-)
create mode 100644 src/egl/main/eglconfigdebug.c
create mode 100644 src/egl/main/eglconfigdebug.h
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index 5e56948ab72..ea4b3c15f3f 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -40,6 +40,7 @@
#include "util/macros.h"
#include "eglconfig.h"
+#include "eglconfigdebug.h"
#include "egldisplay.h"
#include "eglcurrent.h"
#include "egllog.h"
@@ -1039,14 +1040,21 @@ _eglChooseConfig(_EGLDisplay *disp, const EGLint *attrib_list,
EGLConfig *configs, EGLint config_size, EGLint *num_configs)
{
_EGLConfig criteria;
+ EGLBoolean result;
if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
- return _eglFilterConfigArray(disp->Configs,
- configs, config_size, num_configs,
- _eglFallbackMatch, _eglFallbackCompare,
- (void *) &criteria);
+ result = _eglFilterConfigArray(disp->Configs,
+ configs, config_size, num_configs,
+ _eglFallbackMatch, _eglFallbackCompare,
+ (void *) &criteria);
+
+ if (result && (_eglGetLogLevel() == _EGL_DEBUG))
+ eglPrintConfigDebug(disp, configs, *num_configs,
+ EGL_CONFIG_DEBUG_CHOOSE);
+
+ return result;
}
@@ -1096,5 +1104,9 @@ _eglGetConfigs(_EGLDisplay *disp, EGLConfig *configs,
*num_config = _eglFlattenArray(disp->Configs, (void *) configs,
sizeof(configs[0]), config_size, _eglFlattenConfig);
+ if (_eglGetLogLevel() == _EGL_DEBUG)
+ eglPrintConfigDebug(disp, configs, *num_config,
+ EGL_CONFIG_DEBUG_GET);
+
return EGL_TRUE;
}
diff --git a/src/egl/main/eglconfigdebug.c b/src/egl/main/eglconfigdebug.c
new file mode 100644
index 00000000000..92ac41a5614
--- /dev/null
+++ b/src/egl/main/eglconfigdebug.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2017 Imagination Technologies.
+ * All Rights Reserved.
+ *
+ * Based on eglinfo, which has copyright:
+ * Copyright (C) 2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "eglarray.h"
+#include "eglconfig.h"
+#include "eglconfigdebug.h"
+#include "egldisplay.h"
+#include "egllog.h"
+#include "egltypedefs.h"
+
+/* Max debug message length */
+#define CONFIG_DEBUG_MSG_MAX 1000
+
+/*
+ * These are X visual types, so if you're running eglinfo under
+ * something not X, they probably don't make sense.
+ */
+static const char *const vnames[] = { "SG", "GS", "SC", "PC", "TC", "DC" };
+
+struct _printAttributes {
+ EGLint id, size, level;
+ EGLint red, green, blue, alpha;
+ EGLint depth, stencil;
+ EGLint renderable, surfaces;
+ EGLint vid, vtype, caveat, bindRgb, bindRgba;
+ EGLint samples, sampleBuffers;
+ char surfString[100];
+ EGLint colorBufferType;
+ EGLint numPlanes, subsample, order;
+};
+
+static void
+_printHeaderFormat(void)
+{
+ /*
+ * EGL configuration output legend:
+ *
+ * chosen --------------- eglChooseConfig returned config priority,
+ * only relevant when eglChooseConfig is called.
+ * id ------------------- EGL_CONFIG_ID
+ * bfsz ----------------- EGL_BUFFER_SIZE
+ * lvl ------------------ EGL_LEVEL
+ *
+ * color size
+ * r -------------------- EGL_RED_SIZE
+ * g -------------------- EGL_GREEN_SIZE
+ * b -------------------- EGL_BLUE_SIZE
+ * a -------------------- EGL_ALPHA_SIZE
+ * dpth ----------------- EGL_DEPTH_SIZE
+ * stcl ----------------- EGL_STENCIL_SIZE
+ *
+ * multisample
+ * ns ------------------- EGL_SAMPLES
+ * b -------------------- EGL_SAMPLE_BUFFERS
+ * visid ---------------- EGL_NATIVE_VISUAL_ID/EGL_NATIVE_VISUAL_TYPE
+ * caveat --------------- EGL_CONFIG_CAVEAT
+ * bind ----------------- EGL_BIND_TO_TEXTURE_RGB/EGL_BIND_TO_TEXTURE_RGBA
+ *
+ * renderable
+ * gl, es, es2, es3, vg - EGL_RENDERABLE_TYPE
+ *
+ * supported
+ * surfaces ------------- EGL_SURFACE_TYPE
+ * colbuf --------------- EGL_COLOR_BUFFER_TYPE
+ *
+ * yuv
+ * p -------------------- EGL_YUV_NUMBER_OF_PLANES_EXT
+ * sub ------------------ EGL_YUV_SUBSAMPLE_EXT
+ * ord ------------------ EGL_YUV_ORDER_EXT
+ */
+ _eglLog(_EGL_DEBUG, "---------------");
+ _eglLog(_EGL_DEBUG, "Configurations:");
+ _eglLog(_EGL_DEBUG, "cho bf lv color size dp st ms vis cav bi renderable supported"
+ " col yuv ");
+ _eglLog(_EGL_DEBUG, "sen id sz l r g b a th cl ns b id eat nd gl es es2 es3 vg surfaces"
+ " buf p sub ord");
+ _eglLog(_EGL_DEBUG, "---------------");
+}
+
+static void
+_snprintfStrcat(char *const msg, const int maxSize, const char *fmt, ...)
+{
+ int maxAllowed;
+ va_list args;
+
+ maxAllowed = maxSize - strlen(msg);
+
+ va_start(args, fmt);
+ (void) vsnprintf(&msg[strlen(msg)], maxAllowed, fmt, args);
+ va_end(args);
+}
+
+static inline const char *_enumToString(EGLint constant)
+{
+ switch (constant) {
+ case EGL_YUV_SUBSAMPLE_4_2_0_EXT: return "420";
+ case EGL_YUV_SUBSAMPLE_4_2_2_EXT: return "422";
+ case EGL_YUV_SUBSAMPLE_4_4_4_EXT: return "444";
+ case EGL_YUV_ORDER_AYUV_EXT: return "AYUV";
+ case EGL_YUV_ORDER_UYVY_EXT: return "UYVY";
+ case EGL_YUV_ORDER_VYUY_EXT: return "VYUY";
+ case EGL_YUV_ORDER_YUYV_EXT: return "YUYV";
+ case EGL_YUV_ORDER_YVYU_EXT: return "YVYU";
+ case EGL_YUV_ORDER_YUV_EXT: return "YUV";
+ case EGL_YUV_ORDER_YVU_EXT: return "YVU";
+ case EGL_LUMINANCE_BUFFER: return "lum";
+ case EGL_YUV_BUFFER_EXT: return "yuv";
+ case EGL_RGB_BUFFER: return "rgb";
+ default: return "?";
+ }
+}
+
+static void
+_eglGetConfigAttrs(_EGLDisplay *const dpy, _EGLConfig *const conf,
+ struct _printAttributes *const attr)
+{
+ EGLBoolean success = EGL_TRUE;
+
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_CONFIG_ID, &attr->id);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_BUFFER_SIZE, &attr->size);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_LEVEL, &attr->level);
+
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_RED_SIZE, &attr->red);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_GREEN_SIZE, &attr->green);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_BLUE_SIZE, &attr->blue);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_ALPHA_SIZE, &attr->alpha);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_DEPTH_SIZE, &attr->depth);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_STENCIL_SIZE, &attr->stencil);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_NATIVE_VISUAL_ID, &attr->vid);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_NATIVE_VISUAL_TYPE, &attr->vtype);
+
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_CONFIG_CAVEAT, &attr->caveat);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_BIND_TO_TEXTURE_RGB, &attr->bindRgb);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_BIND_TO_TEXTURE_RGBA, &attr->bindRgba);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_RENDERABLE_TYPE, &attr->renderable);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_SURFACE_TYPE, &attr->surfaces);
+
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_SAMPLES, &attr->samples);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_SAMPLE_BUFFERS, &attr->sampleBuffers);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_COLOR_BUFFER_TYPE, &attr->colorBufferType);
+
+ if (conf->Display->Extensions.EXT_yuv_surface) {
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_YUV_NUMBER_OF_PLANES_EXT,
+ &attr->numPlanes);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_YUV_SUBSAMPLE_EXT, &attr->subsample);
+ success &= _eglGetConfigAttrib(dpy, conf, EGL_YUV_ORDER_EXT, &attr->order);
+ }
+
+ if (!success)
+ _eglLog(_EGL_DEBUG, "%s: config tainted, could not obtain all attributes",
+ __func__);
+}
+
+static void
+_eglPrintConfig(_EGLDisplay *const dpy, _EGLConfig *const conf,
+ char *const printMsg, const int maxMsgSize)
+{
+ struct _printAttributes attr = { 0 };
+
+ _eglGetConfigAttrs(dpy, conf, &attr);
+
+ if (attr.surfaces & EGL_WINDOW_BIT)
+ strcat(attr.surfString, "win,");
+ if (attr.surfaces & EGL_PBUFFER_BIT)
+ strcat(attr.surfString, "pb,");
+ if (attr.surfaces & EGL_PIXMAP_BIT)
+ strcat(attr.surfString, "pix,");
+ if (attr.surfaces & EGL_STREAM_BIT_KHR)
+ strcat(attr.surfString, "str,");
+ if (attr.surfaces & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
+ strcat(attr.surfString, "prsv,");
+ if (strlen(attr.surfString) > 0)
+ attr.surfString[strlen(attr.surfString) - 1] = 0;
+
+ _snprintfStrcat(printMsg, maxMsgSize,
+ "0x%03x %2d %2d %2d %2d %2d %2d %2d %2d %2d%2d 0x%08x%2s ",
+ attr.id, attr.size, attr.level,
+ attr.red, attr.green, attr.blue, attr.alpha,
+ attr.depth, attr.stencil,
+ attr.samples, attr.sampleBuffers, attr.vid,
+ attr.vtype < 6 ? vnames[attr.vtype] : "--");
+
+ _snprintfStrcat(printMsg, maxMsgSize,
+ "%c %c %c %c %c %c %c %15s",
+ (attr.caveat != EGL_NONE) ? 'y' : ' ',
+ (attr.bindRgba) ? 'a' : (attr.bindRgb) ? 'y' : ' ',
+ (attr.renderable & EGL_OPENGL_BIT) ? 'y' : ' ',
+ (attr.renderable & EGL_OPENGL_ES_BIT) ? 'y' : ' ',
+ (attr.renderable & EGL_OPENGL_ES2_BIT) ? 'y' : ' ',
+ (attr.renderable & EGL_OPENGL_ES3_BIT) ? 'y' : ' ',
+ (attr.renderable & EGL_OPENVG_BIT) ? 'y' : ' ',
+ attr.surfString);
+
+ _snprintfStrcat(printMsg, maxMsgSize, " %3.3s",
+ _enumToString(attr.colorBufferType));
+
+ if (attr.colorBufferType == EGL_YUV_BUFFER_EXT)
+ _snprintfStrcat(printMsg, maxMsgSize, " %1.1d %3.3s %4.4s", attr.numPlanes,
+ _enumToString(attr.subsample), _enumToString(attr.order));
+
+ _eglLog(_EGL_DEBUG, printMsg);
+}
+
+static void
+_eglMarkChosenConfig(_EGLConfig *const config,
+ _EGLConfig *const *const chosenConfigs,
+ const EGLint numConfigs, char *const printMsg,
+ const int maxMsgSize)
+{
+ const char padding[] = " ";
+
+ if (chosenConfigs == NULL) {
+ _snprintfStrcat(printMsg, maxMsgSize, "%s ", &padding[0]);
+ return;
+ }
+
+ /* Find a match, "mark" and return */
+ for (EGLint i = 0; i < numConfigs; i++) {
+ if (config == chosenConfigs[i]) {
+ _snprintfStrcat(printMsg, maxMsgSize, "%*d ", strlen(padding), i);
+ return;
+ }
+ }
+
+ _snprintfStrcat(printMsg, maxMsgSize, "%s ", &padding[0]);
+}
+
+static void
+_eglPrintConfigs(_EGLDisplay *const dpy,
+ EGLConfig *const configs, const EGLint numConfigs,
+ const enum EGL_CONFIG_DEBUG_OPTION printOption)
+{
+ const int maxMsgSize = CONFIG_DEBUG_MSG_MAX;
+ EGLint numConfigsToPrint;
+ _EGLConfig **configsToPrint;
+ _EGLConfig **chosenConfigs;
+ char *printMsg;
+
+ printMsg = malloc(maxMsgSize);
+ if (!printMsg) {
+ _eglLog(_EGL_DEBUG, "%s: failed to allocate the print message", __func__);
+ return;
+ }
+
+ /*
+ * If the printout request came from the 'eglChooseConfig', all
+ * configs are printed, and the "chosen" configs are marked.
+ */
+ if (printOption == EGL_CONFIG_DEBUG_CHOOSE) {
+ configsToPrint = (_EGLConfig **) dpy->Configs->Elements;
+ numConfigsToPrint = dpy->Configs->Size;
+ chosenConfigs = (_EGLConfig **) configs;
+ } else {
+ assert(printOption == EGL_CONFIG_DEBUG_GET);
+ configsToPrint = (_EGLConfig **) configs;
+ numConfigsToPrint = numConfigs;
+ chosenConfigs = NULL;
+ }
+
+ _printHeaderFormat();
+ for (EGLint i = 0; i < numConfigsToPrint; i++) {
+ _EGLConfig *configToPrint = configsToPrint[i];
+
+ /* "clear" message */
+ printMsg[0] = '\0';
+
+ _eglMarkChosenConfig(configToPrint, chosenConfigs, numConfigs,
+ printMsg, maxMsgSize);
+
+ _eglPrintConfig(dpy, configToPrint, printMsg, maxMsgSize);
+ }
+
+ free(printMsg);
+}
+
+void eglPrintConfigDebug(_EGLDisplay *const dpy,
+ EGLConfig *const configs, const EGLint numConfigs,
+ const enum EGL_CONFIG_DEBUG_OPTION printOption)
+{
+ if (!numConfigs || !configs) {
+ _eglLog(_EGL_DEBUG, "%s: nothing to print", __func__);
+ return;
+ }
+
+ switch (printOption) {
+ case EGL_CONFIG_DEBUG_CHOOSE:
+ case EGL_CONFIG_DEBUG_GET:
+ _eglPrintConfigs(dpy, configs, numConfigs, printOption);
+ break;
+ default:
+ _eglLog(_EGL_DEBUG, "%s: bad debug option", __func__);
+ break;
+ }
+}
diff --git a/src/egl/main/eglconfigdebug.h b/src/egl/main/eglconfigdebug.h
new file mode 100644
index 00000000000..562aefff9de
--- /dev/null
+++ b/src/egl/main/eglconfigdebug.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+ * Copyright 2017 Imagination Technologies.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef EGLCONFIGDEBUG_INCLUDED
+#define EGLCONFIGDEBUG_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "egltypedefs.h"
+
+/**
+ * Config printout options.
+ */
+enum EGL_CONFIG_DEBUG_OPTION {
+ EGL_CONFIG_DEBUG_CHOOSE,
+ EGL_CONFIG_DEBUG_GET,
+};
+
+/**
+ * Print the list of configs and the associated attributes.
+ */
+void eglPrintConfigDebug(_EGLDisplay *const dpy,
+ EGLConfig *const configs, const EGLint numConfigs,
+ const enum EGL_CONFIG_DEBUG_OPTION printOption);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EGLCONFIGDEBUG_INCLUDED */
diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c
index 973b7600ab1..7a9032f9bbb 100644
--- a/src/egl/main/egllog.c
+++ b/src/egl/main/egllog.c
@@ -153,6 +153,15 @@ _eglInitLogger(void)
}
}
+/**
+ * Return the log level.
+ */
+EGLint
+_eglGetLogLevel(void)
+{
+ return logging.level;
+}
+
/**
* Log a message with message logger.
diff --git a/src/egl/main/egllog.h b/src/egl/main/egllog.h
index 2a06a34684a..a1cf9770ed8 100644
--- a/src/egl/main/egllog.h
+++ b/src/egl/main/egllog.h
@@ -44,6 +44,10 @@ extern "C" {
#define _EGL_DEBUG 3 /* useful info for debugging */
+extern EGLint
+_eglGetLogLevel(void);
+
+
extern void
_eglLog(EGLint level, const char *fmtStr, ...);
diff --git a/src/egl/meson.build b/src/egl/meson.build
index daa6a3a04f0..384bb98ebb3 100644
--- a/src/egl/meson.build
+++ b/src/egl/meson.build
@@ -31,6 +31,8 @@ files_egl = files(
'main/eglapi.c',
'main/eglarray.c',
'main/eglarray.h',
+ 'main/eglconfigdebug.c',
+ 'main/eglconfigdebug.h',
'main/eglconfig.c',
'main/eglconfig.h',
'main/eglcontext.c',
--
2.25.1

View File

@@ -0,0 +1,217 @@
From d1d64a3c11fbab083d6225857554ac1c9ad645b6 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Tue, 29 Jan 2019 14:36:25 +0000
Subject: [PATCH 38/67] egl: add support for EXT_image_gl_colorspace
---
src/egl/drivers/dri2/egl_dri2.c | 57 +++++++++++++++++++++++++++++++--
src/egl/main/eglapi.c | 1 +
src/egl/main/egldisplay.h | 1 +
src/egl/main/eglimage.c | 14 ++++++++
src/egl/main/eglimage.h | 3 ++
5 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 2f8414e0c60..6b26ff979ae 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1084,6 +1084,9 @@ dri2_setup_screen(_EGLDisplay *disp)
dri2_dpy->image->createImageFromBuffer) {
disp->Extensions.IMG_cl_image = EGL_TRUE;
}
+
+ if (disp->Extensions.KHR_gl_colorspace)
+ disp->Extensions.EXT_image_gl_colorspace = EGL_TRUE;
}
if (dri2_dpy->flush_control)
@@ -2724,6 +2727,11 @@ dri2_create_image_wayland_wl_buffer_tizen(_EGLDisplay *disp, _EGLContext *ctx,
return NULL;
}
+ if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+ _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+ return NULL;
+ }
+
if (tbm_surface_get_info(tbm_surf, &info)) {
_eglError(EGL_BAD_PARAMETER, "tbm_surface_get_info");
return NULL;
@@ -2799,6 +2807,11 @@ dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
if (!_eglParseImageAttribList(&attrs, disp, attr_list))
return NULL;
+ if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+ _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+ return NULL;
+ }
+
plane = attrs.PlaneWL;
f = buffer->driver_format;
if (plane < 0 || plane >= f->nplanes) {
@@ -2862,6 +2875,11 @@ dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
if (!_eglParseImageAttribList(&attrs, disp, attr_list))
return EGL_NO_IMAGE_KHR;
+ if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+ _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+ return EGL_NO_IMAGE_KHR;
+ }
+
switch (target) {
case EGL_GL_TEXTURE_2D_KHR:
if (!disp->Extensions.KHR_gl_texture_2D_image) {
@@ -3007,6 +3025,11 @@ dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
return NULL;
}
+ if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+ _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+ return NULL;
+ }
+
switch (attrs.DRMBufferFormatMESA) {
case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
format = __DRI_IMAGE_FORMAT_ARGB8888;
@@ -3189,6 +3212,23 @@ dri2_num_fourcc_format_planes(EGLint format)
}
}
+static int
+dri2_get_srgb_fourcc(int drm_fourcc)
+{
+ switch (drm_fourcc) {
+ case DRM_FORMAT_ARGB8888:
+ return __DRI_IMAGE_FOURCC_SARGB8888;
+ case DRM_FORMAT_ABGR8888:
+ return __DRI_IMAGE_FOURCC_SABGR8888;
+ case DRM_FORMAT_BGR888:
+ return __DRI_IMAGE_FOURCC_SBGR888;
+ default:
+ _eglLog(_EGL_DEBUG, "%s: no matching sRGB FourCC for %#x",
+ __func__, drm_fourcc);
+ return 0;
+ }
+}
+
/* Returns the total number of file descriptors. Zero indicates an error. */
static unsigned
dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
@@ -3334,6 +3374,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
int fds[DMA_BUF_MAX_PLANES];
int pitches[DMA_BUF_MAX_PLANES];
int offsets[DMA_BUF_MAX_PLANES];
+ int fourcc;
uint64_t modifier;
bool has_modifier = false;
unsigned error;
@@ -3359,6 +3400,18 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
if (!num_fds)
return NULL;
+ if (attrs.GLColorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
+ fourcc = dri2_get_srgb_fourcc(attrs.DMABufFourCC.Value);
+ if (fourcc == 0) {
+ _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+ return NULL;
+ }
+ } else {
+ assert(attrs.GLColorspace == EGL_GL_COLORSPACE_LINEAR_KHR ||
+ attrs.GLColorspace == EGL_GL_COLORSPACE_DEFAULT_EXT);
+ fourcc = attrs.DMABufFourCC.Value;
+ }
+
for (unsigned i = 0; i < num_fds; ++i) {
fds[i] = attrs.DMABufPlaneFds[i].Value;
pitches[i] = attrs.DMABufPlanePitches[i].Value;
@@ -3403,7 +3456,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
}
dri_image =
dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen,
- attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
+ attrs.Width, attrs.Height, fourcc,
modifier, fds, num_fds, pitches, offsets,
attrs.DMABufYuvColorSpaceHint.Value,
attrs.DMABufSampleRangeHint.Value,
@@ -3415,7 +3468,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
else {
dri_image =
dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
- attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
+ attrs.Width, attrs.Height, fourcc,
fds, num_fds, pitches, offsets,
attrs.DMABufYuvColorSpaceHint.Value,
attrs.DMABufSampleRangeHint.Value,
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index e4f2c43b4ef..2d3931dfd26 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -508,6 +508,7 @@ _eglCreateExtensionsString(_EGLDisplay *disp)
_EGL_CHECK_EXTENSION(EXT_create_context_robustness);
_EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
_EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
+ _EGL_CHECK_EXTENSION(EXT_image_gl_colorspace);
_EGL_CHECK_EXTENSION(EXT_protected_surface);
_EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata);
_EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata);
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 8489af9dde2..6e5b29fe1ac 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -108,6 +108,7 @@ struct _egl_extensions
EGLBoolean EXT_create_context_robustness;
EGLBoolean EXT_image_dma_buf_import;
EGLBoolean EXT_image_dma_buf_import_modifiers;
+ EGLBoolean EXT_image_gl_colorspace;
EGLBoolean EXT_pixel_format_float;
EGLBoolean EXT_protected_surface;
EGLBoolean EXT_surface_CTA861_3_metadata;
diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c
index 64bf7f2bfe9..73d4e85b82e 100644
--- a/src/egl/main/eglimage.c
+++ b/src/egl/main/eglimage.c
@@ -46,6 +46,18 @@ _eglParseKHRImageAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
attrs->ImagePreserved = val;
break;
+ case EGL_GL_COLORSPACE_KHR:
+ if (!disp->Extensions.EXT_image_gl_colorspace)
+ return EGL_BAD_PARAMETER;
+
+ if (val != EGL_GL_COLORSPACE_SRGB_KHR &&
+ val != EGL_GL_COLORSPACE_LINEAR_KHR &&
+ val != EGL_GL_COLORSPACE_DEFAULT_EXT)
+ return EGL_BAD_PARAMETER;
+
+ attrs->GLColorspace = val;
+ break;
+
case EGL_GL_TEXTURE_LEVEL_KHR:
if (!disp->Extensions.KHR_gl_texture_2D_image)
return EGL_BAD_PARAMETER;
@@ -285,6 +297,8 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *disp,
memset(attrs, 0, sizeof(*attrs));
+ attrs->GLColorspace = EGL_GL_COLORSPACE_DEFAULT_EXT;
+
if (!attrib_list)
return EGL_TRUE;
diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h
index 9837f05dad1..fc02d7a265c 100644
--- a/src/egl/main/eglimage.h
+++ b/src/egl/main/eglimage.h
@@ -80,6 +80,9 @@ struct _egl_image_attribs
struct _egl_image_attrib_int DMABufChromaHorizontalSiting;
struct _egl_image_attrib_int DMABufChromaVerticalSiting;
+ /* EGL_EXT_image_gl_colorspace */
+ EGLint GLColorspace;
+
/* EGL_EXT_protected_surface */
EGLBoolean ProtectedContent;
};
--
2.25.1

View File

@@ -0,0 +1,35 @@
From c8a6405eaf4c9693f32381fa7aa6d292e7f95716 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 24 Jun 2019 09:35:39 +0100
Subject: [PATCH 39/67] meson: force C++ 2011 for "thread_local"
For some combinations of Meson and the GNU C++ compiler, Meson does
not add '-std=c++11' to the command line arguments, resulting in
compilation errors, due to the use of the "thread_local" keyword (a
C++ 2011 feature). If the C++ compiler doesn't understand the
"thread_local" keyword by default, add '-std=c++11' to the compiler
command line arguments.
---
meson.build | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/meson.build b/meson.build
index 2018562a1ec..21d93d372c2 100644
--- a/meson.build
+++ b/meson.build
@@ -32,6 +32,12 @@ project(
cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')
+if not cpp.compiles('thread_local int x = 0;', name : 'thread_local')
+ if cpp.has_argument('-std=c++11')
+ add_project_arguments('-std=c++11', language : 'cpp')
+ endif
+endif
+
null_dep = dependency('', required : false)
if get_option('layout') != 'mirror'
--
2.25.1

View File

@@ -0,0 +1,785 @@
From dbb0d023abb9e4bfed70144514595f0477840f3e Mon Sep 17 00:00:00 2001
From: Luigi Santivetti <luigi.santivetti@imgtec.com>
Date: Wed, 19 Jun 2019 16:36:06 +0100
Subject: [PATCH 40/67] dri2: add support for swap intervals other than 1
Before this change, the swap interval was fixed at 1, with page flips
scheduled on the next vblank. This change allows any swap interval
between 0 and 10 to be set.
An additional thread is created, so as not to rely on the application
polling for previously scheduled drm events (be it a flip or a vblank).
Instead, each call to swap buffers made by the application will be
queued, and consumed asynchronously by the additional thread. This
ensures that drm events will be handled as soon as possible,
regardless of the timing of subsequent calls to swap buffers.
Change-Id: If7c0495df7ddfaa08583a14f820c46e1b97da788
Signed-off-by: Luigi Santivetti <luigi.santivetti@imgtec.com>
---
src/egl/drivers/dri2/egl_dri2.h | 34 +-
src/egl/drivers/dri2/platform_null.c | 541 +++++++++++++++++++++++----
2 files changed, 497 insertions(+), 78 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index eb2127e3fe6..64d60ed66e4 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -332,6 +332,23 @@ struct tpl_swap_queue_elem
};
#endif
+#ifdef HAVE_NULL_PLATFORM
+struct swap_queue_elem
+{
+ uint32_t swap_interval;
+ uint32_t back_id;
+ uint32_t fb_id;
+};
+
+enum {
+ SWAP_IDLE,
+ SWAP_FLIP,
+ SWAP_VBLANK,
+ SWAP_POLL,
+ SWAP_ERROR,
+};
+#endif
+
struct dri2_egl_surface
{
_EGLSurface base;
@@ -370,13 +387,18 @@ struct dri2_egl_surface
#ifdef HAVE_TIZEN_PLATFORM
tpl_surface_t *tpl_surf;
bool reset;
+ struct tpl_swap_queue_elem swap_queue[DRI2_SURFACE_NUM_COLOR_BUFFERS];
+#endif
+#if defined(HAVE_TIZEN_PLATFORM) || defined(HAVE_NULL_PLATFORM)
/*
* Protects swap_queue_idx_head, swap_queue_idx_tail and
* color_buffers.locked.
*/
pthread_mutex_t mutex;
pthread_cond_t swap_queue_cond;
- struct tpl_swap_queue_elem swap_queue[DRI2_SURFACE_NUM_COLOR_BUFFERS];
+#if defined(HAVE_NULL_PLATFORM)
+ pthread_cond_t swap_unlock_buffer_cond;
+#endif
int swap_queue_idx_head;
int swap_queue_idx_tail;
pthread_t swap_queue_processor;
@@ -412,7 +434,7 @@ struct dri2_egl_surface
#endif
bool locked;
int age;
- } color_buffers[4], *back, *current;
+ } color_buffers[DRI2_SURFACE_NUM_COLOR_BUFFERS], *back, *current;
#endif
#ifdef HAVE_ANDROID_PLATFORM
@@ -442,7 +464,13 @@ struct dri2_egl_surface
#endif
#ifdef HAVE_NULL_PLATFORM
- uint32_t front_fb_id;
+ uint32_t front_fb_id;
+ struct swap_queue_elem swap_queue[DRI2_SURFACE_NUM_COLOR_BUFFERS];
+ struct swap_queue_elem *swap_data;
+ int swap_state;
+ bool mutex_init;
+ bool cond_init;
+ bool cond_init_unlock_buffer;
#endif
int out_fence_fd;
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index fb03ecc36fd..5b7c1ec426c 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -31,6 +31,7 @@
#include <drm_fourcc.h>
#include <fcntl.h>
#include <poll.h>
+#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
@@ -58,6 +59,17 @@ struct object_property {
uint64_t prop_value;
};
+static inline
+uint32_t get_back_buffer_id(struct dri2_egl_surface *dri2_surf)
+{
+ uintptr_t offset = ((uintptr_t) dri2_surf->back) -
+ ((uintptr_t) &dri2_surf->color_buffers[0]);
+
+ assert(dri2_surf->back && !(offset >> 32));
+
+ return (uint32_t) (offset / sizeof(dri2_surf->color_buffers[0]));
+}
+
#define object_property_set_named(output, object_type, prop_name, value) \
{ \
.object_id = (output)->object_type##_id, \
@@ -176,36 +188,6 @@ property_id_get_for_name(drmModePropertyRes **prop_res, const char *prop_name)
return 0;
}
-static void
-flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
- unsigned int tv_usec, void *user_data)
-{
- bool *plocked = user_data;
-
- if (plocked)
- *plocked = false;
-}
-
-static bool
-flip_process(int fd)
-{
- static drmEventContext evctx =
- {.version = 2, .page_flip_handler = flip_handler};
- struct pollfd pfd = {.fd = fd, .events = POLLIN};
- int ret;
-
- do {
- ret = poll(&pfd, 1, -1);
- } while (ret > 0 && pfd.revents != pfd.events);
-
- if (ret <= 0)
- return false;
-
- drmHandleEvent(fd, &evctx);
-
- return true;
-}
-
static drmModePropertyRes **
object_get_property_resources(int fd, uint32_t object_id, uint32_t object_type)
{
@@ -495,6 +477,113 @@ display_output_atomic_modeset(int fd, struct display_output *output, uint32_t fb
DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
}
+static void
+swap_enqueue_data(struct dri2_egl_surface *dri2_surf, uint32_t back_id,
+ uint32_t interval)
+{
+ struct swap_queue_elem *swap_data;
+
+ pthread_mutex_lock(&dri2_surf->mutex);
+ swap_data = &dri2_surf->swap_queue[dri2_surf->swap_queue_idx_tail];
+ swap_data->swap_interval = interval;
+ swap_data->fb_id = dri2_surf->back->fb_id;
+ swap_data->back_id = back_id;
+
+ dri2_surf->swap_queue_idx_tail++;
+ dri2_surf->swap_queue_idx_tail %= ARRAY_SIZE(dri2_surf->swap_queue);
+
+ /* Notify the swap thread there is new work to do */
+ pthread_cond_signal(&dri2_surf->swap_queue_cond);
+ pthread_mutex_unlock(&dri2_surf->mutex);
+}
+
+static void
+swap_dequeue_data_start(struct dri2_egl_surface *dri2_surf)
+{
+ pthread_mutex_lock(&dri2_surf->mutex);
+ while (dri2_surf->swap_queue_idx_head == dri2_surf->swap_queue_idx_tail)
+ pthread_cond_wait(&dri2_surf->swap_queue_cond, &dri2_surf->mutex);
+
+ dri2_surf->swap_data =
+ &dri2_surf->swap_queue[dri2_surf->swap_queue_idx_head];
+ pthread_mutex_unlock(&dri2_surf->mutex);
+}
+
+static void
+swap_dequeue_data_finish(struct dri2_egl_surface *dri2_surf)
+{
+ pthread_mutex_lock(&dri2_surf->mutex);
+
+ if (dri2_surf->current)
+ dri2_surf->current->locked = false;
+
+ dri2_surf->current =
+ &dri2_surf->color_buffers[dri2_surf->swap_data->back_id];
+ dri2_surf->swap_state = SWAP_IDLE;
+
+ dri2_surf->swap_queue_idx_head++;
+ dri2_surf->swap_queue_idx_head %= ARRAY_SIZE(dri2_surf->swap_queue);
+
+ /* Notify get_back_bo that a buffer has become available */
+ pthread_cond_signal(&dri2_surf->swap_unlock_buffer_cond);
+ pthread_mutex_unlock(&dri2_surf->mutex);
+}
+
+static void
+flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
+ unsigned int tv_usec, void *flip_data)
+{
+ struct dri2_egl_surface *dri2_surf = flip_data;
+
+ (void) tv_sec;
+ (void) tv_usec;
+ (void) sequence;
+
+ /* Ultimate queueing ops */
+ swap_dequeue_data_finish(dri2_surf);
+}
+
+static void
+vblank_handler(int fd, unsigned int sequence, unsigned int tv_sec,
+ unsigned int tv_usec, void *vblank_data)
+{
+ struct dri2_egl_surface *dri2_surf = vblank_data;
+
+ (void) tv_sec;
+ (void) tv_usec;
+ (void) sequence;
+
+ dri2_surf->swap_state = SWAP_FLIP;
+}
+
+static int
+drm_event_process(int fd)
+{
+ static drmEventContext evctx = {
+ .version = 2,
+ .page_flip_handler = flip_handler,
+ .vblank_handler = vblank_handler
+ };
+ struct pollfd pfd = {.fd = fd, .events = POLLIN};
+ int ret;
+
+ do {
+ ret = poll(&pfd, 1, -1);
+ } while (ret > 0 && pfd.revents != pfd.events);
+
+ if (ret <= 0)
+ /* Man says:
+ *
+ * On error, -1 is returned, and errno is set to indicate the
+ * cause of the error.
+ */
+ return -1;
+
+ drmHandleEvent(fd, &evctx);
+
+ return 0;
+}
+
static bool
display_output_init(int fd, struct display_output *output, bool use_atomic)
{
@@ -571,10 +660,46 @@ static int
display_output_flip(int fd, struct display_output *output, uint32_t fb_id,
uint32_t flags, void *flip_data)
{
- if (output->atomic_state)
- return display_output_atomic_flip(fd, output, fb_id, flags, flip_data);
+ int err;
+
+ do {
+ if (output->atomic_state)
+ err = display_output_atomic_flip(fd, output, fb_id, flags, flip_data);
+ else
+ err = drmModePageFlip(fd, output->crtc_id, fb_id, flags, flip_data);
+ } while (err == -EBUSY);
+
+ return err;
+}
+
+static int
+display_request_vblank(int fd, uint32_t target_frame, uint32_t flags,
+ void *vblank_data)
+{
+ drmVBlank vblank = {
+ .request = {
+ .type = flags,
+ .sequence = target_frame,
+ .signal = (unsigned long)vblank_data,
+ }
+ };
+
+ return drmWaitVBlank(fd, &vblank);
+}
+
+static int
+display_get_vblank_sequence(int fd, uint32_t *current_vblank_out)
+{
+ drmVBlank vblank = { .request = { .type = DRM_VBLANK_RELATIVE } };
+ int err;
+
+ err = drmWaitVBlank(fd, &vblank);
+ if (err)
+ return err;
- return drmModePageFlip(fd, output->crtc_id, fb_id, flags, flip_data);
+ *current_vblank_out = vblank.reply.sequence;
+
+ return 0;
}
static int
@@ -587,6 +712,213 @@ display_output_modeset(int fd, struct display_output *output, uint32_t fb_id)
&output->connector_id, 1, &output->mode);
}
+static int
+swap_idle_get_target_frame(struct dri2_egl_surface *dri2_surf,
+ uint32_t *current_vblank_out, uint32_t *target_frame_out)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ int err;
+
+ /* For intarvals bigger than 1, always update current_vblank. The
+ * spec isn't fully clear, nonetheless page 25 and 26 of the PDF of the
+ * EGL 1.5 spec say:
+ *
+ * "[the parameter interval] indicates the number of swap intervals
+ * that will elapse before a buffer swap takes place after calling
+ * eglSwapBuffers."
+ *
+ * We need to guarantee that the target frame is always ahead of the
+ * current vblank by the number of intervals set at the time swapBuffer
+ * is called. For intervals of 1 or 0, we don't need a target frame.
+ */
+ err = display_get_vblank_sequence(dri2_dpy->fd, current_vblank_out);
+ if (err)
+ return err;
+
+ assert(dri2_surf->swap_data->swap_interval > 0);
+
+ /* -1 accounts for vsync locked flip, so get a vblank one frame earlier */
+ *target_frame_out =
+ *current_vblank_out + dri2_surf->swap_data->swap_interval - 1;
+
+ return 0;
+}
+
+static int
+swap_idle_state_transition(struct dri2_egl_surface *dri2_surf,
+ uint32_t *target_frame_out)
+{
+ uint32_t current_vblank = 0;
+ uint32_t target_frame = 0;
+ int err;
+
+ /* update dri2_surf->swap_data */
+ swap_dequeue_data_start(dri2_surf);
+
+ /* update next target frame */
+ if (dri2_surf->swap_data->swap_interval > 1) {
+ err = swap_idle_get_target_frame(dri2_surf, &current_vblank,
+ &target_frame);
+ if (err) {
+ dri2_surf->swap_state = SWAP_ERROR;
+ return err;
+ }
+ }
+
+ dri2_surf->swap_state =
+ target_frame <= current_vblank ? SWAP_FLIP : SWAP_VBLANK;
+ *target_frame_out = target_frame;
+
+ return 0;
+}
+
+static int
+swap_vblank_state_transition(struct dri2_egl_surface *dri2_surf,
+ uint32_t target_frame)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ uint32_t flags = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ int err;
+
+ err = display_request_vblank(dri2_dpy->fd, target_frame,
+ flags, dri2_surf);
+ if (err) {
+ dri2_surf->swap_state = SWAP_ERROR;
+ return err;
+ }
+
+ dri2_surf->swap_state = SWAP_POLL;
+
+ return 0;
+}
+
+static int
+swap_flip_state_transition(struct dri2_egl_surface *dri2_surf)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ uint32_t flags;
+ int err;
+
+ flags = DRM_MODE_PAGE_FLIP_EVENT;
+ if (dri2_surf->swap_data->swap_interval == 0) {
+ assert(!dri2_dpy->atomic_enabled);
+ flags |= DRM_MODE_PAGE_FLIP_ASYNC;
+ }
+
+ err = display_output_flip(dri2_dpy->fd, &dri2_dpy->output,
+ dri2_surf->swap_data->fb_id, flags, dri2_surf);
+ if (err) {
+ dri2_surf->swap_state = SWAP_ERROR;
+ return err;
+ }
+
+ dri2_surf->swap_state = SWAP_POLL;
+
+ return 0;
+}
+
+static int
+swap_poll_state_transition(struct dri2_egl_surface *dri2_surf)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ int err;
+
+ /* dri2_surf->swap_state is being set inside the handler */
+ err = drm_event_process(dri2_dpy->fd);
+ if (err) {
+ dri2_surf->swap_state = SWAP_ERROR;
+ return err;
+ }
+
+ return 0;
+}
+
+static inline void
+swap_error_print_message(const int state, const int err)
+{
+ switch (state) {
+ case SWAP_IDLE:
+ _eglLog(_EGL_WARNING,
+ "failed to get a target frame (err=%d)", err);
+ break;
+ case SWAP_FLIP:
+ _eglLog(_EGL_WARNING,
+ "failed to schedule a pageflip (err=%d)", err);
+ break;
+ case SWAP_VBLANK:
+ _eglLog(_EGL_WARNING,
+ "failed to request a vblank event (err=%d)", err);
+ break;
+ case SWAP_POLL:
+ _eglLog(_EGL_WARNING,
+ "failed to poll for drm event (err=%d)", err);
+ break;
+ case SWAP_ERROR:
+ _eglLog(_EGL_WARNING,
+ "failed to swap buffers, unknown swap state");
+ break;
+ default:
+ _eglLog(_EGL_FATAL,
+ "failed to swap buffers (unknown error)");
+ };
+}
+
+static void
+swap_error_state_handler(struct dri2_egl_surface *dri2_surf,
+ int state, int err)
+{
+ static bool do_log = true;
+
+ if (do_log) {
+ swap_error_print_message(state, err);
+ do_log = false;
+ }
+
+ swap_dequeue_data_finish(dri2_surf);
+}
+
+static void *
+swap_queue_processor_worker(void *data)
+{
+ struct dri2_egl_surface *dri2_surf = data;
+ int state = SWAP_IDLE, err = SWAP_ERROR;
+ uint32_t target_frame = 0;
+
+ assert(dri2_surf->swap_state == SWAP_IDLE);
+
+ while (1) {
+ switch (dri2_surf->swap_state) {
+ case SWAP_IDLE:
+ err = swap_idle_state_transition(dri2_surf, &target_frame);
+ break;
+ case SWAP_VBLANK:
+ err = swap_vblank_state_transition(dri2_surf, target_frame);
+ break;
+ case SWAP_FLIP:
+ err = swap_flip_state_transition(dri2_surf);
+ break;
+ case SWAP_POLL:
+ err = swap_poll_state_transition(dri2_surf);
+ break;
+ case SWAP_ERROR:
+ swap_error_state_handler(dri2_surf, state, err);
+ break;
+ default:
+ dri2_surf->swap_state = SWAP_ERROR;
+ break;
+ }
+
+ if (!err)
+ state = dri2_surf->swap_state;
+ }
+
+ return NULL;
+}
+
static bool
add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
uint32_t *fb_id_out)
@@ -651,15 +983,18 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
- if (!dri2_surf->back) {
+ pthread_mutex_lock(&dri2_surf->mutex);
+ while (!dri2_surf->back) {
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
if (!dri2_surf->color_buffers[i].locked) {
dri2_surf->back = &dri2_surf->color_buffers[i];
break;
}
}
+
+ /* Wait for a flip to get a buffer off the screen and unlock it */
if (!dri2_surf->back)
- return false;
+ pthread_cond_wait(&dri2_surf->swap_unlock_buffer_cond, &dri2_surf->mutex);
}
if (!dri2_surf->back->dri_image) {
@@ -671,19 +1006,23 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
__DRI_IMAGE_USE_SCANOUT,
NULL);
if (!dri2_surf->back->dri_image)
- return false;
+ goto err_unlock;
}
if (!dri2_surf->back->fb_id) {
if (!add_fb_for_dri_image(dri2_dpy, dri2_surf->back->dri_image,
- &dri2_surf->back->fb_id)) {
- return false;
- }
+ &dri2_surf->back->fb_id))
+ goto err_unlock;
}
dri2_surf->back->locked = 1;
+ pthread_mutex_unlock(&dri2_surf->mutex);
return true;
+
+err_unlock:
+ pthread_mutex_unlock(&dri2_surf->mutex);
+ return false;
}
static _EGLSurface *
@@ -770,6 +1109,26 @@ dri2_null_create_window_surface(_EGLDisplay *disp, _EGLConfig *config,
dri2_surf->base.Width = dri2_dpy->output.mode.hdisplay;
dri2_surf->base.Height = dri2_dpy->output.mode.vdisplay;
+ /* After the dri2_surf is created, init thread's data */
+ dri2_surf->mutex_init = !pthread_mutex_init(&dri2_surf->mutex, NULL);
+ if (!dri2_surf->mutex_init) {
+ _eglError(EGL_BAD_ALLOC, "failed to init swap thread mutex");
+ goto err_destroy_surface;
+ }
+
+ dri2_surf->cond_init = !pthread_cond_init(&dri2_surf->swap_queue_cond, NULL);
+ if (!dri2_surf->cond_init) {
+ _eglError(EGL_BAD_ALLOC, "failed to init swap queue condition");
+ goto err_destroy_surface;
+ }
+
+ dri2_surf->cond_init_unlock_buffer =
+ !pthread_cond_init(&dri2_surf->swap_unlock_buffer_cond, NULL);
+ if (!dri2_surf->cond_init_unlock_buffer) {
+ _eglError(EGL_BAD_ALLOC, "failed to init swap buffer unlock condition");
+ goto err_destroy_surface;
+ }
+
if (!get_front_bo(dri2_surf)) {
_eglError(EGL_BAD_NATIVE_WINDOW, "window get buffer");
goto err_destroy_surface;
@@ -783,6 +1142,14 @@ dri2_null_create_window_surface(_EGLDisplay *disp, _EGLConfig *config,
}
dri2_dpy->output.in_use = true;
+ dri2_surf->swap_state = SWAP_IDLE;
+
+ err = pthread_create(&dri2_surf->swap_queue_processor, NULL,
+ swap_queue_processor_worker, dri2_surf);
+ if (err) {
+ _eglError(EGL_BAD_ALLOC, "failed to create swap thread");
+ goto err_destroy_surface;
+ }
return surf;
@@ -808,8 +1175,27 @@ dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
/* If there's a current surface then a page flip has been performed, so make
* sure we process the flip event.
*/
- if (dri2_surf->current)
- flip_process(dri2_dpy->fd);
+ if (dri2_surf->swap_queue_processor) {
+ pthread_mutex_lock(&dri2_surf->mutex);
+
+ /* Wait for any outstanding swaps to complete */
+ while (dri2_surf->swap_queue_idx_head != dri2_surf->swap_queue_idx_tail)
+ pthread_cond_wait(&dri2_surf->swap_unlock_buffer_cond,
+ &dri2_surf->mutex);
+
+ pthread_mutex_unlock(&dri2_surf->mutex);
+ pthread_cancel(dri2_surf->swap_queue_processor);
+ pthread_join(dri2_surf->swap_queue_processor, NULL);
+ }
+
+ if (dri2_surf->cond_init)
+ pthread_cond_destroy(&dri2_surf->swap_queue_cond);
+
+ if (dri2_surf->cond_init_unlock_buffer)
+ pthread_cond_destroy(&dri2_surf->swap_unlock_buffer_cond);
+
+ if (dri2_surf->mutex_init)
+ pthread_mutex_destroy(&dri2_surf->mutex);
if (dri2_surf->front)
dri2_dpy->image->destroyImage(dri2_surf->front);
@@ -837,9 +1223,7 @@ dri2_null_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
- bool *plocked = NULL;
- uint32_t flags;
- int err;
+ uint32_t back_id;
if (dri2_surf->base.Type != EGL_WINDOW_BIT)
return EGL_TRUE;
@@ -858,34 +1242,13 @@ dri2_null_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
dri2_flush_drawable_for_swapbuffers(disp, draw);
dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
- if (dri2_surf->current) {
- /* Wait for the previous flip to happen so the next one can be queued */
- if (!flip_process(dri2_dpy->fd)) {
- _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_null_swap_buffers process");
- return EGL_FALSE;
- }
+ back_id = get_back_buffer_id(dri2_surf);
+ assert(dri2_surf->back == &dri2_surf->color_buffers[back_id]);
- plocked = &dri2_surf->current->locked;
- }
-
- flags = DRM_MODE_PAGE_FLIP_EVENT;
- if (draw->SwapInterval == 0)
- flags |= DRM_MODE_PAGE_FLIP_ASYNC;
-
- do {
- err = display_output_flip(dri2_dpy->fd, &dri2_dpy->output,
- dri2_surf->back->fb_id, flags, plocked);
- } while (err == -EBUSY);
-
- if (err) {
- _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_null_swap_buffers flip");
- dri2_surf->back->locked = false;
- dri2_surf->back = NULL;
- return EGL_FALSE;
- }
+ swap_enqueue_data(dri2_surf, back_id, draw->SwapInterval);
+ /* This back buffer is tracked in the swap_data, safe to drop it now */
dri2_surf->back->age = 1;
- dri2_surf->current = dri2_surf->back;
dri2_surf->back = NULL;
return EGL_TRUE;
@@ -904,11 +1267,20 @@ dri2_null_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
return dri2_surf->back->age;
}
+static EGLBoolean
+dri2_null_swap_interval(_EGLDisplay *dpy, _EGLSurface *draw, EGLint interval)
+{
+ _eglLog(_EGL_DEBUG, "DRI2: set swap interval to %d", interval);
+ draw->SwapInterval = interval;
+ return EGL_TRUE;
+}
+
static struct dri2_egl_display_vtbl dri2_null_display_vtbl = {
.create_window_surface = dri2_null_create_window_surface,
.create_pbuffer_surface = dri2_null_create_pbuffer_surface,
.destroy_surface = dri2_null_destroy_surface,
.create_image = dri2_create_image_khr,
+ .swap_interval = dri2_null_swap_interval,
.swap_buffers = dri2_null_swap_buffers,
.query_buffer_age = dri2_null_query_buffer_age,
.get_dri_drawable = dri2_surface_get_dri_drawable,
@@ -1062,12 +1434,35 @@ dri2_null_add_configs_for_formats(_EGLDisplay *disp)
return count != 0;
}
+static void
+dri2_null_setup_swap_interval(_EGLDisplay *disp)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ const int swap_max_interval = 10; /* Arbitrary max value */
+ uint64_t value;
+ int err;
+
+ dri2_setup_swap_interval(disp, swap_max_interval);
+
+ err = drmGetCap(dri2_dpy->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
+ if (err || value == 0)
+ dri2_dpy->min_swap_interval = 1;
+
+ /**
+ * drm/atomic: Reject FLIP_ASYNC unconditionally
+ * upstream f2cbda2dba11de868759cae9c0d2bab5b8411406
+ *
+ * Only allow swap interval 0 for legacy DRM/KMS and let
+ * the app be aware that swap interval is clamped to 1.
+ */
+ if (dri2_dpy->atomic_enabled)
+ dri2_dpy->min_swap_interval = 1;
+}
EGLBoolean
dri2_initialize_null(_EGLDisplay *disp)
{
struct dri2_egl_display *dri2_dpy;
- uint64_t value;
int err;
dri2_dpy = calloc(1, sizeof(*dri2_dpy));
@@ -1114,11 +1509,7 @@ dri2_initialize_null(_EGLDisplay *disp)
}
dri2_setup_screen(disp);
- dri2_setup_swap_interval(disp, 1);
-
- err = drmGetCap(dri2_dpy->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
- if (err || value == 0)
- dri2_dpy->min_swap_interval = 1;
+ dri2_null_setup_swap_interval(disp);
if (dri2_dpy->image->base.version < NULL_IMAGE_EXTENSION_VERSION_MIN) {
_eglError(EGL_NOT_INITIALIZED, "image extension version too old");
--
2.25.1

View File

@@ -0,0 +1,214 @@
From d286d05d0d84c913c8bfcbe8f693083caf3bcc77 Mon Sep 17 00:00:00 2001
From: Silvestrs Timofejevs <silvestrs.timofejevs@imgtec.com>
Date: Mon, 2 Sep 2019 09:32:01 +0100
Subject: [PATCH 41/67] null_platform: add support for explicit synchronisation
This change adds support for the 'in' fence, the 'out' fence will
potentially be added in subsequent optimisation changes.
Explicit synchronisation KMS 'in' and 'out' properties have been first
added in Linux kernel 4.10 as an additional feature to the atomic mode
setting.
9626014258a5957ff120b3987ee72decdbe0c798 - 'in' property
beaf5af48034c9e2ebb8b2b1fb12dc4d8aeba99e - 'out' property
Unlike many other features - it doesn't have an in kernel capability
flag, so the support for it can be tested in the following way:
KMS creates an additional set of properties when the version of kernel
is new enough to support it ('in' and 'out' fence properties). When
the user-space requests all the properties from the kernel via
drmModeObjectGetProperties it is possible to determine whether the
required property is supported by the kernel or not.
The explicit synchronisation is used when available, otherwise the
implicit sync model is used instead. If explicit synchronisation is
available but 'in' fence failed to attach in KMS, the system falls
back to the implicit synchronisation model.
egl_dri2.c already creates the GPU 'out' fence that is then used by
the null_platform as KMS 'in' fence. null_platform takes owenership of
this fence fd during the swap buffers operation, at which point the
fence fd is no longer available to be used outside of null_platform.
EGL_LOG_LEVEL=debug should give some useful information in case of
explicit synchronisation failure. As mentioned above, this failure
will result in implicit synchronisation being used instead.
Change-Id: Ib9c4a0bc3ea1b21192ee37909d7580d6b7b366ec
---
src/egl/drivers/dri2/egl_dri2.h | 2 +
src/egl/drivers/dri2/platform_null.c | 77 +++++++++++++++++++++++++++-
2 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 64d60ed66e4..eb6e4551087 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -106,6 +106,7 @@ struct wl_buffer;
#ifdef HAVE_NULL_PLATFORM
struct display_output {
bool in_use;
+ bool in_fence_supported;
uint32_t connector_id;
drmModePropertyRes **connector_prop_res;
uint32_t crtc_id;
@@ -338,6 +339,7 @@ struct swap_queue_elem
uint32_t swap_interval;
uint32_t back_id;
uint32_t fb_id;
+ int kms_in_fence_fd;
};
enum {
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index 5b7c1ec426c..d36dc0ced2a 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -401,6 +401,9 @@ display_output_atomic_init(int fd, struct display_output *output)
if (!output->atomic_state)
goto err_destroy_mode_prop_blob;
+ if (property_id_get_for_name(plane_prop_res, "IN_FENCE_FD"))
+ output->in_fence_supported = true;
+
output->connector_prop_res = connector_prop_res;
output->crtc_prop_res = crtc_prop_res;
output->plane_prop_res = plane_prop_res;
@@ -418,6 +421,53 @@ err_free_connector_prop_res:
return false;
}
+static void
+display_output_atomic_add_in_fence(struct display_output *output,
+ int kms_in_fence_fd)
+{
+ const struct object_property obj_sync_props[] = {
+ object_property_set_named(output, plane, "IN_FENCE_FD", kms_in_fence_fd),
+ };
+ int err;
+
+ /* Explicit synchronisation is not being used */
+ if (kms_in_fence_fd < 0)
+ return;
+
+ err = atomic_state_add_object_properties(output->atomic_state,
+ obj_sync_props,
+ ARRAY_SIZE(obj_sync_props));
+ if (err)
+ _eglLog(_EGL_DEBUG, "%s: failed to add props ERR = %d", __func__, err);
+}
+
+static void
+atomic_claim_in_fence_fd(struct dri2_egl_surface *dri2_surf,
+ struct swap_queue_elem *swap_data)
+{
+ /* Explicit synchronisation is not being used */
+ if (!dri2_surf->enable_out_fence)
+ return;
+
+ if (dri2_surf->out_fence_fd < 0) {
+ _eglLog(_EGL_DEBUG, "%s: missing 'in' fence", __func__);
+ return;
+ }
+
+ /* Take ownership of the fd */
+ swap_data->kms_in_fence_fd = dri2_surf->out_fence_fd;
+ dri2_surf->out_fence_fd = -1;
+}
+
+static void
+atomic_relinquish_in_fence_fd(struct dri2_egl_surface *dri2_surf,
+ struct swap_queue_elem *swap_data)
+{
+ /* KMS is now in control of the fence (post drmModeAtomicCommit) */
+ close(swap_data->kms_in_fence_fd);
+ swap_data->kms_in_fence_fd = -1;
+}
+
static int
display_output_atomic_flip(int fd, struct display_output *output, uint32_t fb_id,
uint32_t flags, void *flip_data)
@@ -425,6 +475,8 @@ display_output_atomic_flip(int fd, struct display_output *output, uint32_t fb_id
const struct object_property obj_props[] = {
object_property_set_named(output, plane, "FB_ID", fb_id),
};
+ struct dri2_egl_surface *dri2_surf = flip_data;
+ struct swap_queue_elem *swap_data = dri2_surf->swap_data;
int err;
/* Reset atomic state */
@@ -435,13 +487,19 @@ display_output_atomic_flip(int fd, struct display_output *output, uint32_t fb_id
if (err)
return err;
+ display_output_atomic_add_in_fence(output, swap_data->kms_in_fence_fd);
+
/*
* Don't block - like drmModePageFlip, drmModeAtomicCommit will return
* -EBUSY if the commit can't be queued in the kernel.
*/
flags |= DRM_MODE_ATOMIC_NONBLOCK;
- return drmModeAtomicCommit(fd, output->atomic_state, flags, flip_data);
+ err = drmModeAtomicCommit(fd, output->atomic_state, flags, flip_data);
+
+ atomic_relinquish_in_fence_fd(dri2_surf, swap_data);
+
+ return err;
}
static int
@@ -489,6 +547,8 @@ swap_enqueue_data(struct dri2_egl_surface *dri2_surf, uint32_t back_id,
swap_data->fb_id = dri2_surf->back->fb_id;
swap_data->back_id = back_id;
+ atomic_claim_in_fence_fd(dri2_surf, swap_data);
+
dri2_surf->swap_queue_idx_tail++;
dri2_surf->swap_queue_idx_tail %= ARRAY_SIZE(dri2_surf->swap_queue);
@@ -1025,11 +1085,21 @@ err_unlock:
return false;
}
+static void surface_swap_queue_init(struct dri2_egl_surface *dri2_surf)
+{
+ struct swap_queue_elem *swap_queue = &dri2_surf->swap_queue[0];
+ const int num_el = ARRAY_SIZE(dri2_surf->swap_queue);
+
+ for (int i = 0; i < num_el; i++)
+ swap_queue[i].kms_in_fence_fd = -1;
+}
+
static _EGLSurface *
create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
const EGLint *attrib_list)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct display_output *output = &dri2_dpy->output;
struct dri2_egl_config *dri2_config = dri2_egl_config(config);
struct dri2_egl_surface *dri2_surf;
const __DRIconfig *dri_config;
@@ -1043,7 +1113,8 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
}
surf = &dri2_surf->base;
- if (!dri2_init_surface(surf, disp, type, config, attrib_list, false, NULL))
+ if (!dri2_init_surface(surf, disp, type, config, attrib_list,
+ output->in_fence_supported, NULL))
goto err_free_surface;
dri_config = dri2_get_dri_config(dri2_config, type,
@@ -1066,6 +1137,8 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
dri2_surf->format = dri2_null_formats[format_idx].dri_image_format;
+ surface_swap_queue_init(dri2_surf);
+
return surf;
err_free_surface:
--
2.25.1

View File

@@ -0,0 +1,401 @@
From 4f9ca104c16a6eb1af770e2447adb4413fb41cb7 Mon Sep 17 00:00:00 2001
From: Luigi Santivetti <luigi.santivetti@imgtec.com>
Date: Thu, 26 Sep 2019 13:32:15 +0100
Subject: [PATCH 42/68] egl/null: add support for DRM image format modifiers
This change introduces support for image modifiers to platform_null. In
order for it to create an image with modifiers, it relies on libdrm to
iterate all formats with associated modifiers supported by the display
for the primary drm plane in use.
drmModeFormatModifierBlobIterNext() is added to the DRM api in a different
change and it is not upstream at present.
Internal notes:
[1] IN_FORMATS blobs are available since kernel 4.14:
- db1689aa61bd1efb5ce9b896e7aa860a85b7f1b6
- https://patchwork.freedesktop.org/patch/168543
[2] the dri image->base.version threshold is 14.
- Unlike for platform_wayland, where no details were found regarding
why it's using 15
- dri_interface.h makes createImageWithModifiers available since
version 14
- dri/gbm_dri.c as an example checks for minimum version 14.
Change-Id: I0f7b030f6e1943690692674bf18daabfc153208a
Signed-off-by: Luigi Santivetti <luigi.santivetti@imgtec.com>
---
meson.build | 5 +
src/egl/drivers/dri2/egl_dri2.h | 3 +
src/egl/drivers/dri2/platform_null.c | 221 +++++++++++++++++++++++----
3 files changed, 203 insertions(+), 26 deletions(-)
diff --git a/meson.build b/meson.build
index 21d93d372c2..ca89b8ac20d 100644
--- a/meson.build
+++ b/meson.build
@@ -1581,6 +1581,11 @@ if with_gallium_etnaviv
_drm_ver = '2.4.89'
endif
+# platform_null relies on DRM format-modifier iterators available since 2.4.108
+if with_platform_null
+ _drm_ver = '2.4.108'
+endif
+
# Loop over the enables versions and get the highest libdrm requirement for all
# active drivers.
_drm_blame = ''
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index eb6e4551087..32ad720b343 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -117,6 +117,8 @@ struct display_output {
uint32_t mode_blob_id;
unsigned formats;
drmModeAtomicReq *atomic_state;
+ uint32_t in_formats_id;
+ struct u_vector modifiers;
};
#endif
@@ -280,6 +282,7 @@ struct dri2_egl_display
#ifdef HAVE_NULL_PLATFORM
bool atomic_enabled;
+ bool in_formats_enabled;
struct display_output output;
#endif
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index d36dc0ced2a..2c79199da26 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -40,6 +40,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <util/u_vector.h>
#include <xf86drm.h>
#include "egl_dri2.h"
@@ -156,6 +157,18 @@ format_idx_get_from_drm_format(uint32_t drm_format)
return -1;
}
+static inline uint32_t
+blob_id_from_property_value(uint64_t prop_value)
+{
+ /* The KMS properties documetation, 01.org/linuxgraphics, says:
+ *
+ * For all property types except blob properties the value is a 64-bit
+ * unsigned integer.
+ */
+ assert(!(prop_value >> 32));
+ return (uint32_t) prop_value;
+}
+
static int
atomic_state_add_object_properties(drmModeAtomicReq *atomic_state,
const struct object_property *props,
@@ -645,7 +658,66 @@ drm_event_process(int fd)
}
static bool
-display_output_init(int fd, struct display_output *output, bool use_atomic)
+plane_init_in_formats(int fd, drmModePlane *plane, struct u_vector *modifiers,
+ uint32_t *in_formats_id_out, unsigned *formats_out)
+{
+ uint32_t blob_id, prev_fmt = DRM_FORMAT_INVALID, count_formats = 0;
+ drmModeFormatModifierIterator drm_iter = {0};
+ drmModePropertyBlobRes *blob;
+ uint64_t prop_value;
+ int idx, err;
+
+ assert(plane && in_formats_id_out && formats_out);
+
+ err = !object_property_value_for_name(fd, plane->plane_id,
+ DRM_MODE_OBJECT_PLANE,
+ "IN_FORMATS", &prop_value);
+ if (err)
+ return false;
+
+ blob_id = blob_id_from_property_value(prop_value);
+ blob = drmModeGetPropertyBlob(fd, blob_id);
+
+ while (drmModeFormatModifierBlobIterNext(blob, &drm_iter)) {
+ if (drm_iter.fmt != prev_fmt) {
+ prev_fmt = drm_iter.fmt;
+ count_formats++;
+
+ idx = format_idx_get_from_drm_format(drm_iter.fmt);
+ if (idx < 0)
+ continue;
+
+ *formats_out |= (1 << idx);
+ }
+ }
+
+ drmModeFreePropertyBlob(blob);
+
+ if (!count_formats) {
+ /* None of the formats in the IN_FORMATS blob has associated modifiers */
+ _eglLog(_EGL_WARNING, "no format-modifiers found in IN_FORMATS");
+ return false;
+ }
+
+ if (plane->count_formats != count_formats)
+ /* Only some of the formats in the IN_FORMATS blob have associated modifiers,
+ * try to use this subset.
+ */
+ _eglLog(_EGL_WARNING, "discarding formats without modifiers");
+
+ /* Allocate space for modifiers, if ENOMEM fallback to plane formats */
+ if (!u_vector_init(modifiers, sizeof(uint64_t), 64)) {
+ _eglLog(_EGL_WARNING, "failed to allocate modifiers");
+ return false;
+ }
+
+ *in_formats_id_out = blob_id;
+ return true;
+}
+
+static bool
+display_output_init(int fd, struct display_output *output, bool use_atomic,
+ bool prefer_in_formats, bool *in_formats_enabled_out)
{
drmModeRes *resources;
drmModeConnector *connector;
@@ -674,16 +746,34 @@ display_output_init(int fd, struct display_output *output, bool use_atomic)
goto err_free_plane;
output->mode = connector->modes[mode_idx];
- /* Record the display supported formats */
- for (unsigned i = 0; i < plane->count_formats; i++) {
- int format_idx;
+ assert(in_formats_enabled_out && !(*in_formats_enabled_out));
- format_idx = format_idx_get_from_drm_format(plane->formats[i]);
- if (format_idx == -1)
- continue;
+ /* Track display supported formats. Look them up from IN_FORMATS blobs
+ * if they are available, otherwise use plane formats.
+ */
+ if (prefer_in_formats)
+ *in_formats_enabled_out = plane_init_in_formats(fd, plane,
+ &output->modifiers,
+ &output->in_formats_id,
+ &output->formats);
- output->formats |= (1 << format_idx);
+ if (!*in_formats_enabled_out) {
+ _eglLog(_EGL_WARNING, "fallback to plane formats");
+
+ for (unsigned i = 0; i < plane->count_formats; i++) {
+ int format_idx;
+
+ format_idx = format_idx_get_from_drm_format(plane->formats[i]);
+ if (format_idx == -1)
+ continue;
+
+ output->formats |= (1 << format_idx);
+ }
}
+
+ /* At this point we can only shut down if the look up failed and
+ * it is safe to pass NULL to drmModeFreeFormats().
+ */
if (!output->formats)
goto err_free_plane;
@@ -983,10 +1073,12 @@ static bool
add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
uint32_t *fb_id_out)
{
+ uint64_t modifiers[4] = {0};
uint32_t handles[4] = {0};
uint32_t pitches[4] = {0};
uint32_t offsets[4] = {0};
- int handle, stride, width, height, format;
+ uint32_t flags = 0;
+ int handle, stride, width, height, format, l_mod, h_mod;
int format_idx;
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &handle);
@@ -1001,9 +1093,47 @@ add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
format_idx = format_idx_get_from_dri_image_format(format);
assert(format_idx != -1);
- return !drmModeAddFB2(dri2_dpy->fd, width, height,
- dri2_null_formats[format_idx].drm_format,
- handles, pitches, offsets, fb_id_out, 0);
+ if (dri2_dpy->in_formats_enabled) {
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, &h_mod);
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, &l_mod);
+
+ modifiers[0] = combine_u32_into_u64((uint32_t) h_mod, (uint32_t) l_mod);
+ flags |= DRM_MODE_FB_MODIFIERS;
+ }
+
+ return !drmModeAddFB2WithModifiers(dri2_dpy->fd, width, height,
+ dri2_null_formats[format_idx].drm_format,
+ handles, pitches, offsets, modifiers,
+ fb_id_out, flags);
+}
+
+static __DRIimage *
+create_image(struct dri2_egl_surface *dri2_surf, uint32_t flags)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ uint32_t count_modifiers;
+ uint64_t *modifiers;
+
+ if (dri2_dpy->in_formats_enabled) {
+ count_modifiers = u_vector_length(&dri2_dpy->output.modifiers);
+ modifiers = u_vector_tail(&dri2_dpy->output.modifiers);
+
+ return dri2_dpy->image->createImageWithModifiers(dri2_dpy->dri_screen,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ dri2_surf->format,
+ modifiers,
+ count_modifiers,
+ NULL);
+ }
+
+ return dri2_dpy->image->createImage(dri2_dpy->dri_screen,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ dri2_surf->format,
+ flags,
+ NULL);
}
static bool
@@ -1016,12 +1146,7 @@ get_front_bo(struct dri2_egl_surface *dri2_surf)
if (dri2_surf->base.Type == EGL_WINDOW_BIT)
use |= __DRI_IMAGE_USE_SCANOUT;
- dri2_surf->front = dri2_dpy->image->createImage(dri2_dpy->dri_screen,
- dri2_surf->base.Width,
- dri2_surf->base.Height,
- dri2_surf->format,
- use,
- NULL);
+ dri2_surf->front = create_image(dri2_surf, use);
if (!dri2_surf->front)
return false;
@@ -1058,13 +1183,8 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
}
if (!dri2_surf->back->dri_image) {
- dri2_surf->back->dri_image =
- dri2_dpy->image->createImage(dri2_dpy->dri_screen,
- dri2_surf->base.Width,
- dri2_surf->base.Height,
- dri2_surf->format,
- __DRI_IMAGE_USE_SCANOUT,
- NULL);
+ dri2_surf->back->dri_image = create_image(dri2_surf,
+ __DRI_IMAGE_USE_SCANOUT);
if (!dri2_surf->back->dri_image)
goto err_unlock;
}
@@ -1094,6 +1214,30 @@ static void surface_swap_queue_init(struct dri2_egl_surface *dri2_surf)
swap_queue[i].kms_in_fence_fd = -1;
}
+static bool
+in_formats_get_modifiers(const int fd, const uint32_t in_formats_id,
+ const int drm_format, struct u_vector *modifiers)
+{
+ drmModeFormatModifierIterator drm_iter = {0};
+ drmModePropertyBlobRes *blob;
+ uint64_t *mod = NULL;
+
+ blob = drmModeGetPropertyBlob(fd, in_formats_id);
+
+ while (drmModeFormatModifierBlobIterNext(blob, &drm_iter)) {
+ if (drm_iter.fmt == drm_format) {
+ assert(drm_iter.mod != DRM_FORMAT_MOD_INVALID);
+
+ mod = u_vector_add(modifiers);
+ *mod = drm_iter.mod;
+ }
+ }
+
+ drmModeFreePropertyBlob(blob);
+
+ return mod != NULL;
+}
+
static _EGLSurface *
create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
const EGLint *attrib_list)
@@ -1105,6 +1249,7 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
const __DRIconfig *dri_config;
_EGLSurface *surf;
int format_idx;
+ bool ret;
dri2_surf = calloc(1, sizeof(*dri2_surf));
if (!dri2_surf) {
@@ -1137,6 +1282,15 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
dri2_surf->format = dri2_null_formats[format_idx].dri_image_format;
+ if (dri2_dpy->in_formats_enabled) {
+ ret = in_formats_get_modifiers(dri2_dpy->fd,
+ dri2_dpy->output.in_formats_id,
+ dri2_null_formats[format_idx].drm_format,
+ &dri2_dpy->output.modifiers);
+ if (!ret)
+ goto err_free_surface;
+ }
+
surface_swap_queue_init(dri2_surf);
return surf;
@@ -1536,6 +1690,8 @@ EGLBoolean
dri2_initialize_null(_EGLDisplay *disp)
{
struct dri2_egl_display *dri2_dpy;
+ bool prefer_in_formats = false;
+ uint64_t value;
int err;
dri2_dpy = calloc(1, sizeof(*dri2_dpy));
@@ -1589,8 +1745,19 @@ dri2_initialize_null(_EGLDisplay *disp)
goto cleanup;
}
+ err = drmGetCap(dri2_dpy->fd_dpy, DRM_CAP_ADDFB2_MODIFIERS, &value);
+ if (!err && value) {
+ /* in_formats could be supported by the platform, however not being
+ * actually enabled, i.e. in_formats init can still fail.
+ */
+ prefer_in_formats = dri2_dpy->image->base.version >= 14 &&
+ dri2_dpy->image->createImageWithModifiers;
+ }
+
if (!display_output_init(dri2_dpy->fd, &dri2_dpy->output,
- dri2_dpy->atomic_enabled)) {
+ dri2_dpy->atomic_enabled,
+ prefer_in_formats,
+ &dri2_dpy->in_formats_enabled)) {
_eglError(EGL_NOT_INITIALIZED, "failed to create output");
goto cleanup;
}
@@ -1640,4 +1807,6 @@ dri2_teardown_null(struct dri2_egl_display *dri2_dpy)
drmModeFreeProperty(dri2_dpy->output.connector_prop_res[i]);
free(dri2_dpy->output.connector_prop_res);
}
+
+ u_vector_finish(&dri2_dpy->output.modifiers);
}
--
2.25.1

View File

@@ -0,0 +1,203 @@
From 1e6466e541e1fc67198be3eeb090e3af22bd6d19 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 10 Feb 2020 09:23:03 +0000
Subject: [PATCH 43/67] egl: query the supported ES2 context version
For OpenGL ES contexts, the EGL specification states that querying
EGL_CONTEXT_CLIENT_VERSION with eglQueryContext may return a version
that differs from that specified at context creation time. For example,
if an OpenGL ES2 context is specified at context creation time, an
OpenGL ES3 context may be created, and so "3" should be returned
when EGL_CONTEXT_CLIENT_VERSION is queried.
A new EGL driver API function has been added,
QueryContextClientVersion, that is called when the context client
version is queried, allowing EGL drivers to override the default
value (i.e. the version specified at context creation time). If the
function returns zero, the default is used.
For DRI drivers, QueryContextClientVersion returns zero for all API
contexts other than OpenGL ES2. For OpenGL ES2, the supported context
client version is queried via the Query Renderer driver extension, using
integer query __DRI2_RENDERER_OPENGL_ES2_CONTEXT_CLIENT_VERSION_IMG. If
the query isn't supported, or the query returns zero, zero is returned
to the caller.
IMG NOTE: In order to avoid potential name and value clashes, "_IMG"
has been added to the end of the new query name, this should be removed
if an attempt is made to push this patch upstream. The value of the new
query should be adjusted to be the next one in sequence, rather than the
large value it currently has.
---
include/GL/internal/dri_interface.h | 2 ++
src/egl/drivers/dri2/egl_dri2.c | 21 +++++++++++++++++++++
src/egl/drivers/haiku/egl_haiku.cpp | 9 +++++++++
src/egl/main/eglapi.c | 2 +-
src/egl/main/eglcontext.c | 16 ++++++++++++++--
src/egl/main/eglcontext.h | 3 ++-
src/egl/main/egldriver.h | 1 +
7 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 6490f6e80e2..9c7bcac4cae 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -2052,6 +2052,8 @@ typedef struct __DRIDriverVtableExtensionRec {
#define __DRI2_RENDERER_HAS_PROTECTED_CONTENT 0x000e
+#define __DRI2_RENDERER_OPENGL_ES2_CONTEXT_CLIENT_VERSION_IMG 0x7001
+
typedef struct __DRI2rendererQueryExtensionRec __DRI2rendererQueryExtension;
struct __DRI2rendererQueryExtensionRec {
__DRIextension base;
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 6b26ff979ae..c4a49cae592 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -2055,6 +2055,26 @@ dri2_make_current(_EGLDisplay *disp, _EGLSurface *dsurf,
return EGL_TRUE;
}
+static EGLint
+dri2_query_context_client_version(_EGLDisplay *disp, _EGLContext *ctx)
+{
+ struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ switch (dri2_ctx->base.ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ switch (dri2_ctx->base.ClientMajorVersion) {
+ case 2:
+ return dri2_renderer_query_integer(dri2_dpy,
+ __DRI2_RENDERER_OPENGL_ES2_CONTEXT_CLIENT_VERSION_IMG);
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
__DRIdrawable *
dri2_surface_get_dri_drawable(_EGLSurface *surf)
{
@@ -4336,6 +4356,7 @@ const _EGLDriver _eglDriver = {
.CreateContext = dri2_create_context,
.DestroyContext = dri2_destroy_context,
.MakeCurrent = dri2_make_current,
+ .QueryContextClientVersion = dri2_query_context_client_version,
.CreateWindowSurface = dri2_create_window_surface,
.CreatePixmapSurface = dri2_create_pixmap_surface,
.CreatePbufferSurface = dri2_create_pbuffer_surface,
diff --git a/src/egl/drivers/haiku/egl_haiku.cpp b/src/egl/drivers/haiku/egl_haiku.cpp
index 18c73c9cd8b..2690a82eb75 100644
--- a/src/egl/drivers/haiku/egl_haiku.cpp
+++ b/src/egl/drivers/haiku/egl_haiku.cpp
@@ -297,6 +297,14 @@ haiku_make_current(_EGLDisplay *disp, _EGLSurface *dsurf,
}
+extern "C"
+EGLint
+haiku_dri2_query_context_client_version(_EGLDisplay *disp, _EGLContext *ctx)
+{
+ // Tell caller to use the default value.
+ return 0;
+}
+
extern "C"
EGLBoolean
haiku_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf)
@@ -316,6 +324,7 @@ const _EGLDriver _eglDriver = {
.CreateContext = haiku_create_context,
.DestroyContext = haiku_destroy_context,
.MakeCurrent = haiku_make_current,
+ .QueryContextClientVersion = haiku_dri2_query_context_client_version,
.CreateWindowSurface = haiku_create_window_surface,
.CreatePixmapSurface = haiku_create_pixmap_surface,
.CreatePbufferSurface = haiku_create_pbuffer_surface,
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 2d3931dfd26..1cbff9656e4 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -948,7 +948,7 @@ eglQueryContext(EGLDisplay dpy, EGLContext ctx,
_EGL_CHECK_CONTEXT(disp, context, EGL_FALSE);
- ret = _eglQueryContext(context, attribute, value);
+ ret = _eglQueryContext(disp, context, attribute, value);
RETURN_EGL_EVAL(disp, ret);
}
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 15de7c99496..7274d246194 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -35,6 +35,7 @@
#include "eglcontext.h"
#include "egldisplay.h"
#include "eglcurrent.h"
+#include "egldriver.h"
#include "eglsurface.h"
#include "egllog.h"
#include "util/macros.h"
@@ -670,8 +671,19 @@ _eglQueryContextRenderBuffer(_EGLContext *ctx)
}
+static EGLint
+_eglQueryContextClientVersion(_EGLDisplay *disp, _EGLContext *ctx)
+{
+ EGLint version;
+
+ version = disp->Driver->QueryContextClientVersion(disp, ctx);
+
+ return (version) ? version : ctx->ClientMajorVersion;
+}
+
EGLBoolean
-_eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)
+_eglQueryContext(_EGLDisplay *disp, _EGLContext *c,
+ EGLint attribute, EGLint *value)
{
if (!value)
return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
@@ -688,7 +700,7 @@ _eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)
*value = c->Config ? c->Config->ConfigID : 0;
break;
case EGL_CONTEXT_CLIENT_VERSION:
- *value = c->ClientMajorVersion;
+ *value = _eglQueryContextClientVersion(disp, c);
break;
case EGL_CONTEXT_CLIENT_TYPE:
*value = c->ClientAPI;
diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h
index 06029e81251..d890217852d 100644
--- a/src/egl/main/eglcontext.h
+++ b/src/egl/main/eglcontext.h
@@ -74,7 +74,8 @@ _eglInitContext(_EGLContext *ctx, _EGLDisplay *disp,
extern EGLBoolean
-_eglQueryContext(_EGLContext *ctx, EGLint attribute, EGLint *value);
+_eglQueryContext(_EGLDisplay *disp, _EGLContext *ctx,
+ EGLint attribute, EGLint *value);
extern EGLBoolean
diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h
index 12f9a0aab86..92af8bd16d5 100644
--- a/src/egl/main/egldriver.h
+++ b/src/egl/main/egldriver.h
@@ -97,6 +97,7 @@ struct _egl_driver
EGLBoolean (*MakeCurrent)(_EGLDisplay *disp,
_EGLSurface *draw, _EGLSurface *read,
_EGLContext *ctx);
+ EGLint (*QueryContextClientVersion)(_EGLDisplay *disp, _EGLContext *ctx);
/* surface funcs */
_EGLSurface *(*CreateWindowSurface)(_EGLDisplay *disp, _EGLConfig *config,
--
2.25.1

View File

@@ -0,0 +1,144 @@
From 64e6997ded5825f10125313ea15e3164bdad769b Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 11 Jun 2020 12:29:51 +0100
Subject: [PATCH 44/67] meson: allow libGL to be built without GLX
If Meson is run with option "glx" set to "null", build the
OpenGL library without GLX.
The "eglBindAPI workaround for dEQP bug" change to eglcurrent.h
(commit 2d46c91040aeb8ebad486214159c34417fbc87db) has been
modified to use a new EGL_WITH_OPENGL define, which indicates
whether OpneGL is present or not. This allows EGL to be used
with OpenGL on platforms other than X11.
---
meson.build | 8 ++++++--
meson_options.txt | 2 +-
src/egl/main/eglcurrent.h | 7 +++----
src/glx/meson.build | 20 ++++++++++++++++----
src/meson.build | 2 +-
5 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/meson.build b/meson.build
index 21d93d372c2..8db1699729a 100644
--- a/meson.build
+++ b/meson.build
@@ -485,6 +485,10 @@ if with_egl and not _platforms.contains(egl_native_platform)
error('-Degl-native-platform does not specify an enabled platform')
endif
+if with_egl and with_opengl and with_glx != 'disabled'
+ pre_args += '-DEGL_WITH_OPENGL'
+endif
+
# Android uses emutls for versions <= P/28. For USE_ELF_TLS we need ELF TLS.
use_elf_tls = false
if (not ['freebsd', 'openbsd', 'haiku'].contains(host_machine.system()) and
@@ -502,7 +506,7 @@ if (not ['freebsd', 'openbsd', 'haiku'].contains(host_machine.system()) and
endif
endif
-if with_glx != 'disabled'
+if with_glx != 'disabled' and with_glx != 'null'
if not (with_platform_x11 and with_any_opengl)
error('Cannot build GLX support without X11 platform support and at least one OpenGL API')
elif with_glx == 'gallium-xlib'
@@ -564,7 +568,7 @@ if with_any_vk and (with_platform_x11 and not with_dri3)
error('Vulkan drivers require dri3 for X11 support')
endif
if with_dri
- if with_glx == 'disabled' and not with_egl and not with_gbm
+ if (with_glx == 'disabled' or with_glx == 'null') and not with_egl and not with_gbm
error('building dri drivers require at least one windowing system')
endif
endif
diff --git a/meson_options.txt b/meson_options.txt
index d90a25f97ff..d36e714ea4c 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -290,7 +290,7 @@ option(
'glx',
type : 'combo',
value : 'auto',
- choices : ['auto', 'disabled', 'dri', 'xlib', 'gallium-xlib'],
+ choices : ['auto', 'disabled', 'dri', 'xlib', 'gallium-xlib', 'null'],
description : 'Build support for GLX platform'
)
option(
diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h
index 32570970947..dcc418afd6f 100644
--- a/src/egl/main/eglcurrent.h
+++ b/src/egl/main/eglcurrent.h
@@ -71,11 +71,10 @@ struct _egl_thread_info
static inline EGLBoolean
_eglIsApiValid(EGLenum api)
{
-#ifndef HAVE_X11_PLATFORM
- /* OpenGL is not a valid/supported API on Android */
- return api == EGL_OPENGL_ES_API;
-#else
+#ifdef EGL_WITH_OPENGL
return (api == EGL_OPENGL_ES_API || api == EGL_OPENGL_API);
+#else
+ return api == EGL_OPENGL_ES_API;
#endif
}
diff --git a/src/glx/meson.build b/src/glx/meson.build
index 8f642d5e14b..605a9717e37 100644
--- a/src/glx/meson.build
+++ b/src/glx/meson.build
@@ -122,7 +122,15 @@ else
)
endif
-libglx = static_library(
+gl_lib_cargs = [
+ '-D_REENTRANT',
+]
+
+if with_glx == 'null'
+ libglx_link = [libglapi]
+ libglx_link_whole = [libglapi_static]
+else
+ libglx = static_library(
'glx',
[files_libglx, glx_generated],
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_glapi, inc_loader],
@@ -138,13 +146,17 @@ libglx = static_library(
idep_mesautil, idep_xmlconfig,
dep_libdrm, dep_dri2proto, dep_glproto, dep_x11, dep_glvnd,
],
-)
+ )
+
+ libglx_link = [libglapi_static,libglapi]
+ libglx_link_whole = [libglx]
+endif
libgl = shared_library(
gl_lib_name,
[],
- link_with : [libglapi_static, libglapi],
- link_whole : libglx,
+ link_with : libglx_link,
+ link_whole : libglx_link_whole,
link_args : [ld_args_bsymbolic, ld_args_gc_sections, extra_ld_args_libgl],
dependencies : [
dep_libdrm, dep_dl, dep_m, dep_thread, dep_x11, dep_xcb_glx, dep_xcb,
diff --git a/src/meson.build b/src/meson.build
index c3bab27718d..f6eede56648 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -110,7 +110,7 @@ subdir('loader')
if with_platform_haiku
subdir('hgl')
endif
-if with_glx == 'dri'
+if with_glx == 'dri' or with_glx == 'null'
subdir('glx')
endif
if with_gbm
--
2.25.1

View File

@@ -0,0 +1,38 @@
From 394d340dda351452571ec8861d6768c52d338251 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 25 Aug 2020 14:12:32 +0100
Subject: [PATCH 45/67] egl/wayland: process non-resized window movement
The dx and dy parameters to the wl_egl_window_resize function were
not being processed unless the window width or height were being
changed.
---
src/egl/drivers/dri2/platform_wayland.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 72456d5d748..06272d4081e 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -266,6 +266,9 @@ resize_callback(struct wl_egl_window *wl_win, void *data)
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
+ dri2_surf->dx = wl_win->dx;
+ dri2_surf->dy = wl_win->dy;
+
if (dri2_surf->base.Width == wl_win->width &&
dri2_surf->base.Height == wl_win->height)
return;
@@ -786,8 +789,6 @@ update_buffers(struct dri2_egl_display *dri2_dpy,
dri2_surf->base.Width = dri2_surf->wl_win->width;
dri2_surf->base.Height = dri2_surf->wl_win->height;
- dri2_surf->dx = dri2_surf->wl_win->dx;
- dri2_surf->dy = dri2_surf->wl_win->dy;
}
if (dri2_surf->wl_win &&
--
2.25.1

View File

@@ -0,0 +1,539 @@
From ed4671544a6add01e87e94c04df59a600403dd21 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 10 Mar 2014 13:43:45 +0000
Subject: [PATCH 46/67] Separate EXT_framebuffer_object from ARB version
This patch separates the EXT_framebuffer_object entry points from the ARB
equivalents.
Probably not all this separation is necessary; it looks like only
BindRenderbuffer
BindFramebuffer
GetFramebufferAttachmentParameteriv
take advantage of the split.
Next time this patch is implemented, see if it can be trimmed down to
just the above functions, as it may be more upstreamable.
We may need to implement the EXT restrictions if we want to upstream.
---
src/mapi/glapi/gen/EXT_framebuffer_object.xml | 30 +++----
src/mapi/glapi/gen/static_data.py | 15 ++++
src/mesa/main/fbobject.c | 83 +++++++++++++++++++
src/mesa/main/fbobject.h | 54 ++++++++++++
src/mesa/main/genmipmap.c | 6 ++
src/mesa/main/genmipmap.h | 3 +
6 files changed, 176 insertions(+), 15 deletions(-)
diff --git a/src/mapi/glapi/gen/EXT_framebuffer_object.xml b/src/mapi/glapi/gen/EXT_framebuffer_object.xml
index 6c0e54af1c9..957b6a3a632 100644
--- a/src/mapi/glapi/gen/EXT_framebuffer_object.xml
+++ b/src/mapi/glapi/gen/EXT_framebuffer_object.xml
@@ -70,7 +70,7 @@
</enum>
<enum name="INVALID_FRAMEBUFFER_OPERATION_EXT" value="0x0506"/>
- <function name="IsRenderbufferEXT" alias="IsRenderbuffer">
+ <function name="IsRenderbufferEXT">
<param name="renderbuffer" type="GLuint"/>
<return type="GLboolean"/>
</function>
@@ -81,30 +81,30 @@
<glx rop="4316"/>
</function>
- <function name="DeleteRenderbuffersEXT" alias="DeleteRenderbuffers">
+ <function name="DeleteRenderbuffersEXT">
<param name="n" type="GLsizei"/>
<param name="renderbuffers" type="const GLuint *"/>
</function>
- <function name="GenRenderbuffersEXT" alias="GenRenderbuffers">
+ <function name="GenRenderbuffersEXT">
<param name="n" type="GLsizei"/>
<param name="renderbuffers" type="GLuint *"/>
</function>
- <function name="RenderbufferStorageEXT" alias="RenderbufferStorage">
+ <function name="RenderbufferStorageEXT">
<param name="target" type="GLenum"/>
<param name="internalformat" type="GLenum"/>
<param name="width" type="GLsizei"/>
<param name="height" type="GLsizei"/>
</function>
- <function name="GetRenderbufferParameterivEXT" alias="GetRenderbufferParameteriv">
+ <function name="GetRenderbufferParameterivEXT">
<param name="target" type="GLenum"/>
<param name="pname" type="GLenum"/>
<param name="params" type="GLint *"/>
</function>
- <function name="IsFramebufferEXT" alias="IsFramebuffer">
+ <function name="IsFramebufferEXT">
<param name="framebuffer" type="GLuint"/>
<return type="GLboolean"/>
</function>
@@ -115,22 +115,22 @@
<glx rop="4319"/>
</function>
- <function name="DeleteFramebuffersEXT" alias="DeleteFramebuffers">
+ <function name="DeleteFramebuffersEXT">
<param name="n" type="GLsizei"/>
<param name="framebuffers" type="const GLuint *"/>
</function>
- <function name="GenFramebuffersEXT" alias="GenFramebuffers">
+ <function name="GenFramebuffersEXT">
<param name="n" type="GLsizei"/>
<param name="framebuffers" type="GLuint *"/>
</function>
- <function name="CheckFramebufferStatusEXT" alias="CheckFramebufferStatus">
+ <function name="CheckFramebufferStatusEXT">
<param name="target" type="GLenum"/>
<return type="GLenum"/>
</function>
- <function name="FramebufferTexture1DEXT" alias="FramebufferTexture1D">
+ <function name="FramebufferTexture1DEXT">
<param name="target" type="GLenum"/>
<param name="attachment" type="GLenum"/>
<param name="textarget" type="GLenum"/>
@@ -138,7 +138,7 @@
<param name="level" type="GLint"/>
</function>
- <function name="FramebufferTexture2DEXT" alias="FramebufferTexture2D">
+ <function name="FramebufferTexture2DEXT">
<param name="target" type="GLenum"/>
<param name="attachment" type="GLenum"/>
<param name="textarget" type="GLenum"/>
@@ -146,7 +146,7 @@
<param name="level" type="GLint"/>
</function>
- <function name="FramebufferTexture3DEXT" alias="FramebufferTexture3D">
+ <function name="FramebufferTexture3DEXT">
<param name="target" type="GLenum"/>
<param name="attachment" type="GLenum"/>
<param name="textarget" type="GLenum"/>
@@ -155,21 +155,21 @@
<param name="zoffset" type="GLint"/>
</function>
- <function name="FramebufferRenderbufferEXT" alias="FramebufferRenderbuffer">
+ <function name="FramebufferRenderbufferEXT">
<param name="target" type="GLenum"/>
<param name="attachment" type="GLenum"/>
<param name="renderbuffertarget" type="GLenum"/>
<param name="renderbuffer" type="GLuint"/>
</function>
- <function name="GetFramebufferAttachmentParameterivEXT" alias="GetFramebufferAttachmentParameteriv">
+ <function name="GetFramebufferAttachmentParameterivEXT">
<param name="target" type="GLenum"/>
<param name="attachment" type="GLenum"/>
<param name="pname" type="GLenum"/>
<param name="params" type="GLint *"/>
</function>
- <function name="GenerateMipmapEXT" alias="GenerateMipmap">
+ <function name="GenerateMipmapEXT">
<param name="target" type="GLenum"/>
</function>
</category>
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index e231c176264..974f366d7b4 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1706,6 +1706,21 @@ offsets = {
"FramebufferTextureMultisampleMultiviewOVR" : 1670,
"MultiDrawArraysIndirectEXT" : 1671,
"MultiDrawElementsIndirectEXT" : 1672,
+ "IsRenderbufferEXT" : 1673,
+ "DeleteRenderbuffersEXT" : 1674,
+ "GenRenderbuffersEXT" : 1675,
+ "RenderbufferStorageEXT" : 1676,
+ "GetRenderbufferParameterivEXT" : 1677,
+ "IsFramebufferEXT" : 1678,
+ "DeleteFramebuffersEXT" : 1679,
+ "GenFramebuffersEXT" : 1680,
+ "CheckFramebufferStatusEXT" : 1681,
+ "FramebufferTexture1DEXT" : 1682,
+ "FramebufferTexture2DEXT" : 1683,
+ "FramebufferTexture3DEXT" : 1684,
+ "FramebufferRenderbufferEXT" : 1685,
+ "GetFramebufferAttachmentParameterivEXT" : 1686,
+ "GenerateMipmapEXT" : 1687,
}
functions = [
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 49893165250..885aa442911 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -1995,6 +1995,11 @@ _mesa_detach_renderbuffer(struct gl_context *ctx,
return progress;
}
+GLboolean GLAPIENTRY
+_mesa_IsRenderbufferEXT(GLuint renderbuffer)
+{
+ return _mesa_IsRenderbuffer(renderbuffer);
+}
void GLAPIENTRY
_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
@@ -2722,6 +2727,12 @@ renderbuffer_storage_target(GLenum target, GLenum internalFormat,
}
+void GLAPIENTRY
+_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
+{
+ _mesa_DeleteRenderbuffers(n, renderbuffers);
+}
+
void GLAPIENTRY
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
{
@@ -2752,6 +2763,11 @@ _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
}
+void GLAPIENTRY
+_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
+{
+ _mesa_GenRenderbuffers(n, renderbuffers);
+}
/**
* Helper function for _mesa_GetRenderbufferParameteriv() and
@@ -2784,6 +2800,12 @@ _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
NO_SAMPLES, 0, "glRenderbufferStorage");
}
+void GLAPIENTRY
+_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ _mesa_RenderbufferStorage(target, internalFormat, width, height);
+}
void GLAPIENTRY
_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
@@ -2985,6 +3007,11 @@ _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
"glGetNamedRenderbufferParameteriv");
}
+void GLAPIENTRY
+_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
+{
+ _mesa_GetRenderbufferParameteriv(target, pname, params);
+}
void GLAPIENTRY
_mesa_GetNamedRenderbufferParameterivEXT(GLuint renderbuffer, GLenum pname,
@@ -3018,6 +3045,11 @@ _mesa_IsFramebuffer(GLuint framebuffer)
return GL_FALSE;
}
+GLboolean GLAPIENTRY
+_mesa_IsFramebufferEXT(GLuint framebuffer)
+{
+ return _mesa_IsFramebuffer(framebuffer);
+}
/**
* Check if any of the attachments of the given framebuffer are textures
@@ -3253,6 +3285,11 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
}
}
+void GLAPIENTRY
+_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
+{
+ _mesa_DeleteFramebuffers(n, framebuffers);
+}
/**
* This is the implementation for glGenFramebuffers and glCreateFramebuffers.
@@ -3299,6 +3336,11 @@ create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
_mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
}
+void GLAPIENTRY
+_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
+{
+ _mesa_GenFramebuffers(n, framebuffers);
+}
void GLAPIENTRY
_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
@@ -3338,6 +3380,11 @@ _mesa_check_framebuffer_status(struct gl_context *ctx,
return buffer->_Status;
}
+GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatusEXT(GLenum target)
+{
+ return _mesa_CheckFramebufferStatus(target);
+}
GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus_no_error(GLenum target)
@@ -3950,6 +3997,12 @@ _mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
texture, level, 0);
}
+void GLAPIENTRY
+_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ _mesa_FramebufferTexture1D(target, attachment, textarget, texture, level);
+}
void GLAPIENTRY
_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
@@ -3990,6 +4043,12 @@ _mesa_FramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment,
false);
}
+void GLAPIENTRY
+_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ _mesa_FramebufferTexture2D(target, attachment, textarget, texture, level);
+}
void GLAPIENTRY
_mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
@@ -4100,6 +4159,15 @@ frame_buffer_texture(GLuint framebuffer, GLenum target,
level, 0, layer, layered);
}
+void GLAPIENTRY
+_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset)
+{
+ _mesa_FramebufferTexture3D(target, attachment, textarget, texture,
+ level, zoffset);
+}
+
void GLAPIENTRY
_mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
GLuint texture, GLint level,
@@ -4353,6 +4421,15 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
renderbuffer, "glFramebufferRenderbuffer");
}
+void GLAPIENTRY
+_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
+ GLenum renderbufferTarget,
+ GLuint renderbuffer)
+{
+ _mesa_FramebufferRenderbuffer(target, attachment, renderbufferTarget,
+ renderbuffer);
+}
+
void GLAPIENTRY
_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
GLenum attachment,
@@ -4754,6 +4831,12 @@ invalid_pname_enum:
return;
}
+void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ _mesa_GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+}
void GLAPIENTRY
_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h
index 2a32c158e68..98271d76f50 100644
--- a/src/mesa/main/fbobject.h
+++ b/src/mesa/main/fbobject.h
@@ -145,6 +145,9 @@ _mesa_bind_framebuffers(struct gl_context *ctx,
extern GLboolean GLAPIENTRY
_mesa_IsRenderbuffer(GLuint renderbuffer);
+extern GLboolean GLAPIENTRY
+_mesa_IsRenderbufferEXT(GLuint renderbuffer);
+
extern void GLAPIENTRY
_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer);
@@ -157,12 +160,18 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers);
void GLAPIENTRY
_mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers);
+extern void GLAPIENTRY
+_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers);
+
extern void GLAPIENTRY
_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers);
void GLAPIENTRY
_mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers);
+extern void GLAPIENTRY
+_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers);
+
extern void GLAPIENTRY
_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers);
@@ -170,6 +179,10 @@ extern void GLAPIENTRY
_mesa_RenderbufferStorage(GLenum target, GLenum internalformat,
GLsizei width, GLsizei height);
+extern void GLAPIENTRY
+_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalformat,
+ GLsizei width, GLsizei height);
+
extern void GLAPIENTRY
_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalformat,
@@ -213,6 +226,10 @@ extern void GLAPIENTRY
_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname,
GLint *params);
+extern void GLAPIENTRY
+_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname,
+ GLint *params);
+
void GLAPIENTRY
_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
GLint *params);
@@ -220,6 +237,9 @@ _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
extern GLboolean GLAPIENTRY
_mesa_IsFramebuffer(GLuint framebuffer);
+extern GLboolean GLAPIENTRY
+_mesa_IsFramebufferEXT(GLuint framebuffer);
+
extern void GLAPIENTRY
_mesa_BindFramebuffer(GLenum target, GLuint framebuffer);
@@ -229,9 +249,15 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer);
extern void GLAPIENTRY
_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
+extern void GLAPIENTRY
+_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers);
+
extern void GLAPIENTRY
_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers);
+extern void GLAPIENTRY
+_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers);
+
extern void GLAPIENTRY
_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers);
@@ -241,6 +267,9 @@ _mesa_CheckFramebufferStatus_no_error(GLenum target);
extern GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus(GLenum target);
+extern GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatusEXT(GLenum target);
+
extern GLenum GLAPIENTRY
_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target);
@@ -259,6 +288,11 @@ extern void GLAPIENTRY
_mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level);
+
+extern void GLAPIENTRY
+_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level);
+
extern void GLAPIENTRY
_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level);
@@ -272,6 +306,11 @@ extern void GLAPIENTRY
_mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level, GLint layer);
+
+extern void GLAPIENTRY
+_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level);
+
extern void GLAPIENTRY
_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
@@ -281,6 +320,12 @@ extern void GLAPIENTRY
_mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
GLuint texture, GLint level,
GLint layer);
+
+extern void GLAPIENTRY
+_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset);
+
extern void GLAPIENTRY
_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
GLuint texture, GLint level, GLint layer);
@@ -342,6 +387,11 @@ _mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
GLenum renderbuffertarget,
GLuint renderbuffer);
+extern void GLAPIENTRY
+_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
extern void GLAPIENTRY
_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
GLenum renderbuffertarget,
@@ -390,6 +440,10 @@ _mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
const GLenum *attachments, GLint x,
GLint y, GLsizei width, GLsizei height);
+extern void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params);
+
extern void GLAPIENTRY
_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
diff --git a/src/mesa/main/genmipmap.c b/src/mesa/main/genmipmap.c
index 36727bb7060..8d262e53852 100644
--- a/src/mesa/main/genmipmap.c
+++ b/src/mesa/main/genmipmap.c
@@ -267,3 +267,9 @@ _mesa_GenerateMultiTexMipmapEXT(GLenum texunit, GLenum target)
validate_params_and_generate_mipmap(texObj,
"glGenerateMultiTexMipmapEXT");
}
+
+void GLAPIENTRY
+_mesa_GenerateMipmapEXT(GLenum target)
+{
+ _mesa_GenerateMipmap(target);
+}
diff --git a/src/mesa/main/genmipmap.h b/src/mesa/main/genmipmap.h
index c661f2184c7..ff3b45a4417 100644
--- a/src/mesa/main/genmipmap.h
+++ b/src/mesa/main/genmipmap.h
@@ -44,6 +44,9 @@ _mesa_GenerateMipmap(GLenum target);
void GLAPIENTRY
_mesa_GenerateTextureMipmap_no_error(GLuint texture);
+extern void GLAPIENTRY
+_mesa_GenerateMipmapEXT(GLenum target);
+
extern void GLAPIENTRY
_mesa_GenerateTextureMipmap(GLuint texture);
--
2.25.1

View File

@@ -0,0 +1,321 @@
From f775167cbe3f324468f8f355be13bd6efa7d4567 Mon Sep 17 00:00:00 2001
From: Luigi Santivetti <luigi.santivetti@imgtec.com>
Date: Mon, 21 Oct 2019 09:21:52 +0100
Subject: [PATCH 47/67] egl/null: add support for async flip with front buffer
rendering
This change enables the application to render into the buffer being
scanned out if the display driver doesn't support
DRM_CAP_ASYNC_PAGE_FLIP.
The egl display now tracks the DRM async flip capabilities, allowing
platform_null to always return the buffer on screen to the application
when the swap interval is set to 0, but the DRM driver doesn't support
async flip.
platform_null can be in several alternative states by the time
eglSwapInterval() is called, following is a summary of them.
1. platform_null was initialised and it has already flipped. In this
case, return to the client API a reference to the buffer on screen
2. platform_null was initialised but no back buffer was requested yet
from the client API. In this case, return a reference to the front
buffer
3. platform_null was initialised and the client API has already got
a back buffer, but no flip was scheduled. In this case, make sure
to flip and return the buffer on the screen
Note that this change also refactors the color buffers and front
buffer code. Platform null after this change has a dedicated struct
for storing front buffer DRI data and framebuffer id.
Also be noted that min_swap_interval is no longer clamped to 1 when
DRM_CAP_ASYNC_PAGE_FLIP isn't supported. This is because,
if min_swap_interval is automatically promoted to 1, Mesa EGL will de
facto prevent the application from requesting any swap interval less
than 1.
Change-Id: I3930cfcdb30bfb5358166911bcf84a78bdb4548d
Signed-off-by: Luigi Santivetti <luigi.santivetti@imgtec.com>
---
src/egl/drivers/dri2/egl_dri2.h | 8 +-
src/egl/drivers/dri2/platform_null.c | 153 +++++++++++++++++++++------
2 files changed, 129 insertions(+), 32 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 0f683d76e18..13b808bff80 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -282,6 +282,7 @@ struct dri2_egl_display
#ifdef HAVE_NULL_PLATFORM
bool atomic_enabled;
bool in_formats_enabled;
+ bool async_flip_enabled;
struct display_output output;
#endif
@@ -442,8 +443,12 @@ struct dri2_egl_surface
#endif
bool locked;
int age;
+#ifdef HAVE_NULL_PLATFORM
+ } color_buffers[DRI2_SURFACE_NUM_COLOR_BUFFERS], *back, *current, front_buffer;
+#else
} color_buffers[DRI2_SURFACE_NUM_COLOR_BUFFERS], *back, *current;
#endif
+#endif
#ifdef HAVE_ANDROID_PLATFORM
struct ANativeWindow *window;
@@ -472,12 +477,13 @@ struct dri2_egl_surface
#endif
#ifdef HAVE_NULL_PLATFORM
- uint32_t front_fb_id;
struct swap_queue_elem swap_queue[DRI2_SURFACE_NUM_COLOR_BUFFERS];
struct swap_queue_elem *swap_data;
int swap_state;
bool mutex_init;
bool cond_init;
+ bool front_render_enabled;
+ bool front_render_init;
bool cond_init_unlock_buffer;
#endif
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index 48a586b6f38..33cf576f147 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -601,6 +601,15 @@ swap_dequeue_data_finish(struct dri2_egl_surface *dri2_surf)
pthread_mutex_unlock(&dri2_surf->mutex);
}
+static void
+swap_drain_queue_data(struct dri2_egl_surface *dri2_surf)
+{
+ pthread_mutex_lock(&dri2_surf->mutex);
+ while (dri2_surf->swap_queue_idx_head != dri2_surf->swap_queue_idx_tail)
+ pthread_cond_wait(&dri2_surf->swap_unlock_buffer_cond, &dri2_surf->mutex);
+ pthread_mutex_unlock(&dri2_surf->mutex);
+}
+
static void
flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
unsigned int tv_usec, void *flip_data)
@@ -1118,15 +1127,15 @@ get_front_bo(struct dri2_egl_surface *dri2_surf)
if (dri2_surf->base.Type == EGL_WINDOW_BIT)
use |= __DRI_IMAGE_USE_SCANOUT;
- dri2_surf->front = create_image(dri2_surf, use);
- if (!dri2_surf->front)
+ dri2_surf->front_buffer.dri_image = create_image(dri2_surf, use);
+ if (!dri2_surf->front_buffer.dri_image)
return false;
if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
- if (!add_fb_for_dri_image(dri2_dpy, dri2_surf->front,
- &dri2_surf->front_fb_id)) {
- dri2_dpy->image->destroyImage(dri2_surf->front);
- dri2_surf->front = NULL;
+ if (!add_fb_for_dri_image(dri2_dpy, dri2_surf->front_buffer.dri_image,
+ &dri2_surf->front_buffer.fb_id)) {
+ dri2_dpy->image->destroyImage(dri2_surf->front_buffer.dri_image);
+ dri2_surf->front_buffer.dri_image = NULL;
return false;
}
}
@@ -1330,7 +1339,7 @@ dri2_null_create_window_surface(_EGLDisplay *disp, _EGLConfig *config,
}
err = display_output_modeset(dri2_dpy->fd, &dri2_dpy->output,
- dri2_surf->front_fb_id);
+ dri2_surf->front_buffer.fb_id);
if (err) {
_eglError(EGL_BAD_NATIVE_WINDOW, "window set mode");
goto err_destroy_surface;
@@ -1360,6 +1369,60 @@ dri2_null_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *config,
return create_surface(disp, config, EGL_PBUFFER_BIT, attrib_list);
}
+static void
+dri2_null_init_front_buffer_render(_EGLSurface *draw)
+{
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+
+ dri2_surf->front_render_init = true;
+
+ /* Drain the queue. swap_buffer_unlock_cond signals for the last time
+ * when the last back buffer in the queue went on screen and it's being
+ * tracked as current by then.
+ */
+ swap_drain_queue_data(dri2_surf);
+
+ /* If previously flipped, take a reference to the current buffer */
+ if (dri2_surf->current) {
+ assert(dri2_surf->current->dri_image);
+ dri2_surf->back = dri2_surf->current;
+
+ for (unsigned i = 0; i < DRI2_SURFACE_NUM_COLOR_BUFFERS; i++)
+ dri2_surf->color_buffers[i].age = 0;
+
+ return;
+ }
+
+ /* If the application hasn't yet fetched a back buffer, then it's not too
+ * late to use front buffer's dri_image and fb_id.
+ */
+ if (!dri2_surf->back) {
+ assert(dri2_surf->front_buffer.dri_image);
+ dri2_surf->back = &dri2_surf->front_buffer;
+
+ /* Don't need to reset buffer age since no flip was requested yet */
+
+ return;
+ }
+
+ /* In order to initialise one color buffer for front buffer rendering,
+ * one page flip must occur.
+ */
+ swap_enqueue_data(dri2_surf, get_back_buffer_id(dri2_surf), 1);
+
+ return dri2_null_init_front_buffer_render(draw);
+}
+
+static void
+dri2_null_disable_front_buffer_render(_EGLSurface *draw)
+{
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+
+ dri2_surf->front_render_enabled = false;
+ dri2_surf->front_render_init = false;
+ dri2_surf->back = NULL;
+}
+
static EGLBoolean
dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
{
@@ -1371,14 +1434,7 @@ dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
* sure we process the flip event.
*/
if (dri2_surf->swap_queue_processor) {
- pthread_mutex_lock(&dri2_surf->mutex);
-
- /* Wait for any outstanding swaps to complete */
- while (dri2_surf->swap_queue_idx_head != dri2_surf->swap_queue_idx_tail)
- pthread_cond_wait(&dri2_surf->swap_unlock_buffer_cond,
- &dri2_surf->mutex);
-
- pthread_mutex_unlock(&dri2_surf->mutex);
+ swap_drain_queue_data(dri2_surf);
pthread_cancel(dri2_surf->swap_queue_processor);
pthread_join(dri2_surf->swap_queue_processor, NULL);
}
@@ -1392,11 +1448,11 @@ dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
if (dri2_surf->mutex_init)
pthread_mutex_destroy(&dri2_surf->mutex);
- if (dri2_surf->front)
- dri2_dpy->image->destroyImage(dri2_surf->front);
+ if (dri2_surf->front_buffer.dri_image)
+ dri2_dpy->image->destroyImage(dri2_surf->front_buffer.dri_image);
- if (dri2_surf->front_fb_id)
- drmModeRmFB(dri2_dpy->fd, dri2_surf->front_fb_id);
+ if (dri2_surf->front_buffer.fb_id)
+ drmModeRmFB(dri2_dpy->fd, dri2_surf->front_buffer.fb_id);
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
if (dri2_surf->color_buffers[i].fb_id)
@@ -1423,6 +1479,16 @@ dri2_null_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
if (dri2_surf->base.Type != EGL_WINDOW_BIT)
return EGL_TRUE;
+ /* Flush and early return, no swap takes place */
+ if (dri2_surf->front_render_enabled) {
+ dri2_flush_drawable_for_swapbuffers(disp, draw);
+
+ if (!dri2_surf->front_render_init)
+ dri2_null_init_front_buffer_render(draw);
+
+ return EGL_TRUE;
+ }
+
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
if (dri2_surf->color_buffers[i].age > 0)
dri2_surf->color_buffers[i].age++;
@@ -1465,6 +1531,22 @@ dri2_null_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
static EGLBoolean
dri2_null_swap_interval(_EGLDisplay *dpy, _EGLSurface *draw, EGLint interval)
{
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+
+ /* dri2_dpy tracks whether the display driver is async flip capable.
+ * If it isn't, enable front buffer rendering when swap interval
+ * 0 is passed in from the application.
+ */
+ if (!interval && !dri2_dpy->async_flip_enabled) {
+ if (!dri2_surf->front_render_enabled)
+ dri2_surf->front_render_enabled = true;
+ } else {
+ if (dri2_surf->front_render_enabled)
+ dri2_null_disable_front_buffer_render(draw);
+ }
+
_eglLog(_EGL_DEBUG, "DRI2: set swap interval to %d", interval);
draw->SwapInterval = interval;
return EGL_TRUE;
@@ -1502,7 +1584,7 @@ dri2_null_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format,
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
- buffers->front = dri2_surf->front;
+ buffers->front = dri2_surf->front_buffer.dri_image;
}
if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
@@ -1640,18 +1722,27 @@ dri2_null_setup_swap_interval(_EGLDisplay *disp)
dri2_setup_swap_interval(disp, swap_max_interval);
err = drmGetCap(dri2_dpy->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
- if (err || value == 0)
- dri2_dpy->min_swap_interval = 1;
+ if (err || value == 0) {
- /**
- * drm/atomic: Reject FLIP_ASYNC unconditionally
- * upstream f2cbda2dba11de868759cae9c0d2bab5b8411406
- *
- * Only allow swap interval 0 for legacy DRM/KMS and let
- * the app be aware that swap interval is clamped to 1.
- */
- if (dri2_dpy->atomic_enabled)
- dri2_dpy->min_swap_interval = 1;
+ /* DRM/KMS does not support async page flip. In order to support
+ * swap interval 0, use front buffer rendering.
+ */
+ _eglLog(_EGL_DEBUG,
+ "drm async flip not supported, use front buffer");
+ } else {
+
+ /* drm/atomic: Reject FLIP_ASYNC unconditionally
+ * upstream f2cbda2dba11de868759cae9c0d2bab5b8411406
+ *
+ * Legacy DRM/KMS can use DRM_MODE_PAGE_FLIP_ASYNC, for atomic
+ * drivers fallback to front buffer rendering.
+ */
+ if (dri2_dpy->atomic_enabled)
+ _eglLog(_EGL_DEBUG,
+ "async flip not supported by atomic, use front buffer");
+ else
+ dri2_dpy->async_flip_enabled = true;
+ }
}
EGLBoolean
--
2.25.1

View File

@@ -0,0 +1,229 @@
From 4d19dc5cc9be4f3f25ed8befbfcda70c047065d3 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Fri, 21 Aug 2020 12:13:28 +0100
Subject: [PATCH 48/67] gbm: add pbuffer support
The EGL backend GLX provider for XWayland may get the EGL configs it
uses to generate the GLX ones from GBM. That platform doesn't support
pbuffers. When the client tries to match GLX configs with the DRI ones,
a mismatch in the pbuffer attributes will result in the GLX config
being rejected.
Although support for creating pbuffers has been added, this isn't
required when using the EGL backend GLX provider, as indirect GLX
isn't supported.
---
src/egl/drivers/dri2/egl_dri2.h | 3 +
src/egl/drivers/dri2/platform_drm.c | 110 +++++++++++++++++++++++++---
2 files changed, 103 insertions(+), 10 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 13b808bff80..141df1b1732 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -471,6 +471,9 @@ struct dri2_egl_surface
/* surfaceless and device */
__DRIimage *front;
unsigned int visual;
+#ifdef HAVE_DRM_PLATFORM
+ struct gbm_bo *front_bo;
+#endif
#ifdef HAVE_WAYLAND_PLATFORM
void *swrast_front;
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 2b329437f88..258e8b6593e 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -41,6 +41,38 @@
#include "egl_dri2.h"
#include "loader.h"
+static bool
+dri2_drm_alloc_front_image(struct dri2_egl_surface *dri2_surf)
+{
+ if (!dri2_surf->front_bo) {
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+
+ struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
+
+ dri2_surf->front_bo = gbm_bo_create(&dri2_dpy->gbm_dri->base,
+ surf->base.v0.width,
+ surf->base.v0.height,
+ surf->base.v0.format,
+ surf->base.v0.flags);
+ if (!dri2_surf->front_bo) {
+ _eglError(EGL_BAD_ALLOC, "failed to allocate front buffer");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void
+dri2_drm_free_front_image(struct dri2_egl_surface *dri2_surf)
+{
+ if (dri2_surf->front_bo) {
+ gbm_bo_destroy(dri2_surf->front_bo);
+ dri2_surf->front_bo = NULL;
+ }
+}
+
static struct gbm_bo *
lock_front_buffer(struct gbm_surface *_surf)
{
@@ -138,8 +170,8 @@ dri2_drm_config_is_compatible(struct dri2_egl_display *dri2_dpy,
}
static _EGLSurface *
-dri2_drm_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
- void *native_surface, const EGLint *attrib_list)
+dri2_drm_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
+ void *native_surface, const EGLint *attrib_list)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
@@ -154,11 +186,25 @@ dri2_drm_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
return NULL;
}
- if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf,
+ if (!dri2_init_surface(&dri2_surf->base, disp, type, conf,
attrib_list, false, native_surface))
goto cleanup_surf;
- config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
+ if (type == EGL_PBUFFER_BIT) {
+ struct gbm_device *gbm = disp->PlatformDisplay;
+ _EGLSurface *surf = &dri2_surf->base;
+
+ assert(!surface);
+
+ surface = gbm_surface_create(gbm, surf->Width, surf->Height,
+ conf->NativeVisualID, GBM_BO_USE_RENDERING);
+ if (!surface) {
+ _eglError(EGL_BAD_ALLOC, "Failed to allocate pbuffer GBM surface");
+ goto cleanup_surf;
+ }
+ }
+
+ config = dri2_get_dri_config(dri2_conf, type,
dri2_surf->base.GLColorspace);
if (!config) {
@@ -183,11 +229,22 @@ dri2_drm_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
return &dri2_surf->base;
cleanup_surf:
+ if (type == EGL_PBUFFER_BIT && surface != NULL)
+ gbm_surface_destroy(surface);
+
free(dri2_surf);
return NULL;
}
+static _EGLSurface *
+dri2_drm_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
+ void *native_surface, const EGLint *attrib_list)
+{
+ return dri2_drm_create_surface(disp, EGL_WINDOW_BIT, conf,
+ native_surface, attrib_list);
+}
+
static _EGLSurface *
dri2_drm_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
void *native_window, const EGLint *attrib_list)
@@ -202,6 +259,14 @@ dri2_drm_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
return NULL;
}
+static _EGLSurface *
+dri2_drm_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
+ const EGLint *attrib_list)
+{
+ return dri2_drm_create_surface(disp, EGL_PBUFFER_BIT, conf,
+ NULL, attrib_list);
+}
+
static EGLBoolean
dri2_drm_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
{
@@ -217,6 +282,11 @@ dri2_drm_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
dri2_egl_surface_free_local_buffers(dri2_surf);
+ dri2_drm_free_front_image(dri2_surf);
+
+ if (surf->Type == EGL_PBUFFER_BIT)
+ gbm_surface_destroy(&dri2_surf->gbm_surf->base);
+
dri2_fini_surface(surf);
free(surf);
@@ -402,12 +472,27 @@ dri2_drm_image_get_buffers(__DRIdrawable *driDrawable,
struct dri2_egl_surface *dri2_surf = loaderPrivate;
struct gbm_dri_bo *bo;
- if (get_back_bo(dri2_surf) < 0)
- return 0;
+ buffers->image_mask = 0;
+ buffers->front = NULL;
+ buffers->back = NULL;
- bo = gbm_dri_bo(dri2_surf->back->bo);
- buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
- buffers->back = bo->image;
+ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
+ if (!dri2_drm_alloc_front_image(dri2_surf))
+ return 0;
+
+ bo = gbm_dri_bo(dri2_surf->front_bo);
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
+ buffers->front = bo->image;
+ }
+
+ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
+ if (get_back_bo(dri2_surf) < 0)
+ return 0;
+
+ bo = gbm_dri_bo(dri2_surf->back->bo);
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
+ buffers->back = bo->image;
+ }
return 1;
}
@@ -425,6 +510,9 @@ dri2_drm_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+ if (dri2_surf->base.Type != EGL_WINDOW_BIT)
+ return EGL_TRUE;
+
if (!dri2_dpy->flush) {
dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
return EGL_TRUE;
@@ -648,7 +736,8 @@ drm_add_configs_for_visuals(_EGLDisplay *disp)
};
dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
- config_count + 1, EGL_WINDOW_BIT, attr_list, NULL, NULL);
+ config_count + 1, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ attr_list, NULL, NULL);
if (dri2_conf) {
if (dri2_conf->base.ConfigID == config_count + 1)
config_count++;
@@ -672,6 +761,7 @@ static const struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
.authenticate = dri2_drm_authenticate,
.create_window_surface = dri2_drm_create_window_surface,
.create_pixmap_surface = dri2_drm_create_pixmap_surface,
+ .create_pbuffer_surface = dri2_drm_create_pbuffer_surface,
.destroy_surface = dri2_drm_destroy_surface,
.create_image = dri2_drm_create_image_khr,
.swap_buffers = dri2_drm_swap_buffers,
--
2.25.1

View File

@@ -0,0 +1,347 @@
From b0ea3289c16d31d840af71876187cf30b2b32e9a Mon Sep 17 00:00:00 2001
From: Luigi Santivetti <luigi.santivetti@imgtec.com>
Date: Thu, 2 Sep 2021 22:47:54 +0100
Subject: [PATCH 49/68] egl/null: expose EXT_yuv_surface support
---
include/GL/internal/dri_interface.h | 2 +
src/egl/drivers/dri2/platform_null.c | 177 ++++++++++++++++++++++++---
src/mesa/drivers/dri/pvr/pvrutil.c | 8 ++
3 files changed, 173 insertions(+), 14 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 9c7bcac4cae..888a117d56e 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1411,6 +1411,8 @@ struct __DRIdri2ExtensionRec {
#define __DRI_IMAGE_FORMAT_ARGB4444 0x1018
#define __DRI_IMAGE_FORMAT_YVU444_PACK10_IMG 0x1019
#define __DRI_IMAGE_FORMAT_BGR888 0x101a
+#define __DRI_IMAGE_FORMAT_NV12 0x101b
+#define __DRI_IMAGE_FORMAT_NV21 0x101c
#define __DRI_IMAGE_USE_SHARE 0x0001
#define __DRI_IMAGE_USE_SCANOUT 0x0002
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index f2c481c256b..d1e576af5ce 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -79,6 +79,35 @@ uint32_t get_back_buffer_id(struct dri2_egl_surface *dri2_surf)
.prop_value = value, \
}
+static const struct dri2_null_yuv_attrib {
+ uint32_t order;
+ uint32_t subsample;
+ uint32_t num_planes;
+ uint32_t plane_bpp;
+} dri2_null_yuv_attribs[] = {
+ {
+ /* __DRI_IMAGE_FORMAT_YUYV */
+ .order = __DRI_ATTRIB_YUV_ORDER_YUYV_BIT,
+ .subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_2_BIT,
+ .num_planes = 1,
+ .plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT,
+ },
+ {
+ /* __DRI_IMAGE_FORMAT_NV12 */
+ .order = __DRI_ATTRIB_YUV_ORDER_YUV_BIT,
+ .subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT,
+ .num_planes = 2,
+ .plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT,
+ },
+ {
+ /* __DRI_IMAGE_FORMAT_NV21 */
+ .order = __DRI_ATTRIB_YUV_ORDER_YVU_BIT,
+ .subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT,
+ .num_planes = 2,
+ .plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT,
+ },
+};
+
/*
* The index of entries in this table is used as a bitmask in
* dri2_dpy->formats, which tracks the formats supported by the display.
@@ -88,24 +117,49 @@ static const struct dri2_null_format {
int dri_image_format;
int rgba_shifts[4];
unsigned int rgba_sizes[4];
+ const struct dri2_null_yuv_attrib *yuv;
} dri2_null_formats[] = {
{
.drm_format = DRM_FORMAT_XRGB8888,
.dri_image_format = __DRI_IMAGE_FORMAT_XRGB8888,
.rgba_shifts = { 16, 8, 0, -1 },
.rgba_sizes = { 8, 8, 8, 0 },
+ .yuv = NULL,
},
{
.drm_format = DRM_FORMAT_ARGB8888,
.dri_image_format = __DRI_IMAGE_FORMAT_ARGB8888,
.rgba_shifts = { 16, 8, 0, 24 },
.rgba_sizes = { 8, 8, 8, 8 },
+ .yuv = NULL,
},
{
.drm_format = DRM_FORMAT_RGB565,
.dri_image_format = __DRI_IMAGE_FORMAT_RGB565,
.rgba_shifts = { 11, 5, 0, -1 },
.rgba_sizes = { 5, 6, 5, 0 },
+ .yuv = NULL,
+ },
+ {
+ .drm_format = DRM_FORMAT_YUYV,
+ .dri_image_format = __DRI_IMAGE_FORMAT_YUYV,
+ .rgba_shifts = { -1, -1, -1, -1 },
+ .rgba_sizes = { 0, 0, 0, 0 },
+ .yuv = &dri2_null_yuv_attribs[0],
+ },
+ {
+ .drm_format = DRM_FORMAT_NV12,
+ .dri_image_format = __DRI_IMAGE_FORMAT_NV12,
+ .rgba_shifts = { -1, -1, -1, -1 },
+ .rgba_sizes = { 0, 0, 0, 0 },
+ .yuv = &dri2_null_yuv_attribs[1],
+ },
+ {
+ .drm_format = DRM_FORMAT_NV21,
+ .dri_image_format = __DRI_IMAGE_FORMAT_NV21,
+ .rgba_shifts = { -1, -1, -1, -1 },
+ .rgba_sizes = { 0, 0, 0, 0 },
+ .yuv = &dri2_null_yuv_attribs[2],
},
};
@@ -137,6 +191,36 @@ format_idx_get_from_config(struct dri2_egl_display *dri2_dpy,
return -1;
}
+static int
+yuv_format_idx_get_from_config(struct dri2_egl_display *dri2_dpy,
+ const __DRIconfig *dri_config)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(dri2_null_formats); i++) {
+ const struct dri2_null_yuv_attrib *yuv = dri2_null_formats[i].yuv;
+ unsigned order, subsample, num_planes, plane_bpp;
+
+ if (!yuv)
+ continue;
+
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_ORDER,
+ &order);
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_SUBSAMPLE,
+ &subsample);
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_NUMBER_OF_PLANES,
+ &num_planes);
+ dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_PLANE_BPP,
+ &plane_bpp);
+
+ if (order != yuv->order || subsample != yuv->subsample ||
+ num_planes != yuv->num_planes || plane_bpp != yuv->plane_bpp)
+ continue;
+
+ return i;
+ }
+
+ return -1;
+}
+
static int
format_idx_get_from_dri_image_format(uint32_t dri_image_format)
{
@@ -1082,23 +1166,21 @@ static bool
add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
uint32_t *fb_id_out)
{
- uint64_t modifiers[4] = {0};
+ int handle, stride, width, height, format, l_mod, h_mod, offset;
+ uint64_t modifier = DRM_FORMAT_MOD_INVALID;
+ uint64_t *modifiers = NULL, mods[4] = {0};
uint32_t handles[4] = {0};
uint32_t pitches[4] = {0};
uint32_t offsets[4] = {0};
+ __DRIimage *p_image;
uint32_t flags = 0;
- int handle, stride, width, height, format, l_mod, h_mod;
int format_idx;
+ int num_planes;
- dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &handle);
- dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width);
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
- handles[0] = (uint32_t) handle;
- pitches[0] = (uint32_t) stride;
-
format_idx = format_idx_get_from_dri_image_format(format);
assert(format_idx != -1);
@@ -1106,10 +1188,44 @@ add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, &h_mod);
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, &l_mod);
- modifiers[0] = combine_u32_into_u64((uint32_t) h_mod, (uint32_t) l_mod);
+ modifier = combine_u32_into_u64((uint32_t) h_mod, (uint32_t) l_mod);
+ modifiers = mods;
+
flags |= DRM_MODE_FB_MODIFIERS;
}
+ dri2_dpy->image->queryImage(image,
+ __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes);
+ if (num_planes <= 0)
+ num_planes = 1;
+
+ for (int i = 0; i < num_planes; i++) {
+ if (dri2_dpy->in_formats_enabled) {
+ assert(modifiers && modifier != DRM_FORMAT_MOD_INVALID);
+ modifiers[i] = modifier;
+ }
+
+ p_image = dri2_dpy->image->fromPlanar(image, i, NULL);
+ if (!p_image) {
+ assert(i == 0);
+ p_image = image;
+ }
+
+ dri2_dpy->image->queryImage(p_image, __DRI_IMAGE_ATTRIB_STRIDE,
+ &stride);
+ dri2_dpy->image->queryImage(p_image, __DRI_IMAGE_ATTRIB_OFFSET,
+ &offset);
+ dri2_dpy->image->queryImage(p_image, __DRI_IMAGE_ATTRIB_HANDLE,
+ &handle);
+
+ if (p_image != image)
+ dri2_dpy->image->destroyImage(p_image);
+
+ pitches[i] = (uint32_t) stride;
+ offsets[i] = (uint32_t) offset;
+ handles[i] = (uint32_t) handle;
+ }
+
return !drmModeAddFB2WithModifiers(dri2_dpy->fd, width, height,
dri2_null_formats[format_idx].drm_format,
handles, pitches, offsets, modifiers,
@@ -1256,6 +1372,7 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
struct dri2_egl_config *dri2_config = dri2_egl_config(config);
struct dri2_egl_surface *dri2_surf;
const __DRIconfig *dri_config;
+ unsigned int render_type;
_EGLSurface *surf;
int format_idx;
bool ret;
@@ -1286,7 +1403,14 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
goto err_free_surface;
}
- format_idx = format_idx_get_from_config(dri2_dpy, dri_config);
+ if (!dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_RENDER_TYPE,
+ &render_type))
+ goto err_free_surface;
+
+ if (render_type & __DRI_ATTRIB_YUV_BIT)
+ format_idx = yuv_format_idx_get_from_config(dri2_dpy, dri_config);
+ else
+ format_idx = format_idx_get_from_config(dri2_dpy, dri_config);
assert(format_idx != -1);
dri2_surf->format = dri2_null_formats[format_idx].dri_image_format;
@@ -1627,6 +1751,17 @@ dri2_null_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format,
return 1;
}
+static unsigned
+dri2_null_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
+{
+ switch (cap) {
+ case DRI_LOADER_CAP_YUV_SURFACE_IMG:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static void
dri2_null_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
{
@@ -1635,10 +1770,11 @@ dri2_null_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
}
static const __DRIimageLoaderExtension image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 1 },
+ .base = { __DRI_IMAGE_LOADER, 2 },
.getBuffers = dri2_null_image_get_buffers,
.flushFrontBuffer = dri2_null_flush_front_buffer,
+ .getCapability = dri2_null_get_capability,
};
static const __DRIextension *image_loader_extensions[] = {
@@ -1720,10 +1856,24 @@ dri2_null_add_configs_for_formats(_EGLDisplay *disp)
for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
struct dri2_egl_config *dri2_conf;
+ EGLint surface_type = EGL_WINDOW_BIT;
+ unsigned int render_type;
int format_idx;
- format_idx = format_idx_get_from_config(dri2_dpy,
- dri2_dpy->driver_configs[i]);
+ if (!dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
+ __DRI_ATTRIB_RENDER_TYPE,
+ &render_type))
+ continue;
+
+ if (render_type & __DRI_ATTRIB_YUV_BIT) {
+ format_idx = yuv_format_idx_get_from_config(dri2_dpy,
+ dri2_dpy->driver_configs[i]);
+ } else {
+ format_idx = format_idx_get_from_config(dri2_dpy,
+ dri2_dpy->driver_configs[i]);
+ surface_type |= EGL_PBUFFER_BIT;
+ }
+
if (format_idx == -1)
continue;
@@ -1735,8 +1885,7 @@ dri2_null_add_configs_for_formats(_EGLDisplay *disp)
dri2_conf = dri2_add_config(disp,
dri2_dpy->driver_configs[i], count + 1,
- EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
- NULL, NULL, NULL);
+ surface_type, NULL, NULL, NULL);
if (dri2_conf)
count++;
}
diff --git a/src/mesa/drivers/dri/pvr/pvrutil.c b/src/mesa/drivers/dri/pvr/pvrutil.c
index 945e18cf220..d107a5dafad 100644
--- a/src/mesa/drivers/dri/pvr/pvrutil.c
+++ b/src/mesa/drivers/dri/pvr/pvrutil.c
@@ -174,6 +174,10 @@ PVRDRIFormatToFourCC(int dri_format)
return DRM_FORMAT_YVU444_PACK10_IMG;
case __DRI_IMAGE_FORMAT_BGR888:
return DRM_FORMAT_BGR888;
+ case __DRI_IMAGE_FORMAT_NV12:
+ return DRM_FORMAT_NV12;
+ case __DRI_IMAGE_FORMAT_NV21:
+ return DRM_FORMAT_NV21;
default:
__driUtilMessage("%s: Unknown format: %d", __func__, dri_format);
break;
@@ -230,6 +234,10 @@ PVRDRIFourCCToDRIFormat(int iFourCC)
return __DRI_IMAGE_FORMAT_YVU444_PACK10_IMG;
case DRM_FORMAT_BGR888:
return __DRI_IMAGE_FORMAT_BGR888;
+ case DRM_FORMAT_NV12:
+ return __DRI_IMAGE_FORMAT_NV12;
+ case DRM_FORMAT_NV21:
+ return __DRI_IMAGE_FORMAT_NV21;
default:
__driUtilMessage("%s: Unknown format: %d", __func__, iFourCC);
break;
--
2.25.1

View File

@@ -0,0 +1,433 @@
From db015d5fd0ded075e759677c047c581151bb1b52 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 9 Mar 2021 17:15:30 +0000
Subject: [PATCH 50/67] dri: preserve the original FD for driver use.
If an application uses a different GPU from the default, allow the
file descriptor (FD) for that original GPU/display to be preserved
for use by drivers. Drivers may wish to use the original FD to
allocate shared surfaces, to ensure the surface properties are
compatible with the original GPU/display (e.g. for X11 or Wayland).
This feature is only available on platforms that choose to support
it, by implementing the new getDisplayFD function in the DRI image,
and DRI2 loader extensions.
If the feature is available, drivers can obtain the original FD
by calling the getDisplayFD function in the relevant loader extension.
Drivers should check the FD is valid before use (i.e. not -1). If
the FD is valid, it may be equal to the current GPU FD if a different
GPU is not being used. The FD is owned by the platform, not the
driver, and the platform is responsible for closing it.
The feature is currently supported by the Wayland, and DRI3 based
X11 EGL and GLX platforms.
---
include/GL/internal/dri_interface.h | 26 +++++++++++++++++--
src/egl/drivers/dri2/egl_dri2.c | 10 +++++++
src/egl/drivers/dri2/egl_dri2.h | 1 +
src/egl/drivers/dri2/platform_wayland.c | 31 ++++++++++++++++++++--
src/egl/drivers/dri2/platform_x11.c | 3 +++
src/egl/drivers/dri2/platform_x11_dri3.c | 27 ++++++++++++++++++-
src/glx/dri3_glx.c | 33 ++++++++++++++++++++++--
src/glx/dri3_priv.h | 1 +
8 files changed, 125 insertions(+), 7 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 888a117d56e..2fb440feb50 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1146,7 +1146,7 @@ struct __DRIbufferRec {
};
#define __DRI_DRI2_LOADER "DRI_DRI2Loader"
-#define __DRI_DRI2_LOADER_VERSION 5
+#define __DRI_DRI2_LOADER_VERSION 6
enum dri_loader_cap {
/* Whether the loader handles RGBA channel ordering correctly. If not,
@@ -1227,6 +1227,17 @@ struct __DRIdri2LoaderExtensionRec {
* \since 5
*/
void (*destroyLoaderImageState)(void *loaderPrivate);
+
+ /**
+ * Get the display FD
+ *
+ * Get the FD of the display device.
+ *
+ * \param loaderPrivate The last parameter of createNewScreen or
+ * createNewScreen2.
+ * \since 6
+ */
+ int (*getDisplayFD)(void *loaderPrivate);
};
/**
@@ -2131,7 +2142,7 @@ struct __DRIimageList {
};
#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
-#define __DRI_IMAGE_LOADER_VERSION 4
+#define __DRI_IMAGE_LOADER_VERSION 5
struct __DRIimageLoaderExtensionRec {
__DRIextension base;
@@ -2199,6 +2210,17 @@ struct __DRIimageLoaderExtensionRec {
* \since 4
*/
void (*destroyLoaderImageState)(void *loaderPrivate);
+
+ /**
+ * Get the display FD
+ *
+ * Get the FD of the display device.
+ *
+ * \param loaderPrivate The last parameter of createNewScreen or
+ * createNewScreen2.
+ * \since 5
+ */
+ int (*getDisplayFD)(void *loaderPrivate);
};
/**
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index c4a49cae592..1df53ef011c 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1367,6 +1367,16 @@ dri2_display_destroy(_EGLDisplay *disp)
break;
}
+ switch (disp->Platform) {
+ case _EGL_PLATFORM_WAYLAND:
+ case _EGL_PLATFORM_X11:
+ if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
+ close(dri2_dpy->fd_dpy);
+ break;
+ default:
+ break;
+ }
+
if (dri2_dpy->fd >= 0)
close(dri2_dpy->fd);
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 141df1b1732..af03caee623 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -230,6 +230,7 @@ struct dri2_egl_display
const __DRIconfigOptionsExtension *configOptions;
const __DRImutableRenderBufferDriverExtension *mutable_render_buffer;
int fd;
+ int fd_dpy;
/* dri2_initialize/dri2_terminate increment/decrement this count, so does
* dri2_make_current (tracks if there are active contexts/surfaces). */
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 06272d4081e..b393e058770 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -44,6 +44,7 @@
#include "loader.h"
#include "util/u_vector.h"
#include "util/anon_file.h"
+#include "util/os_file.h"
#include "eglglobals.h"
#include <wayland-egl-backend.h>
@@ -973,21 +974,32 @@ dri2_wl_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
}
}
+static int
+dri2_wl_get_display_fd(void *loaderPrivate)
+{
+ _EGLDisplay *disp = loaderPrivate;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ return dri2_dpy->fd_dpy;
+}
+
static const __DRIdri2LoaderExtension dri2_loader_extension = {
- .base = { __DRI_DRI2_LOADER, 4 },
+ .base = { __DRI_DRI2_LOADER, 6 },
.getBuffers = dri2_wl_get_buffers,
.flushFrontBuffer = dri2_wl_flush_front_buffer,
.getBuffersWithFormat = dri2_wl_get_buffers_with_format,
.getCapability = dri2_wl_get_capability,
+ .getDisplayFD = dri2_wl_get_display_fd,
};
static const __DRIimageLoaderExtension image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 2 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = image_get_buffers,
.flushFrontBuffer = dri2_wl_flush_front_buffer,
.getCapability = dri2_wl_get_capability,
+ .getDisplayFD = dri2_wl_get_display_fd,
};
static void
@@ -1640,12 +1652,14 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
{
_EGLDevice *dev;
struct dri2_egl_display *dri2_dpy;
+ int fd_old;
dri2_dpy = calloc(1, sizeof *dri2_dpy);
if (!dri2_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
disp->DriverData = (void *) dri2_dpy;
if (disp->PlatformDisplay == NULL) {
dri2_dpy->wl_dpy = wl_display_connect(NULL);
@@ -1690,8 +1704,20 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
(roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated))
goto cleanup;
+ fd_old = dri2_dpy->fd;
+ dri2_dpy->fd_dpy = os_dupfd_cloexec(dri2_dpy->fd);
dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
&dri2_dpy->is_different_gpu);
+ if (dri2_dpy->fd == fd_old) {
+ if (dri2_dpy->fd_dpy != -1)
+ close(dri2_dpy->fd_dpy);
+
+ dri2_dpy->fd_dpy = dri2_dpy->fd;
+ } else if (dri2_dpy->fd_dpy == -1) {
+ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to dup display FD");
+ goto cleanup;
+ }
+
dev = _eglAddDevice(dri2_dpy->fd, false);
if (!dev) {
_eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
@@ -2236,6 +2262,7 @@ dri2_initialize_wayland_swrast(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
disp->DriverData = (void *) dri2_dpy;
if (disp->PlatformDisplay == NULL) {
dri2_dpy->wl_dpy = wl_display_connect(NULL);
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 5ffdf132184..5cf3ce2a369 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -1277,6 +1277,7 @@ dri2_initialize_x11_swrast(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
if (!dri2_get_xcb_connection(disp, dri2_dpy))
goto cleanup;
@@ -1364,6 +1365,7 @@ dri2_initialize_x11_dri3(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
if (!dri2_get_xcb_connection(disp, dri2_dpy))
goto cleanup;
@@ -1472,6 +1474,7 @@ dri2_initialize_x11_dri2(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
if (!dri2_get_xcb_connection(disp, dri2_dpy))
goto cleanup;
diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
index e117105fcb6..0babf9f867e 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -32,6 +32,7 @@
#include <xf86drm.h>
#include "util/macros.h"
+#include "util/os_file.h"
#include "egl_dri2.h"
#include "platform_x11_dri3.h"
@@ -414,11 +415,21 @@ dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
_eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
}
+static int
+dri3_get_display_fd(void *loaderPrivate)
+{
+ _EGLDisplay *disp = loaderPrivate;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ return dri2_dpy->fd_dpy;
+}
+
const __DRIimageLoaderExtension dri3_image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 1 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = loader_dri3_get_buffers,
.flushFrontBuffer = dri3_flush_front_buffer,
+ .getDisplayFD = dri3_get_display_fd,
};
static EGLBoolean
@@ -537,6 +548,7 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
xcb_generic_error_t *error;
const xcb_query_extension_reply_t *extension;
+ int fd_old;
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
@@ -616,12 +628,25 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
return EGL_FALSE;
}
+ fd_old = dri2_dpy->fd;
+ dri2_dpy->fd_dpy = os_dupfd_cloexec(dri2_dpy->fd);
dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
+ if (dri2_dpy->fd == fd_old) {
+ if (dri2_dpy->fd_dpy != -1)
+ close(dri2_dpy->fd_dpy);
+
+ dri2_dpy->fd_dpy = dri2_dpy->fd;
+ } else if (dri2_dpy->fd_dpy == -1) {
+ _eglLog(_EGL_WARNING, "DRI3: failed to dup display FD");
+ close(dri2_dpy->fd);
+ return EGL_FALSE;
+ }
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
if (!dri2_dpy->driver_name) {
_eglLog(_EGL_WARNING, "DRI3: No driver found");
close(dri2_dpy->fd);
+ close(dri2_dpy->fd_dpy);
return EGL_FALSE;
}
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index db1b079663f..1ed6b60ffe8 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -77,6 +77,7 @@
#include "dri3_priv.h"
#include "loader.h"
#include "dri2.h"
+#include "util/os_file.h"
static struct dri3_drawable *
loader_drawable_to_dri3_drawable(struct loader_dri3_drawable *draw) {
@@ -529,6 +530,14 @@ dri3_flush_swap_buffers(__DRIdrawable *driDrawable, void *loaderPrivate)
loader_dri3_swapbuffer_barrier(draw);
}
+static int
+dri3_get_display_fd(void *loaderPrivate)
+{
+ struct dri3_screen *psc = (struct dri3_screen *)loaderPrivate;
+
+ return psc->fd_dpy;
+}
+
static void
dri_set_background_context(void *loaderPrivate)
{
@@ -548,11 +557,12 @@ dri_is_thread_safe(void *loaderPrivate)
/* The image loader extension record for DRI3
*/
static const __DRIimageLoaderExtension imageLoaderExtension = {
- .base = { __DRI_IMAGE_LOADER, 3 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = loader_dri3_get_buffers,
.flushFrontBuffer = dri3_flush_front_buffer,
.flushSwapBuffers = dri3_flush_swap_buffers,
+ .getDisplayFD = dri3_get_display_fd,
};
const __DRIuseInvalidateExtension dri3UseInvalidate = {
@@ -618,6 +628,10 @@ dri3_destroy_screen(struct glx_screen *base)
loader_dri3_close_screen(psc->driScreen);
(*psc->core->destroyScreen) (psc->driScreen);
driDestroyConfigs(psc->driver_configs);
+
+ if (psc->fd_dpy != psc->fd)
+ close(psc->fd_dpy);
+
close(psc->fd);
free(psc);
}
@@ -842,8 +856,9 @@ dri3_create_screen(int screen, struct glx_display * priv)
struct dri3_screen *psc;
__GLXDRIscreen *psp;
struct glx_config *configs = NULL, *visuals = NULL;
- char *driverName, *driverNameDisplayGPU, *tmp;
+ char *driverName = NULL, *driverNameDisplayGPU, *tmp;
int i;
+ int fd_old;
psc = calloc(1, sizeof *psc);
if (psc == NULL)
@@ -851,6 +866,7 @@ dri3_create_screen(int screen, struct glx_display * priv)
psc->fd = -1;
psc->fd_display_gpu = -1;
+ psc->fd_dpy = -1;
if (!glx_screen_init(&psc->base, screen, priv)) {
free(psc);
@@ -871,12 +887,23 @@ dri3_create_screen(int screen, struct glx_display * priv)
return NULL;
}
+ fd_old = psc->fd;
+ psc->fd_dpy = os_dupfd_cloexec(psc->fd);
psc->fd_display_gpu = fcntl(psc->fd, F_DUPFD_CLOEXEC, 3);
psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu);
if (!psc->is_different_gpu) {
close(psc->fd_display_gpu);
psc->fd_display_gpu = -1;
}
+ if (psc->fd == fd_old) {
+ if (psc->fd_dpy != -1)
+ close(psc->fd_dpy);
+
+ psc->fd_dpy = psc->fd;
+ } else if (psc->fd_dpy == -1) {
+ ErrorMessageF("Unable to dup the display FD");
+ goto handle_error;
+ }
driverName = loader_get_driver_for_fd(psc->fd);
if (!driverName) {
@@ -1049,6 +1076,8 @@ handle_error:
if (psc->driScreenDisplayGPU)
psc->core->destroyScreen(psc->driScreenDisplayGPU);
psc->driScreenDisplayGPU = NULL;
+ if (psc->fd_dpy >= 0 && psc->fd_dpy != psc->fd)
+ close(psc->fd_dpy);
if (psc->fd >= 0)
close(psc->fd);
if (psc->fd_display_gpu >= 0)
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
index c0e833c16ef..b3dccf28c06 100644
--- a/src/glx/dri3_priv.h
+++ b/src/glx/dri3_priv.h
@@ -107,6 +107,7 @@ struct dri3_screen {
void *driver;
int fd;
+ int fd_dpy;
bool is_different_gpu;
/* fd for display GPU in case of prime */
--
2.25.1

View File

@@ -0,0 +1,56 @@
From 627ec429d684c57bdee45a21354009810fc03186 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Wed, 28 Apr 2021 10:57:15 +0100
Subject: [PATCH 51/67] egl/wayland: a linear buffer is not needed with DRM
format modifiers
If the compositor supports DRM format modifiers, there is no
need for an additional linear buffer, as the client can allocate
buffers with attributes known to the compositor.
---
src/egl/drivers/dri2/platform_wayland.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index b393e058770..60683fa6c1a 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -695,7 +695,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
use_flags |= __DRI_IMAGE_USE_PROTECTED;
}
- if (dri2_dpy->is_different_gpu &&
+ if (dri2_dpy->is_different_gpu && !num_modifiers &&
dri2_surf->back->linear_copy == NULL) {
/* The LINEAR modifier should be a perfect alias of the LINEAR use
* flag; try the new interface first before the old, then fall back. */
@@ -811,7 +811,7 @@ update_buffers(struct dri2_egl_display *dri2_dpy,
dri2_surf->color_buffers[i].wl_buffer) {
wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
- if (dri2_dpy->is_different_gpu)
+ if (dri2_surf->color_buffers[i].linear_copy)
dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
dri2_surf->color_buffers[i].wl_buffer = NULL;
dri2_surf->color_buffers[i].dri_image = NULL;
@@ -1247,7 +1247,7 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
if (!dri2_surf->current->wl_buffer) {
__DRIimage *image;
- if (dri2_dpy->is_different_gpu)
+ if (dri2_surf->current->linear_copy)
image = dri2_surf->current->linear_copy;
else
image = dri2_surf->current->dri_image;
@@ -1281,7 +1281,7 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
dri2_flush_drawable_for_swapbuffers(disp, draw);
- if (dri2_dpy->is_different_gpu) {
+ if (dri2_surf->current->linear_copy) {
_EGLContext *ctx = _eglGetCurrentContext();
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
dri2_dpy->image->blitImage(dri2_ctx->dri_context,
--
2.25.1

View File

@@ -0,0 +1,303 @@
From e57b9a1b34a733f88af51b1395eebe647006939d Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Wed, 28 Apr 2021 16:33:42 +0100
Subject: [PATCH 52/67] dri3: a linear buffer is not needed with DRM format
modifiers
If the X Server supports DRM format modifiers, there is no need
for an additional linear buffer, as the client can allocate buffers
with attributes known to the Server.
---
src/egl/drivers/dri2/platform_x11_dri3.c | 7 +-
src/glx/dri3_glx.c | 137 +++++++++++++++--------
src/loader/loader_dri3_helper.c | 15 +++
src/loader/loader_dri3_helper.h | 4 +
4 files changed, 113 insertions(+), 50 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
index 0babf9f867e..94205a495a6 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -143,6 +143,7 @@ dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
struct dri3_egl_surface *dri3_surf;
const __DRIconfig *dri_config;
xcb_drawable_t drawable;
+ bool is_incompat_gpu;
dri3_surf = calloc(1, sizeof *dri3_surf);
if (!dri3_surf) {
@@ -150,6 +151,10 @@ dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
return NULL;
}
+ is_incompat_gpu = dri2_dpy->is_different_gpu &&
+ !loader_dri3_has_modifiers(dri2_dpy->multibuffers_available,
+ dri2_dpy->image);
+
if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf,
attrib_list, false, native_surface))
goto cleanup_surf;
@@ -174,7 +179,7 @@ dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
dri2_dpy->dri_screen,
- dri2_dpy->is_different_gpu,
+ is_incompat_gpu,
dri2_dpy->multibuffers_available,
dri_config,
&dri2_dpy->loader_dri3_ext,
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index 1ed6b60ffe8..025ad0128ec 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -354,6 +354,21 @@ dri3_destroy_drawable(__GLXDRIdrawable *base)
free(pdraw);
}
+static bool
+dri3_has_multibuffer(const __DRIimageExtension *image,
+ const struct dri3_display *pdp)
+{
+#ifdef HAVE_DRI3_MODIFIERS
+ return (image && image->base.version >= 15) &&
+ (pdp->dri3Major > 1 ||
+ (pdp->dri3Major == 1 && pdp->dri3Minor >= 2)) &&
+ (pdp->presentMajor > 1 ||
+ (pdp->presentMajor == 1 && pdp->presentMinor >= 2));
+#else
+ return false;
+#endif
+}
+
static __GLXDRIdrawable *
dri3_create_drawable(struct glx_screen *base, XID xDrawable,
GLXDrawable drawable, struct glx_config *config_base)
@@ -361,11 +376,9 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,
struct dri3_drawable *pdraw;
struct dri3_screen *psc = (struct dri3_screen *) base;
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
- bool has_multibuffer = false;
-#ifdef HAVE_DRI3_MODIFIERS
const struct dri3_display *const pdp = (struct dri3_display *)
base->display->dri3Display;
-#endif
+ bool has_multibuffer = dri3_has_multibuffer(psc->image, pdp);
pdraw = calloc(1, sizeof(*pdraw));
if (!pdraw)
@@ -376,14 +389,6 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,
pdraw->base.drawable = drawable;
pdraw->base.psc = &psc->base;
-#ifdef HAVE_DRI3_MODIFIERS
- if ((psc->image && psc->image->base.version >= 15) &&
- (pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >= 2)) &&
- (pdp->presentMajor > 1 ||
- (pdp->presentMajor == 1 && pdp->presentMinor >= 2)))
- has_multibuffer = true;
-#endif
-
(void) __glXInitialize(psc->base.dpy);
if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy),
@@ -737,13 +742,14 @@ static const struct glx_context_vtable dri3_context_vtable = {
.interop_export_object = dri3_interop_export_object
};
-/** dri3_bind_extensions
+/** dri3_bind_extensions_part1
*
- * Enable all of the extensions supported on DRI3
+ * Enable the extensions supported on DRI3 that don't depend on
+ * whether we are using a different GPU.
*/
static void
-dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
- const char *driverName)
+dri3_bind_extensions_part1(struct dri3_screen *psc, struct glx_display * priv,
+ const char *driverName)
{
const __DRIextension **extensions;
unsigned mask;
@@ -774,16 +780,6 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
}
for (i = 0; extensions[i]; i++) {
- /* when on a different gpu than the server, the server pixmaps
- * can have a tiling mode we can't read. Thus we can't create
- * a texture from them.
- */
- if (!psc->is_different_gpu &&
- (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
- psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
- __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
- }
-
if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
psc->f = (__DRI2flushExtension *) extensions[i];
/* internal driver extension, no GL extension exposed */
@@ -817,6 +813,33 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
}
}
+/** dri3_bind_extensions_part2
+ *
+ * Enable the extensions supported on DRI3 that depend on whether we
+ * are using a different GPU.
+ */
+static void
+dri3_bind_extensions_part2(struct dri3_screen *psc, struct glx_display * priv,
+ const char *driverName)
+{
+ const __DRIextension **extensions;
+ int i;
+
+ extensions = psc->core->getExtensions(psc->driScreen);
+
+ for (i = 0; extensions[i]; i++) {
+ /* when on a different gpu than the server, the server pixmaps
+ * can have a tiling mode we can't read. Thus we can't create
+ * a texture from them.
+ */
+ if (!psc->is_different_gpu &&
+ (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
+ psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
+ __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
+ }
+ }
+}
+
static char *
dri3_get_driver_name(struct glx_screen *glx_screen)
{
@@ -859,6 +882,8 @@ dri3_create_screen(int screen, struct glx_display * priv)
char *driverName = NULL, *driverNameDisplayGPU, *tmp;
int i;
int fd_old;
+ bool is_different_gpu;
+ bool have_modifiers;
psc = calloc(1, sizeof *psc);
if (psc == NULL)
@@ -890,8 +915,8 @@ dri3_create_screen(int screen, struct glx_display * priv)
fd_old = psc->fd;
psc->fd_dpy = os_dupfd_cloexec(psc->fd);
psc->fd_display_gpu = fcntl(psc->fd, F_DUPFD_CLOEXEC, 3);
- psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu);
- if (!psc->is_different_gpu) {
+ psc->fd = loader_get_user_preferred_fd(psc->fd, &is_different_gpu);
+ if (!is_different_gpu) {
close(psc->fd_display_gpu);
psc->fd_display_gpu = -1;
}
@@ -933,27 +958,6 @@ dri3_create_screen(int screen, struct glx_display * priv)
goto handle_error;
}
- if (psc->is_different_gpu) {
- driverNameDisplayGPU = loader_get_driver_for_fd(psc->fd_display_gpu);
- if (driverNameDisplayGPU) {
-
- /* check if driver name is matching so that non mesa drivers
- * will not crash. Also need this check since image extension
- * pointer from render gpu is shared with display gpu. Image
- * extension pointer is shared because it keeps things simple.
- */
- if (strcmp(driverName, driverNameDisplayGPU) == 0) {
- psc->driScreenDisplayGPU =
- psc->image_driver->createNewScreen2(screen, psc->fd_display_gpu,
- pdp->loader_extensions,
- extensions,
- &driver_configs, psc);
- }
-
- free(driverNameDisplayGPU);
- }
- }
-
psc->driScreen =
psc->image_driver->createNewScreen2(screen, psc->fd,
pdp->loader_extensions,
@@ -965,7 +969,42 @@ dri3_create_screen(int screen, struct glx_display * priv)
goto handle_error;
}
- dri3_bind_extensions(psc, priv, driverName);
+ dri3_bind_extensions_part1(psc, priv, driverName);
+
+ have_modifiers = loader_dri3_has_modifiers(dri3_has_multibuffer(psc->image,
+ pdp),
+ psc->image);
+
+ if (is_different_gpu) {
+ if (have_modifiers) {
+ close(psc->fd_display_gpu);
+ psc->fd_display_gpu = -1;
+ } else {
+ driverNameDisplayGPU = loader_get_driver_for_fd(psc->fd_display_gpu);
+ if (driverNameDisplayGPU) {
+
+ /* check if driver name is matching so that non mesa drivers
+ * will not crash. Also need this check since image extension
+ * pointer from render gpu is shared with display gpu. Image
+ * extension pointer is shared because it keeps things simple.
+ */
+ if (strcmp(driverName, driverNameDisplayGPU) == 0) {
+ psc->driScreenDisplayGPU =
+ psc->image_driver->createNewScreen2(screen,
+ psc->fd_display_gpu,
+ pdp->loader_extensions,
+ extensions,
+ &driver_configs, psc);
+ }
+
+ free(driverNameDisplayGPU);
+ }
+ }
+ }
+
+ psc->is_different_gpu = is_different_gpu && !have_modifiers;
+
+ dri3_bind_extensions_part2(psc, priv, driverName);
if (!psc->image || psc->image->base.version < 7 || !psc->image->createImageFromFds) {
ErrorMessageF("Version 7 or imageFromFds image extension not found\n");
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index ff6d1ffc660..5c0379ab5de 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -2288,3 +2288,18 @@ dri3_find_back_alloc(struct loader_dri3_drawable *draw)
return back;
}
+
+bool
+loader_dri3_has_modifiers(bool multiplanes_available,
+ const __DRIimageExtension *image)
+{
+#ifdef HAVE_DRI3_MODIFIERS
+ return multiplanes_available && image &&
+ image->base.version >= 15 &&
+ image->queryDmaBufModifiers &&
+ image->createImageWithModifiers &&
+ image->createImageFromDmaBufs2;
+#else
+ return false;
+#endif
+}
diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
index 028e25dc070..5790f5444f5 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -287,4 +287,8 @@ loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw);
void
loader_dri3_close_screen(__DRIscreen *dri_screen);
+
+bool
+loader_dri3_has_modifiers(bool multiplanes_available,
+ const __DRIimageExtension *image);
#endif
--
2.25.1

View File

@@ -0,0 +1,267 @@
From 8de0535741ce8d126da4d9b0b0eb8c46dd4810b5 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 20 May 2021 14:43:29 +0100
Subject: [PATCH 53/67] egl/drm: add support for DRI_PRIME GPU selection
Add support for selecting the GPU to be used for rendering using
the DRI_PRIME environment variable. If a different GPU is selected,
a duplicate of the file descriptor for the original GPU/display is
preserved, which can be obtained by calling the getDisplayFD
function in the image loader extension.
For server side Wayland, the ability to support PRIME is
determined by checking for the PRIME import and export
capabilities on the driver file descriptor, which may no
longer support them if a different GPU from the default has
been selected. It may be that the driver can still support
PRIME; for example, by making use of the original (default)
file descriptor. The driver can indicate it supports PRIME
via the getCapabilities function in the DRI Image extension.
---
include/GL/internal/dri_interface.h | 2 ++
src/egl/drivers/dri2/egl_dri2.c | 10 ++++++++
src/egl/drivers/dri2/platform_drm.c | 19 ++++++++++-----
src/gbm/backends/dri/gbm_dri.c | 38 +++++++++++++++++++++++++----
src/gbm/backends/dri/gbm_driint.h | 8 ++++++
5 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 2fb440feb50..080d191b0a3 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1548,6 +1548,8 @@ enum __DRIChromaSiting {
*/
/*@{*/
#define __DRI_IMAGE_CAP_GLOBAL_NAMES 1
+#define __DRI_IMAGE_CAP_PRIME_IMPORT 0x2000
+#define __DRI_IMAGE_CAP_PRIME_EXPORT 0x4000
/*@}*/
/**
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 1df53ef011c..ec4ac602a84 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1368,6 +1368,7 @@ dri2_display_destroy(_EGLDisplay *disp)
}
switch (disp->Platform) {
+ case _EGL_PLATFORM_DRM:
case _EGL_PLATFORM_WAYLAND:
case _EGL_PLATFORM_X11:
if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
@@ -3943,6 +3944,15 @@ dri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
dri2_dpy->image->base.version >= 7 &&
dri2_dpy->image->createImageFromFds != NULL)
flags |= WAYLAND_DRM_PRIME;
+ else if (dri2_dpy->image->base.version >= 10 &&
+ dri2_dpy->image->getCapabilities != NULL) {
+ int capabilities;
+
+ capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
+ if ((capabilities & __DRI_IMAGE_CAP_PRIME_IMPORT) != 0 &&
+ (capabilities & __DRI_IMAGE_CAP_PRIME_EXPORT) != 0)
+ flags |= WAYLAND_DRM_PRIME;
+ }
dri2_dpy->wl_server_drm =
wayland_drm_init(wl_dpy, device_name,
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 258e8b6593e..f160ad1175e 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -595,7 +595,7 @@ dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- return drmAuthMagic(dri2_dpy->fd, id);
+ return drmAuthMagic(dri2_dpy->fd_dpy, id);
}
static void
@@ -782,6 +782,7 @@ dri2_initialize_drm(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
disp->DriverData = (void *) dri2_dpy;
gbm = disp->PlatformDisplay;
@@ -789,16 +790,16 @@ dri2_initialize_drm(_EGLDisplay *disp)
char buf[64];
int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0);
if (n != -1 && n < sizeof(buf))
- dri2_dpy->fd = loader_open_device(buf);
- gbm = gbm_create_device(dri2_dpy->fd);
+ dri2_dpy->fd_dpy = loader_open_device(buf);
+ gbm = gbm_create_device(dri2_dpy->fd_dpy);
if (gbm == NULL) {
err = "DRI2: failed to create gbm device";
goto cleanup;
}
dri2_dpy->own_device = true;
} else {
- dri2_dpy->fd = os_dupfd_cloexec(gbm_device_get_fd(gbm));
- if (dri2_dpy->fd < 0) {
+ dri2_dpy->fd_dpy = os_dupfd_cloexec(gbm_device_get_fd(gbm));
+ if (dri2_dpy->fd_dpy < 0) {
err = "DRI2: failed to fcntl() existing gbm device";
goto cleanup;
}
@@ -810,6 +811,12 @@ dri2_initialize_drm(_EGLDisplay *disp)
goto cleanup;
}
+ if (gbm_dri_device_get_fd(dri2_dpy->gbm_dri) ==
+ gbm_device_get_fd(gbm))
+ dri2_dpy->fd = dri2_dpy->fd_dpy;
+ else
+ dri2_dpy->fd = os_dupfd_cloexec(gbm_dri_device_get_fd(dri2_dpy->gbm_dri));
+
dev = _eglAddDevice(dri2_dpy->fd, dri2_dpy->gbm_dri->software);
if (!dev) {
err = "DRI2: failed to find EGLDevice";
@@ -872,7 +879,7 @@ dri2_initialize_drm(_EGLDisplay *disp)
disp->Extensions.EXT_buffer_age = EGL_TRUE;
#ifdef HAVE_WAYLAND_PLATFORM
- dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
+ dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd_dpy);
#endif
dri2_set_WL_bind_wayland_display(disp);
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index 5acb15b516f..c1586f42e46 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -51,6 +51,7 @@
#include "loader.h"
#include "util/debug.h"
#include "util/macros.h"
+#include "util/os_file.h"
/* For importing wl_buffer */
#if HAVE_WAYLAND_PLATFORM
@@ -141,6 +142,14 @@ image_get_buffers(__DRIdrawable *driDrawable,
surf->dri_private, buffer_mask, buffers);
}
+static int
+dri_get_display_fd(void *loaderPrivate)
+{
+ struct gbm_dri_device *dri = loaderPrivate;
+
+ return dri->base.v0.fd;
+}
+
static void
swrast_get_drawable_info(__DRIdrawable *driDrawable,
int *x,
@@ -220,20 +229,22 @@ static const __DRIimageLookupExtension image_lookup_extension = {
};
static const __DRIdri2LoaderExtension dri2_loader_extension = {
- .base = { __DRI_DRI2_LOADER, 4 },
+ .base = { __DRI_DRI2_LOADER, 6 },
.getBuffers = dri_get_buffers,
.flushFrontBuffer = dri_flush_front_buffer,
.getBuffersWithFormat = dri_get_buffers_with_format,
.getCapability = dri_get_capability,
+ .getDisplayFD = dri_get_display_fd,
};
static const __DRIimageLoaderExtension image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 2 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = image_get_buffers,
.flushFrontBuffer = dri_flush_front_buffer,
.getCapability = dri_get_capability,
+ .getDisplayFD = dri_get_display_fd,
};
static const __DRIswrastLoaderExtension swrast_loader_extension = {
@@ -398,12 +409,12 @@ dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name)
return -1;
if (dri->dri2->base.version >= 4) {
- dri->screen = dri->dri2->createNewScreen2(0, dri->base.v0.fd,
+ dri->screen = dri->dri2->createNewScreen2(0, dri->fd,
dri->loader_extensions,
dri->driver_extensions,
&dri->driver_configs, dri);
} else {
- dri->screen = dri->dri2->createNewScreen(0, dri->base.v0.fd,
+ dri->screen = dri->dri2->createNewScreen(0, dri->fd,
dri->loader_extensions,
&dri->driver_configs, dri);
}
@@ -470,8 +481,20 @@ static int
dri_screen_create(struct gbm_dri_device *dri)
{
char *driver_name;
+ int dup_fd, new_fd;
+ bool is_different_gpu;
- driver_name = loader_get_driver_for_fd(dri->base.v0.fd);
+ dup_fd = os_dupfd_cloexec(dri->fd);
+ if (dup_fd < 0)
+ return -1;
+
+ new_fd = loader_get_user_preferred_fd(dup_fd, &is_different_gpu);
+ if (new_fd == dup_fd)
+ close(new_fd);
+ else
+ dri->fd = new_fd;
+
+ driver_name = loader_get_driver_for_fd(dri->fd);
if (!driver_name)
return -1;
@@ -1424,6 +1447,9 @@ dri_destroy(struct gbm_device *gbm)
dlclose(dri->driver);
free(dri->driver_name);
+ if (dri->fd >= 0 && dri->fd != dri->base.v0.fd)
+ close (dri->fd);
+
free(dri);
}
@@ -1445,6 +1471,8 @@ dri_device_create(int fd, uint32_t gbm_backend_version)
if (!dri)
return NULL;
+ dri->fd = fd;
+
dri->base.v0.fd = fd;
dri->base.v0.backend_version = gbm_backend_version;
dri->base.v0.bo_create = gbm_dri_bo_create;
diff --git a/src/gbm/backends/dri/gbm_driint.h b/src/gbm/backends/dri/gbm_driint.h
index 9e77ba5887c..e33a96edb0b 100644
--- a/src/gbm/backends/dri/gbm_driint.h
+++ b/src/gbm/backends/dri/gbm_driint.h
@@ -61,6 +61,8 @@ struct gbm_dri_visual {
struct gbm_dri_device {
struct gbm_device base;
+ int fd;
+
void *driver;
char *driver_name; /* Name of the DRI module, without the _dri suffix */
bool software; /* A software driver was loaded */
@@ -191,4 +193,10 @@ gbm_dri_bo_unmap_dumb(struct gbm_dri_bo *bo)
bo->map = NULL;
}
+static inline int
+gbm_dri_device_get_fd(struct gbm_dri_device *dri)
+{
+ return dri->fd;
+}
+
#endif
--
2.25.1

View File

@@ -0,0 +1,304 @@
From f1f625dbcb4e0cc062369729b1da3d7fc65969e8 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 20 May 2021 20:16:18 +0100
Subject: [PATCH 54/67] egl/null: add support for DRI_PRIME GPU selection
Add support for selecting the GPU to be used for rendering using
the DRI_PRIME environment variable. If a different GPU is selected,
a duplicate of the file descriptor for the original GPU/display is
preserved, which can be obtained by calling the getDisplayFD
function in the image loader extension.
This change includes code, in function dri2_null_try_device, to
skip display devices that are not supported by the PVR driver.
This is to prevent failure on PC based test systems, that often
include display hardware that is incompatible with the driver.
This code would not be needed for systems that don't use the PVR
driver, or on production systems that use the PVR driver.
---
src/egl/drivers/dri2/egl_dri2.c | 1 +
src/egl/drivers/dri2/platform_null.c | 133 +++++++++++++++++++--------
2 files changed, 98 insertions(+), 36 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index ec4ac602a84..56b5175db6e 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1369,6 +1369,7 @@ dri2_display_destroy(_EGLDisplay *disp)
switch (disp->Platform) {
case _EGL_PLATFORM_DRM:
+ case _EGL_PLATFORM_NULL:
case _EGL_PLATFORM_WAYLAND:
case _EGL_PLATFORM_X11:
if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index db6f1147670..af77ea4dd89 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -44,6 +44,7 @@
#include "egl_dri2.h"
#include "loader.h"
+#include "util/os_file.h"
#define NULL_CARD_MINOR_MAX 63U
@@ -953,7 +954,7 @@ swap_idle_get_target_frame(struct dri2_egl_surface *dri2_surf,
* current vblank by the number of intervals set at the time swapBuffer
* is called. For intervals of 1 or 0, we don't need a target frame.
*/
- err = display_get_vblank_sequence(dri2_dpy->fd, current_vblank_out);
+ err = display_get_vblank_sequence(dri2_dpy->fd_dpy, current_vblank_out);
if (err)
return err;
@@ -1003,7 +1004,7 @@ swap_vblank_state_transition(struct dri2_egl_surface *dri2_surf,
uint32_t flags = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
int err;
- err = display_request_vblank(dri2_dpy->fd, target_frame,
+ err = display_request_vblank(dri2_dpy->fd_dpy, target_frame,
flags, dri2_surf);
if (err) {
dri2_surf->swap_state = SWAP_ERROR;
@@ -1029,7 +1030,7 @@ swap_flip_state_transition(struct dri2_egl_surface *dri2_surf)
flags |= DRM_MODE_PAGE_FLIP_ASYNC;
}
- err = display_output_flip(dri2_dpy->fd, &dri2_dpy->output,
+ err = display_output_flip(dri2_dpy->fd_dpy, &dri2_dpy->output,
dri2_surf->swap_data->fb_id, flags, dri2_surf);
if (err) {
dri2_surf->swap_state = SWAP_ERROR;
@@ -1049,7 +1050,7 @@ swap_poll_state_transition(struct dri2_egl_surface *dri2_surf)
int err;
/* dri2_surf->swap_state is being set inside the handler */
- err = drm_event_process(dri2_dpy->fd);
+ err = drm_event_process(dri2_dpy->fd_dpy);
if (err) {
dri2_surf->swap_state = SWAP_ERROR;
return err;
@@ -1201,7 +1202,7 @@ add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
handles[i] = (uint32_t) handle;
}
- return !drmModeAddFB2WithModifiers(dri2_dpy->fd, width, height,
+ return !drmModeAddFB2WithModifiers(dri2_dpy->fd_dpy, width, height,
dri2_null_formats[format_idx].drm_format,
handles, pitches, offsets, modifiers,
fb_id_out, flags);
@@ -1459,7 +1460,7 @@ dri2_null_create_window_surface(_EGLDisplay *disp, _EGLConfig *config,
goto err_destroy_surface;
}
- err = display_output_modeset(dri2_dpy->fd, &dri2_dpy->output,
+ err = display_output_modeset(dri2_dpy->fd_dpy, &dri2_dpy->output,
dri2_surf->front_buffer.fb_id);
if (err) {
_eglError(EGL_BAD_NATIVE_WINDOW, "window set mode");
@@ -1573,11 +1574,11 @@ dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
dri2_dpy->image->destroyImage(dri2_surf->front_buffer.dri_image);
if (dri2_surf->front_buffer.fb_id)
- drmModeRmFB(dri2_dpy->fd, dri2_surf->front_buffer.fb_id);
+ drmModeRmFB(dri2_dpy->fd_dpy, dri2_surf->front_buffer.fb_id);
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
if (dri2_surf->color_buffers[i].fb_id)
- drmModeRmFB(dri2_dpy->fd, dri2_surf->color_buffers[i].fb_id);
+ drmModeRmFB(dri2_dpy->fd_dpy, dri2_surf->color_buffers[i].fb_id);
if (dri2_surf->color_buffers[i].dri_image)
dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
}
@@ -1734,12 +1735,22 @@ dri2_null_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
(void) loaderPrivate;
}
+static int
+dri2_null_get_display_fd(void *loaderPrivate)
+{
+ _EGLDisplay *disp = loaderPrivate;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ return dri2_dpy->fd_dpy;
+}
+
static const __DRIimageLoaderExtension image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 2 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = dri2_null_image_get_buffers,
.flushFrontBuffer = dri2_null_flush_front_buffer,
.getCapability = dri2_null_get_capability,
+ .getDisplayFD = dri2_null_get_display_fd,
};
static const __DRIextension *image_loader_extensions[] = {
@@ -1768,12 +1779,74 @@ dri2_null_device_is_kms(int fd)
return is_kms;
}
+static bool
+dri2_null_try_device(_EGLDisplay *disp)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ if (!dri2_null_device_is_kms(dri2_dpy->fd_dpy))
+ return false;
+
+#if 1
+ /* Skip devices not supported by the pvr driver */
+ {
+ char *driver_name = loader_get_driver_for_fd(dri2_dpy->fd_dpy);
+ bool skip = !driver_name || !!strcmp(driver_name, "pvr");
+
+ free(driver_name);
+
+ if (skip)
+ return false;
+ }
+#endif
+
+ dri2_dpy->fd = os_dupfd_cloexec(dri2_dpy->fd_dpy);
+ if (dri2_dpy->fd < 0) {
+ _eglLog(_EGL_WARNING, "DRI2: failed to dup display FD");
+ dri2_dpy->fd = dri2_dpy->fd_dpy;
+ } else {
+ int fd_old;
+ bool is_different_gpu;
+
+ fd_old = dri2_dpy->fd;
+ dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
+ &is_different_gpu);
+ if (dri2_dpy->fd == fd_old) {
+ close (dri2_dpy->fd);
+ dri2_dpy->fd = dri2_dpy->fd_dpy;
+ }
+ }
+
+ dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
+ if (!dri2_dpy->driver_name)
+ return false;
+
+ if (dri2_load_driver_dri3(disp)) {
+ _EGLDevice *dev = _eglAddDevice(dri2_dpy->fd, false);
+ if (!dev) {
+ dlclose(dri2_dpy->driver);
+ _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice");
+ } else {
+ dri2_dpy->loader_extensions = image_loader_extensions;
+ dri2_dpy->own_device = 1;
+ disp->Device = dev;
+ return true;
+ }
+ }
+
+ free(dri2_dpy->driver_name);
+ dri2_dpy->driver_name = NULL;
+
+ return false;
+}
+
static bool
dri2_null_probe_device(_EGLDisplay *disp)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
for (unsigned i = 0; i <= NULL_CARD_MINOR_MAX; i++) {
char *card_path;
@@ -1781,32 +1854,20 @@ dri2_null_probe_device(_EGLDisplay *disp)
if (asprintf(&card_path, DRM_DEV_NAME, DRM_DIR_NAME, i) < 0)
continue;
- dri2_dpy->fd = loader_open_device(card_path);
+ dri2_dpy->fd_dpy = loader_open_device(card_path);
free(card_path);
- if (dri2_dpy->fd < 0)
+ if (dri2_dpy->fd_dpy < 0)
continue;
- if (dri2_null_device_is_kms(dri2_dpy->fd)) {
- dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
- if (dri2_dpy->driver_name) {
- if (dri2_load_driver_dri3(disp)) {
- _EGLDevice *dev = _eglAddDevice(dri2_dpy->fd, false);
- if (!dev) {
- dlclose(dri2_dpy->driver);
- _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice");
- } else {
- dri2_dpy->loader_extensions = image_loader_extensions;
- dri2_dpy->own_device = 1;
- disp->Device = dev;
- return true;
- }
- }
- free(dri2_dpy->driver_name);
- dri2_dpy->driver_name = NULL;
- }
- }
+ if (dri2_null_try_device(disp))
+ return true;
+
+ close(dri2_dpy->fd_dpy);
+
+ if (dri2_dpy->fd >= 0 && dri2_dpy->fd != dri2_dpy->fd_dpy)
+ close(dri2_dpy->fd);
- close(dri2_dpy->fd);
+ dri2_dpy->fd_dpy = -1;
dri2_dpy->fd = -1;
}
@@ -1867,7 +1928,7 @@ dri2_null_setup_swap_interval(_EGLDisplay *disp)
dri2_setup_swap_interval(disp, swap_max_interval);
- err = drmGetCap(dri2_dpy->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
+ err = drmGetCap(dri2_dpy->fd_dpy, DRM_CAP_ASYNC_PAGE_FLIP, &value);
if (err || value == 0) {
/* DRM/KMS does not support async page flip. In order to support
@@ -1914,7 +1975,7 @@ dri2_initialize_null(_EGLDisplay *disp)
* modesetting if not. If this succeeds then universal planes will also have
* been enabled.
*/
- err = drmSetClientCap(dri2_dpy->fd, DRM_CLIENT_CAP_ATOMIC, 1);
+ err = drmSetClientCap(dri2_dpy->fd_dpy, DRM_CLIENT_CAP_ATOMIC, 1);
dri2_dpy->atomic_enabled = !err;
if (!dri2_dpy->atomic_enabled) {
@@ -1922,7 +1983,7 @@ dri2_initialize_null(_EGLDisplay *disp)
* Enable universal planes so that we can get the pixel formats for the
* primary plane
*/
- err = drmSetClientCap(dri2_dpy->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+ err = drmSetClientCap(dri2_dpy->fd_dpy, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
if (err) {
_eglError(EGL_NOT_INITIALIZED, "failed to enable universal planes");
goto cleanup;
@@ -1955,7 +2016,7 @@ dri2_initialize_null(_EGLDisplay *disp)
prefer_in_formats = dri2_dpy->image->base.version >= 14 &&
dri2_dpy->image->createImageWithModifiers;
- if (!display_output_init(dri2_dpy->fd, &dri2_dpy->output,
+ if (!display_output_init(dri2_dpy->fd_dpy, &dri2_dpy->output,
dri2_dpy->atomic_enabled,
prefer_in_formats,
&dri2_dpy->in_formats_enabled)) {
@@ -1990,7 +2051,7 @@ dri2_teardown_null(struct dri2_egl_display *dri2_dpy)
drmModeFreeFormats(dri2_dpy->output.in_formats);
if (dri2_dpy->output.mode_blob_id)
- drmModeDestroyPropertyBlob(dri2_dpy->fd, dri2_dpy->output.mode_blob_id);
+ drmModeDestroyPropertyBlob(dri2_dpy->fd_dpy, dri2_dpy->output.mode_blob_id);
if (dri2_dpy->output.plane_prop_res) {
for (unsigned i = 0; dri2_dpy->output.plane_prop_res[i]; i++)
--
2.25.1

View File

@@ -0,0 +1,120 @@
From 693fff6d87abfcae887afde7f80f402b7ff5c0ab Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 28 Jun 2021 16:36:15 +0100
Subject: [PATCH 55/67] egl/null: introduce NULL_DRM_DISPLAY
Introduce the NULL_DRM_DISPLAY environment variable, which allows
a particular DRM display to be selected, rather than the first
suitable DRM device found.
To select a particular display, NULL_DRM_DISPLAY should be set to
the card number (i.e. minor number) of the DRM device representing
the display. For example, NULL_DRM_DISPLAY=2 will select
/dev/dri/card2.
---
src/egl/drivers/dri2/platform_null.c | 65 ++++++++++++++++++++--------
1 file changed, 46 insertions(+), 19 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index af77ea4dd89..529cc7a2a2f 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -1784,6 +1784,8 @@ dri2_null_try_device(_EGLDisplay *disp)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ dri2_dpy->fd = -1;
+
if (!dri2_null_device_is_kms(dri2_dpy->fd_dpy))
return false;
@@ -1841,34 +1843,56 @@ dri2_null_try_device(_EGLDisplay *disp)
}
static bool
-dri2_null_probe_device(_EGLDisplay *disp)
+dri2_null_probe_device(_EGLDisplay *disp, unsigned minor)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ char *card_path;
- dri2_dpy->fd = -1;
- dri2_dpy->fd_dpy = -1;
+ if (asprintf(&card_path, DRM_DEV_NAME, DRM_DIR_NAME, minor) < 0)
+ goto cleanup;
- for (unsigned i = 0; i <= NULL_CARD_MINOR_MAX; i++) {
- char *card_path;
+ dri2_dpy->fd_dpy = loader_open_device(card_path);
+ free(card_path);
+ if (dri2_dpy->fd_dpy < 0)
+ goto cleanup;
- if (asprintf(&card_path, DRM_DEV_NAME, DRM_DIR_NAME, i) < 0)
- continue;
+ if (dri2_null_try_device(disp))
+ return true;
- dri2_dpy->fd_dpy = loader_open_device(card_path);
- free(card_path);
- if (dri2_dpy->fd_dpy < 0)
- continue;
+ close(dri2_dpy->fd_dpy);
- if (dri2_null_try_device(disp))
- return true;
+ if (dri2_dpy->fd >= 0 && dri2_dpy->fd != dri2_dpy->fd_dpy)
+ close(dri2_dpy->fd);
- close(dri2_dpy->fd_dpy);
+cleanup:
+ dri2_dpy->fd_dpy = -1;
+ dri2_dpy->fd = -1;
- if (dri2_dpy->fd >= 0 && dri2_dpy->fd != dri2_dpy->fd_dpy)
- close(dri2_dpy->fd);
+ return false;
+}
+
+static bool
+dri2_null_probe_devices(_EGLDisplay *disp)
+{
+ const char *null_drm_display = getenv("NULL_DRM_DISPLAY");
+
+ if (null_drm_display) {
+ char *endptr;
+ long val = strtol(null_drm_display, &endptr, 10);
- dri2_dpy->fd_dpy = -1;
- dri2_dpy->fd = -1;
+ if (endptr != null_drm_display && !*endptr &&
+ val >= 0 && val <= NULL_CARD_MINOR_MAX) {
+ if (dri2_null_probe_device(disp, (unsigned)val))
+ return true;
+ } else {
+ _eglLog(_EGL_FATAL, "NULL_DRM_DISPLAY is invalid: %s",
+ null_drm_display);
+ }
+ } else {
+ for (unsigned i = 0; i <= NULL_CARD_MINOR_MAX; i++) {
+ if (dri2_null_probe_device(disp, i))
+ return true;
+ }
}
return false;
@@ -1965,7 +1989,10 @@ dri2_initialize_null(_EGLDisplay *disp)
disp->DriverData = (void *) dri2_dpy;
- if (!dri2_null_probe_device(disp)) {
+ dri2_dpy->fd_dpy = -1;
+ dri2_dpy->fd = -1;
+
+ if (!dri2_null_probe_devices(disp)) {
_eglError(EGL_NOT_INITIALIZED, "failed to load driver");
goto cleanup;
}
--
2.25.1

View File

@@ -0,0 +1,37 @@
From a422756b7d73b48d3d10d15066a61e9332370719 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Mon, 21 Jun 2021 17:05:17 +0100
Subject: [PATCH 56/67] vulkan/wsi: check the DRI3 and Present XCB reply
pointers
Check that the DRI3 and Present version replies are not NULL
before accessing the version fields.
---
src/vulkan/wsi/wsi_common_x11.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 9dce78eddeb..9eb624df640 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -216,7 +216,7 @@ wsi_x11_connection_create(struct wsi_device *wsi_dev,
ver_cookie = xcb_dri3_query_version(conn, 1, 2);
ver_reply = xcb_dri3_query_version_reply(conn, ver_cookie, NULL);
- has_dri3_v1_2 =
+ has_dri3_v1_2 = ver_reply != NULL &&
(ver_reply->major_version > 1 || ver_reply->minor_version >= 2);
free(ver_reply);
}
@@ -230,7 +230,7 @@ wsi_x11_connection_create(struct wsi_device *wsi_dev,
ver_cookie = xcb_present_query_version(conn, 1, 2);
ver_reply = xcb_present_query_version_reply(conn, ver_cookie, NULL);
- has_present_v1_2 =
+ has_present_v1_2 = ver_reply != NULL &&
(ver_reply->major_version > 1 || ver_reply->minor_version >= 2);
free(ver_reply);
}
--
2.25.1

View File

@@ -0,0 +1,143 @@
From b900d4998b95a8bdfb01600f81635ff76810cfe6 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 16 Feb 2021 20:17:32 +0000
Subject: [PATCH 57/67] vulkan/wsi: Allow host visible memory to be requested
Allow host visible memory to be explicitly requested when allocating
native images.
For a software driver on X11, we need to be able to map the memory on
the host, in order to present the contents to the X Server.
---
src/vulkan/wsi/wsi_common_display.c | 2 +-
src/vulkan/wsi/wsi_common_drm.c | 17 +++++++++++++----
src/vulkan/wsi/wsi_common_private.h | 1 +
src/vulkan/wsi/wsi_common_wayland.c | 3 ++-
src/vulkan/wsi/wsi_common_x11.c | 1 +
5 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
index aa07cada107..71a84e54079 100644
--- a/src/vulkan/wsi/wsi_common_display.c
+++ b/src/vulkan/wsi/wsi_common_display.c
@@ -1031,7 +1031,7 @@ wsi_display_image_init(VkDevice device_h,
return VK_ERROR_DEVICE_LOST;
VkResult result = wsi_create_native_image(&chain->base, create_info,
- 0, NULL, NULL,
+ 0, NULL, NULL, false,
&image->base);
if (result != VK_SUCCESS)
return result;
diff --git a/src/vulkan/wsi/wsi_common_drm.c b/src/vulkan/wsi/wsi_common_drm.c
index 70d934aef13..aabb761908c 100644
--- a/src/vulkan/wsi/wsi_common_drm.c
+++ b/src/vulkan/wsi/wsi_common_drm.c
@@ -66,6 +66,7 @@ wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
static uint32_t
select_memory_type(const struct wsi_device *wsi,
bool want_device_local,
+ bool want_host_visible,
uint32_t type_bits)
{
assert(type_bits);
@@ -74,8 +75,10 @@ select_memory_type(const struct wsi_device *wsi,
for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
const VkMemoryType type = wsi->memory_props.memoryTypes[i];
bool local = type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ bool host = type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
- if ((type_bits & (1 << i)) && local == want_device_local)
+ if ((type_bits & (1 << i)) && local == want_device_local &&
+ (!want_host_visible || host))
return i;
all_local &= local;
}
@@ -83,6 +86,8 @@ select_memory_type(const struct wsi_device *wsi,
/* ignore want_device_local when all memory types are device-local */
if (all_local) {
assert(!want_device_local);
+ /* currently, host visibility is only needed with device local */
+ assert(!want_host_visible);
return ffs(type_bits) - 1;
}
@@ -107,6 +112,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
uint32_t num_modifier_lists,
const uint32_t *num_modifiers,
const uint64_t *const *modifiers,
+ bool host_visible,
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
@@ -317,7 +323,8 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &memory_dedicated_info,
.allocationSize = reqs.size,
- .memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),
+ .memoryTypeIndex = select_memory_type(wsi, true, host_visible,
+ reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &memory_info,
&chain->alloc, &image->memory);
@@ -488,7 +495,8 @@ wsi_create_prime_image(const struct wsi_swapchain *chain,
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &prime_memory_dedicated_info,
.allocationSize = linear_size,
- .memoryTypeIndex = select_memory_type(wsi, false, reqs.memoryTypeBits),
+ .memoryTypeIndex = select_memory_type(wsi, false, false,
+ reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &prime_memory_info,
&chain->alloc, &image->prime.memory);
@@ -542,7 +550,8 @@ wsi_create_prime_image(const struct wsi_swapchain *chain,
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &memory_dedicated_info,
.allocationSize = reqs.size,
- .memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),
+ .memoryTypeIndex = select_memory_type(wsi, true, false,
+ reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &memory_info,
&chain->alloc, &image->memory);
diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h
index 1fe8211f9cb..5ad087b32e0 100644
--- a/src/vulkan/wsi/wsi_common_private.h
+++ b/src/vulkan/wsi/wsi_common_private.h
@@ -94,6 +94,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
uint32_t num_modifier_lists,
const uint32_t *num_modifiers,
const uint64_t *const *modifiers,
+ bool host_visible,
struct wsi_image *image);
VkResult
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index 40f5338314f..983833e880b 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -1074,7 +1074,8 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
result = wsi_create_native_image(&chain->base, pCreateInfo,
chain->num_drm_modifiers > 0 ? 1 : 0,
&chain->num_drm_modifiers,
- &chain->drm_modifiers, &image->base);
+ &chain->drm_modifiers, false,
+ &image->base);
if (result != VK_SUCCESS)
return result;
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 9eb624df640..eb639d6c265 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -1315,6 +1315,7 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
} else {
result = wsi_create_native_image(&chain->base, pCreateInfo,
num_tranches, num_modifiers, modifiers,
+ chain->base.wsi->sw,
&image->base);
}
if (result < 0)
--
2.25.1

View File

@@ -0,0 +1,419 @@
From afcfb076e89365ff1f33c658a6a615d2108d97f5 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 17 Jun 2021 17:17:07 +0100
Subject: [PATCH 58/67] vulkan/wsi: make the display FD available
Pass the display FD to the Vulkan image create and memory
allocation functions when allocating swapchain images.
---
src/vulkan/wsi/wsi_common.h | 14 +++
src/vulkan/wsi/wsi_common_display.c | 2 +-
src/vulkan/wsi/wsi_common_drm.c | 22 ++++-
src/vulkan/wsi/wsi_common_private.h | 2 +
src/vulkan/wsi/wsi_common_wayland.c | 127 ++++++++++++++++++++++------
src/vulkan/wsi/wsi_common_x11.c | 42 ++++++---
6 files changed, 169 insertions(+), 40 deletions(-)
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index d5367db3a94..c2563c677e6 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -37,6 +37,8 @@
#define VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA (VkStructureType)1000001003
#define VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA (VkStructureType)1000001005
#define VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA (VkStructureType)1000001006
+#define VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO2_MESA (VkStructureType)1000001007
+#define VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO2_MESA (VkStructureType)1000001008
/* This is always chained to VkImageCreateInfo when a wsi image is created.
* It indicates that the image can be transitioned to/from
@@ -75,6 +77,18 @@ struct wsi_memory_signal_submit_info {
VkDeviceMemory memory;
};
+struct wsi_image_create_info2 {
+ VkStructureType sType;
+ const void *pNext;
+ int display_fd;
+};
+
+struct wsi_memory_allocate_info2 {
+ VkStructureType sType;
+ const void *pNext;
+ int display_fd;
+};
+
struct wsi_fence {
VkDevice device;
const struct wsi_device *wsi_device;
diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
index 71a84e54079..f135b4e38de 100644
--- a/src/vulkan/wsi/wsi_common_display.c
+++ b/src/vulkan/wsi/wsi_common_display.c
@@ -1032,7 +1032,7 @@ wsi_display_image_init(VkDevice device_h,
VkResult result = wsi_create_native_image(&chain->base, create_info,
0, NULL, NULL, false,
- &image->base);
+ wsi->fd, &image->base);
if (result != VK_SUCCESS)
return result;
diff --git a/src/vulkan/wsi/wsi_common_drm.c b/src/vulkan/wsi/wsi_common_drm.c
index aabb761908c..6201891ca80 100644
--- a/src/vulkan/wsi/wsi_common_drm.c
+++ b/src/vulkan/wsi/wsi_common_drm.c
@@ -113,6 +113,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
const uint32_t *num_modifiers,
const uint64_t *const *modifiers,
bool host_visible,
+ int display_fd,
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
@@ -170,6 +171,12 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
__vk_append_struct(&image_info, &image_format_list);
}
+ struct wsi_image_create_info2 image_wsi_info2 = {
+ .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO2_MESA,
+ .display_fd = display_fd,
+ };
+ __vk_append_struct(&image_info, &image_wsi_info2);
+
VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list;
uint32_t image_modifier_count = 0, modifier_prop_count = 0;
@@ -308,9 +315,14 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
.pNext = NULL,
.implicit_sync = true,
};
+ const struct wsi_memory_allocate_info2 memory_wsi_info2 = {
+ .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO2_MESA,
+ .pNext = &memory_wsi_info,
+ .display_fd = display_fd,
+ };
const VkExportMemoryAllocateInfo memory_export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
- .pNext = &memory_wsi_info,
+ .pNext = &memory_wsi_info2,
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
@@ -440,6 +452,7 @@ VkResult
wsi_create_prime_image(const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
bool use_modifier,
+ int display_fd,
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
@@ -480,9 +493,14 @@ wsi_create_prime_image(const struct wsi_swapchain *chain,
.pNext = NULL,
.implicit_sync = true,
};
+ const struct wsi_memory_allocate_info2 memory_wsi_info2 = {
+ .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO2_MESA,
+ .pNext = &memory_wsi_info,
+ .display_fd = display_fd,
+ };
const VkExportMemoryAllocateInfo prime_memory_export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
- .pNext = &memory_wsi_info,
+ .pNext = &memory_wsi_info2,
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h
index 5ad087b32e0..e46328156dc 100644
--- a/src/vulkan/wsi/wsi_common_private.h
+++ b/src/vulkan/wsi/wsi_common_private.h
@@ -95,12 +95,14 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
const uint32_t *num_modifiers,
const uint64_t *const *modifiers,
bool host_visible,
+ int display_fd,
struct wsi_image *image);
VkResult
wsi_create_prime_image(const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
bool use_modifier,
+ int display_fd,
struct wsi_image *image);
void
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index 983833e880b..1109d3f07b6 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -32,6 +32,8 @@
#include <pthread.h>
#include <poll.h>
#include <sys/mman.h>
+#include <fcntl.h>
+#include <xf86drm.h>
#include "drm-uapi/drm_fourcc.h"
@@ -82,6 +84,9 @@ struct wsi_wl_display {
struct wsi_wayland *wsi_wl;
+ int fd;
+ bool authenticated;
+
/* Points to formats in wsi_wl_display_drm or wsi_wl_display_dmabuf */
struct u_vector * formats;
@@ -261,10 +266,52 @@ wsi_wl_display_add_wl_shm_format(struct wsi_wl_display *display,
}
}
+static int
+open_display_device(const char *name)
+{
+ int fd;
+
+#ifdef O_CLOEXEC
+ fd = open(name, O_RDWR | O_CLOEXEC);
+ if (fd != -1 || errno != EINVAL) {
+ return fd;
+ }
+#endif
+
+ fd = open(name, O_RDWR);
+ if (fd != -1) {
+ long flags = fcntl(fd, F_GETFD);
+
+ if (flags != -1) {
+ if (!fcntl(fd, F_SETFD, flags | FD_CLOEXEC))
+ return fd;
+ }
+ close (fd);
+ }
+
+ return -1;
+}
static void
drm_handle_device(void *data, struct wl_drm *drm, const char *name)
{
+ struct wsi_wl_display *display = data;
+ const int fd = open_display_device(name);
+
+ if (fd != -1) {
+ if (drmGetNodeTypeFromFd(fd) != DRM_NODE_RENDER) {
+ drm_magic_t magic;
+
+ if (drmGetMagic(fd, &magic)) {
+ close(fd);
+ return;
+ }
+ wl_drm_authenticate(drm, magic);
+ } else {
+ display->authenticated = true;
+ }
+ display->fd = fd;
+ }
}
static uint32_t
@@ -346,6 +393,9 @@ drm_handle_format(void *data, struct wl_drm *drm, uint32_t wl_format)
static void
drm_handle_authenticated(void *data, struct wl_drm *drm)
{
+ struct wsi_wl_display *display = data;
+
+ display->authenticated = true;
}
static void
@@ -487,6 +537,9 @@ wsi_wl_display_finish(struct wsi_wl_display *display)
wl_proxy_wrapper_destroy(display->wl_display_wrapper);
if (display->queue)
wl_event_queue_destroy(display->queue);
+
+ if (display->fd != -1)
+ close(display->fd);
}
static VkResult
@@ -501,6 +554,7 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl,
display->wsi_wl = wsi_wl;
display->wl_display = wl_display;
display->sw = sw;
+ display->fd = -1;
if (get_format_list) {
if (!u_vector_init(&display->swrast.formats, sizeof(VkFormat), 8) ||
@@ -542,41 +596,60 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl,
/* Round-trip to get wl_drms and zwp_linux_dmabuf_v1 globals */
wl_display_roundtrip_queue(display->wl_display, display->queue);
+ if (!display->drm.wl_drm && !display->dmabuf.wl_dmabuf && !display->swrast.wl_shm) {
+ result = VK_ERROR_SURFACE_LOST_KHR;
+ goto fail_registry;
+ }
+
/* Round-trip again to get formats, modifiers and capabilities */
- if (display->drm.wl_drm || display->dmabuf.wl_dmabuf || display->swrast.wl_shm)
- wl_display_roundtrip_queue(display->wl_display, display->queue);
+ wl_display_roundtrip_queue(display->wl_display, display->queue);
- if (wsi_wl->wsi->force_bgra8_unorm_first) {
- /* Find BGRA8_UNORM in the list and swap it to the first position if we
- * can find it. Some apps get confused if SRGB is first in the list.
- */
- VkFormat *first_fmt = u_vector_head(display->formats);
- VkFormat *iter_fmt;
- u_vector_foreach(iter_fmt, display->formats) {
- if (*iter_fmt == VK_FORMAT_B8G8R8A8_UNORM) {
- *iter_fmt = *first_fmt;
- *first_fmt = VK_FORMAT_B8G8R8A8_UNORM;
- break;
- }
- }
+ if (display->fd == -1) {
+ result = VK_ERROR_SURFACE_LOST_KHR;
+ goto fail_registry;
}
- /* Prefer the linux-dmabuf protocol if available */
- if (display->sw)
- display->formats = &display->swrast.formats;
- else if (display->dmabuf.wl_dmabuf) {
- display->formats = &display->dmabuf.formats;
- } else if (display->drm.wl_drm &&
- (display->drm.capabilities & WL_DRM_CAPABILITY_PRIME)) {
- /* We need prime support for wl_drm */
- display->formats = &display->drm.formats;
- }
+ wl_display_roundtrip_queue(display->wl_display, display->queue);
- if (!display->formats) {
+ if (!display->authenticated) {
result = VK_ERROR_SURFACE_LOST_KHR;
goto fail_registry;
}
+ if (get_format_list) {
+ /* Prefer the linux-dmabuf protocol if available */
+ if (display->sw)
+ display->formats = &display->swrast.formats;
+ else if(display->dmabuf.wl_dmabuf &&
+ u_vector_length(&display->dmabuf.formats)) {
+ display->formats = &display->dmabuf.formats;
+ } else if (display->drm.wl_drm &&
+ display->drm.capabilities & WL_DRM_CAPABILITY_PRIME) {
+ display->formats = &display->drm.formats;
+ }
+
+ if (!display->formats) {
+ result = VK_ERROR_SURFACE_LOST_KHR;
+ goto fail_registry;
+ }
+
+ if (wsi_wl->wsi->force_bgra8_unorm_first) {
+ /* Find BGRA8_UNORM in the list and swap it to the first position if
+ * we can find it. Some apps get confused if SRGB is first in the
+ * list.
+ */
+ VkFormat *first_fmt = u_vector_tail(display->formats);
+ VkFormat *iter_fmt;
+ u_vector_foreach(iter_fmt, display->formats) {
+ if (*iter_fmt == VK_FORMAT_B8G8R8A8_UNORM) {
+ *iter_fmt = *first_fmt;
+ *first_fmt = VK_FORMAT_B8G8R8A8_UNORM;
+ break;
+ }
+ }
+ }
+ }
+
/* We don't need this anymore */
wl_registry_destroy(registry);
@@ -1075,7 +1148,7 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
chain->num_drm_modifiers > 0 ? 1 : 0,
&chain->num_drm_modifiers,
&chain->drm_modifiers, false,
- &image->base);
+ display->fd, &image->base);
if (result != VK_SUCCESS)
return result;
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index eb639d6c265..ba64e260932 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -1303,7 +1303,8 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
const VkAllocationCallbacks* pAllocator,
const uint64_t *const *modifiers,
const uint32_t *num_modifiers,
- int num_tranches, struct x11_image *image)
+ int num_tranches, int display_fd,
+ struct x11_image *image)
{
xcb_void_cookie_t cookie;
VkResult result;
@@ -1311,11 +1312,12 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
if (chain->base.use_prime_blit) {
bool use_modifier = num_tranches > 0;
- result = wsi_create_prime_image(&chain->base, pCreateInfo, use_modifier, &image->base);
+ result = wsi_create_prime_image(&chain->base, pCreateInfo, use_modifier,
+ display_fd, &image->base);
} else {
result = wsi_create_native_image(&chain->base, pCreateInfo,
num_tranches, num_modifiers, modifiers,
- chain->base.wsi->sw,
+ chain->base.wsi->sw, display_fd,
&image->base);
}
if (result < 0)
@@ -1687,14 +1689,34 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
modifiers, num_modifiers, &num_tranches,
pAllocator);
+
uint32_t image = 0;
- for (; image < chain->base.image_count; image++) {
- result = x11_image_init(device, chain, pCreateInfo, pAllocator,
- (const uint64_t *const *)modifiers,
- num_modifiers, num_tranches,
- &chain->images[image]);
- if (result != VK_SUCCESS)
- goto fail_init_images;
+ {
+ int display_fd = -1;
+
+ if (!wsi_device->sw) {
+ xcb_screen_iterator_t screen_iter =
+ xcb_setup_roots_iterator(xcb_get_setup(conn));
+ xcb_screen_t *screen = screen_iter.data;
+
+ display_fd = wsi_dri3_open(conn, screen->root, None);
+ }
+
+ for (; image < chain->base.image_count; image++) {
+ result = x11_image_init(device, chain, pCreateInfo, pAllocator,
+ (const uint64_t *const *)modifiers,
+ num_modifiers, num_tranches,
+ display_fd, &chain->images[image]);
+ if (result != VK_SUCCESS) {
+ if (display_fd >= 0)
+ close(display_fd);
+
+ goto fail_init_images;
+ }
+ }
+
+ if (display_fd >= 0)
+ close(display_fd);
}
if ((chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR ||
--
2.25.1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,76 @@
From 83953c9325e4cc9adb23ad7654a02ddabdd3fd99 Mon Sep 17 00:00:00 2001
From: brendan King <Brendan.King@imgtec.com>
Date: Fri, 30 Jul 2021 15:34:13 +0100
Subject: [PATCH 60/67] vulkan/wsi: Disable use of VK_EXT_pci_bus_info
The VK_EXT_pci_bus_info related code has been wrapped in
VULKAN_WSI_USE_PCI_BUS_INFO, effectively disabling it.
Not all platforms support the VK_EXT_pci_bus_info extension.
A better fix might be to pass another parameter to wsi_device_init,
to indicate that the device is a PCI one.
---
src/vulkan/wsi/wsi_common.c | 4 ++++
src/vulkan/wsi/wsi_common.h | 2 ++
src/vulkan/wsi/wsi_common_drm.c | 4 ++++
3 files changed, 10 insertions(+)
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index b1360edb911..66d6683a7c1 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -56,11 +56,15 @@ wsi_device_init(struct wsi_device *wsi,
WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties);
#undef WSI_GET_CB
+#if defined(VULKAN_WSI_USE_PCI_BUS_INFO)
wsi->pci_bus_info.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT;
+#endif
VkPhysicalDeviceProperties2 pdp2 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+#if defined(VULKAN_WSI_USE_PCI_BUS_INFO)
.pNext = &wsi->pci_bus_info,
+#endif
};
GetPhysicalDeviceProperties2(pdevice, &pdp2);
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index c2563c677e6..4a733665d2c 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -112,7 +112,9 @@ struct wsi_device {
VkPhysicalDeviceMemoryProperties memory_props;
uint32_t queue_family_count;
+#if defined(VULKAN_WSI_USE_PCI_BUS_INFO)
VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info;
+#endif
bool supports_modifiers;
uint32_t maxImageDimension2D;
diff --git a/src/vulkan/wsi/wsi_common_drm.c b/src/vulkan/wsi/wsi_common_drm.c
index 6201891ca80..49a78cf4c62 100644
--- a/src/vulkan/wsi/wsi_common_drm.c
+++ b/src/vulkan/wsi/wsi_common_drm.c
@@ -45,6 +45,7 @@ wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
if (ret)
return false;
+#if defined(VULKAN_WSI_USE_PCI_BUS_INFO)
bool match = false;
switch (fd_device->bustype) {
case DRM_BUS_PCI:
@@ -57,6 +58,9 @@ wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
default:
break;
}
+#else
+ const bool match = true;
+#endif
drmFreeDevice(&fd_device);
--
2.25.1

View File

@@ -0,0 +1,34 @@
From 10a0d4ec4f9d468c792f5e675d924fa7a8f97373 Mon Sep 17 00:00:00 2001
From: brendan King <Brendan.King@imgtec.com>
Date: Mon, 2 Aug 2021 16:29:36 +0100
Subject: [PATCH 61/67] vulkan/wsi: default to force_bgra8_unorm_first true
If VULKAN_WSI_BGRA8_SNORM_FIRST is not defined, default to
force_bgra8_unorm_first true.
This brings Mesa WSI into line with IMG WSI with regards to the
VK_FORMAT_B8G8R8A8_UNORM and VK_FORMAT_B8G8R8A8_SRGB formats.
With this change, the IMG Vulkan unit test, vkbonjour, will default
to VK_FORMAT_B8G8R8A8_UNORM rather than VK_FORMAT_B8G8R8A8_SRGB.
---
src/vulkan/wsi/wsi_common.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index 66d6683a7c1..1ffca6fecfb 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -158,6 +158,10 @@ wsi_device_init(struct wsi_device *wsi,
driQueryOptionb(dri_options, "vk_wsi_force_bgra8_unorm_first");
}
}
+#if !defined(VULKAN_WSI_BGRA8_SNORM_FIRST)
+ else
+ wsi->force_bgra8_unorm_first = true;
+#endif
return VK_SUCCESS;
#if defined(VK_USE_PLATFORM_XCB_KHR) || \
--
2.25.1

View File

@@ -0,0 +1,64 @@
From 7e8bb12d48651796da6d8f3df1b388551d3b5510 Mon Sep 17 00:00:00 2001
From: brendan King <Brendan.King@imgtec.com>
Date: Mon, 2 Aug 2021 11:21:16 +0100
Subject: [PATCH 62/67] vulkan/wsi: enable additional formats for Wayland
Add VK_FORMAT_R5G6B5_UNORM_PACK16.
This is for compatibility with IMG WSI.
---
src/vulkan/wsi/wsi_common_wayland.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index 1109d3f07b6..e520aa9af00 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -68,6 +68,7 @@ struct wsi_wl_display_dmabuf {
struct {
struct u_vector argb8888;
struct u_vector xrgb8888;
+ struct u_vector rgb565;
} modifiers;
};
@@ -441,6 +442,9 @@ dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
case WL_DRM_FORMAT_XRGB8888:
modifiers = &display->dmabuf.modifiers.xrgb8888;
break;
+ case WL_DRM_FORMAT_RGB565:
+ modifiers = &display->dmabuf.modifiers.rgb565;
+ break;
default:
return; /* Unsupported format */
}
@@ -527,6 +531,7 @@ wsi_wl_display_finish(struct wsi_wl_display *display)
u_vector_finish(&display->dmabuf.formats);
u_vector_finish(&display->dmabuf.modifiers.argb8888);
u_vector_finish(&display->dmabuf.modifiers.xrgb8888);
+ u_vector_finish(&display->dmabuf.modifiers.rgb565);
if (display->swrast.wl_shm)
wl_shm_destroy(display->swrast.wl_shm);
if (display->drm.wl_drm)
@@ -563,6 +568,8 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl,
!u_vector_init(&display->dmabuf.modifiers.argb8888,
sizeof(uint64_t), 32) ||
!u_vector_init(&display->dmabuf.modifiers.xrgb8888,
+ sizeof(uint64_t), 32) ||
+ !u_vector_init(&display->dmabuf.modifiers.rgb565,
sizeof(uint64_t), 32)) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto fail;
@@ -1356,6 +1363,9 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
case WL_DRM_FORMAT_XRGB8888:
modifiers = &chain->display->dmabuf.modifiers.xrgb8888;
break;
+ case WL_DRM_FORMAT_RGB565:
+ modifiers = &chain->display->dmabuf.modifiers.rgb565;
+ break;
default:
modifiers = NULL;
break;
--
2.25.1

View File

@@ -0,0 +1,27 @@
From c2b91fcb7c88bfec23077ae31c0035684249ea1b Mon Sep 17 00:00:00 2001
From: brendan King <Brendan.King@imgtec.com>
Date: Tue, 3 Aug 2021 15:44:57 +0100
Subject: [PATCH 63/67] vulkan/wsi: enable additional formats for Display
Add VK_FORMAT_R5G6B5_UNORM_PACK16.
This is for compatibility with IMG WSI.
---
src/vulkan/wsi/wsi_common_display.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
index f135b4e38de..298c78809c3 100644
--- a/src/vulkan/wsi/wsi_common_display.c
+++ b/src/vulkan/wsi/wsi_common_display.c
@@ -900,6 +900,7 @@ static const struct {
} available_surface_formats[] = {
{ .format = VK_FORMAT_B8G8R8A8_SRGB, .drm_format = DRM_FORMAT_XRGB8888 },
{ .format = VK_FORMAT_B8G8R8A8_UNORM, .drm_format = DRM_FORMAT_XRGB8888 },
+ { .format = VK_FORMAT_R5G6B5_UNORM_PACK16, .drm_format = DRM_FORMAT_RGB565 },
};
static void
--
2.25.1

View File

@@ -0,0 +1,183 @@
From 85762f3538a21a99bf1b71d87345ebe51f9de453 Mon Sep 17 00:00:00 2001
From: Luigi Santivetti <luigi.santivetti@imgtec.com>
Date: Thu, 12 Aug 2021 00:55:46 +0100
Subject: [PATCH 64/67] mesa/main: dri: add YUV420_3PLANE and YVU420_3PLANE
---
include/GL/internal/dri_interface.h | 2 ++
src/gallium/include/pipe/p_format.h | 3 +++
src/mesa/drivers/dri/common/utils.c | 18 ++++++++++++++++++
src/mesa/drivers/dri/pvr/dri_support.h | 2 ++
src/mesa/drivers/dri/pvr/pvrutil.c | 13 +++++++++++++
src/mesa/main/format_info.py | 2 +-
src/mesa/main/formats.c | 2 ++
src/mesa/main/formats.csv | 2 ++
src/mesa/main/formats.h | 6 ++++++
9 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 080d191b0a3..7d9a1bd9ba6 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1424,6 +1424,8 @@ struct __DRIdri2ExtensionRec {
#define __DRI_IMAGE_FORMAT_BGR888 0x101a
#define __DRI_IMAGE_FORMAT_NV12 0x101b
#define __DRI_IMAGE_FORMAT_NV21 0x101c
+#define __DRI_IMAGE_FORMAT_YU12 0x101d
+#define __DRI_IMAGE_FORMAT_YV12 0x101e
#define __DRI_IMAGE_USE_SHARE 0x0001
#define __DRI_IMAGE_USE_SCANOUT 0x0002
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
index fd653379b7a..970f07598d5 100644
--- a/src/gallium/include/pipe/p_format.h
+++ b/src/gallium/include/pipe/p_format.h
@@ -516,6 +516,9 @@ enum pipe_format {
PIPE_FORMAT_YUV420_2PLANE,
PIPE_FORMAT_YVU420_2PLANE,
+ PIPE_FORMAT_YUV420_3PLANE,
+ PIPE_FORMAT_YVU420_3PLANE,
+
PIPE_FORMAT_COUNT
};
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
index d268dc41fbb..df5f8cbfdc0 100644
--- a/src/mesa/drivers/dri/common/utils.c
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -330,6 +330,24 @@ driCreateConfigs(mesa_format format,
yuv_subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT;
yuv_plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT;
break;
+ case MESA_FORMAT_YUV420_3PLANE:
+ masks = format_table[11].masks;
+ shifts = format_table[11].shifts;
+ is_yuv = true; /* FIXME: This should come from formats_info.py */
+ yuv_order = __DRI_ATTRIB_YUV_ORDER_YUV_BIT;
+ yuv_num_planes = 3;
+ yuv_subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT;
+ yuv_plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT;
+ break;
+ case MESA_FORMAT_YVU420_3PLANE:
+ masks = format_table[11].masks;
+ shifts = format_table[11].shifts;
+ is_yuv = true; /* FIXME: This should come from formats_info.py */
+ yuv_order = __DRI_ATTRIB_YUV_ORDER_YVU_BIT;
+ yuv_num_planes = 3;
+ yuv_subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT;
+ yuv_plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT;
+ break;
default:
fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n",
__func__, __LINE__,
diff --git a/src/mesa/drivers/dri/pvr/dri_support.h b/src/mesa/drivers/dri/pvr/dri_support.h
index ab0b9dd9a23..a4999dc36bf 100644
--- a/src/mesa/drivers/dri/pvr/dri_support.h
+++ b/src/mesa/drivers/dri/pvr/dri_support.h
@@ -189,6 +189,8 @@ typedef enum
#define PVRDRI_MESA_FORMAT_YVU420_2PLANE 8
#define PVRDRI_MESA_FORMAT_B8G8R8A8_SRGB 9
#define PVRDRI_MESA_FORMAT_R8G8B8A8_SRGB 10
+#define PVRDRI_MESA_FORMAT_YUV420_3PLANE 11
+#define PVRDRI_MESA_FORMAT_YVU420_3PLANE 12
/* The blit flags match their DRI counterparts */
#define PVRDRI_BLIT_FLAG_FLUSH 0x0001
diff --git a/src/mesa/drivers/dri/pvr/pvrutil.c b/src/mesa/drivers/dri/pvr/pvrutil.c
index d107a5dafad..ee11ac55914 100644
--- a/src/mesa/drivers/dri/pvr/pvrutil.c
+++ b/src/mesa/drivers/dri/pvr/pvrutil.c
@@ -118,6 +118,10 @@ PVRDRIMesaFormatToMesaFormat(int pvrdri_mesa_format)
return MESA_FORMAT_B8G8R8A8_SRGB;
case PVRDRI_MESA_FORMAT_R8G8B8A8_SRGB:
return MESA_FORMAT_R8G8B8A8_SRGB;
+ case PVRDRI_MESA_FORMAT_YUV420_3PLANE:
+ return MESA_FORMAT_YUV420_3PLANE;
+ case PVRDRI_MESA_FORMAT_YVU420_3PLANE:
+ return MESA_FORMAT_YVU420_3PLANE;
default:
__driUtilMessage("%s: Unknown format: %d", __func__, pvrdri_mesa_format);
break;
@@ -178,6 +182,11 @@ PVRDRIFormatToFourCC(int dri_format)
return DRM_FORMAT_NV12;
case __DRI_IMAGE_FORMAT_NV21:
return DRM_FORMAT_NV21;
+ case __DRI_IMAGE_FORMAT_YU12:
+ return DRM_FORMAT_YUV420;
+ case __DRI_IMAGE_FORMAT_YV12:
+ return DRM_FORMAT_YVU420;
+
default:
__driUtilMessage("%s: Unknown format: %d", __func__, dri_format);
break;
@@ -238,6 +247,10 @@ PVRDRIFourCCToDRIFormat(int iFourCC)
return __DRI_IMAGE_FORMAT_NV12;
case DRM_FORMAT_NV21:
return __DRI_IMAGE_FORMAT_NV21;
+ case DRM_FORMAT_YUV420:
+ return __DRI_IMAGE_FORMAT_YU12;
+ case DRM_FORMAT_YVU420:
+ return __DRI_IMAGE_FORMAT_YV12;
default:
__driUtilMessage("%s: Unknown format: %d", __func__, iFourCC);
break;
diff --git a/src/mesa/main/format_info.py b/src/mesa/main/format_info.py
index d58403ea85e..bc18db74f17 100644
--- a/src/mesa/main/format_info.py
+++ b/src/mesa/main/format_info.py
@@ -29,7 +29,7 @@ import sys
def get_gl_base_format(fmat):
if fmat.name == 'MESA_FORMAT_NONE':
return 'GL_NONE'
- elif fmat.name in ['MESA_FORMAT_YCBCR', 'MESA_FORMAT_YCBCR_REV', 'MESA_FORMAT_YUV420_2PLANE', 'MESA_FORMAT_YVU420_2PLANE']:
+ elif fmat.name in ['MESA_FORMAT_YCBCR', 'MESA_FORMAT_YCBCR_REV', 'MESA_FORMAT_YUV420_2PLANE', 'MESA_FORMAT_YVU420_2PLANE', 'MESA_FORMAT_YUV420_3PLANE', 'MESA_FORMAT_YVU420_3PLANE']:
return 'GL_YCBCR_MESA'
elif fmat.has_channel('r'):
if fmat.has_channel('g'):
diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
index f81caeceff4..d7b0d0a07c9 100644
--- a/src/mesa/main/formats.c
+++ b/src/mesa/main/formats.c
@@ -1455,6 +1455,8 @@ _mesa_format_matches_format_and_type(mesa_format mformat,
switch (mformat) {
case MESA_FORMAT_YUV420_2PLANE:
case MESA_FORMAT_YVU420_2PLANE:
+ case MESA_FORMAT_YUV420_3PLANE:
+ case MESA_FORMAT_YVU420_3PLANE:
return false;
default:
diff --git a/src/mesa/main/formats.csv b/src/mesa/main/formats.csv
index b2d476577e0..825443b10ce 100644
--- a/src/mesa/main/formats.csv
+++ b/src/mesa/main/formats.csv
@@ -94,6 +94,8 @@ MESA_FORMAT_YCBCR , other , 1, 1, 1, x16 , , ,
MESA_FORMAT_YCBCR_REV , other , 1, 1, 1, x16 , , , , xyzw, yuv
MESA_FORMAT_YUV420_2PLANE , other , 1, 1, 1, x8 , , , , y___, yuv
MESA_FORMAT_YVU420_2PLANE , other , 1, 1, 1, x8 , , , , y___, yuv
+MESA_FORMAT_YUV420_3PLANE , other , 1, 1, 1, x8 , , , , y___, yuv
+MESA_FORMAT_YVU420_3PLANE , other , 1, 1, 1, x8 , , , , y___, yuv
MESA_FORMAT_RG_RB_UNORM8 , other , 2, 1, 1, x16 , , , , xyz1, rgb
MESA_FORMAT_GR_BR_UNORM8 , other , 2, 1, 1, x16 , , , , xyz1, rgb
diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
index 0e778d64467..1ab03d2be7e 100644
--- a/src/mesa/main/formats.h
+++ b/src/mesa/main/formats.h
@@ -624,6 +624,12 @@ typedef enum pipe_format mesa_format;
#define HAVE_MESA_FORMAT_YVU420_2PLANE
#define MESA_FORMAT_YVU420_2PLANE PIPE_FORMAT_YVU420_2PLANE
+#define HAVE_MESA_FORMAT_YUV420_3PLANE
+#define MESA_FORMAT_YUV420_3PLANE PIPE_FORMAT_YUV420_3PLANE
+
+#define HAVE_MESA_FORMAT_YVU420_3PLANE
+#define MESA_FORMAT_YVU420_3PLANE PIPE_FORMAT_YVU420_3PLANE
+
#define MESA_FORMAT_COUNT PIPE_FORMAT_COUNT
/* Packed to array format adapters */
--
2.25.1

View File

@@ -0,0 +1,58 @@
From 89f34a04c15c8657cb77bbbc94fb9b9d0ac76980 Mon Sep 17 00:00:00 2001
From: Luigi Santivetti <luigi.santivetti@imgtec.com>
Date: Mon, 23 Aug 2021 09:18:37 +0100
Subject: [PATCH 65/67] egl/null: add support for YU12 and YV12
---
src/egl/drivers/dri2/platform_null.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
index 529cc7a2a2f..2e86d6533de 100644
--- a/src/egl/drivers/dri2/platform_null.c
+++ b/src/egl/drivers/dri2/platform_null.c
@@ -106,6 +106,20 @@ static const struct dri2_null_yuv_attrib {
.num_planes = 2,
.plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT,
},
+ {
+ /* __DRI_IMAGE_FORMAT_YU12 */
+ .order = __DRI_ATTRIB_YUV_ORDER_YUV_BIT,
+ .subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT,
+ .num_planes = 3,
+ .plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT,
+ },
+ {
+ /* __DRI_IMAGE_FORMAT_YV12 */
+ .order = __DRI_ATTRIB_YUV_ORDER_YVU_BIT,
+ .subsample = __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT,
+ .num_planes = 3,
+ .plane_bpp = __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT,
+ },
};
/*
@@ -161,6 +175,20 @@ static const struct dri2_null_format {
.rgba_sizes = { 0, 0, 0, 0 },
.yuv = &dri2_null_yuv_attribs[2],
},
+ {
+ .drm_format = DRM_FORMAT_YUV420,
+ .dri_image_format = __DRI_IMAGE_FORMAT_YU12,
+ .rgba_shifts = { -1, -1, -1, -1 },
+ .rgba_sizes = { 0, 0, 0, 0 },
+ .yuv = &dri2_null_yuv_attribs[3],
+ },
+ {
+ .drm_format = DRM_FORMAT_YVU420,
+ .dri_image_format = __DRI_IMAGE_FORMAT_YV12,
+ .rgba_shifts = { -1, -1, -1, -1 },
+ .rgba_sizes = { 0, 0, 0, 0 },
+ .yuv = &dri2_null_yuv_attribs[4],
+ },
};
--
2.25.1

View File

@@ -0,0 +1,59 @@
From 28e4349702566ba34dad4c214c64bfd702177c8a Mon Sep 17 00:00:00 2001
From: brendan King <Brendan.King@imgtec.com>
Date: Thu, 16 Sep 2021 17:46:28 +0100
Subject: [PATCH 66/67] mesa: partially revert pbuffer attribute removal
This partially reverts commit 5ffd1ebe6b3c8c7dd316dd47fac088044222e6ef
("mesa: Remove misc pbuffer attributes from struct gl_config").
The IMG PowerVR driver sets meaningful values for the maximum
pbuffer width, height and pixels.
---
src/mesa/drivers/dri/common/utils.c | 7 ++++---
src/mesa/main/mtypes.h | 5 +++++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
index df5f8cbfdc0..28debe4e013 100644
--- a/src/mesa/drivers/dri/common/utils.c
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -480,6 +480,7 @@ __DRIconfig **driConcatConfigs(__DRIconfig **a,
return all;
}
+/* careful, lack of trailing semicolon */
#define __ATTRIB(attrib, field) case attrib: *value = config->modes.field; break
/**
@@ -555,9 +556,9 @@ driGetConfigAttribIndex(const __DRIconfig *config,
__ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask);
__ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask);
__ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask);
- case __DRI_ATTRIB_MAX_PBUFFER_WIDTH:
- case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT:
- case __DRI_ATTRIB_MAX_PBUFFER_PIXELS:
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth);
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight);
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels);
case __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH:
case __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT:
case __DRI_ATTRIB_VISUAL_SELECT_GROUP:
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 8f77d4c58dd..e37c61d23d0 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -175,6 +175,11 @@ struct gl_config
/* ARB_multisample / SGIS_multisample */
GLuint samples;
+ /* GLX 1.3 */
+ GLint maxPbufferWidth;
+ GLint maxPbufferHeight;
+ GLint maxPbufferPixels;
+
/* OML_swap_method */
GLint swapMethod;
--
2.25.1

View File

@@ -0,0 +1,66 @@
From 9bb8868ebab2d041c24c76487b6419a8039a5ce7 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Wed, 4 Jun 2014 13:43:03 +0100
Subject: [PATCH 67/67] egl_dri2: set pbuffer config attribs to 0 for
non-pbuffer configs
If the EGL_PBUFFER_BIT isn't set in the surface type, don't set the
EGL_MAX_PBUFFER_WIDTH, EGL_MAX_PBUFFER_HEIGHT and
EGL_MAX_PBUFFER_PIXELS attributes to non-zero values when adding an
EGL config. If the EGL_PBUFFER_BIT is set, don't override non-zero
values from the DRI config.
---
src/egl/drivers/dri2/egl_dri2.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 56b5175db6e..1b10c2e7362 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -407,6 +407,7 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
_EGLConfig base;
unsigned int attrib, value, double_buffer;
+ unsigned int pbuffer_width = 0, pbuffer_height = 0, pbuffer_pixels = 0;
bool srgb = false;
EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
int dri_shifts[4] = { -1, -1, -1, -1 };
@@ -530,11 +531,17 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
break;
case __DRI_ATTRIB_MAX_PBUFFER_WIDTH:
- base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
+ pbuffer_width = (value != 0) ? value : _EGL_MAX_PBUFFER_WIDTH;
break;
+
case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT:
- base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
+ pbuffer_height = (value != 0) ? value : _EGL_MAX_PBUFFER_HEIGHT;
+ break;
+
+ case __DRI_ATTRIB_MAX_PBUFFER_PIXELS:
+ pbuffer_pixels = value;
break;
+
case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER:
if (disp->Extensions.KHR_mutable_render_buffer)
surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
@@ -614,6 +621,15 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
}
}
+ if (surface_type & EGL_PBUFFER_BIT) {
+ if (pbuffer_pixels == 0)
+ pbuffer_pixels = pbuffer_width * pbuffer_height;
+
+ base.MaxPbufferWidth = pbuffer_width;
+ base.MaxPbufferHeight = pbuffer_height;
+ base.MaxPbufferPixels = pbuffer_pixels;
+ }
+
if (attr_list)
for (int i = 0; attr_list[i] != EGL_NONE; i += 2)
_eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
--
2.25.1

View File

@@ -0,0 +1,146 @@
From f9c028d508bac22d7c78b0232c625e27d13340a7 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 11 Nov 2021 12:09:38 +0000
Subject: [PATCH 68/68] GL_ARB_geometry_shader4 entry points.
---
src/mapi/glapi/gen/ARB_geometry_shader4.xml | 97 +++++++++++++++++++++
src/mapi/glapi/gen/gl_API.xml | 2 +-
src/mapi/glapi/gen/static_data.py | 4 +
3 files changed, 102 insertions(+), 1 deletion(-)
create mode 100644 src/mapi/glapi/gen/ARB_geometry_shader4.xml
diff --git a/src/mapi/glapi/gen/ARB_geometry_shader4.xml b/src/mapi/glapi/gen/ARB_geometry_shader4.xml
new file mode 100644
index 00000000000..d92dc577b17
--- /dev/null
+++ b/src/mapi/glapi/gen/ARB_geometry_shader4.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+<category name="GL_ARB_geometry_shader4" number="47">
+ <enum name="GEOMETRY_SHADER_ARB" value="0x8DD9"/>
+ <enum name="GEOMETRY_VERTICES_OUT_ARB" value="0x8DDA"/>
+ <enum name="GEOMETRY_INPUT_TYPE_ARB" value="0x8DDB"/>
+ <enum name="GEOMETRY_OUTPUT_TYPE_ARB" value="0x8DDC"/>
+
+ <enum name="MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB"
+ count="1" value="0x8C29">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_GEOMETRY_VARYING_COMPONENTS_ARB"
+ count="1" value="0x8DDD">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_VERTEX_VARYING_COMPONENTS_ARB"
+ count="1" value="0x8DDE">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_VARYING_COMPONENTS"
+ count="1" value="0x8B4B">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB"
+ count="1" value="0x8DDF">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_GEOMETRY_OUTPUT_VERTICES_ARB"
+ count="1" value="0x8DE0">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB"
+ count="1" value="0x8DE1">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <enum name="LINES_ADJACENCY_ARB" value="0xA"/>
+ <enum name="LINE_STRIP_ADJACENCY_ARB" value="0xB"/>
+ <enum name="TRIANGLES_ADJACENCY_ARB" value="0xC"/>
+ <enum name="TRIANGLE_STRIP_ADJACENCY_ARB" value="0xD"/>
+
+ <enum name="FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB" value="0x8DA8"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB" value="0x8DA9"/>
+
+
+ <enum name="FRAMEBUFFER_ATTACHMENT_LAYERED_ARB"
+ count="1" value="0x8DA7">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER"
+ count="1" value="0x8CD4">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+
+ <enum name="PROGRAM_POINT_SIZE_ARB" value="0x8642"/>
+ <enum name="PROGRAM_POINT_SIZE_ARB"
+ count="1" value="0x8642">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="ProgramParameteriARB" exec="dynamic">
+ <param name="program" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="value" type="GLint"/>
+ </function>
+
+ <function name="FramebufferTextureARB" exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ </function>
+
+ <function name="FramebufferTextureLayerARB" exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="layer" type="GLint"/>
+ </function>
+
+ <function name="FramebufferTextureFaceARB" exec="dynamic">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="face" type="GLenum"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 4e35de0f4ea..d5a5e7f5386 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -8064,7 +8064,7 @@
<!-- 46. GL_ARB_framebuffer_sRGB -->
-<!-- 47. GL_ARB_geometry_shader4. There are no intentions to implement this extension -->
+<xi:include href="ARB_geometry_shader4.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<!-- 48. GL_ARB_half_float_vertex -->
diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py
index 974f366d7b4..833ad73dd6a 100644
--- a/src/mapi/glapi/gen/static_data.py
+++ b/src/mapi/glapi/gen/static_data.py
@@ -1721,6 +1721,10 @@ offsets = {
"FramebufferRenderbufferEXT" : 1685,
"GetFramebufferAttachmentParameterivEXT" : 1686,
"GenerateMipmapEXT" : 1687,
+ "ProgramParameteriARB" : 1688,
+ "FramebufferTextureARB" : 1689,
+ "FramebufferTextureLayerARB" : 1690,
+ "FramebufferTextureFaceARB" : 1691,
}
functions = [
--
2.25.1