From c50e5ba7a5e897d65b4983ad532a3f84b3cbfd4d Mon Sep 17 00:00:00 2001 From: Windsome Zeng Date: Tue, 21 Jun 2022 14:08:48 +0800 Subject: [PATCH] Add Wayland with GPU support. Cherry-pick from http://192.168.110.45/sdk/buildroot/-/commit/ed70e2b79cbc7a504792899e2cd3577777fd54bd --- package/mesa3d/0001-Add-pvr-dri-driver.patch | 10205 ++++++++++++++++ ...rt-isinf-for-uclibc-based-toolchains.patch | 30 - ...e-the-PVR-driver-for-platform-device.patch | 34 + ...t-proper-value-for-LIBCLC_INCLUDEDIR.patch | 41 - ...Add-some-new-DRI-formats-and-fourccs.patch | 80 + ...tion-to-disable-optional-neon-suppor.patch | 84 - ...4-GL_EXT_sparse_texture-entry-points.patch | 104 + ...r-Include-stddef.h-to-fix-build-erro.patch | 40 - ...-support-for-various-GLES-extensions.patch | 106 + ...-fix-build-on-32-bit-architectures-u.patch | 43 - .../0006-Add-EGL_IMG_cl_image-extension.patch | 187 + ...ffer-config-attribs-to-0-for-non-pbu.patch | 66 + ...when-making-a-context-current-withou.patch | 51 + ...MakeCurrent-for-the-case-where-nothi.patch | 46 + ...er_pixel_local_storage2-entry-points.patch | 84 + ..._framebuffer_downsample-entry-points.patch | 85 + .../0012-GL_OVR_multiview-entry-points.patch | 53 + ...iview_multisampled_render_to_texture.patch | 68 + ...all-wayland-drm.xml-to-the-configure.patch | 57 + ...fer-sharing-in-the-kms_swrast-driver.patch | 27 + ...-add-support-for-RGB565-back-buffers.patch | 46 + ...-dri3-fix-segfault-in-eglCopyBuffers.patch | 49 + ...y-call-eglReleaseThread-on-thread-te.patch | 78 + .../0019-egl-add-Tizen-platform-support.patch | 1637 +++ ...t-for-EGL_TIZEN_image_native_surface.patch | 231 + ...nd-post-maximum-damage-when-blitting.patch | 33 + ...d-flush-the-drawable-before-blitting.patch | 46 + ...-an-internal-_EGLImage-for-each-tbm-.patch | 380 + ...supported-API-in-driCreateNewContext.patch | 54 + package/mesa3d/0025-gbm-add-gbm_bo_blit.patch | 157 + ...assert-if-DRI-context-creation-fails.patch | 44 + ...0027-egl-wayland-add-pbuffer-support.patch | 471 + ...t-DRI-driver-handling-of-swap-preser.patch | 121 + ...l-eglBindAPI-workaround-for-dEQP-bug.patch | 29 + ...EXT_multi_draw_indirect-entry-points.patch | 56 + ...1-dri-add-support-for-YUV-DRI-config.patch | 494 + ...-egl-add-support-for-EXT_yuv_surface.patch | 541 + ...__DRI_IMAGE_COMPONENTS-define-for-EG.patch | 35 + ...yland-expose-EXT_yuv_surface-support.patch | 74 + ...tizen-expose-EXT_yuv_surface-support.patch | 357 + .../0036-gbm-add-some-new-GBM-formats.patch | 69 + .../mesa3d/0037-egl-add-null-platform.patch | 1471 +++ .../0038-egl-add-config-debug-printout.patch | 480 + ...-support-for-EXT_image_gl_colorspace.patch | 217 + ...-meson-force-C-2011-for-thread_local.patch | 35 + ...port-for-swap-intervals-other-than-1.patch | 785 ++ ...d-support-for-explicit-synchronisati.patch | 214 + ...dri2-add-support-for-image-modifiers.patch | 372 + ...ry-the-supported-ES2-context-version.patch | 203 + ...-allow-libGL-to-be-built-without-GLX.patch | 140 + ...-process-non-resized-window-movement.patch | 38 + ..._framebuffer_object-from-ARB-version.patch | 539 + ...port-for-async-flip-with-front-buffe.patch | 321 + .../mesa3d/0049-gbm-add-pbuffer-support.patch | 229 + ...-null-expose-EXT_yuv_surface-support.patch | 84 + package/mesa3d/Config.in | 7 + package/mesa3d/mesa3d.hash | 6 +- package/mesa3d/mesa3d.mk | 9 +- package/starfive/Config.in | 1 + package/starfive/img-gpu-powervr/Config.in | 97 + .../img-gpu-powervr/img-gpu-powervr.hash | 5 + .../img-gpu-powervr/img-gpu-powervr.mk | 99 + ...ble-bo-geometry-out-of-bounds-messag.patch | 29 + ...-checks-for-dmabufs-with-DRM-modifie.patch | 63 + package/weston/Config.in | 4 +- 65 files changed, 21691 insertions(+), 250 deletions(-) create mode 100644 package/mesa3d/0001-Add-pvr-dri-driver.patch delete mode 100644 package/mesa3d/0001-c99_math-import-isinf-for-uclibc-based-toolchains.patch create mode 100644 package/mesa3d/0002-Force-Mesa-to-use-the-PVR-driver-for-platform-device.patch delete mode 100644 package/mesa3d/0002-meson-Set-proper-value-for-LIBCLC_INCLUDEDIR.patch create mode 100644 package/mesa3d/0003-dri-Add-some-new-DRI-formats-and-fourccs.patch delete mode 100644 package/mesa3d/0003-vc4-add-meson-option-to-disable-optional-neon-suppor.patch create mode 100644 package/mesa3d/0004-GL_EXT_sparse_texture-entry-points.patch delete mode 100644 package/mesa3d/0004-src-util-rand_xor-Include-stddef.h-to-fix-build-erro.patch create mode 100644 package/mesa3d/0005-Add-support-for-various-GLES-extensions.patch delete mode 100644 package/mesa3d/0005-src-util-futex.h-fix-build-on-32-bit-architectures-u.patch create mode 100644 package/mesa3d/0006-Add-EGL_IMG_cl_image-extension.patch create mode 100644 package/mesa3d/0007-egl_dri2-set-pbuffer-config-attribs-to-0-for-non-pbu.patch create mode 100644 package/mesa3d/0008-egl-Be-stricter-when-making-a-context-current-withou.patch create mode 100644 package/mesa3d/0009-egl-optimise-eglMakeCurrent-for-the-case-where-nothi.patch create mode 100644 package/mesa3d/0010-GL_EXT_shader_pixel_local_storage2-entry-points.patch create mode 100644 package/mesa3d/0011-GL_IMG_framebuffer_downsample-entry-points.patch create mode 100644 package/mesa3d/0012-GL_OVR_multiview-entry-points.patch create mode 100644 package/mesa3d/0013-Add-OVR_multiview_multisampled_render_to_texture.patch create mode 100644 package/mesa3d/0014-wayland-drm-install-wayland-drm.xml-to-the-configure.patch create mode 100644 package/mesa3d/0015-Enable-buffer-sharing-in-the-kms_swrast-driver.patch create mode 100644 package/mesa3d/0016-egl-wayland-add-support-for-RGB565-back-buffers.patch create mode 100644 package/mesa3d/0017-egl-dri3-fix-segfault-in-eglCopyBuffers.patch create mode 100644 package/mesa3d/0018-egl-automatically-call-eglReleaseThread-on-thread-te.patch create mode 100644 package/mesa3d/0019-egl-add-Tizen-platform-support.patch create mode 100644 package/mesa3d/0020-egl-add-support-for-EGL_TIZEN_image_native_surface.patch create mode 100644 package/mesa3d/0021-egl-wayland-post-maximum-damage-when-blitting.patch create mode 100644 package/mesa3d/0022-egl-wayland-flush-the-drawable-before-blitting.patch create mode 100644 package/mesa3d/0023-egl-tizen-create-an-internal-_EGLImage-for-each-tbm-.patch create mode 100644 package/mesa3d/0024-dri-use-a-supported-API-in-driCreateNewContext.patch create mode 100644 package/mesa3d/0025-gbm-add-gbm_bo_blit.patch create mode 100644 package/mesa3d/0026-gbm-don-t-assert-if-DRI-context-creation-fails.patch create mode 100644 package/mesa3d/0027-egl-wayland-add-pbuffer-support.patch create mode 100644 package/mesa3d/0028-egl-tizen-support-DRI-driver-handling-of-swap-preser.patch create mode 100644 package/mesa3d/0029-egl-eglBindAPI-workaround-for-dEQP-bug.patch create mode 100644 package/mesa3d/0030-GL_EXT_multi_draw_indirect-entry-points.patch create mode 100644 package/mesa3d/0031-dri-add-support-for-YUV-DRI-config.patch create mode 100644 package/mesa3d/0032-egl-add-support-for-EXT_yuv_surface.patch create mode 100644 package/mesa3d/0033-dri-add-missing-__DRI_IMAGE_COMPONENTS-define-for-EG.patch create mode 100644 package/mesa3d/0034-egl-wayland-expose-EXT_yuv_surface-support.patch create mode 100644 package/mesa3d/0035-egl-tizen-expose-EXT_yuv_surface-support.patch create mode 100644 package/mesa3d/0036-gbm-add-some-new-GBM-formats.patch create mode 100644 package/mesa3d/0037-egl-add-null-platform.patch create mode 100644 package/mesa3d/0038-egl-add-config-debug-printout.patch create mode 100644 package/mesa3d/0039-egl-add-support-for-EXT_image_gl_colorspace.patch create mode 100644 package/mesa3d/0040-meson-force-C-2011-for-thread_local.patch create mode 100644 package/mesa3d/0041-dri2-add-support-for-swap-intervals-other-than-1.patch create mode 100644 package/mesa3d/0042-null_platform-add-support-for-explicit-synchronisati.patch create mode 100644 package/mesa3d/0043-dri2-add-support-for-image-modifiers.patch create mode 100644 package/mesa3d/0044-egl-query-the-supported-ES2-context-version.patch create mode 100644 package/mesa3d/0045-meson-allow-libGL-to-be-built-without-GLX.patch create mode 100644 package/mesa3d/0046-egl-wayland-process-non-resized-window-movement.patch create mode 100644 package/mesa3d/0047-Separate-EXT_framebuffer_object-from-ARB-version.patch create mode 100644 package/mesa3d/0048-egl-null-add-support-for-async-flip-with-front-buffe.patch create mode 100644 package/mesa3d/0049-gbm-add-pbuffer-support.patch create mode 100644 package/mesa3d/0050-egl-null-expose-EXT_yuv_surface-support.patch create mode 100644 package/starfive/img-gpu-powervr/Config.in create mode 100644 package/starfive/img-gpu-powervr/img-gpu-powervr.hash create mode 100644 package/starfive/img-gpu-powervr/img-gpu-powervr.mk create mode 100644 package/weston/0005-backend-drm-disable-bo-geometry-out-of-bounds-messag.patch create mode 100644 package/weston/0006-libweston-reduce-checks-for-dmabufs-with-DRM-modifie.patch diff --git a/package/mesa3d/0001-Add-pvr-dri-driver.patch b/package/mesa3d/0001-Add-pvr-dri-driver.patch new file mode 100644 index 00000000..574d87a9 --- /dev/null +++ b/package/mesa3d/0001-Add-pvr-dri-driver.patch @@ -0,0 +1,10205 @@ +From 2c1b96a851f2313e6832989fe13d49ca05c4545c Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Tue, 14 Apr 2020 09:47:46 +0100 +Subject: [PATCH 01/50] Add pvr dri driver + +--- + meson.build | 19 +- + meson_options.txt | 2 +- + src/mesa/drivers/dri/meson.build | 5 + + src/mesa/drivers/dri/pvr/dri_support.h | 1270 ++++++++++++++++ + src/mesa/drivers/dri/pvr/img_drm_fourcc.h | 113 ++ + src/mesa/drivers/dri/pvr/imgpixfmts.h | 307 ++++ + src/mesa/drivers/dri/pvr/imgyuv.h | 58 + + src/mesa/drivers/dri/pvr/mesa_context.c | 208 +++ + src/mesa/drivers/dri/pvr/meson.build | 53 + + src/mesa/drivers/dri/pvr/pvrcb.c | 282 ++++ + src/mesa/drivers/dri/pvr/pvrcompat.c | 1552 ++++++++++++++++++++ + src/mesa/drivers/dri/pvr/pvrdrawable_mod.c | 385 +++++ + src/mesa/drivers/dri/pvr/pvrdri.c | 603 ++++++++ + src/mesa/drivers/dri/pvr/pvrdri.h | 176 +++ + src/mesa/drivers/dri/pvr/pvrdri_mod.c | 584 ++++++++ + src/mesa/drivers/dri/pvr/pvrdri_mod.h | 450 ++++++ + src/mesa/drivers/dri/pvr/pvrdri_support.h | 439 ++++++ + src/mesa/drivers/dri/pvr/pvrext.c | 698 +++++++++ + src/mesa/drivers/dri/pvr/pvrext_mod.c | 276 ++++ + src/mesa/drivers/dri/pvr/pvrimage_mod.c | 1282 ++++++++++++++++ + src/mesa/drivers/dri/pvr/pvrmesa.h | 36 + + src/mesa/drivers/dri/pvr/pvrutil.c | 239 +++ + src/mesa/drivers/dri/pvr/pvrutil_mod.c | 921 ++++++++++++ + src/meson.build | 1 + + 24 files changed, 9950 insertions(+), 9 deletions(-) + create mode 100644 src/mesa/drivers/dri/pvr/dri_support.h + create mode 100644 src/mesa/drivers/dri/pvr/img_drm_fourcc.h + create mode 100644 src/mesa/drivers/dri/pvr/imgpixfmts.h + create mode 100644 src/mesa/drivers/dri/pvr/imgyuv.h + create mode 100644 src/mesa/drivers/dri/pvr/mesa_context.c + create mode 100644 src/mesa/drivers/dri/pvr/meson.build + create mode 100644 src/mesa/drivers/dri/pvr/pvrcb.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrcompat.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrdrawable_mod.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrdri.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrdri.h + create mode 100644 src/mesa/drivers/dri/pvr/pvrdri_mod.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrdri_mod.h + create mode 100644 src/mesa/drivers/dri/pvr/pvrdri_support.h + create mode 100644 src/mesa/drivers/dri/pvr/pvrext.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrext_mod.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrimage_mod.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrmesa.h + create mode 100644 src/mesa/drivers/dri/pvr/pvrutil.c + create mode 100644 src/mesa/drivers/dri/pvr/pvrutil_mod.c + +diff --git a/meson.build b/meson.build +index 932eb136681..15e08dfea1c 100644 +--- a/meson.build ++++ b/meson.build +@@ -160,11 +160,11 @@ if dri_drivers.contains('auto') + if system_has_kms_drm + # TODO: PPC, Sparc + if ['x86', 'x86_64'].contains(host_machine.cpu_family()) +- dri_drivers = ['i915', 'i965', 'r100', 'r200', 'nouveau'] ++ dri_drivers = ['i915', 'i965', 'r100', 'r200', 'nouveau', 'pvr'] + elif ['arm', 'aarch64'].contains(host_machine.cpu_family()) +- dri_drivers = [] ++ dri_drivers = ['pvr'] + elif ['mips', 'mips64'].contains(host_machine.cpu_family()) +- dri_drivers = ['r100', 'r200', 'nouveau'] ++ dri_drivers = ['r100', 'r200', 'nouveau', 'pvr'] + else + error('Unknown architecture @0@. Please pass -Ddri-drivers to set driver options. Patches gladly accepted to fix this.'.format( + host_machine.cpu_family())) +@@ -183,6 +183,7 @@ with_dri_i965 = dri_drivers.contains('i965') + with_dri_r100 = dri_drivers.contains('r100') + with_dri_r200 = dri_drivers.contains('r200') + with_dri_nouveau = dri_drivers.contains('nouveau') ++with_dri_pvr = dri_drivers.contains('pvr') + + with_dri = dri_drivers.length() != 0 + +@@ -1435,14 +1436,16 @@ _drm_amdgpu_ver = '2.4.100' + _drm_radeon_ver = '2.4.71' + _drm_nouveau_ver = '2.4.102' + _drm_intel_ver = '2.4.75' ++_drm_pvr_ver = '2.4.60' + _drm_ver = '2.4.81' + + _libdrm_checks = [ +- ['intel', with_dri_i915 or with_gallium_i915], +- ['amdgpu', with_amd_vk or with_gallium_radeonsi], ++ ['intel', with_dri_i915 or with_gallium_i915, true], ++ ['amdgpu', with_amd_vk or with_gallium_radeonsi, true], + ['radeon', (with_gallium_radeonsi or with_dri_r100 or with_dri_r200 or +- with_gallium_r300 or with_gallium_r600)], +- ['nouveau', (with_gallium_nouveau or with_dri_nouveau)], ++ with_gallium_r300 or with_gallium_r600), true], ++ ['nouveau', (with_gallium_nouveau or with_dri_nouveau), true], ++ ['pvr', with_dri_pvr, false], + ] + + # VC4 only needs core libdrm support of this version, not a libdrm_vc4 +@@ -1472,7 +1475,7 @@ endif + + # Then get each libdrm module + foreach d : _libdrm_checks +- if d[1] ++ if d[1] and d[2] + set_variable( + 'dep_libdrm_' + d[0], + dependency('libdrm_' + d[0], version : '>=' + _drm_ver) +diff --git a/meson_options.txt b/meson_options.txt +index fc73f6e1c24..6f001343ae6 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -45,7 +45,7 @@ option( + 'dri-drivers', + type : 'array', + value : ['auto'], +- choices : ['auto', 'i915', 'i965', 'r100', 'r200', 'nouveau'], ++ choices : ['auto', 'i915', 'i965', 'r100', 'r200', 'nouveau', 'pvr'], + description : 'List of dri drivers to build. If this is set to auto all drivers applicable to the target OS/architecture will be built' + ) + option( +diff --git a/src/mesa/drivers/dri/meson.build b/src/mesa/drivers/dri/meson.build +index 97210c8e638..2018e3fc1c4 100644 +--- a/src/mesa/drivers/dri/meson.build ++++ b/src/mesa/drivers/dri/meson.build +@@ -47,6 +47,11 @@ if with_dri_nouveau + _dri_drivers += libnouveau_vieux + _dri_link += 'nouveau_vieux_dri.so' + endif ++if with_dri_pvr ++ subdir('pvr') ++ _dri_drivers += libpvr ++ _dri_link += 'pvr_dri.so' ++endif + + if _dri_drivers != [] + libmesa_dri_drivers = shared_library( +diff --git a/src/mesa/drivers/dri/pvr/dri_support.h b/src/mesa/drivers/dri/pvr/dri_support.h +new file mode 100644 +index 00000000000..b5da4d95a03 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/dri_support.h +@@ -0,0 +1,1270 @@ ++/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ ++/* vi: set ts=8 sw=8 sts=8: */ ++/*************************************************************************/ /*! ++@File ++@Title PVR DRI interface definition ++@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved ++@License MIT ++ ++The contents of this file are subject to the MIT license as set out below. ++ ++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 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. ++*/ /**************************************************************************/ ++ ++#if !defined(__PVRDRIIFCE_H__) ++#define __PVRDRIIFCE_H__ ++ ++#include ++#include ++ ++#include "imgpixfmts.h" ++#include "imgyuv.h" ++ ++typedef enum ++{ ++ PVRDRI_DEVICE_TYPE_INVALID = 0, ++ PVRDRI_DEVICE_TYPE_UNKNOWN, ++ PVRDRI_DEVICE_TYPE_DISPLAY, ++ PVRDRI_DEVICE_TYPE_RENDER, ++ PVRDRI_DEVICE_TYPE_CARD, ++} PVRDRIDeviceType; ++ ++/* API type. */ ++typedef enum ++{ ++ PVRDRI_API_NONE = 0, ++ PVRDRI_API_GLES1 = 2, ++ PVRDRI_API_GLES2 = 3, ++ PVRDRI_API_CL = 4, ++ PVRDRI_API_GL_COMPAT = 5, ++ PVRDRI_API_GL_CORE = 6, ++} PVRDRIAPIType; ++ ++/* API sub type. */ ++typedef enum ++{ ++ PVRDRI_API_SUB_NONE, ++} PVRDRIAPISubType; ++ ++typedef enum ++{ ++ PVRDRI_DRAWABLE_NONE = 0, ++ PVRDRI_DRAWABLE_WINDOW = 1, ++ PVRDRI_DRAWABLE_PIXMAP = 2, ++ PVRDRI_DRAWABLE_PBUFFER = 3, ++} PVRDRIDrawableType; ++ ++typedef enum ++{ ++ PVRDRI_IMAGE = 1, ++ PVRDRI_IMAGE_FROM_NAMES, ++ PVRDRI_IMAGE_FROM_EGLIMAGE, ++ PVRDRI_IMAGE_FROM_DMABUFS, ++ PVRDRI_IMAGE_SUBIMAGE, ++} PVRDRIImageType; ++ ++typedef enum ++{ ++ PVRDRI_EGLIMAGE_NONE = 0, ++ PVRDRI_EGLIMAGE_IMGEGL, ++ PVRDRI_EGLIMAGE_IMGOCL, ++} PVRDRIEGLImageType; ++ ++typedef enum ++{ ++ /* Since PVRDRICallbacks version 2 */ ++ PVRDRI_CONFIG_ATTRIB_INVALID = 0, ++ PVRDRI_CONFIG_ATTRIB_RENDERABLE_TYPE = 1, ++ PVRDRI_CONFIG_ATTRIB_RGB_MODE = 2, ++ PVRDRI_CONFIG_ATTRIB_DOUBLE_BUFFER_MODE = 3, ++ PVRDRI_CONFIG_ATTRIB_RED_BITS = 4, ++ PVRDRI_CONFIG_ATTRIB_GREEN_BITS = 5, ++ PVRDRI_CONFIG_ATTRIB_BLUE_BITS = 6, ++ PVRDRI_CONFIG_ATTRIB_ALPHA_BITS = 7, ++ PVRDRI_CONFIG_ATTRIB_RGB_BITS = 8, ++ PVRDRI_CONFIG_ATTRIB_DEPTH_BITS = 9, ++ PVRDRI_CONFIG_ATTRIB_STENCIL_BITS = 10, ++ PVRDRI_CONFIG_ATTRIB_SAMPLE_BUFFERS = 11, ++ PVRDRI_CONFIG_ATTRIB_SAMPLES = 12, ++ PVRDRI_CONFIG_ATTRIB_BIND_TO_TEXTURE_RGB = 13, ++ PVRDRI_CONFIG_ATTRIB_BIND_TO_TEXTURE_RGBA = 14, ++ PVRDRI_CONFIG_ATTRIB_YUV_ORDER = 15, ++ PVRDRI_CONFIG_ATTRIB_YUV_NUM_OF_PLANES = 16, ++ PVRDRI_CONFIG_ATTRIB_YUV_SUBSAMPLE = 17, ++ PVRDRI_CONFIG_ATTRIB_YUV_DEPTH_RANGE = 18, ++ PVRDRI_CONFIG_ATTRIB_YUV_CSC_STANDARD = 19, ++ PVRDRI_CONFIG_ATTRIB_YUV_PLANE_BPP = 20, ++ ++ /* Valid for use with with PVRDRICallbacksV2 */ ++ PVRDRI_CONFIG_ATTRIB_RED_MASK = 21, ++ PVRDRI_CONFIG_ATTRIB_GREEN_MASK = 22, ++ PVRDRI_CONFIG_ATTRIB_BLUE_MASK = 23, ++ PVRDRI_CONFIG_ATTRIB_ALPHA_MASK = 24, ++ PVRDRI_CONFIG_ATTRIB_SRGB_CAPABLE = 25 ++} PVRDRIConfigAttrib; ++ ++typedef enum ++{ ++ /* Since PVRDRICallbacks version 2 */ ++ PVRDRI_BUFFER_ATTRIB_INVALID = 0, ++ PVRDRI_BUFFER_ATTRIB_TYPE = 1, ++ PVRDRI_BUFFER_ATTRIB_WIDTH = 2, ++ PVRDRI_BUFFER_ATTRIB_HEIGHT = 3, ++ PVRDRI_BUFFER_ATTRIB_STRIDE = 4, ++ PVRDRI_BUFFER_ATTRIB_PIXEL_FORMAT = 5, ++} PVRDRIBufferAttrib; ++ ++/* The context flags match their __DRI_CTX_FLAG and EGL_CONTEXT counterparts */ ++#define PVRDRI_CONTEXT_FLAG_DEBUG 0x00000001 ++#define PVRDRI_CONTEXT_FLAG_FORWARD_COMPATIBLE 0x00000002 ++#define PVRDRI_CONTEXT_FLAG_ROBUST_BUFFER_ACCESS 0x00000004 ++ ++/* The context error codes match their __DRI_CTX_ERROR counterparts */ ++#define PVRDRI_CONTEXT_ERROR_SUCCESS 0 ++/* Out of memory */ ++#define PVRDRI_CONTEXT_ERROR_NO_MEMORY 1 ++/* Unsupported API */ ++#define PVRDRI_CONTEXT_ERROR_BAD_API 2 ++/* Unsupported version of API */ ++#define PVRDRI_CONTEXT_ERROR_BAD_VERSION 3 ++/* Unsupported context flag or combination of flags */ ++#define PVRDRI_CONTEXT_ERROR_BAD_FLAG 4 ++/* Unrecognised context attribute */ ++#define PVRDRI_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE 5 ++/* Unrecognised context flag */ ++#define PVRDRI_CONTEXT_ERROR_UNKNOWN_FLAG 6 ++ ++/* ++ * The context priority defines match their __DRI_CTX counterparts, and ++ * the context priority values used by the DDK. ++ */ ++#define PVRDRI_CONTEXT_PRIORITY_LOW 0 ++#define PVRDRI_CONTEXT_PRIORITY_MEDIUM 1 ++#define PVRDRI_CONTEXT_PRIORITY_HIGH 2 ++ ++/* The image error flags match their __DRI_IMAGE_ERROR counterparts */ ++#define PVRDRI_IMAGE_ERROR_SUCCESS 0 ++#define PVRDRI_IMAGE_ERROR_BAD_ALLOC 1 ++#define PVRDRI_IMAGE_ERROR_BAD_MATCH 2 ++#define PVRDRI_IMAGE_ERROR_BAD_PARAMETER 3 ++#define PVRDRI_IMAGE_ERROR_BAD_ACCESS 4 ++ ++/* The buffer flags match their __DRI_IMAGE_USE counterparts */ ++#define PVDRI_BUFFER_USE_SHARE 0x0001 ++#define PVDRI_BUFFER_USE_SCANOUT 0x0002 ++#define PVDRI_BUFFER_USE_CURSOR 0x0004 ++#define PVDRI_BUFFER_USE_LINEAR 0x0008 ++ ++/* EGL_RENDERABLE_TYPE mask bits */ ++#define PVRDRI_API_BIT_GLES 0x0001 ++#define PVRDRI_API_BIT_GLES2 0x0004 ++#define PVRDRI_API_BIT_GL 0x0008 ++#define PVRDRI_API_BIT_GLES3 0x0040 ++ ++/* Mesa config formats. These need not match their MESA_FORMAT counterparts */ ++#define PVRDRI_MESA_FORMAT_NONE 0 ++#define PVRDRI_MESA_FORMAT_B8G8R8A8_UNORM 1 ++#define PVRDRI_MESA_FORMAT_B8G8R8X8_UNORM 2 ++#define PVRDRI_MESA_FORMAT_B5G6R5_UNORM 3 ++#define PVRDRI_MESA_FORMAT_R8G8B8A8_UNORM 4 ++#define PVRDRI_MESA_FORMAT_R8G8B8X8_UNORM 5 ++#define PVRDRI_MESA_FORMAT_YCBCR 6 ++#define PVRDRI_MESA_FORMAT_YUV420_2PLANE 7 ++#define PVRDRI_MESA_FORMAT_YVU420_2PLANE 8 ++#define PVRDRI_MESA_FORMAT_B8G8R8A8_SRGB 9 ++#define PVRDRI_MESA_FORMAT_R8G8B8A8_SRGB 10 ++ ++/* The blit flags match their DRI counterparts */ ++#define PVRDRI_BLIT_FLAG_FLUSH 0x0001 ++#define PVRDRI_BLIT_FLAG_FINISH 0x0002 ++ ++/* The image mapping flags match their DRI counterparts */ ++#define PVRDRI_IMAGE_TRANSFER_READ 0x1 ++#define PVRDRI_IMAGE_TRANSFER_WRITE 0x2 ++#define PVRDRI_IMAGE_TRANSFER_READ_WRITE \ ++ (PVRDRI_IMAGE_TRANSFER_READ | PVRDRI_IMAGE_TRANSFER_WRITE) ++ ++/* The PVRDRI_YUV defines match their __DRI_ATTRIB_YUV counterparts */ ++#define PVRDRI_YUV_ORDER_NONE 0x0 ++#define PVRDRI_YUV_ORDER_YUV 0x1 ++#define PVRDRI_YUV_ORDER_YVU 0x2 ++#define PVRDRI_YUV_ORDER_YUYV 0x4 ++#define PVRDRI_YUV_ORDER_UYVY 0x8 ++#define PVRDRI_YUV_ORDER_YVYU 0x10 ++#define PVRDRI_YUV_ORDER_VYUY 0x20 ++#define PVRDRI_YUV_ORDER_AYUV 0x40 ++ ++#define PVRDRI_YUV_SUBSAMPLE_NONE 0x0 ++#define PVRDRI_YUV_SUBSAMPLE_4_2_0 0x1 ++#define PVRDRI_YUV_SUBSAMPLE_4_2_2 0x2 ++#define PVRDRI_YUV_SUBSAMPLE_4_4_4 0x4 ++ ++#define PVRDRI_YUV_DEPTH_RANGE_NONE 0x0 ++#define PVRDRI_YUV_DEPTH_RANGE_LIMITED 0x1 ++#define PVRDRI_YUV_DEPTH_RANGE_FULL 0x2 ++ ++#define PVRDRI_YUV_CSC_STANDARD_NONE 0x0 ++#define PVRDRI_YUV_CSC_STANDARD_601 0x1 ++#define PVRDRI_YUV_CSC_STANDARD_709 0x2 ++#define PVRDRI_YUV_CSC_STANDARD_2020 0x4 ++ ++#define PVRDRI_YUV_PLANE_BPP_NONE 0x0 ++#define PVRDRI_YUV_PLANE_BPP_0 0x1 ++#define PVRDRI_YUV_PLANE_BPP_8 0x2 ++#define PVRDRI_YUV_PLANE_BPP_10 0x4 ++ ++/* Flags for PVRDRICallbacks.DrawableGetParametersV2 */ ++/* Since PVRDRICallbacks version 2 */ ++#define PVRDRI_GETPARAMS_FLAG_ALLOW_RECREATE 0x1 ++/* Since PVRDRICallbacks version 3 */ ++#define PVRDRI_GETPARAMS_FLAG_NO_UPDATE 0x2 ++ ++/* ++ * Capabilities that might be returned by PVRDRIInterface.GetFenceCapabilities. ++ * These match their _DRI_FENCE_CAP counterparts. ++ * ++ * Since PVRDRIInterface version 2. ++ */ ++#define PVRDRI_FENCE_CAP_NATIVE_FD 0x1 ++ ++typedef struct ++{ ++ IMG_PIXFMT ePixFormat; ++ uint32_t uiWidth; ++ uint32_t uiHeight; ++ uint32_t uiStrideInBytes; ++} PVRDRIBufferAttribs; ++ ++typedef struct ++{ ++ int sampleBuffers; ++ int samples; ++ ++ int redBits; ++ int greenBits; ++ int blueBits; ++ int alphaBits; ++ ++ int rgbBits; ++ int depthBits; ++ int stencilBits; ++ ++ bool doubleBufferMode; ++ ++ int bindToTextureRgb; ++ int bindToTextureRgba; ++} PVRDRIConfigInfo; ++ ++typedef struct IMGEGLImageRec IMGEGLImage; ++typedef struct __DRIimageRec __DRIimage; ++ ++/* PVRDRI interface opaque types */ ++typedef struct PVRDRIScreenImplRec PVRDRIScreenImpl; ++typedef struct PVRDRIContextImplRec PVRDRIContextImpl; ++typedef struct PVRDRIDrawableImplRec PVRDRIDrawableImpl; ++typedef struct PVRDRIBufferImplRec PVRDRIBufferImpl; ++ ++typedef struct PVRDRIDrawable_TAG PVRDRIDrawable; ++ ++typedef void (*PVRDRIGLAPIProc)(void); ++ ++/* Since PVRDRICallbacks version 2 */ ++typedef struct PVRDRIConfigRec PVRDRIConfig; ++ ++/* PVRDRISupportInterface (deprecated) */ ++typedef struct { ++ /********************************************************************** ++ * Version 0 interface ++ **********************************************************************/ ++ ++ PVRDRIDeviceType (*GetDeviceTypeFromFd)(int iFd); ++ ++ bool (*IsFirstScreen)(PVRDRIScreenImpl *psScreenImpl); ++ ++ uint32_t (*PixFmtGetDepth)(IMG_PIXFMT eFmt); ++ uint32_t (*PixFmtGetBPP)(IMG_PIXFMT eFmt); ++ uint32_t (*PixFmtGetBlockSize)(IMG_PIXFMT eFmt); ++ ++ /* ScreenImpl functions */ ++ PVRDRIScreenImpl *(*CreateScreen)(int iFd); ++ void (*DestroyScreen)(PVRDRIScreenImpl *psScreenImpl); ++ ++ int (*APIVersion)(PVRDRIAPIType eAPI, ++ PVRDRIAPISubType eAPISub, ++ PVRDRIScreenImpl *psScreenImpl); ++ ++ void *(*EGLGetLibHandle)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl); ++ ++ PVRDRIGLAPIProc (*EGLGetProcAddress)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ const char *psProcName); ++ ++ bool (*EGLFlushBuffers)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl, ++ bool bFlushAllSurfaces, ++ bool bSwapBuffers, ++ bool bWaitForHW); ++ /* Obsolete (no longer supported) */ ++ bool (*EGLFreeResources)(PVRDRIScreenImpl *psPVRScreenImpl); ++ void (*EGLMarkRendersurfaceInvalid)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl); ++ /* Obsolete (no longer supported) */ ++ void (*EGLSetFrontBufferCallback)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl, ++ void (*pfnCallback)(PVRDRIDrawable *)); ++ ++ /* Obsolete (no longer supported) */ ++ unsigned (*CreateContext)(PVRDRIContextImpl **ppsContextImpl, ++ PVRDRIAPIType eAPI, ++ PVRDRIAPISubType eAPISub, ++ PVRDRIScreenImpl *psScreenImpl, ++ const PVRDRIConfigInfo *psConfigInfo, ++ unsigned uMajorVersion, ++ unsigned uMinorVersion, ++ uint32_t uFlags, ++ bool bNotifyReset, ++ unsigned uPriority, ++ PVRDRIContextImpl *psSharedContextImpl); ++ ++ void (*DestroyContext)(PVRDRIContextImpl *psContextImpl, ++ PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl); ++ ++ bool (*MakeCurrentGC)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psWriteImpl, ++ PVRDRIDrawableImpl *psReadImpl); ++ ++ void (*MakeUnCurrentGC)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl); ++ ++ unsigned (*GetImageSource)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ uint32_t uiTarget, ++ uintptr_t uiBuffer, ++ uint32_t uiLevel, ++ IMGEGLImage *psEGLImage); ++ ++ bool (*BindTexImage)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++ ++ void (*ReleaseTexImage)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++ ++ /* Obsolete (no longer supported) */ ++ PVRDRIDrawableImpl *(*CreateDrawable)(PVRDRIDrawable *psPVRDrawable); ++ ++ void (*DestroyDrawable)(PVRDRIDrawableImpl *psScreenImpl); ++ bool (*EGLDrawableCreate)(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++ bool (*EGLDrawableRecreate)(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++ bool (*EGLDrawableDestroy)(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++ void (*EGLDrawableDestroyConfig)(PVRDRIDrawableImpl *psDrawableImpl); ++ ++ /* Buffer functions */ ++ PVRDRIBufferImpl *(*BufferCreate)(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, ++ int iHeight, ++ unsigned int uiBpp, ++ unsigned int uiUseFlags, ++ unsigned int *puiStride); ++ ++ PVRDRIBufferImpl *(*BufferCreateWithModifiers)(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, ++ int iHeight, ++ int iFormat, ++ IMG_PIXFMT eIMGPixelFormat, ++ const uint64_t *puiModifiers, ++ unsigned int uiModifierCount, ++ unsigned int *puiStride); ++ ++ PVRDRIBufferImpl *(*BufferCreateFromNames)(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, ++ int iHeight, ++ unsigned uiNumPlanes, ++ const int *piName, ++ const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift); ++ ++ /* Obsolete (no longer supported) */ ++ PVRDRIBufferImpl *(*BufferCreateFromName)(PVRDRIScreenImpl *psScreenImpl, ++ int iName, ++ int iWidth, ++ int iHeight, ++ int iStride, ++ int iOffset); ++ ++ /* Obsolete (no longer supported) */ ++ PVRDRIBufferImpl *(*BufferCreateFromFds)(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, ++ int iHeight, ++ unsigned uiNumPlanes, ++ const int *piFd, ++ const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift); ++ ++ PVRDRIBufferImpl *(*BufferCreateFromFdsWithModifier)(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, ++ int iHeight, ++ uint64_t uiModifier, ++ unsigned uiNumPlanes, ++ const int *piFd, ++ const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift); ++ ++ PVRDRIBufferImpl *(*SubBufferCreate)(PVRDRIScreenImpl *psScreen, ++ PVRDRIBufferImpl *psParent, ++ int plane); ++ ++ void (*BufferDestroy)(PVRDRIBufferImpl *psBuffer); ++ ++ int (*BufferGetFd)(PVRDRIBufferImpl *psBuffer); ++ ++ int (*BufferGetHandle)(PVRDRIBufferImpl *psBuffer); ++ ++ uint64_t (*BufferGetModifier)(PVRDRIBufferImpl *psBuffer); ++ ++ int (*BufferGetName)(PVRDRIBufferImpl *psBuffer); ++ ++ int (*BufferGetOffset)(PVRDRIBufferImpl *psBuffer); ++ ++ /* Image functions */ ++ IMGEGLImage *(*EGLImageCreate)(void); ++ IMGEGLImage *(*EGLImageCreateFromBuffer)(int iWidth, ++ int iHeight, ++ int iStride, ++ IMG_PIXFMT ePixelFormat, ++ IMG_YUV_COLORSPACE eColourSpace, ++ IMG_YUV_CHROMA_INTERP eChromaUInterp, ++ IMG_YUV_CHROMA_INTERP eChromaVInterp, ++ PVRDRIBufferImpl *psBuffer); ++ ++ IMGEGLImage *(*EGLImageCreateFromSubBuffer)(IMG_PIXFMT ePixelFormat, ++ PVRDRIBufferImpl *psSubBuffer); ++ ++ IMGEGLImage *(*EGLImageDup)(IMGEGLImage *psIn); ++ ++ void (*EGLImageSetCallbackData)(IMGEGLImage *psEGLImage, __DRIimage *image); ++ ++ void (*EGLImageDestroyExternal)(PVRDRIScreenImpl *psScreenImpl, ++ IMGEGLImage *psEGLImage, ++ PVRDRIEGLImageType eglImageType); ++ void (*EGLImageFree)(IMGEGLImage *psEGLImage); ++ ++ void (*EGLImageGetAttribs)(IMGEGLImage *psEGLImage, ++ PVRDRIBufferAttribs *psAttribs); ++ ++ /* Sync functions */ ++ void *(*CreateFence)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl); ++ ++ void (*DestroyFence)(void *psDRIFence); ++ ++ /* ++ * When calling ClientWaitSync, the eAPI, psContextImpl and ++ * bFlushCommands parameters must be set to PVRDRI_API_NONE, ++ * NULL and false, respectively. ++ */ ++ bool (*ClientWaitSync)(PVRDRIAPIType eAPI, ++ PVRDRIContextImpl *psContextImpl, ++ void *psDRIFence, ++ bool bFlushCommands, ++ bool bTimeout, ++ uint64_t uiTimeout); ++ ++ bool (*ServerWaitSync)(PVRDRIAPIType eAPI, ++ PVRDRIContextImpl *psContextImpl, ++ void *psDRIFence); ++ ++ /* Obsolete (no longer supported) */ ++ void (*DestroyFences)(PVRDRIScreenImpl *psScreenImpl); ++ ++ /* EGL interface functions */ ++ ++ /* Obsolete (no longer supported) */ ++ bool (*EGLDrawableConfigFromGLMode)(PVRDRIDrawableImpl *psPVRDrawable, ++ PVRDRIConfigInfo *psConfigInfo, ++ int supportedAPIs, ++ IMG_PIXFMT ePixFmt); ++ ++ /* Blit functions */ ++ bool (*BlitEGLImage)(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psDstImage, ++ PVRDRIBufferImpl *psDstBuffer, ++ IMGEGLImage *psSrcImage, ++ PVRDRIBufferImpl *psSrcBuffer, ++ int iDstX, int iDstY, ++ int iDstWidth, int iDstHeight, ++ int iSrcX, int iSrcY, ++ int iSrcWidth, int iSrcHeight, ++ int iFlushFlag); ++ ++ /* Mapping functions */ ++ void *(*MapEGLImage)(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psImage, ++ PVRDRIBufferImpl *psBuffer, ++ int iX, int iY, ++ int iWidth, int iHeight, ++ unsigned iFlags, ++ int *piStride, ++ void **ppvData); ++ ++ bool (*UnmapEGLImage)(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psImage, PVRDRIBufferImpl *psBuffer, ++ void *pvData); ++ ++ /* PVR utility support functions */ ++ bool (*MesaFormatSupported)(unsigned fmt); ++ unsigned (*DepthStencilBitArraySize)(void); ++ const uint8_t *(*DepthBitsArray)(void); ++ const uint8_t *(*StencilBitsArray)(void); ++ unsigned (*MSAABitArraySize)(void); ++ const uint8_t *(*MSAABitsArray)(void); ++ uint32_t (*MaxPBufferWidth)(void); ++ uint32_t (*MaxPBufferHeight)(void); ++ ++ unsigned (*GetNumAPIFuncs)(PVRDRIAPIType eAPI); ++ const char *(*GetAPIFunc)(PVRDRIAPIType eAPI, unsigned index); ++ ++ int (*QuerySupportedFormats)(PVRDRIScreenImpl *psScreenImpl, ++ unsigned uNumFormats, ++ const int *piFormats, ++ const IMG_PIXFMT *peImgFormats, ++ bool *pbSupported); ++ ++ int (*QueryModifiers)(PVRDRIScreenImpl *psScreenImpl, ++ int iFormat, ++ IMG_PIXFMT eImgFormat, ++ uint64_t *puModifiers, ++ unsigned *puExternalOnly); ++ ++ /********************************************************************** ++ * Version 1 functions ++ **********************************************************************/ ++ ++ unsigned (*CreateContextV1)(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psSharedContextImpl, ++ PVRDRIConfig *psConfig, ++ PVRDRIAPIType eAPI, ++ PVRDRIAPISubType eAPISub, ++ unsigned uMajorVersion, ++ unsigned uMinorVersion, ++ uint32_t uFlags, ++ bool bNotifyReset, ++ unsigned uPriority, ++ PVRDRIContextImpl **ppsContextImpl); ++ ++ PVRDRIDrawableImpl *(*CreateDrawableWithConfig)(PVRDRIDrawable *psPVRDrawable, ++ PVRDRIConfig *psConfig); ++ ++ /********************************************************************** ++ * Version 2 functions ++ **********************************************************************/ ++ ++ unsigned (*GetFenceCapabilities)(PVRDRIScreenImpl *psScreenImpl); ++ ++ void *(*CreateFenceFd)(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ int iFd); ++ ++ int (*GetFenceFd)(void *psDRIFence); ++} PVRDRISupportInterface; ++ ++/* Callbacks into non-impl layer (deprecated) */ ++typedef struct ++{ ++ /********************************************************************** ++ * Version 0 callbacks ++ **********************************************************************/ ++ ++ /* Obsolete (no longer supported) */ ++ bool (*DrawableRecreate)(PVRDRIDrawable *psPVRDrawable); ++ /* Obsolete (no longer supported) */ ++ bool (*DrawableGetParameters)(PVRDRIDrawable *psPVRDrawable, ++ PVRDRIBufferImpl **ppsDstBuffer, ++ PVRDRIBufferImpl **ppsAccumBuffer, ++ PVRDRIBufferAttribs *psAttribs, ++ bool *pbDoubleBuffered); ++ ++ PVRDRIImageType (*ImageGetSharedType)(__DRIimage *image); ++ PVRDRIBufferImpl *(*ImageGetSharedBuffer)(__DRIimage *image); ++ IMGEGLImage *(*ImageGetSharedEGLImage)(__DRIimage *image); ++ IMGEGLImage *(*ImageGetEGLImage)(__DRIimage *image); ++ __DRIimage *(*ScreenGetDRIImage)(void *hEGLImage); ++ void (*RefImage)(__DRIimage *image); ++ void (*UnrefImage)(__DRIimage *image); ++ ++ /* ++ * If the DRI module calls PVRDRIRegisterCallbacks, or ++ * PVRDRIRegisterVersionedCallbacks with any version number, ++ * the DRI support library can use the callbacks above. ++ * The callbacks below can only be called if ++ * PVRDRIRegisterVersionedCallbacks is called with a suitable ++ * version number. ++ */ ++ ++ /********************************************************************** ++ * Version 1 callbacks ++ **********************************************************************/ ++ ++ /* Obsolete (no longer supported) */ ++ bool (*DrawableGetParametersV1)(PVRDRIDrawable *psPVRDrawable, ++ bool bAllowRecreate, ++ PVRDRIBufferImpl **ppsDstBuffer, ++ PVRDRIBufferImpl **ppsAccumBuffer, ++ PVRDRIBufferAttribs *psAttribs, ++ bool *pbDoubleBuffered); ++ ++ /* ++ * Register the DRI Support interface with the DRI module. ++ * The caller is not required to preserve the PVRDRICallbacks structure ++ * after the call, so the callee must make a copy. ++ */ ++ bool (*RegisterSupportInterfaceV1)(const PVRDRISupportInterface *psInterface, ++ unsigned uVersion); ++ ++ /********************************************************************** ++ * Version 2 callbacks ++ **********************************************************************/ ++ ++ bool (*ConfigQuery)(const PVRDRIConfig *psConfig, ++ PVRDRIConfigAttrib eConfigAttrib, ++ int *piValueOut); ++ /* ++ * DrawableGetParametersV2 is a replacement for DrawableGetParametersV1. ++ * Unlike earlier versions, the caller is expected to query drawable ++ * information (via DrawableQuery) instead of this information being ++ * returned by the callback. ++ */ ++ bool (*DrawableGetParametersV2)(PVRDRIDrawable *psPVRDrawable, ++ uint32_t uiFlags, ++ PVRDRIBufferImpl **ppsDstBuffer, ++ PVRDRIBufferImpl **ppsAccumBuffer); ++ bool (*DrawableQuery)(const PVRDRIDrawable *psPVRDrawable, ++ PVRDRIBufferAttrib eBufferAttrib, ++ uint32_t *uiValueOut); ++ ++ /********************************************************************** ++ * Version 3 callbacks ++ **********************************************************************/ ++} PVRDRICallbacks; ++ ++/* ++ * The caller of PVRDRIRegisterVersionedCallbacks is not required to preserve ++ * the PVRDRICallbacks structure after the call, so the callee may need to ++ * make a copy of the structure. ++ */ ++bool PVRDRIRegisterVersionedCallbacks(const PVRDRICallbacks *psCallbacks, ++ unsigned uVersion); ++ ++/* The context flags match their __DRI_CTX_RESET counterparts */ ++#define PVRDRI_CONTEXT_RESET_NO_NOTIFICATION 0 ++#define PVRDRI_CONTEXT_RESET_LOSE_CONTEXT 1 ++ ++/* The context flags match their __DRI_CTX_RELEASE counterparts */ ++#define PVRDRI_CONTEXT_RELEASE_BEHAVIOR_NONE 0 ++#define PVRDRI_CONTEXT_RELEASE_BEHAVIOR_FLUSH 1 ++ ++/* The flush flags match their __DRI2_FLUSH counterparts */ ++#define PVRDRI_FLUSH_DRAWABLE (1 << 0) ++#define PVRDRI_FLUSH_CONTEXT (1 << 1) ++#define PVRDRI_FLUSH_INVALIDATE_ANCILLARY (1 << 2) ++ ++/* The throttle reason defines match their __DRI2_THROTTLE counterparts */ ++#define PVRDRI_THROTTLE_SWAPBUFFER 0 ++#define PVRDRI_THROTTLE_COPYSUBBUFFER 1 ++#define PVRDRI_THROTTLE_FLUSHFRONT 2 ++ ++/* The render query defines match their __DRI2_RENDERER counterparts */ ++#define PVRDRI_RENDERER_VENDOR_ID 0x0000 ++#define PVRDRI_RENDERER_DEVICE_ID 0x0001 ++ ++#define PVRDRI_RENDERER_HAS_TEXTURE_3D 0x000b ++#define PVRDRI_RENDERER_HAS_FRAMEBUFFER_SRGB 0x000c ++ ++#define PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY 0x000d ++#define PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY_LOW (1 << 0) ++#define PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY_MEDIUM (1 << 1) ++#define PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY_HIGH (1 << 2) ++ ++#define PVRDRI_RENDERER_OPENGL_ES2_CONTEXT_CLIENT_VERSION_IMG 0x7001 ++ ++/* The fence extension defines match their __DRI2_FENCE counterparts */ ++#define PVRDRI_FENCE_TIMEOUT_INFINITE 0xffffffffffffffffull ++#define PVRDRI_FENCE_FLAG_FLUSH_COMMANDS (1 << 0) ++ ++/* The YUV defines match their __DRI_YUV counterparts */ ++#define PVRDRI_YUV_COLOR_SPACE_UNDEFINED 0 ++#define PVRDRI_YUV_COLOR_SPACE_ITU_REC601 0x327F ++#define PVRDRI_YUV_COLOR_SPACE_ITU_REC709 0x3280 ++#define PVRDRI_YUV_COLOR_SPACE_ITU_REC2020 0x3281 ++ ++#define PVRDRI_YUV_RANGE_UNDEFINED 0 ++#define PVRDRI_YUV_FULL_RANGE 0x3282 ++#define PVRDRI_YUV_NARROW_RANGE 0x3283 ++ ++#define PVRDRI_YUV_CHROMA_SITING_UNDEFINED 0 ++#define PVRDRI_YUV_CHROMA_SITING_0 0x3284 ++#define PVRDRI_YUV_CHROMA_SITING_0_5 0x3285 ++ ++/* ++ * The image component defines match their __DRI2_IMAGE_COMPONENTS ++ * counterparts. ++ */ ++#define PVRDRI_IMAGE_COMPONENTS_RGB 0x3001 ++#define PVRDRI_IMAGE_COMPONENTS_RGBA 0x3002 ++#define PVRDRI_IMAGE_COMPONENTS_Y_U_V 0x3003 ++#define PVRDRI_IMAGE_COMPONENTS_Y_UV 0x3004 ++#define PVRDRI_IMAGE_COMPONENTS_Y_XUXV 0x3005 ++#define PVRDRI_IMAGE_COMPONENTS_R 0x3006 ++#define PVRDRI_IMAGE_COMPONENTS_RG 0x3007 ++#define PVRDRI_IMAGE_COMPONENTS_Y_UXVX 0x3008 ++#define PVRDRI_IMAGE_COMPONENTS_AYUV 0x3009 ++#define PVRDRI_IMAGE_COMPONENTS_XYUV 0x300A ++#define PVRDRI_IMAGE_COMPONENTS_EXTERNAL 0x300B ++ ++/* ++ * The image format modifier attribute defines match their ++ * __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB counterparts. ++ */ ++#define PVRDRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT 0x0001 ++ ++/* The image attribute defines match their __DRI_IMAGE_ATTRIB counterparts */ ++#define PVRDRI_IMAGE_ATTRIB_STRIDE 0x2000 ++#define PVRDRI_IMAGE_ATTRIB_HANDLE 0x2001 ++#define PVRDRI_IMAGE_ATTRIB_NAME 0x2002 ++#define PVRDRI_IMAGE_ATTRIB_FORMAT 0x2003 ++#define PVRDRI_IMAGE_ATTRIB_WIDTH 0x2004 ++#define PVRDRI_IMAGE_ATTRIB_HEIGHT 0x2005 ++#define PVRDRI_IMAGE_ATTRIB_COMPONENTS 0x2006 ++#define PVRDRI_IMAGE_ATTRIB_FD 0x2007 ++#define PVRDRI_IMAGE_ATTRIB_FOURCC 0x2008 ++#define PVRDRI_IMAGE_ATTRIB_NUM_PLANES 0x2009 ++#define PVRDRI_IMAGE_ATTRIB_OFFSET 0x200A ++#define PVRDRI_IMAGE_ATTRIB_MODIFIER_LOWER 0x200B ++#define PVRDRI_IMAGE_ATTRIB_MODIFIER_UPPER 0x200C ++ ++/* The GL defines match their EGL_GL counterparts */ ++#define PVRDRI_GL_RENDERBUFFER 0x30B9 ++#define PVRDRI_GL_TEXTURE_2D 0x30B1 ++#define PVRDRI_GL_TEXTURE_3D 0x30B2 ++#define PVRDRI_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3 ++#define PVRDRI_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4 ++#define PVRDRI_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5 ++#define PVRDRI_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 ++#define PVRDRI_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 ++#define PVRDRI_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 ++ ++/* The CL defines match their EGL_CL counterparts */ ++#define PVRDRI_CL_IMAGE_IMG 0x6010 ++ ++/* The swap attribute defines match their __DRI_ATTRIB_SWAP counterparts */ ++#define PVRDRI_ATTRIB_SWAP_NONE 0x0000 ++#define PVRDRI_ATTRIB_SWAP_EXCHANGE 0x8061 ++#define PVRDRI_ATTRIB_SWAP_COPY 0x8062 ++#define PVRDRI_ATTRIB_SWAP_UNDEFINED 0x8063 ++ ++struct __DRIscreenRec; ++struct __DRIcontextRec; ++struct __DRIdrawableRec; ++struct __DRIbufferRec; ++struct __DRIconfigRec; ++ ++struct DRISUPScreen; ++struct DRISUPContext; ++struct DRISUPDrawable; ++struct DRISUPBuffer; ++ ++struct PVRDRIContextConfig ++{ ++ unsigned int uMajorVersion; ++ unsigned int uMinorVersion; ++ uint32_t uFlags; ++ ++ int iResetStrategy; ++ unsigned int uPriority; ++ int iReleaseBehavior; ++}; ++ ++/* The image capability defines match their __DRI_IMAGE_CAP counterparts */ ++#define PVRDRI_IMAGE_CAP_GLOBAL_NAMES 1 ++ ++/* ++ * PVR DRI Support interface V2. ++ * This structure may change over time, as older interfaces become obsolete. ++ * For example, the v0 interface may be removed if superseded by newer ++ * interfaces. ++ */ ++struct PVRDRISupportInterfaceV2 ++{ ++ struct ++ { ++ struct DRISUPScreen *(*CreateScreen) ++ (struct __DRIscreenRec *psDRIScreen, ++ int iFD, ++ bool bUseInvalidate, ++ void *pvLoaderPrivate, ++ const struct __DRIconfigRec ***pppsConfigs, ++ int *piMaxGLES1Version, ++ int *piMaxGLES2Version); ++ ++ void (*DestroyScreen) ++ (struct DRISUPScreen *psDRISUPScreen); ++ ++ unsigned int (*CreateContext) ++ (PVRDRIAPIType eAPI, ++ PVRDRIConfig *psPVRDRIConfig, ++ struct PVRDRIContextConfig *psCtxConfig, ++ struct __DRIcontextRec *psDRIContext, ++ struct DRISUPContext *psDRISUPSharedContext, ++ struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPContext **ppsDRISUPContext); ++ ++ void (*DestroyContext) ++ (struct DRISUPContext *psDRISUPContext); ++ ++ struct DRISUPDrawable *(*CreateDrawable) ++ (struct __DRIdrawableRec *psDRIDrawable, ++ struct DRISUPScreen *psDRISUPDrawable, ++ void *pvLoaderPrivate, ++ PVRDRIConfig *psPVRDRIConfig); ++ ++ void (*DestroyDrawable) ++ (struct DRISUPDrawable *psDRISUPDrawable); ++ ++ bool (*MakeCurrent) ++ (struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPWrite, ++ struct DRISUPDrawable *psDRISUPRead); ++ ++ bool (*UnbindContext) ++ (struct DRISUPContext *psDRISUPContext); ++ ++ struct DRISUPBuffer *(*AllocateBuffer) ++ (struct DRISUPScreen *psDRISUPScreen, ++ unsigned int uAttachment, ++ unsigned int uFormat, ++ int iWidth, ++ int iHeight, ++ unsigned int *puName, ++ unsigned int *puPitch, ++ unsigned int *puCPP, ++ unsigned int *puFlags); ++ ++ void (*ReleaseBuffer) ++ (struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPBuffer *psDRISUPBuffer); ++ ++ /* Functions to support the DRI TexBuffer extension */ ++ void (*SetTexBuffer2) ++ (struct DRISUPContext *psDRISUPContext, ++ int iTarget, ++ int iFormat, ++ struct DRISUPDrawable *psDRISUPDrawable); ++ ++ void (*ReleaseTexBuffer) ++ (struct DRISUPContext *psDRISUPContext, ++ int iTarget, ++ struct DRISUPDrawable *psDRISUPDrawable); ++ ++ /* Functions to support the DRI Flush extension */ ++ void (*Flush) ++ (struct DRISUPDrawable *psDRISUPDrawable); ++ ++ void (*Invalidate) ++ (struct DRISUPDrawable *psDRISUPDrawable); ++ ++ void (*FlushWithFlags) ++ (struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uFlags, ++ unsigned int uThrottleReason); ++ ++ /* Functions to support the DRI Image extension */ ++ __DRIimage *(*CreateImageFromName) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, ++ int iHeight, ++ int iFourCC, ++ int iName, ++ int iPitch, ++ void *pvLoaderPrivate); ++ ++ __DRIimage *(*CreateImageFromRenderbuffer) ++ (struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, ++ void *pvLoaderPrivate); ++ ++ void (*DestroyImage) ++ (__DRIimage *psImage); ++ ++ __DRIimage *(*CreateImage) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, ++ int iHeight, ++ int iFourCC, ++ unsigned int uUse, ++ void *pvLoaderPrivate); ++ ++ bool (*QueryImage) ++ (__DRIimage *psImage, ++ int iAttrib, ++ int *iValue); ++ ++ __DRIimage *(*DupImage) ++ (__DRIimage *psImage, ++ void *pvLoaderPrivate); ++ ++ bool (*ValidateImageUsage) ++ (__DRIimage *psImage, ++ unsigned int uUse); ++ ++ __DRIimage *(*CreateImageFromNames) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, ++ int iHeight, ++ int iFourCC, ++ int *piNames, ++ int iNumNames, ++ int *piStrides, ++ int *piOffsets, ++ void *pvLoaderPrivate); ++ __DRIimage *(*FromPlanar)(__DRIimage *psImage, ++ int iPlane, ++ void *pvLoaderPrivate); ++ ++ __DRIimage *(*CreateImageFromTexture) ++ (struct DRISUPContext *psDRISUPContext, ++ int iTarget, ++ unsigned int uTexture, ++ int iDepth, ++ int iLevel, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++ __DRIimage *(*CreateImageFromFDs) ++ (struct DRISUPScreen *psDRISUPcreen, ++ int iWidth, ++ int iHeight, ++ int iFourCC, ++ int *piFDs, ++ int iNumFDs, ++ int *piStrides, ++ int *piOffsets, ++ void *pvLoaderPrivate); ++ ++ __DRIimage *(*CreateImageFromDMABufs) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, ++ int iHeight, ++ int iFourCC, ++ int *piFDs, ++ int iNumFDs, ++ int *piStrides, ++ int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++ int (*GetImageCapabilities) ++ (struct DRISUPScreen *psDRISUPScreen); ++ ++ void (*BlitImage) ++ (struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psDst, ++ __DRIimage *psSrc, ++ int iDstX0, ++ int iDstY0, ++ int iDstWidth, ++ int iDstHeight, ++ int iSrcX0, int ++ iSrcY0, ++ int iSrcWidth, ++ int iSrcHeight, ++ int iFlushFlag); ++ ++ void *(*MapImage) ++ (struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psImage, ++ int iX0, ++ int iY0, ++ int iWidth, ++ int iHeight, ++ unsigned int uFlags, ++ int *piStride, ++ void **ppvData); ++ ++ void (*UnmapImage) ++ (struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psImage, ++ void *pvData); ++ ++ __DRIimage *(*CreateImageWithModifiers) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, ++ int iHeight, ++ int iFourCC, ++ const uint64_t *puModifiers, ++ const unsigned int uModifierCount, ++ void *pvLoaderPrivate); ++ ++ __DRIimage *(*CreateImageFromDMABufs2) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, ++ int iHeight, ++ int iFourCC, ++ uint64_t uModifier, ++ int *piFDs, ++ int iNumFDs, ++ int *piStrides, ++ int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++ bool (*QueryDMABufFormats) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iMax, ++ int *piFormats, ++ int *piCount); ++ ++ bool (*QueryDMABufModifiers) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iFourCC, ++ int iMax, ++ uint64_t *puModifiers, ++ unsigned int *piExternalOnly, ++ int *piCount); ++ ++ bool (*QueryDMABufFormatModifierAttribs) ++ (struct DRISUPScreen *psDRISUPScreen, ++ uint32_t uFourcc, ++ uint64_t uModifier, ++ int iAttrib, ++ uint64_t *puValue); ++ ++ __DRIimage *(*CreateImageFromRenderBuffer2) ++ (struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, ++ void *pvLoaderPrivate, ++ unsigned int *puError); ++ ++ __DRIimage *(*CreateImageFromBuffer) ++ (struct DRISUPContext *psDRISUPContext, ++ int iTarget, ++ void *pvBuffer, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++ /* Functions to support the DRI Renderer Query extension */ ++ int (*QueryRendererInteger) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, ++ unsigned int *puValue); ++ ++ int (*QueryRendererString) ++ (struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, ++ const char **ppszValue); ++ ++ /* Functions to support the DRI Fence extension */ ++ void *(*CreateFence) ++ (struct DRISUPContext *psDRISUPContext); ++ ++ void (*DestroyFence) ++ (struct DRISUPScreen *psDRISUPScreen, ++ void *pvFence); ++ ++ bool (*ClientWaitSync) ++ (struct DRISUPContext *psDRISUPContext, ++ void *pvFence, ++ unsigned int uFlags, ++ uint64_t uTimeout); ++ ++ void (*ServerWaitSync) ++ (struct DRISUPContext *psDRISUPContext, ++ void *pvFence, ++ unsigned int uFlags); ++ ++ unsigned int (*GetFenceCapabilities) ++ (struct DRISUPScreen *psDRISUPScreen); ++ ++ void *(*CreateFenceFD) ++ (struct DRISUPContext *psDRISUPContext, ++ int iFD); ++ ++ int (*GetFenceFD) ++ (struct DRISUPScreen *psDRISUPScreen, ++ void *pvFence); ++ ++ unsigned int (*GetNumAPIProcs) ++ (struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI); ++ ++ const char *(*GetAPIProcName) ++ (struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI, ++ unsigned int uIndex); ++ ++ void *(*GetAPIProcAddress) ++ (struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI, ++ unsigned int uIndex); ++ ++ void (*SetDamageRegion) ++ (struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uNRects, ++ int *piRects); ++ } v0; ++ /* The v1 interface is an extension of v0, so v0 is required as well */ ++ struct { ++ void *(*GetFenceFromCLEvent) ++ (struct DRISUPScreen *psDRISUPScreen, ++ intptr_t iCLEvent); ++ } v1; ++ /* The v2 interface is an extension of v1, so v1 is required as well */ ++ struct { ++ int (*GetAPIVersion) ++ (struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI); ++ } v2; ++ /* ++ * The v3 interface has no additional entry points. It indicates that ++ * OpenCL event based fences are available, provided the DDK is built ++ * with OpenCL support. ++ */ ++}; ++ ++/* ++ * Buffer mask values for the GetBuffers callback. These are the same as ++ * their enum __DRIimageBufferMask counterparts. ++ */ ++#define PVRDRI_IMAGE_BUFFER_BACK (1U << 0) ++#define PVRDRI_IMAGE_BUFFER_FRONT (1U << 1) ++#define PVRDRI_IMAGE_BUFFER_PREV (1U << 31) ++ ++struct PVRDRIImageList { ++ uint32_t uImageMask; ++ __DRIimage *psBack; ++ __DRIimage *psFront; ++ __DRIimage *psPrev; ++}; ++ ++/* The loader capabilities defines match their dri_loader_cap counterparts */ ++#define PVRDRI_LOADER_CAP_RGBA_ORDERING 0 ++ ++/* ++ * PVR DRI Support callback interface V2. ++ * This structure may change over time, as older interfaces become obsolete. ++ * For example, the v0 interface may be removed if superseded by newer ++ * interfaces. ++ */ ++struct PVRDRICallbacksV2 ++{ ++ struct { ++ bool (*RegisterSupportInterface) ++ (const void *psInterface, ++ unsigned int uVersion, ++ unsigned int uMinVersion); ++ ++ int (*GetBuffers) ++ (struct __DRIdrawableRec *psDRIDrawable, ++ unsigned int uFourCC, ++ uint32_t *puStamp, ++ void *pvLoaderPrivate, ++ uint32_t uBufferMask, ++ struct PVRDRIImageList *psImageList); ++ ++ bool (*CreateConfigs) ++ (struct __DRIconfigRec ***pppsConfigs, ++ struct __DRIscreenRec *psDRIScreen, ++ int iPVRDRIMesaFormat, ++ const uint8_t *puDepthBits, ++ const uint8_t *puStencilBits, ++ unsigned int uNumDepthStencilBits, ++ const unsigned int *puDBModes, ++ unsigned int uNumDBModes, ++ const uint8_t *puMSAASamples, ++ unsigned int uNumMSAAModes, ++ bool bEnableAccum, ++ bool bColorDepthMatch, ++ bool bMutableRenderBuffer, ++ int iYUVDepthRange, ++ int iYUVCSCStandard, ++ uint32_t uMaxPbufferWidth, ++ uint32_t uMaxPbufferHeight); ++ ++ struct __DRIconfigRec **(*ConcatConfigs) ++ (struct __DRIscreenRec *psDRIScreen, ++ struct __DRIconfigRec **ppsConfigA, ++ struct __DRIconfigRec **ppsConfigB); ++ ++ bool (*ConfigQuery) ++ (const PVRDRIConfig *psConfig, ++ PVRDRIConfigAttrib eConfigAttrib, ++ unsigned int *puValueOut); ++ ++ __DRIimage *(*LookupEGLImage) ++ (struct __DRIscreenRec *psDRIScreen, ++ void *pvImage, ++ void *pvLoaderPrivate); ++ ++ unsigned int (*GetCapability) ++ (struct __DRIscreenRec *psDRIScreen, ++ unsigned int uCapability); ++ } v0; ++ /* The v1 interface is an extension of v0, so v0 is required as well */ ++ struct { ++ void (*FlushFrontBuffer) ++ (struct __DRIdrawableRec *psDRIDrawable, ++ void *pvLoaderPrivate); ++ } v1; ++}; ++ ++#endif /* defined(__PVRDRIIFCE_H__) */ +diff --git a/src/mesa/drivers/dri/pvr/img_drm_fourcc.h b/src/mesa/drivers/dri/pvr/img_drm_fourcc.h +new file mode 100644 +index 00000000000..8d570ff8f53 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/img_drm_fourcc.h +@@ -0,0 +1,113 @@ ++/*************************************************************************/ /*! ++@File ++@Title Wrapper around drm_fourcc.h ++@Description FourCCs and DRM framebuffer modifiers that are not in the ++ Kernel's and libdrm's drm_fourcc.h can be added here. ++@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved ++@License MIT ++ ++The contents of this file are subject to the MIT license as set out below. ++ ++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 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 IMG_DRM_FOURCC_H ++#define IMG_DRM_FOURCC_H ++ ++#if defined(__KERNEL__) ++#include ++#else ++/* ++ * Include types.h to workaround versions of libdrm older than 2.4.68 ++ * not including the correct headers. ++ */ ++#include ++ ++#include ++#endif ++ ++/* ++ * Don't get too inspired by this example :) ++ * ADF doesn't support DRM modifiers, so the memory layout had to be ++ * included in the fourcc name, but the proper way to specify information ++ * additional to pixel formats is to use DRM modifiers. ++ * ++ * See upstream drm_fourcc.h for the proper naming convention. ++ */ ++#ifndef DRM_FORMAT_BGRA8888_DIRECT_16x4 ++#define DRM_FORMAT_BGRA8888_DIRECT_16x4 fourcc_code('I', 'M', 'G', '0') ++#endif ++ ++/* ++ * Upstream doesn't have a floating point format yet, so let's make one ++ * up. ++ * Note: The kernel's core DRM needs to know about this format, ++ * otherwise it won't be supported and should not be exposed by our ++ * kernel modules either. ++ * Refer to the provided kernel patch adding this format. ++ */ ++#if !defined(__KERNEL__) ++#define DRM_FORMAT_ABGR16_IMG fourcc_code('I', 'M', 'G', '1') ++#endif ++ ++/* ++ * Upstream does not have a packed 10 Bits Per Channel YVU format yet, ++ * so let`s make one up. ++ * Note: at the moment this format is not intended to be used with ++ * a framebuffer, so the kernels core DRM doesn`t need to know ++ * about this format. This means that the kernel doesn`t need ++ * to be patched. ++ */ ++#if !defined(__KERNEL__) ++#define DRM_FORMAT_YVU444_PACK10_IMG fourcc_code('I', 'M', 'G', '2') ++#define DRM_FORMAT_YUV422_2PLANE_PACK10_IMG fourcc_code('I', 'M', 'G', '3') ++#define DRM_FORMAT_YUV420_2PLANE_PACK10_IMG fourcc_code('I', 'M', 'G', '4') ++#endif ++ ++/* ++ * Value chosen in the middle of 255 pool to minimise the chance of hitting ++ * the same value potentially defined by other vendors in the drm_fourcc.h ++ */ ++#define DRM_FORMAT_MOD_VENDOR_PVR 0x92 ++ ++#ifndef DRM_FORMAT_MOD_VENDOR_NONE ++#define DRM_FORMAT_MOD_VENDOR_NONE 0 ++#endif ++ ++#ifndef DRM_FORMAT_RESERVED ++#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) ++#endif ++ ++#ifndef fourcc_mod_code ++#define fourcc_mod_code(vendor, val) \ ++ ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL)) ++#endif ++ ++#ifndef DRM_FORMAT_MOD_INVALID ++#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED) ++#endif ++ ++#ifndef DRM_FORMAT_MOD_LINEAR ++#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0) ++#endif ++ ++#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V7 fourcc_mod_code(PVR, 6) ++#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V7 fourcc_mod_code(PVR, 12) ++ ++#endif /* IMG_DRM_FOURCC_H */ +diff --git a/src/mesa/drivers/dri/pvr/imgpixfmts.h b/src/mesa/drivers/dri/pvr/imgpixfmts.h +new file mode 100644 +index 00000000000..da12a0fb5f6 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/imgpixfmts.h +@@ -0,0 +1,307 @@ ++/*************************************************************************/ /*! ++@File imgpixfmts.h ++@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved ++@License MIT ++ ++The contents of this file are subject to the MIT license as set out below. ++ ++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 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. ++*/ /**************************************************************************/ ++ ++/****************************************************************************** ++ ** ++ ** WARNING: File is autogenerated by parsesystable.py - DO NOT EDIT. ++ ** Use fmts_systable.txt to add new formats. ++ ** ++ *****************************************************************************/ ++ ++#if !defined(IMGPIXFMTS_H) ++#define IMGPIXFMTS_H ++ ++typedef enum _IMG_PIXFMT_ ++{ ++ IMG_PIXFMT_UNKNOWN = 0, ++ IMG_PIXFMT_RESERVED_1 = 1, ++ IMG_PIXFMT_RESERVED_2 = 2, ++ IMG_PIXFMT_RESERVED_3 = 3, ++ IMG_PIXFMT_RESERVED_4 = 4, ++ IMG_PIXFMT_RESERVED_5 = 5, ++ IMG_PIXFMT_RESERVED_6 = 6, ++ IMG_PIXFMT_RESERVED_7 = 7, ++ IMG_PIXFMT_RESERVED_8 = 8, ++ IMG_PIXFMT_RESERVED_9 = 9, ++ IMG_PIXFMT_RESERVED_10 = 10, ++ IMG_PIXFMT_RESERVED_11 = 11, ++ IMG_PIXFMT_RESERVED_12 = 12, ++ IMG_PIXFMT_RESERVED_13 = 13, ++ IMG_PIXFMT_RESERVED_14 = 14, ++ IMG_PIXFMT_RESERVED_15 = 15, ++ IMG_PIXFMT_RESERVED_16 = 16, ++ IMG_PIXFMT_RESERVED_17 = 17, ++ IMG_PIXFMT_RESERVED_18 = 18, ++ IMG_PIXFMT_RESERVED_19 = 19, ++ IMG_PIXFMT_RESERVED_20 = 20, ++ IMG_PIXFMT_RESERVED_21 = 21, ++ IMG_PIXFMT_RESERVED_22 = 22, ++ IMG_PIXFMT_RESERVED_23 = 23, ++ IMG_PIXFMT_RESERVED_24 = 24, ++ IMG_PIXFMT_R10G10B10A2_UNORM = 25, ++ IMG_PIXFMT_RESERVED_26 = 26, ++ IMG_PIXFMT_RESERVED_27 = 27, ++ IMG_PIXFMT_B10G10R10A2_UNORM = 28, ++ IMG_PIXFMT_RESERVED_29 = 29, ++ IMG_PIXFMT_RESERVED_30 = 30, ++ IMG_PIXFMT_RESERVED_31 = 31, ++ IMG_PIXFMT_R8G8B8A8_UNORM = 32, ++ IMG_PIXFMT_R8G8B8A8_UNORM_SRGB = 33, ++ IMG_PIXFMT_RESERVED_34 = 34, ++ IMG_PIXFMT_RESERVED_35 = 35, ++ IMG_PIXFMT_RESERVED_36 = 36, ++ IMG_PIXFMT_R8G8B8X8_UNORM = 37, ++ IMG_PIXFMT_RESERVED_38 = 38, ++ IMG_PIXFMT_RESERVED_39 = 39, ++ IMG_PIXFMT_RESERVED_40 = 40, ++ IMG_PIXFMT_RESERVED_41 = 41, ++ IMG_PIXFMT_RESERVED_42 = 42, ++ IMG_PIXFMT_RESERVED_43 = 43, ++ IMG_PIXFMT_RESERVED_44 = 44, ++ IMG_PIXFMT_RESERVED_45 = 45, ++ IMG_PIXFMT_RESERVED_46 = 46, ++ IMG_PIXFMT_RESERVED_47 = 47, ++ IMG_PIXFMT_RESERVED_48 = 48, ++ IMG_PIXFMT_RESERVED_49 = 49, ++ IMG_PIXFMT_RESERVED_50 = 50, ++ IMG_PIXFMT_D32_FLOAT = 51, ++ IMG_PIXFMT_RESERVED_52 = 52, ++ IMG_PIXFMT_RESERVED_53 = 53, ++ IMG_PIXFMT_RESERVED_54 = 54, ++ IMG_PIXFMT_RESERVED_55 = 55, ++ IMG_PIXFMT_RESERVED_56 = 56, ++ IMG_PIXFMT_RESERVED_57 = 57, ++ IMG_PIXFMT_D24_UNORM_X8_TYPELESS = 58, ++ IMG_PIXFMT_RESERVED_59 = 59, ++ IMG_PIXFMT_RESERVED_60 = 60, ++ IMG_PIXFMT_RESERVED_61 = 61, ++ IMG_PIXFMT_R8G8_UNORM = 62, ++ IMG_PIXFMT_RESERVED_63 = 63, ++ IMG_PIXFMT_RESERVED_64 = 64, ++ IMG_PIXFMT_RESERVED_65 = 65, ++ IMG_PIXFMT_RESERVED_66 = 66, ++ IMG_PIXFMT_RESERVED_67 = 67, ++ IMG_PIXFMT_RESERVED_68 = 68, ++ IMG_PIXFMT_D16_UNORM = 69, ++ IMG_PIXFMT_RESERVED_70 = 70, ++ IMG_PIXFMT_RESERVED_71 = 71, ++ IMG_PIXFMT_RESERVED_72 = 72, ++ IMG_PIXFMT_RESERVED_73 = 73, ++ IMG_PIXFMT_RESERVED_74 = 74, ++ IMG_PIXFMT_RESERVED_75 = 75, ++ IMG_PIXFMT_R8_UNORM = 76, ++ IMG_PIXFMT_RESERVED_77 = 77, ++ IMG_PIXFMT_RESERVED_78 = 78, ++ IMG_PIXFMT_RESERVED_79 = 79, ++ IMG_PIXFMT_RESERVED_80 = 80, ++ IMG_PIXFMT_S8_UINT = 81, ++ IMG_PIXFMT_RESERVED_82 = 82, ++ IMG_PIXFMT_RESERVED_83 = 83, ++ IMG_PIXFMT_RESERVED_84 = 84, ++ IMG_PIXFMT_B5G6R5_UNORM = 85, ++ IMG_PIXFMT_R5G6B5_UNORM = 86, ++ IMG_PIXFMT_B5G5R5A1_UNORM = 87, ++ IMG_PIXFMT_B5G5R5X1_UNORM = 88, ++ IMG_PIXFMT_B8G8R8A8_UNORM = 89, ++ IMG_PIXFMT_B8G8R8X8_UNORM = 90, ++ IMG_PIXFMT_B8G8R8A8_UINT = 91, ++ IMG_PIXFMT_B8G8R8A8_SNORM = 92, ++ IMG_PIXFMT_B8G8R8A8_SINT = 93, ++ IMG_PIXFMT_B8G8R8A8_UNORM_SRGB = 94, ++ IMG_PIXFMT_RESERVED_95 = 95, ++ IMG_PIXFMT_RESERVED_96 = 96, ++ IMG_PIXFMT_RESERVED_97 = 97, ++ IMG_PIXFMT_RESERVED_98 = 98, ++ IMG_PIXFMT_RESERVED_99 = 99, ++ IMG_PIXFMT_RESERVED_100 = 100, ++ IMG_PIXFMT_RESERVED_101 = 101, ++ IMG_PIXFMT_RESERVED_102 = 102, ++ IMG_PIXFMT_RESERVED_103 = 103, ++ IMG_PIXFMT_RESERVED_104 = 104, ++ IMG_PIXFMT_RESERVED_105 = 105, ++ IMG_PIXFMT_RESERVED_106 = 106, ++ IMG_PIXFMT_RESERVED_107 = 107, ++ IMG_PIXFMT_RESERVED_108 = 108, ++ IMG_PIXFMT_RESERVED_109 = 109, ++ IMG_PIXFMT_RESERVED_110 = 110, ++ IMG_PIXFMT_RESERVED_111 = 111, ++ IMG_PIXFMT_RESERVED_112 = 112, ++ IMG_PIXFMT_RESERVED_113 = 113, ++ IMG_PIXFMT_RESERVED_114 = 114, ++ IMG_PIXFMT_RESERVED_115 = 115, ++ IMG_PIXFMT_RESERVED_116 = 116, ++ IMG_PIXFMT_RESERVED_117 = 117, ++ IMG_PIXFMT_RESERVED_118 = 118, ++ IMG_PIXFMT_RESERVED_119 = 119, ++ IMG_PIXFMT_RESERVED_120 = 120, ++ IMG_PIXFMT_RESERVED_121 = 121, ++ IMG_PIXFMT_RESERVED_122 = 122, ++ IMG_PIXFMT_RESERVED_123 = 123, ++ IMG_PIXFMT_RESERVED_124 = 124, ++ IMG_PIXFMT_RESERVED_125 = 125, ++ IMG_PIXFMT_RESERVED_126 = 126, ++ IMG_PIXFMT_RESERVED_127 = 127, ++ IMG_PIXFMT_RESERVED_128 = 128, ++ IMG_PIXFMT_RESERVED_129 = 129, ++ IMG_PIXFMT_RESERVED_130 = 130, ++ IMG_PIXFMT_RESERVED_131 = 131, ++ IMG_PIXFMT_RESERVED_132 = 132, ++ IMG_PIXFMT_RESERVED_133 = 133, ++ IMG_PIXFMT_RESERVED_134 = 134, ++ IMG_PIXFMT_RESERVED_135 = 135, ++ IMG_PIXFMT_L8_UNORM = 136, ++ IMG_PIXFMT_RESERVED_137 = 137, ++ IMG_PIXFMT_L8A8_UNORM = 138, ++ IMG_PIXFMT_RESERVED_139 = 139, ++ IMG_PIXFMT_RESERVED_140 = 140, ++ IMG_PIXFMT_RESERVED_141 = 141, ++ IMG_PIXFMT_RESERVED_142 = 142, ++ IMG_PIXFMT_RESERVED_143 = 143, ++ IMG_PIXFMT_RESERVED_144 = 144, ++ IMG_PIXFMT_B4G4R4A4_UNORM = 145, ++ IMG_PIXFMT_RESERVED_146 = 146, ++ IMG_PIXFMT_RESERVED_147 = 147, ++ IMG_PIXFMT_RESERVED_148 = 148, ++ IMG_PIXFMT_RESERVED_149 = 149, ++ IMG_PIXFMT_RESERVED_150 = 150, ++ IMG_PIXFMT_RESERVED_151 = 151, ++ IMG_PIXFMT_RESERVED_152 = 152, ++ IMG_PIXFMT_RESERVED_153 = 153, ++ IMG_PIXFMT_RESERVED_154 = 154, ++ IMG_PIXFMT_RESERVED_155 = 155, ++ IMG_PIXFMT_RESERVED_156 = 156, ++ IMG_PIXFMT_RESERVED_157 = 157, ++ IMG_PIXFMT_RESERVED_158 = 158, ++ IMG_PIXFMT_RESERVED_159 = 159, ++ IMG_PIXFMT_R8G8B8_UNORM = 160, ++ IMG_PIXFMT_R8G8B8_UNORM_SRGB = 161, ++ IMG_PIXFMT_RESERVED_162 = 162, ++ IMG_PIXFMT_RESERVED_163 = 163, ++ IMG_PIXFMT_RESERVED_164 = 164, ++ IMG_PIXFMT_RESERVED_165 = 165, ++ IMG_PIXFMT_RESERVED_166 = 166, ++ IMG_PIXFMT_RESERVED_167 = 167, ++ IMG_PIXFMT_RESERVED_168 = 168, ++ IMG_PIXFMT_RESERVED_169 = 169, ++ IMG_PIXFMT_RESERVED_170 = 170, ++ IMG_PIXFMT_UYVY = 171, ++ IMG_PIXFMT_VYUY = 172, ++ IMG_PIXFMT_YUYV = 173, ++ IMG_PIXFMT_YVYU = 174, ++ IMG_PIXFMT_YVU420_2PLANE = 175, ++ IMG_PIXFMT_YUV420_2PLANE = 176, ++ IMG_PIXFMT_YVU420_2PLANE_MACRO_BLOCK = 177, ++ IMG_PIXFMT_YUV420_3PLANE = 178, ++ IMG_PIXFMT_YVU420_3PLANE = 179, ++ IMG_PIXFMT_RESERVED_180 = 180, ++ IMG_PIXFMT_RESERVED_181 = 181, ++ IMG_PIXFMT_RESERVED_182 = 182, ++ IMG_PIXFMT_RESERVED_183 = 183, ++ IMG_PIXFMT_RESERVED_184 = 184, ++ IMG_PIXFMT_RESERVED_185 = 185, ++ IMG_PIXFMT_RESERVED_186 = 186, ++ IMG_PIXFMT_RESERVED_187 = 187, ++ IMG_PIXFMT_RESERVED_188 = 188, ++ IMG_PIXFMT_RESERVED_189 = 189, ++ IMG_PIXFMT_RESERVED_190 = 190, ++ IMG_PIXFMT_RESERVED_191 = 191, ++ IMG_PIXFMT_RESERVED_192 = 192, ++ IMG_PIXFMT_RESERVED_193 = 193, ++ IMG_PIXFMT_RESERVED_194 = 194, ++ IMG_PIXFMT_RESERVED_195 = 195, ++ IMG_PIXFMT_RESERVED_196 = 196, ++ IMG_PIXFMT_RESERVED_197 = 197, ++ IMG_PIXFMT_RESERVED_198 = 198, ++ IMG_PIXFMT_RESERVED_199 = 199, ++ IMG_PIXFMT_RESERVED_200 = 200, ++ IMG_PIXFMT_YVU8_422_2PLANE_PACK8 = 201, ++ IMG_PIXFMT_RESERVED_202 = 202, ++ IMG_PIXFMT_YVU10_444_1PLANE_PACK10 = 203, ++ IMG_PIXFMT_RESERVED_204 = 204, ++ IMG_PIXFMT_RESERVED_205 = 205, ++ IMG_PIXFMT_RESERVED_206 = 206, ++ IMG_PIXFMT_YUV8_422_2PLANE_PACK8 = 207, ++ IMG_PIXFMT_YUV8_444_3PLANE_PACK8 = 208, ++ IMG_PIXFMT_RESERVED_209 = 209, ++ IMG_PIXFMT_RESERVED_210 = 210, ++ IMG_PIXFMT_RESERVED_211 = 211, ++ IMG_PIXFMT_RESERVED_212 = 212, ++ IMG_PIXFMT_RESERVED_213 = 213, ++ IMG_PIXFMT_RESERVED_214 = 214, ++ IMG_PIXFMT_RESERVED_215 = 215, ++ IMG_PIXFMT_RESERVED_216 = 216, ++ IMG_PIXFMT_RESERVED_217 = 217, ++ IMG_PIXFMT_RESERVED_218 = 218, ++ IMG_PIXFMT_RESERVED_219 = 219, ++ IMG_PIXFMT_RESERVED_220 = 220, ++ IMG_PIXFMT_RESERVED_221 = 221, ++ IMG_PIXFMT_RESERVED_222 = 222, ++ IMG_PIXFMT_RESERVED_223 = 223, ++ IMG_PIXFMT_RESERVED_224 = 224, ++ IMG_PIXFMT_RESERVED_225 = 225, ++ IMG_PIXFMT_RESERVED_226 = 226, ++ IMG_PIXFMT_RESERVED_227 = 227, ++ IMG_PIXFMT_RESERVED_228 = 228, ++ IMG_PIXFMT_RESERVED_229 = 229, ++ IMG_PIXFMT_RESERVED_230 = 230, ++ IMG_PIXFMT_RESERVED_231 = 231, ++ IMG_PIXFMT_RESERVED_232 = 232, ++ IMG_PIXFMT_RESERVED_233 = 233, ++ IMG_PIXFMT_RESERVED_234 = 234, ++ IMG_PIXFMT_RESERVED_235 = 235, ++ IMG_PIXFMT_RESERVED_236 = 236, ++ IMG_PIXFMT_RESERVED_237 = 237, ++ IMG_PIXFMT_RESERVED_238 = 238, ++ IMG_PIXFMT_RESERVED_239 = 239, ++ IMG_PIXFMT_RESERVED_240 = 240, ++ IMG_PIXFMT_RESERVED_241 = 241, ++ IMG_PIXFMT_RESERVED_242 = 242, ++ IMG_PIXFMT_RESERVED_243 = 243, ++ IMG_PIXFMT_RESERVED_244 = 244, ++ IMG_PIXFMT_YVU8_420_2PLANE_PACK8_P = 245, ++ IMG_PIXFMT_RESERVED_246 = 246, ++ IMG_PIXFMT_RESERVED_247 = 247, ++ IMG_PIXFMT_RESERVED_248 = 248, ++ IMG_PIXFMT_YUV8_420_2PLANE_PACK8_P = 249, ++ IMG_PIXFMT_RESERVED_250 = 250, ++ IMG_PIXFMT_RESERVED_251 = 251, ++ IMG_PIXFMT_UYVY10_422_1PLANE_PACK10_CUST1 = 252, ++ IMG_PIXFMT_RESERVED_253 = 253, ++ IMG_PIXFMT_RESERVED_254 = 254, ++ IMG_PIXFMT_RESERVED_255 = 255, ++ IMG_PIXFMT_RESERVED_256 = 256, ++ IMG_PIXFMT_RESERVED_257 = 257, ++ IMG_PIXFMT_RESERVED_258 = 258, ++ IMG_PIXFMT_RESERVED_259 = 259, ++ IMG_PIXFMT_RESERVED_260 = 260, ++ IMG_PIXFMT_RESERVED_261 = 261, ++ IMG_PIXFMT_RESERVED_262 = 262, ++ IMG_PIXFMT_RESERVED_263 = 263, ++ IMG_PIXFMT_RESERVED_264 = 264, ++#define IMG_PIXFMT_ENUM_COUNT 265 ++} IMG_PIXFMT; ++ ++#endif /* IMGPIXFMTS_H */ +diff --git a/src/mesa/drivers/dri/pvr/imgyuv.h b/src/mesa/drivers/dri/pvr/imgyuv.h +new file mode 100644 +index 00000000000..7ae8fd19ac0 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/imgyuv.h +@@ -0,0 +1,58 @@ ++/*************************************************************************/ /*! ++@File ++@Title YUV defines ++@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved ++@License MIT ++ ++The contents of this file are subject to the MIT license as set out below. ++ ++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 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. ++*/ /**************************************************************************/ ++ ++#if !defined(IMGYUV_H) ++#define IMGYUV_H ++ ++typedef enum ++{ ++ IMG_COLORSPACE_UNDEFINED = 0, ++ IMG_COLORSPACE_BT601_CONFORMANT_RANGE = 1, ++ IMG_COLORSPACE_BT601_FULL_RANGE = 2, ++ IMG_COLORSPACE_BT709_CONFORMANT_RANGE = 3, ++ IMG_COLORSPACE_BT709_FULL_RANGE = 4, ++ IMG_COLORSPACE_BT2020_CONFORMANT_RANGE = 5, ++ IMG_COLORSPACE_BT2020_FULL_RANGE = 6, ++ IMG_COLORSPACE_BT601_CONFORMANT_RANGE_INVERSE = 7, ++ IMG_COLORSPACE_BT601_FULL_RANGE_INVERSE = 8, ++ IMG_COLORSPACE_BT709_CONFORMANT_RANGE_INVERSE = 9, ++ IMG_COLORSPACE_BT709_FULL_RANGE_INVERSE = 10, ++ IMG_COLORSPACE_BT2020_CONFORMANT_RANGE_INVERSE = 11, ++ IMG_COLORSPACE_BT2020_FULL_RANGE_INVERSE = 12 ++} IMG_YUV_COLORSPACE; ++ ++typedef enum ++{ ++ IMG_CHROMA_INTERP_UNDEFINED = 0, ++ IMG_CHROMA_INTERP_ZERO = 1, ++ IMG_CHROMA_INTERP_QUARTER = 2, ++ IMG_CHROMA_INTERP_HALF = 3, ++ IMG_CHROMA_INTERP_THREEQUARTERS = 4 ++} IMG_YUV_CHROMA_INTERP; ++ ++ ++#endif /* IMGYUV_H */ +diff --git a/src/mesa/drivers/dri/pvr/mesa_context.c b/src/mesa/drivers/dri/pvr/mesa_context.c +new file mode 100644 +index 00000000000..d36bae5ac54 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/mesa_context.c +@@ -0,0 +1,208 @@ ++/** ++ * \file context.c ++ * Mesa context/visual/framebuffer management functions. ++ * \author Brian Paul ++ */ ++ ++/* ++ * Mesa 3-D graphics library ++ * Version: 7.1 ++ * ++ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++ ++#include "main/version.h" ++#include "main/errors.h" ++ ++#include "dri_support.h" ++#include "dri_util.h" ++#include "glapi.h" ++#include "dispatch.h" ++#include "pvrmesa.h" ++ ++/** ++ * This is the default function we plug into all dispatch table slots This ++ * helps prevents a segfault when someone calls a GL function without first ++ * checking if the extension is supported. ++ */ ++static int ++generic_nop(void) ++{ ++ _mesa_warning(NULL, "User called no-op dispatch function (an unsupported extension function?)"); ++ ++ return 0; ++} ++ ++/** ++ * Allocate and initialise a new dispatch table. ++ */ ++static struct _glapi_table * ++pvrdri_alloc_dispatch_table(void) ++{ ++ unsigned int numEntries = _glapi_get_dispatch_table_size(); ++ _glapi_proc *table; ++ ++ table = malloc(numEntries * sizeof(_glapi_proc)); ++ if (table) ++ for (unsigned int i = 0; i < numEntries; i++) ++ table[i] = (_glapi_proc) generic_nop; ++ ++ return (struct _glapi_table *) table; ++} ++ ++/** ++ * Return a pointer to the pointer to the dispatch table of an API in ++ * PVRDRIScreen. ++ */ ++static struct _glapi_table ** ++pvrdri_get_dispatch_table_ptr(PVRDRIScreen *psPVRScreen, PVRDRIAPIType eAPI) ++{ ++ switch (eAPI) { ++ case PVRDRI_API_GLES1: ++ return &psPVRScreen->psOGLES1Dispatch; ++ case PVRDRI_API_GLES2: ++ return &psPVRScreen->psOGLES2Dispatch; ++ case PVRDRI_API_GL_COMPAT: ++ case PVRDRI_API_GL_CORE: ++ return &psPVRScreen->psOGLDispatch; ++ default: ++ return NULL; ++ } ++} ++ ++/** ++ * Return a pointer to the dispatch table of an API. ++ */ ++static struct _glapi_table * ++pvrdri_get_dispatch_table(PVRDRIScreen *psPVRScreen, PVRDRIAPIType eAPI) ++{ ++ struct _glapi_table **ppsTable = ++ pvrdri_get_dispatch_table_ptr(psPVRScreen, eAPI); ++ ++ return ppsTable ? *ppsTable : NULL; ++} ++ ++/** ++ * Free all dispatch tables. ++ */ ++void ++pvrdri_free_dispatch_tables(PVRDRIScreen *psPVRScreen) ++{ ++ if (psPVRScreen->psOGLES1Dispatch != NULL) { ++ free(psPVRScreen->psOGLES1Dispatch); ++ psPVRScreen->psOGLES1Dispatch = NULL; ++ } ++ ++ if (psPVRScreen->psOGLES2Dispatch != NULL) { ++ free(psPVRScreen->psOGLES2Dispatch); ++ psPVRScreen->psOGLES2Dispatch = NULL; ++ } ++ ++ if (psPVRScreen->psOGLDispatch != NULL) { ++ free(psPVRScreen->psOGLDispatch); ++ psPVRScreen->psOGLDispatch = NULL; ++ } ++} ++ ++static void ++pvrdri_add_mesa_dispatch(struct _glapi_table *psTable, PVRDRIAPIType eAPI, ++ struct DRISUPScreen *psDRISUPScreen, ++ unsigned int uIdx) ++{ ++ const char *asFunc[] = { NULL, NULL }; ++ int iOffset; ++ const char *psFunc; ++ _glapi_proc pfFunc; ++ ++ pfFunc = DRISUPGetAPIProcAddress(psDRISUPScreen, eAPI, uIdx); ++ if (pfFunc == NULL) ++ return; ++ ++ psFunc = DRISUPGetAPIProcName(psDRISUPScreen, eAPI, uIdx); ++ assert(psFunc != NULL); ++ ++ asFunc[0] = psFunc; ++ iOffset = _glapi_add_dispatch(asFunc, ""); ++ if (iOffset == -1) { ++ _mesa_warning(NULL, "Couldn't add %s to the Mesa dispatch table", ++ psFunc); ++ } else { ++ SET_by_offset(psTable, iOffset, pfFunc); ++ } ++} ++ ++static void ++pvrdri_set_mesa_dispatch(struct _glapi_table *psTable, PVRDRIAPIType eAPI, ++ struct DRISUPScreen *psDRISUPScreen, ++ unsigned int uNumFuncs) ++{ ++ for (unsigned int i = 0; i < uNumFuncs; i++) ++ pvrdri_add_mesa_dispatch(psTable, eAPI, psDRISUPScreen, i); ++} ++ ++bool ++pvrdri_create_dispatch_table(PVRDRIScreen *psPVRScreen, PVRDRIAPIType eAPI) ++{ ++ struct DRISUPScreen *psDRISUPScreen = psPVRScreen->psDRISUPScreen; ++ struct _glapi_table **ppsTable; ++ unsigned int uNumFuncs; ++ ++ ppsTable = pvrdri_get_dispatch_table_ptr(psPVRScreen, eAPI); ++ if (ppsTable == NULL) ++ return false; ++ ++ if (*ppsTable != NULL) ++ return true; ++ ++ uNumFuncs = DRISUPGetNumAPIProcs(psDRISUPScreen, eAPI); ++ if (!uNumFuncs) ++ return false; ++ ++ *ppsTable = pvrdri_alloc_dispatch_table(); ++ if (*ppsTable == NULL) ++ return false; ++ ++ pvrdri_set_mesa_dispatch(*ppsTable, eAPI, psDRISUPScreen, uNumFuncs); ++ ++ return true; ++} ++ ++void ++pvrdri_set_null_dispatch_table(void) ++{ ++ _glapi_set_dispatch(NULL); ++} ++ ++void ++pvrdri_set_dispatch_table(PVRDRIContext *psPVRContext) ++{ ++ struct _glapi_table *psTable; ++ ++ psTable = pvrdri_get_dispatch_table(psPVRContext->psPVRScreen, ++ psPVRContext->eAPI); ++ ++ _glapi_set_dispatch(psTable); ++} +diff --git a/src/mesa/drivers/dri/pvr/meson.build b/src/mesa/drivers/dri/pvr/meson.build +new file mode 100644 +index 00000000000..51b3b11948d +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/meson.build +@@ -0,0 +1,53 @@ ++# Copyright (c) Imagination Technologies Ltd. ++# ++# The contents of this file are subject to the MIT license as set out below. ++# ++# 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 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. ++ ++files_pvr = files( ++ 'mesa_context.c', ++ 'pvrcb.c', ++ 'pvrcompat.c', ++ 'pvrdrawable_mod.c', ++ 'pvrdri.c', ++ 'pvrdri_mod.c', ++ 'pvrext.c', ++ 'pvrext_mod.c', ++ 'pvrimage_mod.c', ++ 'pvrutil.c', ++ 'pvrutil_mod.c', ++) ++ ++dep_libpvr = [ ++ dep_libdrm, ++] ++ ++if with_platform_tizen ++ dep_libpvr += dep_dlog ++endif ++ ++libpvr = static_library( ++ 'pvr', ++ [files_pvr, main_dispatch_h], ++ include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, ++ inc_dri_common, inc_util, inc_pvr], ++ c_args : [no_override_init_args], ++ gnu_symbol_visibility : 'hidden', ++ dependencies : [dep_libpvr], ++) +diff --git a/src/mesa/drivers/dri/pvr/pvrcb.c b/src/mesa/drivers/dri/pvr/pvrcb.c +new file mode 100644 +index 00000000000..e1232e5c400 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrcb.c +@@ -0,0 +1,282 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++ ++#include "utils.h" ++#include "pvrdri.h" ++ ++int ++MODSUPGetBuffers(__DRIdrawable *psDRIDrawable, unsigned int uFourCC, ++ uint32_t *puStamp, void *pvLoaderPrivate, ++ uint32_t uBufferMask, struct PVRDRIImageList *psImageList) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ __DRIscreen *psDRIScreen = psDRIDrawable->driScreenPriv; ++ struct __DRIimageList sDRIList; ++ int res; ++ ++#if !defined(DRI_IMAGE_HAS_BUFFER_PREV) ++ uBufferMask &= ~PVRDRI_IMAGE_BUFFER_PREV; ++#endif ++ ++ if (psPVRDrawable->uFourCC != uFourCC) { ++ psPVRDrawable->uDRIFormat = PVRDRIFourCCToDRIFormat(uFourCC); ++ psPVRDrawable->uFourCC = uFourCC; ++ } ++ ++ res = psDRIScreen->image.loader->getBuffers(psDRIDrawable, ++ psPVRDrawable->uDRIFormat, ++ puStamp, ++ pvLoaderPrivate, ++ uBufferMask, &sDRIList); ++ ++ if (res) { ++ psImageList->uImageMask = sDRIList.image_mask; ++ psImageList->psBack = sDRIList.back; ++ psImageList->psFront = sDRIList.front; ++ psImageList->psPrev = sDRIList.prev; ++ } ++ ++ return res; ++} ++ ++bool ++MODSUPCreateConfigs(__DRIconfig ***pppsConfigs, __DRIscreen *psDRIScreen, ++ int iPVRDRIMesaFormat, const uint8_t *puDepthBits, ++ const uint8_t *puStencilBits, ++ unsigned int uNumDepthStencilBits, ++ const unsigned int *puDBModes, unsigned int uNumDBModes, ++ const uint8_t *puMSAASamples, unsigned int uNumMSAAModes, ++ bool bEnableAccum, bool bColorDepthMatch, ++ bool bMutableRenderBuffer, ++ int iYUVDepthRange, int iYUVCSCStandard, ++ uint32_t uMaxPbufferWidth, uint32_t uMaxPbufferHeight) ++{ ++ __DRIconfig **ppsConfigs; ++ mesa_format eFormat = PVRDRIMesaFormatToMesaFormat(iPVRDRIMesaFormat); ++ unsigned int i; ++ ++ (void) psDRIScreen; ++ ++ switch (eFormat) { ++ case MESA_FORMAT_NONE: ++ __driUtilMessage("%s: Unknown PVR DRI format: %u", ++ __func__, iPVRDRIMesaFormat); ++ return false; ++ default: ++ break; ++ } ++ ++ /* ++ * The double buffered modes array argument for driCreateConfigs has ++ * entries of type GLenum. ++ */ ++ static_assert(sizeof(GLenum) == sizeof(unsigned int), ++ "Size mismatch between GLenum and unsigned int"); ++ ++ ppsConfigs = driCreateConfigs(eFormat, puDepthBits, puStencilBits, ++ uNumDepthStencilBits, (GLenum *) puDBModes, ++ uNumDBModes, puMSAASamples, uNumMSAAModes, ++ bEnableAccum, bColorDepthMatch, ++ bMutableRenderBuffer, ++ iYUVDepthRange, iYUVCSCStandard); ++ if (!ppsConfigs) ++ return false; ++ ++ for (i = 0; ppsConfigs[i]; i++) { ++ ppsConfigs[i]->modes.maxPbufferWidth = uMaxPbufferWidth; ++ ppsConfigs[i]->modes.maxPbufferHeight = uMaxPbufferHeight; ++ ppsConfigs[i]->modes.maxPbufferPixels = ++ uMaxPbufferWidth * uMaxPbufferHeight; ++ } ++ ++ *pppsConfigs = ppsConfigs; ++ ++ return true; ++} ++ ++__DRIconfig ** ++MODSUPConcatConfigs(__DRIscreen *psDRIScreen, ++ __DRIconfig **ppsConfigA, __DRIconfig **ppsConfigB) ++{ ++ (void) psDRIScreen; ++ ++ return driConcatConfigs(ppsConfigA, ppsConfigB); ++} ++ ++struct __DRIimageRec * ++MODSUPLookupEGLImage(__DRIscreen *psDRIScreen, void *pvImage, ++ void *pvLoaderPrivate) ++{ ++ return psDRIScreen->dri2.image->lookupEGLImage(psDRIScreen, ++ pvImage, ++ pvLoaderPrivate); ++} ++ ++ ++unsigned int ++MODSUPGetCapability(__DRIscreen *psDRIScreen, unsigned int uCapability) ++{ ++ if (psDRIScreen->image.loader->base.version >= 2 && ++ psDRIScreen->image.loader->getCapability) { ++ enum dri_loader_cap eCapability = ++ (enum dri_loader_cap) uCapability; ++ ++ return psDRIScreen->image.loader->getCapability( ++ psDRIScreen->loaderPrivate, ++ eCapability); ++ } ++ ++ return 0; ++} ++ ++bool ++PVRDRIConfigQuery(const PVRDRIConfig *psConfig, ++ PVRDRIConfigAttrib eConfigAttrib, int *piValueOut) ++{ ++ if (!psConfig || !piValueOut) ++ return false; ++ ++ switch (eConfigAttrib) { ++ case PVRDRI_CONFIG_ATTRIB_RENDERABLE_TYPE: ++ *piValueOut = psConfig->iSupportedAPIs; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_RGB_MODE: ++ *piValueOut = psConfig->sGLMode.rgbMode; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_DOUBLE_BUFFER_MODE: ++ *piValueOut = psConfig->sGLMode.doubleBufferMode; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_RED_BITS: ++ *piValueOut = psConfig->sGLMode.redBits; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_GREEN_BITS: ++ *piValueOut = psConfig->sGLMode.greenBits; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_BLUE_BITS: ++ *piValueOut = psConfig->sGLMode.blueBits; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_ALPHA_BITS: ++ *piValueOut = psConfig->sGLMode.alphaBits; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_RGB_BITS: ++ *piValueOut = psConfig->sGLMode.rgbBits; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_DEPTH_BITS: ++ *piValueOut = psConfig->sGLMode.depthBits; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_STENCIL_BITS: ++ *piValueOut = psConfig->sGLMode.stencilBits; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_SAMPLE_BUFFERS: ++ *piValueOut = psConfig->sGLMode.sampleBuffers; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_SAMPLES: ++ *piValueOut = psConfig->sGLMode.samples; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_BIND_TO_TEXTURE_RGB: ++ *piValueOut = psConfig->sGLMode.bindToTextureRgb; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_BIND_TO_TEXTURE_RGBA: ++ *piValueOut = psConfig->sGLMode.bindToTextureRgba; ++ return true; ++#if defined(__DRI_ATTRIB_YUV_BIT) ++ case PVRDRI_CONFIG_ATTRIB_YUV_ORDER: ++ *piValueOut = psConfig->sGLMode.YUVOrder; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_YUV_NUM_OF_PLANES: ++ *piValueOut = psConfig->sGLMode.YUVNumberOfPlanes; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_YUV_SUBSAMPLE: ++ *piValueOut = psConfig->sGLMode.YUVSubsample; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_YUV_DEPTH_RANGE: ++ *piValueOut = psConfig->sGLMode.YUVDepthRange; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_YUV_CSC_STANDARD: ++ *piValueOut = psConfig->sGLMode.YUVCSCStandard; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_YUV_PLANE_BPP: ++ *piValueOut = psConfig->sGLMode.YUVPlaneBPP; ++ return true; ++#endif ++#if !defined(__DRI_ATTRIB_YUV_BIT) ++ case PVRDRI_CONFIG_ATTRIB_YUV_ORDER: ++ case PVRDRI_CONFIG_ATTRIB_YUV_NUM_OF_PLANES: ++ case PVRDRI_CONFIG_ATTRIB_YUV_SUBSAMPLE: ++ case PVRDRI_CONFIG_ATTRIB_YUV_DEPTH_RANGE: ++ case PVRDRI_CONFIG_ATTRIB_YUV_CSC_STANDARD: ++ case PVRDRI_CONFIG_ATTRIB_YUV_PLANE_BPP: ++ return false; ++#endif ++ case PVRDRI_CONFIG_ATTRIB_RED_MASK: ++ *piValueOut = psConfig->sGLMode.redMask; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_GREEN_MASK: ++ *piValueOut = psConfig->sGLMode.greenMask; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_BLUE_MASK: ++ *piValueOut = psConfig->sGLMode.blueMask; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_ALPHA_MASK: ++ *piValueOut = psConfig->sGLMode.alphaMask; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_SRGB_CAPABLE: ++ *piValueOut = psConfig->sGLMode.sRGBCapable; ++ return true; ++ case PVRDRI_CONFIG_ATTRIB_INVALID: ++ errorMessage("%s: Invalid attribute", __func__); ++ assert(0); ++ return false; ++ default: ++ return false; ++ } ++} ++ ++bool ++MODSUPConfigQuery(const PVRDRIConfig *psConfig, ++ PVRDRIConfigAttrib eConfigAttrib, unsigned int *puValueOut) ++{ ++ bool bRes; ++ int iValue; ++ ++ bRes = PVRDRIConfigQuery(psConfig, eConfigAttrib, &iValue); ++ if (bRes) ++ *puValueOut = (unsigned int) iValue; ++ ++ return bRes; ++} ++ ++void ++MODSUPFlushFrontBuffer(struct __DRIdrawableRec *psDRIDrawable, ++ void *pvLoaderPrivate) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ __DRIscreen *psDRIScreen = psDRIDrawable->driScreenPriv; ++ ++ if (!psPVRDrawable->sConfig.sGLMode.doubleBufferMode) ++ psDRIScreen->image.loader->flushFrontBuffer(psDRIDrawable, ++ pvLoaderPrivate); ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrcompat.c b/src/mesa/drivers/dri/pvr/pvrcompat.c +new file mode 100644 +index 00000000000..70335a2c7d9 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrcompat.c +@@ -0,0 +1,1552 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "pvrdri.h" ++#include "pvrdri_mod.h" ++ ++#ifndef DRM_FORMAT_MOD_INVALID ++#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) ++#endif ++ ++#define _MAKESTRING(x) # x ++#define MAKESTRING(x) _MAKESTRING(x) ++ ++#define PVRDRI_SUPPORT_LIB "libpvr_dri_support.so" ++ ++static void *gpvSupLib; ++static int giSupLibRef; ++ ++static PVRDRISupportInterface gsSup; ++static struct PVRDRISupportInterfaceV2 gsSupV2; ++ ++static pthread_mutex_t gsCompatLock = PTHREAD_MUTEX_INITIALIZER; ++ ++/* Call a function via the DRI Support interface structure */ ++#define CallFunc(field, ...) \ ++ do { \ ++ if (gsSup.field) \ ++ return gsSup.field(__VA_ARGS__); \ ++ } while(0) ++ ++/* Lookup a function, and set the pointer to the function address */ ++#define LookupFunc(func, ptr) \ ++ do { \ ++ ptr = dlsym(gpvSupLib, MAKESTRING(func)); \ ++ } while(0) ++ ++/* ++ * Calculate the size of a particular version of the PVRDRISupportInterface ++ * structure from the name of the last field in that version of the ++ * structure. ++ */ ++#define PVRDRIInterfaceSize(field) \ ++ (offsetof(PVRDRISupportInterface, field) + \ ++ sizeof((PVRDRISupportInterface *)0)->field) ++ ++/* Call a function via the DRI Support interface structure */ ++#define CallFuncV2(field, ...) \ ++ do { \ ++ if (gsSupV2.field) \ ++ return gsSupV2.field(__VA_ARGS__); \ ++ } while(0) ++ ++/* Calculate the start of the PVRDRISupportInterfaceV2 structure */ ++#define PVRDRIInterfaceV2Start(field) \ ++ (offsetof(struct PVRDRISupportInterfaceV2, field)) ++ ++/* Calculate the end of the PVRDRISupportInterfaceV2 structure */ ++#define PVRDRIInterfaceV2End(field) \ ++ (offsetof(struct PVRDRISupportInterfaceV2, field) + \ ++ sizeof((struct PVRDRISupportInterfaceV2 *)0)->field) ++ ++static void ++CompatLock(void) ++{ ++ int ret; ++ ++ ret = pthread_mutex_lock(&gsCompatLock); ++ if (ret) { ++ errorMessage("%s: Failed to lock mutex (%d)", __func__, ret); ++ abort(); ++ } ++} ++ ++static void ++CompatUnlock(void) ++{ ++ int ret; ++ ++ ret = pthread_mutex_unlock(&gsCompatLock); ++ if (ret) { ++ errorMessage("%s: Failed to unlock mutex (%d)", __func__, ret); ++ abort(); ++ } ++} ++ ++static void * ++LoadLib(const char *path) ++{ ++ void *handle; ++ ++ /* Clear the error */ ++ (void) dlerror(); ++ ++ handle = dlopen(path, RTLD_NOW); ++ if (handle) { ++ __driUtilMessage("Loaded %s", path); ++ } else { ++ const char *error; ++ ++ error = dlerror(); ++ if (!error) ++ error = "unknown error"; ++ ++ errorMessage("%s: Couldn't load %s: %s", __func__, path, error); ++ } ++ ++ return handle; ++} ++ ++static void ++UnloadLib(void *handle, const char *name) ++{ ++ if (!handle) ++ return; ++ ++ /* Clear the error */ ++ (void) dlerror(); ++ ++ if (dlclose(handle)) { ++ const char *error; ++ ++ error = dlerror(); ++ if (!error) ++ error = "unknown error"; ++ ++ errorMessage("%s: Couldn't unload %s: %s", __func__, name, error); ++ } else { ++ __driUtilMessage("Unloaded %s", name); ++ } ++} ++ ++static bool ++LoadSupportLib(void) ++{ ++ gpvSupLib = LoadLib(PVRDRI_SUPPORT_LIB); ++ ++ return gpvSupLib != NULL; ++} ++ ++static void ++UnloadSupportLib(void) ++{ ++ UnloadLib(gpvSupLib, PVRDRI_SUPPORT_LIB); ++ gpvSupLib = NULL; ++} ++ ++static void ++CompatDeinit(void) ++{ ++ UnloadSupportLib(); ++ memset(&gsSup, 0, sizeof(gsSup)); ++ memset(&gsSupV2, 0, sizeof(gsSupV2)); ++} ++ ++static void ++SetupLocalDRISupportInterfaceV2(void) ++{ ++ gsSupV2.v0.CreateScreen = DRIMODCreateScreen; ++ gsSupV2.v0.DestroyScreen = DRIMODDestroyScreen; ++ gsSupV2.v0.CreateContext = DRIMODCreateContext; ++ gsSupV2.v0.DestroyContext = DRIMODDestroyContext; ++ gsSupV2.v0.CreateDrawable = DRIMODCreateDrawable; ++ gsSupV2.v0.DestroyDrawable = DRIMODDestroyDrawable; ++ gsSupV2.v0.MakeCurrent = DRIMODMakeCurrent; ++ gsSupV2.v0.UnbindContext = DRIMODUnbindContext; ++ gsSupV2.v0.AllocateBuffer = DRIMODAllocateBuffer; ++ gsSupV2.v0.ReleaseBuffer = DRIMODReleaseBuffer; ++ gsSupV2.v0.SetTexBuffer2 = DRIMODSetTexBuffer2; ++ gsSupV2.v0.ReleaseTexBuffer = DRIMODReleaseTexBuffer; ++ gsSupV2.v0.Flush = DRIMODFlush; ++ gsSupV2.v0.Invalidate = DRIMODInvalidate; ++ gsSupV2.v0.FlushWithFlags = DRIMODFlushWithFlags; ++ gsSupV2.v0.CreateImageFromName = DRIMODCreateImageFromName; ++ gsSupV2.v0.CreateImageFromRenderbuffer = ++ DRIMODCreateImageFromRenderbuffer; ++ gsSupV2.v0.DestroyImage = DRIMODDestroyImage; ++ gsSupV2.v0.CreateImage = DRIMODCreateImage; ++ gsSupV2.v0.QueryImage = DRIMODQueryImage; ++ gsSupV2.v0.DupImage = DRIMODDupImage; ++ gsSupV2.v0.ValidateImageUsage = DRIMODValidateImageUsage; ++ gsSupV2.v0.CreateImageFromNames = DRIMODCreateImageFromNames; ++ gsSupV2.v0.FromPlanar = DRIMODFromPlanar; ++ gsSupV2.v0.CreateImageFromTexture = DRIMODCreateImageFromTexture; ++ gsSupV2.v0.CreateImageFromFDs = DRIMODCreateImageFromFDs; ++ gsSupV2.v0.CreateImageFromDMABufs = DRIMODCreateImageFromDMABufs; ++ gsSupV2.v0.GetImageCapabilities = DRIMODGetImageCapabilities; ++ gsSupV2.v0.BlitImage = DRIMODBlitImage; ++ gsSupV2.v0.MapImage = DRIMODMapImage; ++ gsSupV2.v0.UnmapImage = DRIMODUnmapImage; ++ gsSupV2.v0.CreateImageWithModifiers = DRIMODCreateImageWithModifiers; ++ gsSupV2.v0.CreateImageFromDMABufs2 = DRIMODCreateImageFromDMABufs2; ++ gsSupV2.v0.QueryDMABufFormats = DRIMODQueryDMABufFormats; ++ gsSupV2.v0.QueryDMABufModifiers = DRIMODQueryDMABufModifiers; ++ gsSupV2.v0.QueryDMABufFormatModifierAttribs = ++ DRIMODQueryDMABufFormatModifierAttribs; ++ gsSupV2.v0.CreateImageFromRenderBuffer2 = ++ DRIMODCreateImageFromRenderBuffer2; ++ gsSupV2.v0.CreateImageFromBuffer = DRIMODCreateImageFromBuffer; ++ gsSupV2.v0.QueryRendererInteger = DRIMODQueryRendererInteger; ++ gsSupV2.v0.QueryRendererString = DRIMODQueryRendererString; ++ gsSupV2.v0.CreateFence = DRIMODCreateFence; ++ gsSupV2.v0.DestroyFence = DRIMODDestroyFence; ++ gsSupV2.v0.ClientWaitSync = DRIMODClientWaitSync; ++ gsSupV2.v0.ServerWaitSync = DRIMODServerWaitSync; ++ gsSupV2.v0.GetFenceCapabilities = DRIMODGetFenceCapabilities; ++ gsSupV2.v0.CreateFenceFD = DRIMODCreateFenceFD; ++ gsSupV2.v0.GetFenceFD = DRIMODGetFenceFD; ++ gsSupV2.v0.GetNumAPIProcs = DRIMODGetNumAPIProcs; ++ gsSupV2.v0.GetAPIProcName = DRIMODGetAPIProcName; ++ gsSupV2.v0.GetAPIProcAddress = DRIMODGetAPIProcAddress; ++ gsSupV2.v0.SetDamageRegion = DRIMODSetDamageRegion; ++ ++ PVRDRIAdjustExtensions(0, 0); ++} ++ ++bool ++PVRDRICompatInit(const PVRDRICallbacks *psCallbacks, unsigned int uVersion, ++ const struct PVRDRICallbacksV2 *psCallbacksV2, ++ unsigned int uVersionV2, unsigned int uMinVersionV2) ++{ ++ bool (*pfRegisterVersionedCallbacks)(const PVRDRICallbacks *psCallbacks, ++ unsigned int uVersion); ++ bool (*pfRegisterVersionedCallbacksV2)(const void *pvCallbacks, ++ unsigned int uVersion, ++ unsigned int uMinVersion); ++ bool res; ++ ++ CompatLock(); ++ res = (giSupLibRef++ != 0); ++ if (res) ++ goto Exit; ++ ++ res = LoadSupportLib(); ++ if (!res) ++ goto Exit; ++ ++ LookupFunc(PVRDRIRegisterVersionedCallbacksV2, ++ pfRegisterVersionedCallbacksV2); ++ ++ LookupFunc(PVRDRIRegisterVersionedCallbacks, ++ pfRegisterVersionedCallbacks); ++ ++ res = (pfRegisterVersionedCallbacksV2 != NULL) || ++ (pfRegisterVersionedCallbacks != NULL); ++ if (!res) ++ goto Exit; ++ ++ if (pfRegisterVersionedCallbacksV2) { ++ res = pfRegisterVersionedCallbacksV2(psCallbacksV2, ++ uVersionV2, uMinVersionV2); ++ } else { ++ res = pfRegisterVersionedCallbacks(psCallbacks, uVersion); ++ if (res) ++ SetupLocalDRISupportInterfaceV2(); ++ } ++ ++Exit: ++ if (!res) { ++ CompatDeinit(); ++ giSupLibRef--; ++ } ++ CompatUnlock(); ++ ++ return res; ++} ++ ++void ++PVRDRICompatDeinit(void) ++{ ++ CompatLock(); ++ if (--giSupLibRef == 0) ++ CompatDeinit(); ++ CompatUnlock(); ++} ++ ++bool ++PVRDRIRegisterSupportInterfaceV1(const PVRDRISupportInterface *psInterface, ++ unsigned int uVersion) ++{ ++ size_t uSize; ++ ++ memset(&gsSup, 0, sizeof(gsSup)); ++ memset(&gsSupV2, 0, sizeof(gsSupV2)); ++ ++ /* The "default" case should be associated with the latest version */ ++ switch (uVersion) { ++ default: ++ case 2: ++ uSize = PVRDRIInterfaceSize(GetFenceFd); ++ break; ++ case 1: ++ case 0: ++ return false; ++ } ++ ++ memcpy(&gsSup, psInterface, uSize); ++ ++ return true; ++} ++ ++bool ++MODSUPRegisterSupportInterfaceV2(const void *pvInterface, ++ unsigned int uVersion, ++ unsigned int uMinVersion) ++{ ++ size_t uStart, uEnd; ++ ++ memset(&gsSup, 0, sizeof(gsSup)); ++ memset(&gsSupV2, 0, sizeof(gsSupV2)); ++ ++ if (uVersion < uMinVersion) ++ return false; ++ ++ /* ++ * Minimum versions we support. To prevent the accumulation of old unused ++ * interfaces in the PVRDRIInterfaceV2 structure, the caller specifies the ++ * minimum version it supports. This will be pointed to be the psInterface ++ * argument. Assuming we support that version, we must copy the structure ++ * passed to us into the correct place in our version of the interface ++ * structure. ++ */ ++ switch (uMinVersion) { ++ case 0: ++ uStart = PVRDRIInterfaceV2Start(v0); ++ break; ++ case 1: ++ case 2: ++ /* These versions require version 0 */ ++ return false; ++ default: ++ return false; ++ } ++ ++ /* The "default" case should be associated with the latest version */ ++ switch (uVersion) { ++ default: ++ case 3: ++ /* ++ * This version is an extension of version 2, with no new ++ * entry points. ++ */ ++ case 2: ++ /* This version is an extension of versions 0 and 1 */ ++ if (uMinVersion > 0) ++ return false; ++ ++ uEnd = PVRDRIInterfaceV2End(v2); ++ break; ++ case 1: ++ /* This version is an extension of version 0 */ ++ if (uMinVersion > 0) ++ return false; ++ ++ uEnd = PVRDRIInterfaceV2End(v1); ++ break; ++ case 0: ++ uEnd = PVRDRIInterfaceV2End(v0); ++ break; ++ } ++ ++ memcpy(((char *) &gsSupV2) + uStart, pvInterface, uEnd - uStart); ++ ++ PVRDRIAdjustExtensions(uVersion, uMinVersion); ++ ++ return true; ++} ++ ++struct DRISUPScreen * ++DRISUPCreateScreen(struct __DRIscreenRec *psDRIScreen, int iFD, ++ bool bUseInvalidate, void *pvLoaderPrivate, ++ const struct __DRIconfigRec ***pppsConfigs, ++ int *piMaxGLES1Version, int *piMaxGLES2Version) ++{ ++ CallFuncV2(v0.CreateScreen, ++ psDRIScreen, iFD, bUseInvalidate, pvLoaderPrivate, pppsConfigs, ++ piMaxGLES1Version, piMaxGLES2Version); ++ ++ return NULL; ++} ++ ++void ++DRISUPDestroyScreen(struct DRISUPScreen *psDRISUPScreen) ++{ ++ CallFuncV2(v0.DestroyScreen, ++ psDRISUPScreen); ++} ++ ++unsigned int ++DRISUPCreateContext(PVRDRIAPIType eAPI, PVRDRIConfig *psPVRDRIConfig, ++ struct PVRDRIContextConfig *psCtxConfig, ++ struct __DRIcontextRec *psDRIContext, ++ struct DRISUPContext *psDRISUPSharedContext, ++ struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPContext **ppsDRISUPContext) ++{ ++ CallFuncV2(v0.CreateContext, ++ eAPI, psPVRDRIConfig, psCtxConfig, psDRIContext, ++ psDRISUPSharedContext, psDRISUPScreen, ppsDRISUPContext); ++ ++ return PVRDRI_CONTEXT_ERROR_BAD_API; ++} ++ ++void ++DRISUPDestroyContext(struct DRISUPContext *psDRISUPContext) ++{ ++ CallFuncV2(v0.DestroyContext, ++ psDRISUPContext); ++} ++ ++struct DRISUPDrawable * ++DRISUPCreateDrawable(struct __DRIdrawableRec *psDRIDrawable, ++ struct DRISUPScreen *psDRISUPScreen, ++ void *pvLoaderPrivate, PVRDRIConfig *psPVRDRIConfig) ++{ ++ CallFuncV2(v0.CreateDrawable, ++ psDRIDrawable, psDRISUPScreen, pvLoaderPrivate, psPVRDRIConfig); ++ ++ return NULL; ++} ++ ++void ++DRISUPDestroyDrawable(struct DRISUPDrawable *psDRISUPDrawable) ++{ ++ CallFuncV2(v0.DestroyDrawable, ++ psDRISUPDrawable); ++} ++ ++bool ++DRISUPMakeCurrent(struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPWrite, ++ struct DRISUPDrawable *psDRISUPRead) ++{ ++ CallFuncV2(v0.MakeCurrent, ++ psDRISUPContext, psDRISUPWrite, psDRISUPRead); ++ ++ return false; ++} ++ ++bool ++DRISUPUnbindContext(struct DRISUPContext *psDRISUPContext) ++{ ++ CallFuncV2(v0.UnbindContext, ++ psDRISUPContext); ++ ++ return false; ++} ++ ++struct DRISUPBuffer * ++DRISUPAllocateBuffer(struct DRISUPScreen *psDRISUPScreen, ++ unsigned int uAttachment, unsigned int uFormat, ++ int iWidth, int iHeight, unsigned int *puName, ++ unsigned int *puPitch, unsigned int *puCPP, ++ unsigned int *puFlags) ++{ ++ CallFuncV2(v0.AllocateBuffer, ++ psDRISUPScreen, uAttachment, uFormat, iWidth, iHeight, puName, ++ puPitch, puCPP, puFlags); ++ ++ return NULL; ++} ++ ++void ++DRISUPReleaseBuffer(struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPBuffer *psDRISUPBuffer) ++{ ++ CallFuncV2(v0.ReleaseBuffer, ++ psDRISUPScreen, psDRISUPBuffer); ++} ++ ++void ++DRISUPSetTexBuffer2(struct DRISUPContext *psDRISUPContext, int iTarget, ++ int iFormat, struct DRISUPDrawable *psDRISUPDrawable) ++{ ++ CallFuncV2(v0.SetTexBuffer2, ++ psDRISUPContext, iTarget, iFormat, psDRISUPDrawable); ++} ++ ++void ++DRISUPReleaseTexBuffer(struct DRISUPContext *psDRISUPContext, int iTarget, ++ struct DRISUPDrawable *psDRISUPDrawable) ++{ ++ CallFuncV2(v0.ReleaseTexBuffer, ++ psDRISUPContext, iTarget, psDRISUPDrawable); ++} ++ ++void ++DRISUPFlush(struct DRISUPDrawable *psDRISUPDrawable) ++{ ++ CallFuncV2(v0.Flush, ++ psDRISUPDrawable); ++} ++ ++void ++DRISUPInvalidate(struct DRISUPDrawable *psDRISUPDrawable) ++{ ++ CallFuncV2(v0.Invalidate, ++ psDRISUPDrawable); ++} ++ ++void ++DRISUPFlushWithFlags(struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uFlags, unsigned int uThrottleReason) ++{ ++ CallFuncV2(v0.FlushWithFlags, ++ psDRISUPContext, psDRISUPDrawable, uFlags, uThrottleReason); ++} ++ ++__DRIimage * ++DRISUPCreateImageFromName(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, int iName, ++ int iPitch, void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromName, ++ psDRISUPScreen, iWidth, iHeight, iFourCC, iName, iPitch, ++ pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromRenderbuffer(struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromRenderbuffer, ++ psDRISUPContext, iRenderBuffer, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++void ++DRISUPDestroyImage(__DRIimage *psImage) ++{ ++ CallFuncV2(v0.DestroyImage, psImage); ++} ++ ++__DRIimage * ++DRISUPCreateImage(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, unsigned int uUse, ++ void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImage, ++ psDRISUPScreen, iWidth, iHeight, iFourCC, uUse, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++bool ++DRISUPQueryImage(__DRIimage *psImage, int iAttrib, int *piValue) ++{ ++ CallFuncV2(v0.QueryImage, ++ psImage, iAttrib, piValue); ++ ++ return false; ++} ++ ++__DRIimage * ++DRISUPDupImage(__DRIimage *psImage, void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.DupImage, ++ psImage, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++bool ++DRISUPValidateImageUsage(__DRIimage *psImage, unsigned int uUse) ++{ ++ CallFuncV2(v0.ValidateImageUsage, ++ psImage, uUse); ++ ++ return false; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromNames(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piNames, int iNumNames, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromNames, ++ psDRISUPScreen, iWidth, iHeight, iFourCC, piNames, iNumNames, ++ piStrides, piOffsets, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++__DRIimage * ++DRISUPFromPlanar(__DRIimage *psImage, int iPlane, void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.FromPlanar, ++ psImage, iPlane, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromTexture(struct DRISUPContext *psDRISUPContext, ++ int iTarget, unsigned int uTexture, int iDepth, ++ int iLevel, unsigned int *puError, ++ void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromTexture, ++ psDRISUPContext, iTarget, uTexture, iDepth, iLevel, puError, ++ pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromFDs(struct DRISUPScreen *psDRISUPcreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, int *piStrides, ++ int *piOffsets, void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromFDs, ++ psDRISUPcreen, iWidth, iHeight, iFourCC, piFDs, iNumFDs, ++ piStrides, piOffsets, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromDmaBufs(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromDMABufs, ++ psDRISUPScreen, iWidth, iHeight, iFourCC, piFDs, iNumFDs, ++ piStrides, piOffsets, uColorSpace, uSampleRange, ++ uHorizSiting, uVertSiting, puError, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++int ++DRISUPGetImageCapabilities(struct DRISUPScreen *psDRISUPScreen) ++{ ++ CallFuncV2(v0.GetImageCapabilities, ++ psDRISUPScreen); ++ ++ return 0; ++} ++ ++void ++DRISUPBlitImage(struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psDst, __DRIimage *psSrc, int iDstX0, int iDstY0, ++ int iDstWidth, int iDstHeight, int iSrcX0, int iSrcY0, ++ int iSrcWidth, int iSrcHeight, int iFlushFlag) ++{ ++ CallFuncV2(v0.BlitImage, ++ psDRISUPContext, psDst, psSrc, iDstX0, iDstY0, ++ iDstWidth, iDstHeight, iSrcX0, iSrcY0, ++ iSrcWidth, iSrcHeight, iFlushFlag); ++} ++ ++void * ++DRISUPMapImage(struct DRISUPContext *psDRISUPContext, __DRIimage* psImage, ++ int iX0, int iY0, int iWidth, int iHeight, unsigned int uFlags, ++ int *piStride, void **ppvData) ++{ ++ CallFuncV2(v0.MapImage, ++ psDRISUPContext, psImage, iX0, iY0, iWidth, iHeight, uFlags, ++ piStride, ppvData); ++ ++ return NULL; ++} ++ ++void ++DRISUPUnmapImage(struct DRISUPContext *psDRISUPContext, __DRIimage *psImage, ++ void *pvData) ++{ ++ CallFuncV2(v0.UnmapImage, ++ psDRISUPContext, psImage, pvData); ++} ++ ++__DRIimage * ++DRISUPCreateImageWithModifiers(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ const uint64_t *puModifiers, ++ const unsigned int uModifierCount, ++ void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageWithModifiers, ++ psDRISUPScreen, iWidth, iHeight, iFourCC, puModifiers, ++ uModifierCount, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromDMABufs2(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ uint64_t uModifier, int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromDMABufs2, ++ psDRISUPScreen, iWidth, iHeight, iFourCC, uModifier, ++ piFDs, iNumFDs, piStrides, piOffsets, uColorSpace, uSampleRange, ++ uHorizSiting, uVertSiting, puError, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++bool ++DRISUPQueryDMABufFormats(struct DRISUPScreen *psDRISUPScreen, int iMax, ++ int *piFormats, int *piCount) ++{ ++ CallFuncV2(v0.QueryDMABufFormats, ++ psDRISUPScreen, iMax, piFormats, piCount); ++ ++ return false; ++} ++ ++bool ++DRISUPQueryDMABufModifiers(struct DRISUPScreen *psDRISUPScreen, int iFourCC, ++ int iMax, uint64_t *puModifiers, ++ unsigned int *piExternalOnly, int *piCount) ++{ ++ CallFuncV2(v0.QueryDMABufModifiers, ++ psDRISUPScreen, iFourCC, iMax, puModifiers, piExternalOnly, ++ piCount); ++ ++ return false; ++} ++ ++bool ++DRISUPQueryDMABufFormatModifierAttribs(struct DRISUPScreen *psDRISUPScreen, ++ uint32_t iFourCC, uint64_t uModifier, ++ int iAttrib, uint64_t *puValue) ++{ ++ CallFuncV2(v0.QueryDMABufFormatModifierAttribs, ++ psDRISUPScreen, iFourCC, uModifier, iAttrib, puValue); ++ ++ return false; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromRenderBuffer2(struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, void *pvLoaderPrivate, ++ unsigned int *puError) ++{ ++ CallFuncV2(v0.CreateImageFromRenderBuffer2, ++ psDRISUPContext, iRenderBuffer, pvLoaderPrivate, puError); ++ ++ return NULL; ++} ++ ++__DRIimage * ++DRISUPCreateImageFromBuffer(struct DRISUPContext *psDRISUPContext, ++ int iTarget, void *pvBuffer, ++ unsigned int *puError, void *pvLoaderPrivate) ++{ ++ CallFuncV2(v0.CreateImageFromBuffer, ++ psDRISUPContext, iTarget, pvBuffer, puError, pvLoaderPrivate); ++ ++ return NULL; ++} ++ ++int ++DRISUPQueryRendererInteger(struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, unsigned int *puValue) ++{ ++ CallFuncV2(v0.QueryRendererInteger, ++ psDRISUPScreen, iAttribute, puValue); ++ ++ return -1; ++} ++ ++int ++DRISUPQueryRendererString(struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, const char **ppszValue) ++{ ++ CallFuncV2(v0.QueryRendererString, ++ psDRISUPScreen, iAttribute, ppszValue); ++ ++ return -1; ++} ++ ++void * ++DRISUPCreateFence(struct DRISUPContext *psDRISUPContext) ++{ ++ CallFuncV2(v0.CreateFence, ++ psDRISUPContext); ++ ++ return NULL; ++} ++ ++void ++DRISUPDestroyFence(struct DRISUPScreen *psDRISUPScreen, void *pvFence) ++{ ++ CallFuncV2(v0.DestroyFence, ++ psDRISUPScreen, pvFence); ++} ++ ++bool ++DRISUPClientWaitSync(struct DRISUPContext *psDRISUPContext, void *pvFence, ++ unsigned int uFlags, uint64_t uTimeout) ++{ ++ CallFuncV2(v0.ClientWaitSync, ++ psDRISUPContext, pvFence, uFlags, uTimeout); ++ ++ return false; ++} ++ ++void ++DRISUPServerWaitSync(struct DRISUPContext *psDRISUPContext, void *pvFence, ++ unsigned int uFlags) ++{ ++ CallFuncV2(v0.ServerWaitSync, ++ psDRISUPContext, pvFence, uFlags); ++} ++ ++unsigned int ++DRISUPGetFenceCapabilities(struct DRISUPScreen *psDRISUPScreen) ++{ ++ CallFuncV2(v0.GetFenceCapabilities, ++ psDRISUPScreen); ++ ++ return 0; ++} ++ ++void * ++DRISUPCreateFenceFD(struct DRISUPContext *psDRISUPContext, int iFD) ++{ ++ CallFuncV2(v0.CreateFenceFD, ++ psDRISUPContext, iFD); ++ ++ return NULL; ++} ++ ++int ++DRISUPGetFenceFD(struct DRISUPScreen *psDRISUPScreen, void *pvFence) ++{ ++ CallFuncV2(v0.GetFenceFD, ++ psDRISUPScreen, pvFence); ++ ++ return -1; ++} ++ ++void * ++DRISUPGetFenceFromCLEvent(struct DRISUPScreen *psDRISUPScreen, ++ intptr_t iCLEvent) ++{ ++ CallFuncV2(v1.GetFenceFromCLEvent, ++ psDRISUPScreen, iCLEvent); ++ ++ return NULL; ++} ++ ++int ++DRISUPGetAPIVersion(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI) ++{ ++ CallFuncV2(v2.GetAPIVersion, ++ psDRISUPScreen, eAPI); ++ ++ return 0; ++} ++ ++unsigned int ++DRISUPGetNumAPIProcs(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI) ++{ ++ CallFuncV2(v0.GetNumAPIProcs, ++ psDRISUPScreen, eAPI); ++ ++ return 0; ++} ++ ++const char * ++DRISUPGetAPIProcName(struct DRISUPScreen *psDRISUPScreen, PVRDRIAPIType eAPI, ++ unsigned int uIndex) ++{ ++ CallFuncV2(v0.GetAPIProcName, ++ psDRISUPScreen, eAPI, uIndex); ++ ++ return NULL; ++} ++ ++void * ++DRISUPGetAPIProcAddress(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI, unsigned int uIndex) ++{ ++ CallFuncV2(v0.GetAPIProcAddress, ++ psDRISUPScreen, eAPI, uIndex); ++ ++ return NULL; ++} ++ ++void ++DRISUPSetDamageRegion(struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uNRects, int *piRects) ++{ ++ CallFuncV2(v0.SetDamageRegion, ++ psDRISUPDrawable, uNRects, piRects); ++} ++ ++/****************************************************************************** ++ * PVR DRI Support interface, version 1. ++ * Everything below this point is deprecated. ++ *****************************************************************************/ ++ ++PVRDRIDeviceType ++PVRDRIGetDeviceTypeFromFd(int iFd) ++{ ++ CallFunc(GetDeviceTypeFromFd, iFd); ++ ++ return PVRDRI_DEVICE_TYPE_INVALID; ++} ++ ++ ++bool ++PVRDRIIsFirstScreen(PVRDRIScreenImpl *psScreenImpl) ++{ ++ CallFunc(IsFirstScreen, psScreenImpl); ++ ++ return false; ++} ++ ++ ++uint32_t ++PVRDRIPixFmtGetDepth(IMG_PIXFMT eFmt) ++{ ++ CallFunc(PixFmtGetDepth, eFmt); ++ ++ return 0; ++} ++ ++uint32_t ++PVRDRIPixFmtGetBPP(IMG_PIXFMT eFmt) ++{ ++ CallFunc(PixFmtGetBPP, eFmt); ++ ++ return 0; ++} ++ ++uint32_t ++PVRDRIPixFmtGetBlockSize(IMG_PIXFMT eFmt) ++{ ++ CallFunc(PixFmtGetBlockSize, eFmt); ++ ++ return 0; ++} ++ ++PVRDRIScreenImpl * ++PVRDRICreateScreenImpl(int iFd) ++{ ++ CallFunc(CreateScreen, iFd); ++ ++ return NULL; ++} ++ ++void ++PVRDRIDestroyScreenImpl(PVRDRIScreenImpl *psScreenImpl) ++{ ++ CallFunc(DestroyScreen, psScreenImpl); ++} ++ ++int ++PVRDRIAPIVersion(PVRDRIAPIType eAPI, PVRDRIAPISubType eAPISub, ++ PVRDRIScreenImpl *psScreenImpl) ++{ ++ CallFunc(APIVersion, eAPI, eAPISub, psScreenImpl); ++ ++ return 0; ++} ++ ++void * ++PVRDRIEGLGetLibHandle(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl) ++{ ++ CallFunc(EGLGetLibHandle, eAPI, psScreenImpl); ++ ++ return NULL; ++} ++ ++PVRDRIGLAPIProc ++PVRDRIEGLGetProcAddress(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ const char *psProcName) ++{ ++ CallFunc(EGLGetProcAddress, eAPI, psScreenImpl, psProcName); ++ ++ return (PVRDRIGLAPIProc) NULL; ++} ++ ++bool ++PVRDRIEGLFlushBuffers(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl, ++ bool bFlushAllSurfaces, bool bSwapBuffers, ++ bool bWaitForHW) ++{ ++ CallFunc(EGLFlushBuffers, eAPI, psScreenImpl, psContextImpl, ++ psDrawableImpl, bFlushAllSurfaces, bSwapBuffers, bWaitForHW); ++ ++ return false; ++} ++ ++void ++PVRDRIEGLMarkRendersurfaceInvalid(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl) ++{ ++ CallFunc(EGLMarkRendersurfaceInvalid, eAPI, psScreenImpl, psContextImpl); ++} ++ ++unsigned int ++PVRDRICreateContextV1(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psSharedContextImpl, ++ PVRDRIConfig *psConfig, ++ PVRDRIAPIType eAPI, PVRDRIAPISubType eAPISub, ++ unsigned int uMajorVersion, unsigned int uMinorVersion, ++ uint32_t uFlags, bool bNotifyReset, ++ unsigned int uPriority, ++ PVRDRIContextImpl **ppsContextImpl) ++{ ++ CallFunc(CreateContextV1, psScreenImpl, psSharedContextImpl, psConfig, ++ eAPI, eAPISub, uMajorVersion, uMinorVersion, uFlags, bNotifyReset, ++ uPriority, ppsContextImpl); ++ ++ return PVRDRI_CONTEXT_ERROR_BAD_API; ++} ++ ++void ++PVRDRIDestroyContextImpl(PVRDRIContextImpl *psContextImpl, PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl) ++{ ++ CallFunc(DestroyContext, psContextImpl, eAPI, psScreenImpl); ++} ++ ++bool ++PVRDRIMakeCurrentGC(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psWriteImpl, ++ PVRDRIDrawableImpl *psReadImpl) ++{ ++ CallFunc(MakeCurrentGC, eAPI, psScreenImpl, psContextImpl, psWriteImpl, ++ psReadImpl); ++ ++ return false; ++} ++ ++void ++PVRDRIMakeUnCurrentGC(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl) ++{ ++ CallFunc(MakeUnCurrentGC, eAPI, psScreenImpl); ++} ++ ++unsigned int ++PVRDRIGetImageSource(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, uint32_t uiTarget, ++ uintptr_t uiBuffer, uint32_t uiLevel, ++ IMGEGLImage *psEGLImage) ++{ ++ CallFunc(GetImageSource, eAPI, psScreenImpl, psContextImpl, uiTarget, ++ uiBuffer, uiLevel, psEGLImage); ++ ++ return PVRDRI_IMAGE_ERROR_BAD_MATCH; ++} ++ ++bool ++PVRDRI2BindTexImage(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl) ++{ ++ CallFunc(BindTexImage, eAPI, psScreenImpl, psContextImpl, psDrawableImpl); ++ ++ return false; ++} ++ ++void ++PVRDRI2ReleaseTexImage(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl) ++{ ++ CallFunc(ReleaseTexImage, eAPI, psScreenImpl, psContextImpl, psDrawableImpl); ++} ++ ++PVRDRIDrawableImpl * ++PVRDRICreateDrawableWithConfig(PVRDRIDrawable *psPVRDrawable, ++ PVRDRIConfig *psConfig) ++{ ++ CallFunc(CreateDrawableWithConfig, psPVRDrawable, psConfig); ++ ++ return NULL; ++} ++ ++void ++PVRDRIDestroyDrawableImpl(PVRDRIDrawableImpl *psScreenImpl) ++{ ++ CallFunc(DestroyDrawable, psScreenImpl); ++} ++ ++bool ++PVREGLDrawableCreate(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl) ++{ ++ CallFunc(EGLDrawableCreate, psScreenImpl, psDrawableImpl); ++ ++ return false; ++} ++ ++bool ++PVREGLDrawableRecreate(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl) ++{ ++ CallFunc(EGLDrawableRecreate, psScreenImpl, psDrawableImpl); ++ ++ return false; ++} ++ ++bool ++PVREGLDrawableDestroy(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl) ++{ ++ CallFunc(EGLDrawableDestroy, psScreenImpl, psDrawableImpl); ++ ++ return false; ++} ++ ++void ++PVREGLDrawableDestroyConfig(PVRDRIDrawableImpl *psDrawableImpl) ++{ ++ CallFunc(EGLDrawableDestroyConfig, psDrawableImpl); ++} ++ ++PVRDRIBufferImpl * ++PVRDRIBufferCreate(PVRDRIScreenImpl *psScreenImpl, int iWidth, int iHeight, ++ unsigned int uiBpp, unsigned int uiUseFlags, ++ unsigned int *puiStride) ++{ ++ CallFunc(BufferCreate, psScreenImpl, iWidth, iHeight, uiBpp, uiUseFlags, ++ puiStride); ++ ++ return NULL; ++} ++ ++PVRDRIBufferImpl * ++PVRDRIBufferCreateWithModifiers(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, int iHeight, ++ int format, IMG_PIXFMT eIMGPixelFormat, ++ const uint64_t *puiModifiers, ++ unsigned int uiModifierCount, ++ unsigned int *puiStride) ++{ ++ CallFunc(BufferCreateWithModifiers, psScreenImpl, iWidth, iHeight, format, ++ eIMGPixelFormat, puiModifiers, uiModifierCount, puiStride); ++ ++ return NULL; ++} ++ ++PVRDRIBufferImpl * ++PVRDRIBufferCreateFromNames(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, int iHeight, unsigned int uiNumPlanes, ++ const int *piName, const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift) ++{ ++ CallFunc(BufferCreateFromNames, psScreenImpl, iWidth, iHeight, uiNumPlanes, ++ piName, piStride, piOffset, puiWidthShift, puiHeightShift); ++ ++ return NULL; ++} ++ ++PVRDRIBufferImpl * ++PVRDRIBufferCreateFromFdsWithModifier(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, int iHeight, ++ uint64_t uiModifier, ++ unsigned int uiNumPlanes, ++ const int *piFd, const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift) ++{ ++ CallFunc(BufferCreateFromFdsWithModifier, psScreenImpl, iWidth, iHeight, ++ uiModifier, uiNumPlanes, piFd, piStride, piOffset, ++ puiWidthShift, puiHeightShift); ++ ++ return NULL; ++} ++ ++PVRDRIBufferImpl * ++PVRDRISubBufferCreate(PVRDRIScreenImpl *psScreen, ++ PVRDRIBufferImpl *psParentBuffer, int plane) ++{ ++ CallFunc(SubBufferCreate, psScreen, psParentBuffer, plane); ++ ++ return NULL; ++} ++ ++void ++PVRDRIBufferDestroy(PVRDRIBufferImpl *psBuffer) ++{ ++ CallFunc(BufferDestroy, psBuffer); ++} ++ ++int ++PVRDRIBufferGetFd(PVRDRIBufferImpl *psBuffer) ++{ ++ CallFunc(BufferGetFd, psBuffer); ++ ++ return -1; ++} ++ ++int ++PVRDRIBufferGetHandle(PVRDRIBufferImpl *psBuffer) ++{ ++ CallFunc(BufferGetHandle, psBuffer); ++ ++ return 0; ++} ++ ++uint64_t ++PVRDRIBufferGetModifier(PVRDRIBufferImpl *psBuffer) ++{ ++ CallFunc(BufferGetModifier, psBuffer); ++ ++ return DRM_FORMAT_MOD_INVALID; ++} ++ ++int ++PVRDRIBufferGetName(PVRDRIBufferImpl *psBuffer) ++{ ++ CallFunc(BufferGetName, psBuffer); ++ ++ return 0; ++} ++ ++int ++PVRDRIBufferGetOffset(PVRDRIBufferImpl *psBuffer) ++{ ++ CallFunc(BufferGetOffset, psBuffer); ++ ++ return 0; ++} ++ ++IMGEGLImage * ++PVRDRIEGLImageCreate(void) ++{ ++ CallFunc(EGLImageCreate); ++ ++ return NULL; ++} ++ ++IMGEGLImage * ++PVRDRIEGLImageCreateFromBuffer(int iWidth, int iHeight, int iStride, ++ IMG_PIXFMT ePixelFormat, ++ IMG_YUV_COLORSPACE eColourSpace, ++ IMG_YUV_CHROMA_INTERP eChromaUInterp, ++ IMG_YUV_CHROMA_INTERP eChromaVInterp, ++ PVRDRIBufferImpl *psBuffer) ++{ ++ CallFunc(EGLImageCreateFromBuffer, iWidth, iHeight, iStride, ePixelFormat, ++ eColourSpace, eChromaUInterp, eChromaVInterp, psBuffer); ++ ++ return NULL; ++} ++ ++IMGEGLImage * ++PVRDRIEGLImageCreateFromSubBuffer(IMG_PIXFMT ePixelFormat, ++ PVRDRIBufferImpl *psSubBuffer) ++{ ++ CallFunc(EGLImageCreateFromSubBuffer, ePixelFormat, psSubBuffer); ++ ++ return NULL; ++} ++ ++IMGEGLImage * ++PVRDRIEGLImageDup(IMGEGLImage *psIn) ++{ ++ CallFunc(EGLImageDup, psIn); ++ ++ return NULL; ++} ++ ++void ++PVRDRIEGLImageSetCallbackData(IMGEGLImage *psEGLImage, __DRIimage *image) ++{ ++ CallFunc(EGLImageSetCallbackData, psEGLImage, image); ++} ++ ++void ++PVRDRIEGLImageDestroyExternal(PVRDRIScreenImpl *psScreenImpl, ++ IMGEGLImage *psEGLImage, ++ PVRDRIEGLImageType eglImageType) ++{ ++ CallFunc(EGLImageDestroyExternal, psScreenImpl, psEGLImage, eglImageType); ++} ++ ++void ++PVRDRIEGLImageFree(IMGEGLImage *psEGLImage) ++{ ++ CallFunc(EGLImageFree, psEGLImage); ++} ++ ++void ++PVRDRIEGLImageGetAttribs(IMGEGLImage *psEGLImage, ++ PVRDRIBufferAttribs *psAttribs) ++{ ++ CallFunc(EGLImageGetAttribs, psEGLImage, psAttribs); ++} ++ ++void * ++PVRDRICreateFenceImpl(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl) ++{ ++ CallFunc(CreateFence, eAPI, psScreenImpl, psContextImpl); ++ ++ return NULL; ++} ++ ++void * ++PVRDRICreateFenceFd(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, int iFd) ++{ ++ CallFunc(CreateFenceFd, eAPI, psScreenImpl, psContextImpl, iFd); ++ ++ return NULL; ++} ++ ++unsigned int ++PVRDRIGetFenceCapabilities(PVRDRIScreenImpl *psScreenImpl) ++{ ++ CallFunc(GetFenceCapabilities, psScreenImpl); ++ ++ return 0; ++} ++ ++int ++PVRDRIGetFenceFd(void *pvFence) ++{ ++ CallFunc(GetFenceFd, pvFence); ++ ++ return -1; ++} ++ ++void ++PVRDRIDestroyFenceImpl(void *pvFence) ++{ ++ CallFunc(DestroyFence, pvFence); ++} ++ ++bool ++PVRDRIClientWaitSyncImpl(PVRDRIAPIType eAPI, PVRDRIContextImpl *psContextImpl, ++ void *pvFence, bool bFlushCommands, bool bTimeout, ++ uint64_t uiTimeout) ++{ ++ CallFunc(ClientWaitSync, eAPI, psContextImpl, pvFence, bFlushCommands, ++ bTimeout, uiTimeout); ++ ++ return false; ++} ++ ++bool ++PVRDRIServerWaitSyncImpl(PVRDRIAPIType eAPI, PVRDRIContextImpl *psContextImpl, ++ void *pvFence) ++{ ++ CallFunc(ServerWaitSync, eAPI, psContextImpl, pvFence); ++ ++ return false; ++} ++ ++bool ++PVRDRIBlitEGLImage(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psDstImage, PVRDRIBufferImpl *psDstBuffer, ++ IMGEGLImage *psSrcImage, PVRDRIBufferImpl *psSrcBuffer, ++ int iDstX, int iDstY, int iDstWidth, int iDstHeight, ++ int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, ++ int iFlushFlag) ++{ ++ CallFunc(BlitEGLImage, psScreenImpl, psContextImpl, ++ psDstImage, psDstBuffer, ++ psSrcImage, psSrcBuffer, ++ iDstX, iDstY, iDstWidth, iDstHeight, ++ iSrcX, iSrcY, iSrcWidth, iSrcHeight, ++ iFlushFlag); ++ ++ return false; ++} ++ ++void * ++PVRDRIMapEGLImage(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psImage, PVRDRIBufferImpl *psBuffer, ++ int iX, int iY, int iWidth, int iHeight, ++ unsigned int uiFlags, int *piStride, void **ppvData) ++{ ++ CallFunc(MapEGLImage, psScreenImpl, psContextImpl, psImage, psBuffer, ++ iX, iY, iWidth, iHeight, uiFlags, piStride, ppvData); ++ ++ return NULL; ++} ++ ++bool ++PVRDRIUnmapEGLImage(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psImage, PVRDRIBufferImpl *psBuffer, ++ void *pvData) ++{ ++ CallFunc(UnmapEGLImage, psScreenImpl, psContextImpl, psImage, psBuffer, ++ pvData); ++ ++ return false; ++} ++ ++bool ++PVRDRIMesaFormatSupported(unsigned int iFormat) ++{ ++ CallFunc(MesaFormatSupported, iFormat); ++ ++ return false; ++} ++ ++unsigned int ++PVRDRIDepthStencilBitArraySize(void) ++{ ++ CallFunc(DepthStencilBitArraySize); ++ ++ return 0; ++} ++ ++const uint8_t * ++PVRDRIDepthBitsArray(void) ++{ ++ CallFunc(DepthBitsArray); ++ ++ return NULL; ++} ++ ++const uint8_t * ++PVRDRIStencilBitsArray(void) ++{ ++ CallFunc(StencilBitsArray); ++ ++ return NULL; ++} ++ ++unsigned int ++PVRDRIMSAABitArraySize(void) ++{ ++ CallFunc(MSAABitArraySize); ++ ++ return 0; ++} ++ ++const uint8_t * ++PVRDRIMSAABitsArray(void) ++{ ++ CallFunc(MSAABitsArray); ++ ++ return NULL; ++} ++ ++uint32_t ++PVRDRIMaxPBufferWidth(void) ++{ ++ CallFunc(MaxPBufferWidth); ++ ++ return 0; ++} ++ ++uint32_t ++PVRDRIMaxPBufferHeight(void) ++{ ++ CallFunc(MaxPBufferHeight); ++ ++ return 0; ++} ++ ++ ++unsigned int ++PVRDRIGetNumAPIFuncs(PVRDRIAPIType eAPI) ++{ ++ CallFunc(GetNumAPIFuncs, eAPI); ++ ++ return 0; ++} ++ ++const char * ++PVRDRIGetAPIFunc(PVRDRIAPIType eAPI, unsigned int index) ++{ ++ CallFunc(GetAPIFunc, eAPI, index); ++ ++ return NULL; ++} ++ ++int ++PVRDRIQuerySupportedFormats(PVRDRIScreenImpl *psScreenImpl, ++ unsigned int uNumFormats, const int *piFormats, ++ const IMG_PIXFMT *peImgFormats, bool *bSupported) ++{ ++ CallFunc(QuerySupportedFormats, psScreenImpl, uNumFormats, piFormats, ++ peImgFormats, bSupported); ++ ++ return -1; ++} ++ ++int ++PVRDRIQueryModifiers(PVRDRIScreenImpl *psScreenImpl, ++ int iFormat, IMG_PIXFMT eImgFormat, ++ uint64_t *puModifiers, unsigned int *puExternalOnly) ++{ ++ CallFunc(QueryModifiers, psScreenImpl, iFormat, eImgFormat, puModifiers, ++ puExternalOnly); ++ ++ return -1; ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrdrawable_mod.c b/src/mesa/drivers/dri/pvr/pvrdrawable_mod.c +new file mode 100644 +index 00000000000..505f4329cb8 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrdrawable_mod.c +@@ -0,0 +1,385 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++ ++#include "util/u_atomic.h" ++#include "pvrdri_mod.h" ++ ++static inline void ++PVRDRIMarkRenderSurfaceAsInvalid(struct DRISUPDrawable *psPVRDrawable) ++{ ++ struct DRISUPContext *psPVRContext = psPVRDrawable->psPVRContext; ++ ++ if (psPVRContext) { ++ struct DRISUPScreen *psPVRScreen = psPVRContext->psPVRScreen; ++ ++ PVRDRIEGLMarkRendersurfaceInvalid(psPVRContext->eAPI, ++ psPVRScreen->psImpl, ++ psPVRContext->psImpl); ++ } ++} ++ ++/*************************************************************************//*! ++ PVR drawable local functions (image driver loader) ++ *//**************************************************************************/ ++ ++static inline void ++PVRDrawableImageDestroy(struct DRISUPDrawable *psPVRDrawable) ++{ ++ if (psPVRDrawable->psImage) { ++ PVRDRIUnrefImage(psPVRDrawable->psImage); ++ psPVRDrawable->psImage = NULL; ++ } ++} ++ ++static inline void ++PVRDrawableImageAccumDestroy(struct DRISUPDrawable *psPVRDrawable) ++{ ++ if (psPVRDrawable->psImageAccum) { ++ PVRDRIUnrefImage(psPVRDrawable->psImageAccum); ++ psPVRDrawable->psImageAccum = NULL; ++ } ++} ++ ++static void ++PVRDrawableImageUpdate(struct DRISUPDrawable *psPVRDrawable) ++{ ++ if (psPVRDrawable->psImage != psPVRDrawable->psDRI) { ++ assert(PVRDRIImageGetSharedBuffer(psPVRDrawable->psDRI) != NULL); ++ ++ PVRDrawableImageDestroy(psPVRDrawable); ++ ++ PVRDRIRefImage(psPVRDrawable->psDRI); ++ psPVRDrawable->psImage = psPVRDrawable->psDRI; ++ } ++ ++ if (psPVRDrawable->psImageAccum != psPVRDrawable->psDRIAccum) { ++ PVRDrawableImageAccumDestroy(psPVRDrawable); ++ ++ if (psPVRDrawable->psDRIAccum) { ++ PVRDRIRefImage(psPVRDrawable->psDRIAccum); ++ psPVRDrawable->psImageAccum = psPVRDrawable->psDRIAccum; ++ } ++ } ++} ++ ++/*************************************************************************//*! ++Function Name : PVRImageDrawableGetNativeInfo ++Inputs : psPVRDrawable ++Returns : Boolean ++Description : Update native drawable information. ++ *//**************************************************************************/ ++static bool ++PVRImageDrawableGetNativeInfo(struct DRISUPDrawable *psPVRDrawable) ++{ ++ struct PVRDRIImageList sImages; ++ uint32_t uBufferMask; ++ ++ if (psPVRDrawable->bDoubleBufferMode) ++ uBufferMask = PVRDRI_IMAGE_BUFFER_BACK; ++ else ++ uBufferMask = PVRDRI_IMAGE_BUFFER_FRONT; ++ ++ uBufferMask |= PVRDRI_IMAGE_BUFFER_PREV; ++ ++ if (!MODSUPGetBuffers(psPVRDrawable->psDRIDrawable, ++ psPVRDrawable->psFormat->iDRIFourCC, ++ NULL, psPVRDrawable->pvLoaderPrivate, ++ uBufferMask, &sImages)) { ++ errorMessage("%s: Image get buffers call failed", __func__); ++ return false; ++ } ++ ++ psPVRDrawable->psDRI = ++ (sImages.uImageMask & PVRDRI_IMAGE_BUFFER_BACK) ? ++ sImages.psBack : sImages.psFront; ++ ++ if (sImages.uImageMask & PVRDRI_IMAGE_BUFFER_PREV) ++ psPVRDrawable->psDRIAccum = sImages.psPrev; ++ else ++ psPVRDrawable->psDRIAccum = NULL; ++ ++ return true; ++} ++ ++/*************************************************************************//*! ++Function Name : PVRImageDrawableCreate ++Inputs : psPVRDrawable ++Returns : Boolean ++Description : Create drawable ++ *//**************************************************************************/ ++static bool ++PVRImageDrawableCreate(struct DRISUPDrawable *psPVRDrawable) ++{ ++ uint32_t uBytesPerPixel; ++ PVRDRIBufferAttribs sBufferAttribs; ++ ++ if (!PVRImageDrawableGetNativeInfo(psPVRDrawable)) ++ return false; ++ ++ PVRDRIEGLImageGetAttribs(PVRDRIImageGetEGLImage(psPVRDrawable->psDRI), ++ &sBufferAttribs); ++ uBytesPerPixel = PVRDRIPixFmtGetBlockSize(sBufferAttribs.ePixFormat); ++ ++ psPVRDrawable->uWidth = sBufferAttribs.uiWidth; ++ psPVRDrawable->uHeight = sBufferAttribs.uiHeight; ++ psPVRDrawable->uStride = sBufferAttribs.uiStrideInBytes; ++ psPVRDrawable->uBytesPerPixel = uBytesPerPixel; ++ ++ PVRDrawableImageUpdate(psPVRDrawable); ++ ++ if (!PVREGLDrawableCreate(psPVRDrawable->psPVRScreen->psImpl, ++ psPVRDrawable->psImpl)) { ++ errorMessage("%s: Couldn't create EGL drawable", __func__); ++ return false; ++ } ++ ++ return true; ++} ++ ++/*************************************************************************//*! ++Function Name : PVRImageDrawableUpdate ++Inputs : psPVRDrawable ++Returns : Boolean ++Description : Update drawable ++ *//**************************************************************************/ ++static bool ++PVRImageDrawableUpdate(struct DRISUPDrawable *psPVRDrawable, ++ bool bAllowRecreate) ++{ ++ uint32_t uBytesPerPixel; ++ PVRDRIBufferAttribs sBufferAttribs; ++ bool bRecreate; ++ ++ PVRDRIEGLImageGetAttribs(PVRDRIImageGetEGLImage(psPVRDrawable->psDRI), ++ &sBufferAttribs); ++ uBytesPerPixel = PVRDRIPixFmtGetBlockSize(sBufferAttribs.ePixFormat); ++ ++ bRecreate = ++ (!psPVRDrawable->bDoubleBufferMode && ++ psPVRDrawable->psImage != psPVRDrawable->psDRI) || ++ (psPVRDrawable->uWidth != sBufferAttribs.uiWidth) || ++ (psPVRDrawable->uHeight != sBufferAttribs.uiHeight) || ++ (psPVRDrawable->uStride != sBufferAttribs.uiStrideInBytes) || ++ (psPVRDrawable->uBytesPerPixel != uBytesPerPixel); ++ ++ if (bRecreate) { ++ if (bAllowRecreate) { ++ PVRDRIMarkRenderSurfaceAsInvalid(psPVRDrawable); ++ ++ psPVRDrawable->uWidth = sBufferAttribs.uiWidth; ++ psPVRDrawable->uHeight = sBufferAttribs.uiHeight; ++ psPVRDrawable->uStride = sBufferAttribs.uiStrideInBytes; ++ psPVRDrawable->uBytesPerPixel = uBytesPerPixel; ++ } else { ++ return false; ++ } ++ } ++ ++ PVRDrawableImageUpdate(psPVRDrawable); ++ ++ if (bRecreate) { ++ if (!PVREGLDrawableRecreate(psPVRDrawable->psPVRScreen->psImpl, ++ psPVRDrawable->psImpl)) { ++ errorMessage("%s: Couldn't recreate EGL drawable", __func__); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++/*************************************************************************//*! ++ PVR drawable local functions ++ *//**************************************************************************/ ++ ++/*************************************************************************//*! ++Function Name : PVRDRIDrawableUpdate ++Inputs : psPVRDrawable ++Description : Update drawable ++ *//**************************************************************************/ ++static bool ++PVRDRIDrawableUpdate(struct DRISUPDrawable *psPVRDrawable, bool bAllowRecreate) ++{ ++ bool bRes; ++ int iInfoInvalid = 0; ++ ++ /* ++ * The test for bDrawableUpdating is needed because drawable parameters are ++ * fetched (via KEGLGetDrawableParameters) when a drawable is recreated. ++ * The test for bFlushInProgress is to prevent the drawable information ++ * being updated during a flush, which could result in a call back into the ++ * Mesa platform code during the processing for a buffer swap, which could ++ * corrupt the platform state. ++ */ ++ if (psPVRDrawable->bDrawableUpdating || psPVRDrawable->bFlushInProgress) ++ return false; ++ ++ psPVRDrawable->bDrawableUpdating = true; ++ ++ if (psPVRDrawable->psPVRScreen->bUseInvalidate) { ++ iInfoInvalid = p_atomic_read(&psPVRDrawable->iInfoInvalid); ++ bRes = !iInfoInvalid; ++ if (bRes) ++ goto ExitNotUpdating; ++ } ++ ++ bRes = PVRImageDrawableGetNativeInfo(psPVRDrawable); ++ if (!bRes) ++ goto ExitNotUpdating; ++ ++ bRes = PVRImageDrawableUpdate(psPVRDrawable, bAllowRecreate); ++ if (bRes && iInfoInvalid) ++ p_atomic_add(&psPVRDrawable->iInfoInvalid, -iInfoInvalid); ++ ++ExitNotUpdating: ++ psPVRDrawable->bDrawableUpdating = false; ++ return bRes; ++} ++ ++/*************************************************************************//*! ++ PVR drawable interface ++ *//**************************************************************************/ ++bool ++PVRDRIDrawableInit(struct DRISUPDrawable *psPVRDrawable) ++{ ++ if (psPVRDrawable->bInitialised) ++ return true; ++ ++ if (!PVRImageDrawableCreate(psPVRDrawable)) ++ return false; ++ ++ psPVRDrawable->bInitialised = true; ++ ++ return true; ++} ++ ++void ++PVRDRIDrawableDeinit(struct DRISUPDrawable *psPVRDrawable) ++{ ++ (void) PVREGLDrawableDestroy(psPVRDrawable->psPVRScreen->psImpl, ++ psPVRDrawable->psImpl); ++ ++ PVRDrawableImageDestroy(psPVRDrawable); ++ PVRDrawableImageAccumDestroy(psPVRDrawable); ++ ++ psPVRDrawable->bInitialised = false; ++} ++ ++static bool ++PVRDRIDrawableGetParameters(struct DRISUPDrawable *psPVRDrawable, ++ PVRDRIBufferImpl **ppsDstBuffer, ++ PVRDRIBufferImpl **ppsAccumBuffer) ++{ ++ if (ppsDstBuffer || ppsAccumBuffer) { ++ __DRIimage *psDstImage = psPVRDrawable->psImage; ++ __DRIimage *psAccumImage = psPVRDrawable->psImageAccum; ++ PVRDRIBufferImpl *psDstBuffer, *psAccumBuffer; ++ ++ psDstBuffer = PVRDRIImageGetSharedBuffer(psDstImage); ++ if (!psDstBuffer) { ++ errorMessage("%s: Couldn't get backing buffer", __func__); ++ return false; ++ } ++ ++ if (psAccumImage) { ++ psAccumBuffer = PVRDRIImageGetSharedBuffer(psAccumImage); ++ if (!psAccumBuffer) ++ psAccumBuffer = psDstBuffer; ++ } else { ++ psAccumBuffer = psDstBuffer; ++ } ++ ++ if (ppsDstBuffer) ++ *ppsDstBuffer = psDstBuffer; ++ ++ if (ppsAccumBuffer) ++ *ppsAccumBuffer = psAccumBuffer; ++ } ++ ++ return true; ++} ++ ++bool ++PVRDRIDrawableQuery(const PVRDRIDrawable *psPVRDRIDrawable, ++ PVRDRIBufferAttrib eBufferAttrib, uint32_t *uiValueOut) ++{ ++ const struct DRISUPDrawable *psPVRDrawable; ++ ++ if (!psPVRDRIDrawable || !uiValueOut) ++ return false; ++ ++ psPVRDrawable = (const struct DRISUPDrawable *) psPVRDRIDrawable; ++ ++ switch (eBufferAttrib) { ++ case PVRDRI_BUFFER_ATTRIB_TYPE: ++ *uiValueOut = (uint32_t) psPVRDrawable->eType; ++ return true; ++ case PVRDRI_BUFFER_ATTRIB_WIDTH: ++ *uiValueOut = (uint32_t) psPVRDrawable->uWidth; ++ return true; ++ case PVRDRI_BUFFER_ATTRIB_HEIGHT: ++ *uiValueOut = (uint32_t) psPVRDrawable->uHeight; ++ return true; ++ case PVRDRI_BUFFER_ATTRIB_STRIDE: ++ *uiValueOut = (uint32_t) psPVRDrawable->uStride; ++ return true; ++ case PVRDRI_BUFFER_ATTRIB_PIXEL_FORMAT: ++ *uiValueOut = (uint32_t) psPVRDrawable->psFormat->eIMGPixelFormat; ++ static_assert(sizeof(IMG_PIXFMT) <= sizeof(*uiValueOut), ++ "Type size mismatch"); ++ return true; ++ case PVRDRI_BUFFER_ATTRIB_INVALID: ++ errorMessage("%s: Invalid attribute", __func__); ++ assert(0); ++ return false; ++ default: ++ return false; ++ } ++} ++ ++bool ++PVRDRIDrawableGetParametersV2(PVRDRIDrawable *psPVRDRIDrawable, ++ uint32_t uiFlags, ++ PVRDRIBufferImpl **ppsDstBuffer, ++ PVRDRIBufferImpl **ppsAccumBuffer) ++{ ++ const bool bNoUpdate = uiFlags & PVRDRI_GETPARAMS_FLAG_NO_UPDATE; ++ struct DRISUPDrawable *psPVRDrawable; ++ ++ psPVRDrawable = (struct DRISUPDrawable *) psPVRDRIDrawable; ++ ++ if (!bNoUpdate) { ++ const bool bAllowRecreate = ++ uiFlags & PVRDRI_GETPARAMS_FLAG_ALLOW_RECREATE; ++ ++ if (!PVRDRIDrawableUpdate(psPVRDrawable, bAllowRecreate)) ++ if (bAllowRecreate) ++ return false; ++ } ++ ++ return PVRDRIDrawableGetParameters(psPVRDrawable, ++ ppsDstBuffer, ppsAccumBuffer); ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrdri.c b/src/mesa/drivers/dri/pvr/pvrdri.c +new file mode 100644 +index 00000000000..45950552647 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrdri.c +@@ -0,0 +1,603 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++ ++#include "util/u_atomic.h" ++#include "utils.h" ++ ++#include "pvrdri.h" ++#include "pvrmesa.h" ++#include "pvrdri_mod.h" ++ ++#define PVR_IMAGE_LOADER_VER_MIN 1 ++ ++struct PVRBuffer { ++ __DRIbuffer sDRIBuffer; ++ struct DRISUPBuffer *psDRISUPBuffer; ++}; ++ ++/*************************************************************************//*! ++ Local functions ++ *//**************************************************************************/ ++ ++static bool ++PVRLoaderIsSupported(__DRIscreen *psDRIScreen) ++{ ++ if (psDRIScreen->image.loader) { ++ if (psDRIScreen->image.loader->base.version < PVR_IMAGE_LOADER_VER_MIN) { ++ __driUtilMessage("%s: Image loader extension version %d but need %d", ++ __func__, psDRIScreen->image.loader->base.version, ++ PVR_IMAGE_LOADER_VER_MIN); ++ return false; ++ } else if (!psDRIScreen->image.loader->getBuffers) { ++ __driUtilMessage("%s: Image loader extension missing support for getBuffers", ++ __func__); ++ return false; ++ } ++ } else { ++ __driUtilMessage("%s: Image loader extension required", __func__); ++ return false; ++ } ++ ++ return true; ++} ++ ++static inline struct DRISUPContext * ++getSharedContextImpl(void *pvSharedContextPrivate) ++{ ++ if (pvSharedContextPrivate == NULL) ++ return NULL; ++ ++ return ((PVRDRIContext *) pvSharedContextPrivate)->psDRISUPContext; ++} ++ ++static void ++PVRDRIScreenAddReference(PVRDRIScreen *psPVRScreen) ++{ ++ int iRefCount = p_atomic_inc_return(&psPVRScreen->iRefCount); ++ ++ (void) iRefCount; ++ assert(iRefCount > 1); ++} ++ ++static void ++PVRDRIScreenRemoveReference(PVRDRIScreen *psPVRScreen) ++{ ++ int iRefCount = p_atomic_dec_return(&psPVRScreen->iRefCount); ++ ++ assert(iRefCount >= 0); ++ ++ if (iRefCount != 0) ++ return; ++ ++ pvrdri_free_dispatch_tables(psPVRScreen); ++ DRISUPDestroyScreen(psPVRScreen->psDRISUPScreen); ++ PVRDRICompatDeinit(); ++ free(psPVRScreen); ++} ++ ++static void ++PVRScreenPrintExtensions(__DRIscreen *psDRIScreen) ++{ ++ /* Don't attempt to print anything if LIBGL_DEBUG isn't in the environment */ ++ if (getenv("LIBGL_DEBUG") == NULL) ++ return; ++ ++ if (psDRIScreen->extensions) { ++ const __DRIextension *psScreenExtensionVersionInfo = ++ PVRDRIScreenExtensionVersionInfo(); ++ int i; ++ int j; ++ ++ __driUtilMessage("Supported screen extensions:"); ++ ++ for (i = 0; psDRIScreen->extensions[i]; i++) { ++ for (j = 0; psScreenExtensionVersionInfo[j].name; j++) { ++ if (strcmp(psDRIScreen->extensions[i]->name, ++ psScreenExtensionVersionInfo[j].name) == 0) { ++ __driUtilMessage("\t%s (supported version: %u - max version: %u)", ++ psDRIScreen->extensions[i]->name, ++ psDRIScreen->extensions[i]->version, ++ psScreenExtensionVersionInfo[j].version); ++ break; ++ } ++ } ++ ++ if (psScreenExtensionVersionInfo[j].name == NULL) { ++ __driUtilMessage("\t%s (supported version: %u - max version: unknown)", ++ psDRIScreen->extensions[i]->name, ++ psDRIScreen->extensions[i]->version); ++ } ++ } ++ } else { ++ __driUtilMessage("No screen extensions found"); ++ } ++} ++ ++/*************************************************************************//*! ++ Mesa driver API functions ++ *//**************************************************************************/ ++ ++static const __DRIconfig ** ++PVRDRIInitScreen(__DRIscreen *psDRIScreen) ++{ ++ PVRDRIScreen *psPVRScreen; ++ const __DRIconfig **ppsConfigs; ++ int iMaxGLES1Version, iMaxGLES2Version; ++ const PVRDRICallbacks sDRICallbacks = { ++ /* Version 0 callbacks */ ++ .ImageGetSharedType = PVRDRIImageGetSharedType, ++ .ImageGetSharedBuffer = PVRDRIImageGetSharedBuffer, ++ .ImageGetSharedEGLImage = PVRDRIImageGetSharedEGLImage, ++ .ImageGetEGLImage = PVRDRIImageGetEGLImage, ++ .ScreenGetDRIImage = PVRDRIScreenGetDRIImage, ++ .RefImage = PVRDRIRefImage, ++ .UnrefImage = PVRDRIUnrefImage, ++ ++ /* Version 1 callbacks */ ++ .RegisterSupportInterfaceV1 = PVRDRIRegisterSupportInterfaceV1, ++ ++ /* Version 2 callbacks */ ++ .ConfigQuery = PVRDRIConfigQuery, ++ .DrawableGetParametersV2 = PVRDRIDrawableGetParametersV2, ++ .DrawableQuery = PVRDRIDrawableQuery, ++ }; ++ const struct PVRDRICallbacksV2 sDRICallbacksV2 = { ++ /* Version 0 callbacks */ ++ .v0.RegisterSupportInterface = MODSUPRegisterSupportInterfaceV2, ++ .v0.GetBuffers = MODSUPGetBuffers, ++ .v0.CreateConfigs = MODSUPCreateConfigs, ++ .v0.ConcatConfigs = MODSUPConcatConfigs, ++ .v0.ConfigQuery = MODSUPConfigQuery, ++ .v0.LookupEGLImage = MODSUPLookupEGLImage, ++ .v0.GetCapability = MODSUPGetCapability, ++ /* Version 1 callbacks */ ++ .v1.FlushFrontBuffer = MODSUPFlushFrontBuffer, ++ }; ++ ++ if (!PVRLoaderIsSupported(psDRIScreen)) ++ return NULL; ++ ++ if (!PVRDRICompatInit(&sDRICallbacks, 3, &sDRICallbacksV2, 1, 0)) ++ return NULL; ++ ++ psPVRScreen = calloc(1, sizeof(*psPVRScreen)); ++ if (psPVRScreen == NULL) { ++ __driUtilMessage("%s: Couldn't allocate PVRDRIScreen", __func__); ++ goto ErrorCompatDeinit; ++ } ++ ++ psDRIScreen->driverPrivate = psPVRScreen; ++ psPVRScreen->psDRIScreen = psDRIScreen; ++ psPVRScreen->iRefCount = 1; ++ ++ psPVRScreen->psDRISUPScreen = ++ DRISUPCreateScreen(psDRIScreen, psDRIScreen->fd, ++ psDRIScreen->dri2.useInvalidate != NULL, ++ psDRIScreen->loaderPrivate, ++ &ppsConfigs, &iMaxGLES1Version, &iMaxGLES2Version); ++ if (!psPVRScreen->psDRISUPScreen) ++ goto ErrorScreenFree; ++ ++ psDRIScreen->max_gl_es1_version = iMaxGLES1Version; ++ psDRIScreen->max_gl_es2_version = iMaxGLES2Version; ++ ++ psDRIScreen->max_gl_compat_version = ++ DRISUPGetAPIVersion(psPVRScreen->psDRISUPScreen, PVRDRI_API_GL_COMPAT); ++ psDRIScreen->max_gl_core_version = ++ DRISUPGetAPIVersion(psPVRScreen->psDRISUPScreen, PVRDRI_API_GL_CORE); ++ ++ psDRIScreen->extensions = PVRDRIScreenExtensions(); ++ ++ PVRScreenPrintExtensions(psDRIScreen); ++ ++ return ppsConfigs; ++ ++ErrorScreenFree: ++ psDRIScreen->driverPrivate = NULL; ++ free(psPVRScreen); ++ ++ErrorCompatDeinit: ++ PVRDRICompatDeinit(); ++ ++ return NULL; ++} ++ ++static void ++PVRDRIDestroyScreen(__DRIscreen *psDRIScreen) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++#if defined(DEBUG) ++ if (psPVRScreen->iBufferAlloc != 0 || ++ psPVRScreen->iDrawableAlloc != 0 || ++ psPVRScreen->iContextAlloc != 0) { ++ errorMessage("%s: Outstanding allocations: Contexts: %d Drawables: %d Buffers: %d", ++ __func__, psPVRScreen->iContextAlloc, ++ psPVRScreen->iDrawableAlloc, psPVRScreen->iBufferAlloc); ++ ++ if (psPVRScreen->iRefCount > 1) { ++ errorMessage("%s: PVRDRIScreen resources will not be freed until its %d references are removed", ++ __func__, psPVRScreen->iRefCount - 1); ++ } ++ } ++#endif ++ ++ PVRDRIScreenRemoveReference(psPVRScreen); ++} ++ ++static int ++PVRDRIScreenSupportedAPIs(PVRDRIScreen *psPVRScreen) ++{ ++ unsigned int api_mask = psPVRScreen->psDRIScreen->api_mask; ++ int supported = 0; ++ ++ if ((api_mask & (1 << __DRI_API_GLES)) != 0) ++ supported |= PVRDRI_API_BIT_GLES; ++ ++ if ((api_mask & (1 << __DRI_API_GLES2)) != 0) ++ supported |= PVRDRI_API_BIT_GLES2; ++ ++ if ((api_mask & (1 << __DRI_API_GLES3)) != 0) ++ supported |= PVRDRI_API_BIT_GLES3; ++ ++ if ((api_mask & (1 << __DRI_API_OPENGL)) != 0) ++ supported |= PVRDRI_API_BIT_GL; ++ ++ if ((api_mask & (1 << __DRI_API_OPENGL_CORE)) != 0) ++ supported |= PVRDRI_API_BIT_GL; ++ ++ return supported; ++} ++ ++static GLboolean ++PVRDRICreateContext(gl_api eMesaAPI, const struct gl_config *psGLMode, ++ __DRIcontext *psDRIContext, ++ const struct __DriverContextConfig *psCtxConfig, ++ unsigned int *puError, void *pvSharedContextPrivate) ++{ ++ __DRIscreen *psDRIScreen = psDRIContext->driScreenPriv; ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ PVRDRIContext *psPVRContext; ++ struct DRISUPContext *psDRISUPContext; ++ struct DRISUPContext *psDRISUPSharedContext; ++ struct PVRDRIContextConfig sCtxConfig; ++ PVRDRIAPIType eAPI; ++ ++ psDRISUPSharedContext = getSharedContextImpl(pvSharedContextPrivate); ++ ++ sCtxConfig.uMajorVersion = psCtxConfig->major_version; ++ sCtxConfig.uMinorVersion = psCtxConfig->minor_version; ++ sCtxConfig.uFlags = psCtxConfig->flags; ++ sCtxConfig.iResetStrategy = PVRDRI_CONTEXT_RESET_NO_NOTIFICATION; ++ sCtxConfig.uPriority = PVRDRI_CONTEXT_PRIORITY_MEDIUM; ++ sCtxConfig.iReleaseBehavior = PVRDRI_CONTEXT_RELEASE_BEHAVIOR_FLUSH; ++ ++ psPVRContext = calloc(1, sizeof(*psPVRContext)); ++ if (psPVRContext == NULL) { ++ __driUtilMessage("%s: Couldn't allocate PVRDRIContext", __func__); ++ *puError = __DRI_CTX_ERROR_NO_MEMORY; ++ return GL_FALSE; ++ } ++ ++ psPVRContext->psDRIContext = psDRIContext; ++ psPVRContext->psPVRScreen = psPVRScreen; ++ ++ if (psGLMode) ++ psPVRContext->sConfig.sGLMode = *psGLMode; ++ ++ switch (eMesaAPI) { ++ case API_OPENGLES: ++ eAPI = PVRDRI_API_GLES1; ++ break; ++ case API_OPENGLES2: ++ eAPI = PVRDRI_API_GLES2; ++ break; ++ case API_OPENGL_COMPAT: ++ eAPI = PVRDRI_API_GL_COMPAT; ++ break; ++ case API_OPENGL_CORE: ++ eAPI = PVRDRI_API_GL_CORE; ++ break; ++ default: ++ __driUtilMessage("%s: Unsupported API: %d", ++ __func__, (int) eMesaAPI); ++ *puError = __DRI_CTX_ERROR_BAD_API; ++ goto ErrorContextFree; ++ } ++ psPVRContext->eAPI = eAPI; ++ ++ if ((psCtxConfig->attribute_mask & ++ __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY) != 0) { ++ sCtxConfig.iResetStrategy = psCtxConfig->reset_strategy; ++ } ++ ++ if ((psCtxConfig->attribute_mask & ++ __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR) != 0) { ++ sCtxConfig.iReleaseBehavior = psCtxConfig->release_behavior; ++ } ++ ++ if ((psCtxConfig->attribute_mask & ++ __DRIVER_CONTEXT_ATTRIB_PRIORITY) != 0) { ++ sCtxConfig.uPriority = psCtxConfig->priority; ++ } ++ ++ *puError = DRISUPCreateContext(eAPI, &psPVRContext->sConfig, &sCtxConfig, ++ psDRIContext, psDRISUPSharedContext, ++ psPVRScreen->psDRISUPScreen, ++ &psDRISUPContext); ++ if (*puError != __DRI_CTX_ERROR_SUCCESS) ++ goto ErrorContextFree; ++ ++ psPVRContext->psDRISUPContext = psDRISUPContext; ++ ++ if (!pvrdri_create_dispatch_table(psPVRScreen, eAPI)) { ++ __driUtilMessage("%s: Couldn't create dispatch table", __func__); ++ *puError = __DRI_CTX_ERROR_BAD_API; ++ goto ErrorContextDestroy; ++ } ++#if defined(DEBUG) ++ p_atomic_inc(&psPVRScreen->iContextAlloc); ++#endif ++ ++ psDRIContext->driverPrivate = (void *) psPVRContext; ++ PVRDRIScreenAddReference(psPVRScreen); ++ ++ *puError = __DRI_CTX_ERROR_SUCCESS; ++ ++ return GL_TRUE; ++ ++ErrorContextDestroy: ++ DRISUPDestroyContext(psPVRContext->psDRISUPContext); ++ ++ErrorContextFree: ++ free(psPVRContext); ++ ++ return GL_FALSE; ++} ++ ++static void ++PVRDRIDestroyContext(__DRIcontext *psDRIContext) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ PVRDRIScreen *psPVRScreen = psPVRContext->psPVRScreen; ++ ++ DRISUPDestroyContext(psPVRContext->psDRISUPContext); ++ ++#if defined(DEBUG) ++ p_atomic_dec(&psPVRScreen->iContextAlloc); ++#endif ++ ++ PVRDRIScreenRemoveReference(psPVRScreen); ++ free(psPVRContext); ++} ++ ++static GLboolean ++PVRDRICreateBuffer(__DRIscreen *psDRIScreen, __DRIdrawable *psDRIDrawable, ++ const struct gl_config *psGLMode, GLboolean bIsPixmap) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ PVRDRIDrawable *psPVRDrawable = NULL; ++ ++ /* No known callers ever set this to true */ ++ if (bIsPixmap) ++ return GL_FALSE; ++ ++ if (!psGLMode) { ++ __driUtilMessage("%s: Invalid GL config", __func__); ++ return GL_FALSE; ++ } ++ ++ psPVRDrawable = calloc(1, sizeof(*psPVRDrawable)); ++ if (!psPVRDrawable) { ++ __driUtilMessage("%s: Couldn't allocate PVR drawable", __func__); ++ goto ErrorDrawableFree; ++ } ++ ++ psDRIDrawable->driverPrivate = (void *) psPVRDrawable; ++ psPVRDrawable->psDRIDrawable = psDRIDrawable; ++ psPVRDrawable->psPVRScreen = psPVRScreen; ++ psPVRDrawable->sConfig.sGLMode = *psGLMode; ++ psPVRDrawable->sConfig.iSupportedAPIs = ++ PVRDRIScreenSupportedAPIs(psPVRScreen); ++ ++ psPVRDrawable->psDRISUPDrawable = ++ DRISUPCreateDrawable(psDRIDrawable, psPVRScreen->psDRISUPScreen, ++ psDRIDrawable->loaderPrivate, ++ &psPVRDrawable->sConfig); ++ if (!psPVRDrawable->psDRISUPDrawable) { ++ __driUtilMessage("%s: Couldn't create DRI Support drawable", ++ __func__); ++ goto ErrorDrawableFree; ++ } ++ ++ /* Initialisation is completed in MakeCurrent */ ++#if defined(DEBUG) ++ p_atomic_inc(&psPVRScreen->iDrawableAlloc); ++#endif ++ PVRDRIScreenAddReference(psPVRScreen); ++ return GL_TRUE; ++ ++ErrorDrawableFree: ++ DRISUPDestroyDrawable(psPVRDrawable->psDRISUPDrawable); ++ free(psPVRDrawable); ++ psDRIDrawable->driverPrivate = NULL; ++ ++ return GL_FALSE; ++} ++ ++static void ++PVRDRIDestroyBuffer(__DRIdrawable *psDRIDrawable) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ ++ DRISUPDestroyDrawable(psPVRDrawable->psDRISUPDrawable); ++ ++#if defined(DEBUG) ++ p_atomic_dec(&psPVRDrawable->psPVRScreen->iDrawableAlloc); ++#endif ++ ++ PVRDRIScreenRemoveReference(psPVRDrawable->psPVRScreen); ++ free(psPVRDrawable); ++} ++ ++static GLboolean ++PVRDRIMakeCurrent(__DRIcontext *psDRIContext, ++ __DRIdrawable *psDRIWrite, __DRIdrawable *psDRIRead) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ struct DRISUPDrawable *psDRISUPWrite; ++ struct DRISUPDrawable *psDRISUPRead; ++ ++ if (psDRIWrite) { ++ PVRDRIDrawable *psPVRWrite = psDRIWrite->driverPrivate; ++ ++ psDRISUPWrite = psPVRWrite->psDRISUPDrawable; ++ } else { ++ psDRISUPWrite = NULL; ++ } ++ ++ if (psDRIRead) { ++ PVRDRIDrawable *psPVRRead = psDRIRead->driverPrivate; ++ ++ psDRISUPRead = psPVRRead->psDRISUPDrawable; ++ } else { ++ psDRISUPRead = NULL; ++ } ++ ++ if (!DRISUPMakeCurrent(psPVRContext->psDRISUPContext, ++ psDRISUPWrite, psDRISUPRead)) ++ goto ErrorUnlock; ++ ++ pvrdri_set_dispatch_table(psPVRContext); ++ ++ return GL_TRUE; ++ ++ErrorUnlock: ++ return GL_FALSE; ++} ++ ++static GLboolean ++PVRDRIUnbindContext(__DRIcontext *psDRIContext) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ pvrdri_set_null_dispatch_table(); ++ DRISUPUnbindContext(psPVRContext->psDRISUPContext); ++ ++ return GL_TRUE; ++} ++ ++static __DRIbuffer * ++PVRDRIAllocateBuffer(__DRIscreen *psDRIScreen, unsigned int uAttachment, ++ unsigned int uFormat, int iWidth, int iHeight) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ struct PVRBuffer *psBuffer; ++ ++ psBuffer = calloc(1, sizeof(*psBuffer)); ++ if (psBuffer == NULL) { ++ __driUtilMessage("%s: Failed to allocate buffer", __func__); ++ return NULL; ++ } ++ ++ psBuffer->psDRISUPBuffer = ++ DRISUPAllocateBuffer(psPVRScreen->psDRISUPScreen, uAttachment, uFormat, ++ iWidth, iHeight, &psBuffer->sDRIBuffer.name, ++ &psBuffer->sDRIBuffer.pitch, ++ &psBuffer->sDRIBuffer.cpp, ++ &psBuffer->sDRIBuffer.flags); ++ if (!psBuffer->psDRISUPBuffer) { ++ __driUtilMessage("%s: Failed to create DRI Support buffer", __func__); ++ goto ErrorFreeDRIBuffer; ++ } ++ ++ psBuffer->sDRIBuffer.attachment = uAttachment; ++ ++#if defined(DEBUG) ++ p_atomic_inc(&psPVRScreen->iBufferAlloc); ++#endif ++ ++ return &psBuffer->sDRIBuffer; ++ ++ErrorFreeDRIBuffer: ++ free(psBuffer); ++ ++ return NULL; ++} ++ ++static void ++PVRDRIReleaseBuffer(__DRIscreen *psDRIScreen, __DRIbuffer *psDRIBuffer) ++{ ++ struct PVRBuffer *psPVRBuffer = (struct PVRBuffer *) psDRIBuffer; ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ DRISUPReleaseBuffer(psPVRScreen->psDRISUPScreen, ++ psPVRBuffer->psDRISUPBuffer); ++ ++#if defined(DEBUG) ++ p_atomic_dec(&psPVRScreen->iBufferAlloc); ++#endif ++ ++ free(psPVRBuffer); ++} ++ ++static const struct __DriverAPIRec pvr_driver_api = { ++ .InitScreen = PVRDRIInitScreen, ++ .DestroyScreen = PVRDRIDestroyScreen, ++ .CreateContext = PVRDRICreateContext, ++ .DestroyContext = PVRDRIDestroyContext, ++ .CreateBuffer = PVRDRICreateBuffer, ++ .DestroyBuffer = PVRDRIDestroyBuffer, ++ .SwapBuffers = NULL, ++ .MakeCurrent = PVRDRIMakeCurrent, ++ .UnbindContext = PVRDRIUnbindContext, ++ .AllocateBuffer = PVRDRIAllocateBuffer, ++ .ReleaseBuffer = PVRDRIReleaseBuffer, ++}; ++ ++static const struct __DRIDriverVtableExtensionRec pvr_vtable = { ++ .base = {__DRI_DRIVER_VTABLE, 1}, ++ .vtable = &pvr_driver_api, ++}; ++ ++static const __DRIextension *pvr_driver_extensions[] = { ++ &driCoreExtension.base, ++ &driImageDriverExtension.base, ++ &driDRI2Extension.base, ++ &pvr_vtable.base, ++ NULL ++}; ++ ++const __DRIextension **__driDriverGetExtensions_pvr(void); ++ ++PUBLIC const __DRIextension ** ++__driDriverGetExtensions_pvr(void) ++{ ++ globalDriverAPI = &pvr_driver_api; ++ ++ return pvr_driver_extensions; ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrdri.h b/src/mesa/drivers/dri/pvr/pvrdri.h +new file mode 100644 +index 00000000000..8b37876411a +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrdri.h +@@ -0,0 +1,176 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#if !defined(__PVRDRI_H__) ++#define __PVRDRI_H__ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "main/mtypes.h" ++#include "util/macros.h" ++#include "dri_util.h" ++#include "pvrdri_support.h" ++ ++struct PVRDRIConfigRec { ++ struct gl_config sGLMode; ++ int iSupportedAPIs; ++}; ++ ++/* PVR screen data */ ++typedef struct PVRDRIScreen_TAG { ++ /* DRI screen structure pointer */ ++ __DRIscreen *psDRIScreen; ++ ++ /* Opaque PVR DRI Support screen structure pointer */ ++ struct DRISUPScreen *psDRISUPScreen; ++ ++ /* Reference count */ ++ int iRefCount; ++ ++#if defined(DEBUG) ++ /* Counters of outstanding allocations */ ++ int iContextAlloc; ++ int iDrawableAlloc; ++ int iBufferAlloc; ++#endif ++ ++ /* PVR OGLES 1 dispatch table */ ++ struct _glapi_table *psOGLES1Dispatch; ++ /* PVR OGLES 2/3 dispatch table */ ++ struct _glapi_table *psOGLES2Dispatch; ++ /* PVR OGL dispatch table */ ++ struct _glapi_table *psOGLDispatch; ++} PVRDRIScreen; ++ ++/* PVR context data */ ++typedef struct PVRDRIContext_TAG { ++ /* Pointer to DRI context */ ++ __DRIcontext *psDRIContext; ++ ++ /* Opaque PVR DRI Support context structure pointer */ ++ struct DRISUPContext *psDRISUPContext; ++ ++ /* Pointer to PVRDRIScreen structure */ ++ PVRDRIScreen *psPVRScreen; ++ ++ /* GL config */ ++ PVRDRIConfig sConfig; ++ ++ /* API */ ++ PVRDRIAPIType eAPI; ++} PVRDRIContext; ++ ++/* PVR drawable data */ ++typedef struct PVRDRIDrawable_TAG { ++ PVRDRIScreen *psPVRScreen; ++ __DRIdrawable *psDRIDrawable; ++ PVRDRIConfig sConfig; ++ struct DRISUPDrawable *psDRISUPDrawable; ++ unsigned int uFourCC; ++ unsigned int uDRIFormat; ++} PVRDRIDrawable; ++ ++/*************************************************************************//*! ++ pvrutil.c ++ *//**************************************************************************/ ++ ++void PRINTFLIKE(1, 2) __driUtilMessage(const char *f, ...); ++void PRINTFLIKE(1, 2) errorMessage(const char *f, ...); ++ ++mesa_format PVRDRIMesaFormatToMesaFormat(int pvrdri_mesa_format); ++int PVRDRIFormatToFourCC(int dri_format); ++int PVRDRIFourCCToDRIFormat(int iFourCC); ++ ++/*************************************************************************//*! ++ pvrext.c ++ *//**************************************************************************/ ++ ++const __DRIextension **PVRDRIScreenExtensions(void); ++const __DRIextension *PVRDRIScreenExtensionVersionInfo(void); ++ ++void PVRDRIAdjustExtensions(unsigned int uVersion, unsigned int uMinVersion); ++ ++/*************************************************************************//*! ++ pvrcompat.c ++ *//**************************************************************************/ ++ ++bool PVRDRICompatInit(const PVRDRICallbacks *psCallbacks, ++ unsigned int uVersion, ++ const struct PVRDRICallbacksV2 *psCallbacksV2, ++ unsigned int uVersionV2, unsigned int uMinVersionV2); ++void PVRDRICompatDeinit(void); ++ ++bool PVRDRIRegisterSupportInterfaceV1(const PVRDRISupportInterface *psInterface, ++ unsigned int uVersion); ++bool MODSUPRegisterSupportInterfaceV2(const void *pvInterface, ++ unsigned int uVersion, ++ unsigned int uMinVersion); ++ ++/*************************************************************************//*! ++ pvrcb.c ++ *//**************************************************************************/ ++ ++int MODSUPGetBuffers(struct __DRIdrawableRec *psDRIDrawable, ++ unsigned int uFourCC, uint32_t *puStamp, ++ void *pvLoaderPrivate, uint32_t uBufferMask, ++ struct PVRDRIImageList *psImageList); ++ ++bool MODSUPCreateConfigs(struct __DRIconfigRec ***psConfigs, ++ struct __DRIscreenRec *psDRIScreen, ++ int iPVRDRIMesaFormat, const uint8_t *puDepthBits, ++ const uint8_t *puStencilBits, ++ unsigned int uNumDepthStencilBits, ++ const unsigned int *puDBModes, ++ unsigned int uNumDBModes, ++ const uint8_t *puMSAASamples, ++ unsigned int uNumMSAAModes, bool bEnableAccum, ++ bool bColorDepthMatch, bool bMutableRenderBuffer, ++ int iYUVDepthRange, int iYUVCSCStandard, ++ uint32_t uMaxPbufferWidth, uint32_t uMaxPbufferHeight); ++ ++struct __DRIconfigRec **MODSUPConcatConfigs(struct __DRIscreenRec *psDRIScreen, ++ struct __DRIconfigRec **ppsConfigA, ++ struct __DRIconfigRec **ppsConfigB); ++ ++__DRIimage *MODSUPLookupEGLImage(struct __DRIscreenRec *psDRIScreen, ++ void *pvImage, void *pvLoaderPrivate); ++ ++unsigned int MODSUPGetCapability(struct __DRIscreenRec *psDRIScreen, ++ unsigned int uCapability); ++ ++bool PVRDRIConfigQuery(const PVRDRIConfig *psConfig, ++ PVRDRIConfigAttrib eConfigAttrib, int *piValueOut); ++ ++bool MODSUPConfigQuery(const PVRDRIConfig *psConfig, ++ PVRDRIConfigAttrib eConfigAttrib, ++ unsigned int *puValueOut); ++ ++void MODSUPFlushFrontBuffer(struct __DRIdrawableRec *psDRIDrawable, ++ void *pvLoaderPrivate); ++ ++#endif /* defined(__PVRDRI_H__) */ +diff --git a/src/mesa/drivers/dri/pvr/pvrdri_mod.c b/src/mesa/drivers/dri/pvr/pvrdri_mod.c +new file mode 100644 +index 00000000000..0abe8a38d3a +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrdri_mod.c +@@ -0,0 +1,584 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++ ++#include "pvrdri_mod.h" ++ ++#define PVR_IMAGE_LOADER_VER_MIN 1 ++ ++#define PVRDRI_FLUSH_WAIT_FOR_HW (1U << 0) ++#define PVRDRI_FLUSH_NEW_EXTERNAL_FRAME (1U << 1) ++#define PVRDRI_FLUSH_ALL_SURFACES (1U << 2) ++ ++ ++/* We need to know the current screen in order to lookup EGL images. */ ++static __thread struct DRISUPScreen *gpsPVRScreen; ++ ++/*************************************************************************//*! ++ Local functions ++ *//**************************************************************************/ ++ ++static inline bool ++PVRDRIFlushBuffers(struct DRISUPContext *psPVRContext, ++ struct DRISUPDrawable *psPVRDrawable, uint32_t uiFlags) ++{ ++ PVRDRIDrawableImpl *psDrawableImpl; ++ bool bFlushAllSurfaces = (uiFlags & PVRDRI_FLUSH_ALL_SURFACES) != 0; ++ bool bSwapBuffers = (uiFlags & PVRDRI_FLUSH_NEW_EXTERNAL_FRAME) != 0; ++ bool bWaitForHW = (uiFlags & PVRDRI_FLUSH_WAIT_FOR_HW) != 0; ++ ++ psDrawableImpl = psPVRDrawable ? psPVRDrawable->psImpl : NULL; ++ ++ assert(!(uiFlags & ~(PVRDRI_FLUSH_WAIT_FOR_HW | ++ PVRDRI_FLUSH_NEW_EXTERNAL_FRAME | ++ PVRDRI_FLUSH_ALL_SURFACES))); ++ ++ return PVRDRIEGLFlushBuffers(psPVRContext->eAPI, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, psDrawableImpl, ++ bFlushAllSurfaces, bSwapBuffers, bWaitForHW); ++} ++ ++void ++PVRDRIFlushBuffersForSwap(struct DRISUPContext *psPVRContext, ++ struct DRISUPDrawable *psPVRDrawable) ++{ ++ if (psPVRContext) { ++ /* ++ * The bFlushInProgress flag is intended to prevent new buffers being ++ * fetched whilst a flush is in progress, which may corrupt the state ++ * maintained by the Mesa platform code. ++ */ ++ psPVRDrawable->bFlushInProgress = true; ++ ++ (void) PVRDRIFlushBuffers(psPVRContext, ++ psPVRDrawable, ++ PVRDRI_FLUSH_NEW_EXTERNAL_FRAME); ++ ++ psPVRDrawable->bFlushInProgress = false; ++ } ++} ++ ++static void ++PVRDRIFlushBuffersGC(struct DRISUPContext *psPVRContext, ++ struct DRISUPDrawable *psPVRDrawable) ++{ ++ (void) PVRDRIFlushBuffers(psPVRContext, psPVRDrawable, ++ PVRDRI_FLUSH_WAIT_FOR_HW | ++ PVRDRI_FLUSH_ALL_SURFACES); ++} ++ ++static void ++PVRContextUnbind(struct DRISUPContext *psPVRContext, bool bMakeUnCurrent, ++ bool bMarkSurfaceInvalid) ++{ ++ struct DRISUPScreen *psPVRScreen = psPVRContext->psPVRScreen; ++ struct DRISUPDrawable *psPVRDrawable = psPVRContext->psPVRDrawable; ++ ++ if (bMakeUnCurrent && !psPVRContext->bMakeUncurrentNoFlush) { ++ uint32_t uiFlags = PVRDRI_FLUSH_ALL_SURFACES; ++ ++ (void) PVRDRIFlushBuffers(psPVRContext, psPVRDrawable, uiFlags); ++ } else if (psPVRDrawable) { ++ PVRDRIFlushBuffersGC(psPVRContext, psPVRDrawable); ++ } ++ ++ if (bMakeUnCurrent) ++ PVRDRIMakeUnCurrentGC(psPVRContext->eAPI, psPVRScreen->psImpl); ++ ++ if (psPVRDrawable != NULL) { ++ if (bMarkSurfaceInvalid) { ++ PVRDRIEGLMarkRendersurfaceInvalid(psPVRContext->eAPI, ++ psPVRScreen->psImpl, ++ psPVRContext->psImpl); ++ } ++ ++ psPVRContext->psPVRDrawable = NULL; ++ psPVRDrawable->psPVRContext = NULL; ++ } ++} ++ ++static inline void ++PVRDrawableUnbindContext(struct DRISUPDrawable *psPVRDrawable) ++{ ++ struct DRISUPContext *psPVRContext = psPVRDrawable->psPVRContext; ++ ++ if (psPVRContext) ++ PVRContextUnbind(psPVRContext, false, true); ++} ++ ++/*************************************************************************//*! ++ Mesa driver API functions ++ *//**************************************************************************/ ++struct DRISUPScreen * ++DRIMODCreateScreen(struct __DRIscreenRec *psDRIScreen, int iFD, ++ bool bUseInvalidate, void *pvLoaderPrivate, ++ const struct __DRIconfigRec ***pppsConfigs, ++ int *piMaxGLES1Version, int *piMaxGLES2Version) ++{ ++ struct DRISUPScreen *psPVRScreen; ++ const struct __DRIconfigRec **ppsConfigs; ++ ++ psPVRScreen = calloc(1, sizeof(*psPVRScreen)); ++ if (psPVRScreen == NULL) { ++ __driUtilMessage("%s: Couldn't allocate PVRDRIScreen", __func__); ++ return NULL; ++ } ++ ++ psPVRScreen->psDRIScreen = psDRIScreen; ++ psPVRScreen->iFD = iFD; ++ psPVRScreen->bUseInvalidate = bUseInvalidate; ++ psPVRScreen->pvLoaderPrivate = pvLoaderPrivate; ++ ++ if (!PVRDRIGetMesaFormats(psPVRScreen)) ++ goto ErrorScreenFree; ++ ++ psPVRScreen->psImpl = PVRDRICreateScreenImpl(iFD); ++ if (psPVRScreen->psImpl == NULL) ++ goto ErrorScreenFree; ++ ++ if (!PVRDRIGetSupportedFormats(psPVRScreen)) ++ goto ErrorScreenImplDeinit; ++ ++ ppsConfigs = PVRDRICreateConfigs(psPVRScreen); ++ if (ppsConfigs == NULL) { ++ __driUtilMessage("%s: No framebuffer configs", __func__); ++ goto ErrorDestroyFormatInfo; ++ } ++ ++ *piMaxGLES1Version = PVRDRIAPIVersion(PVRDRI_API_GLES1, ++ PVRDRI_API_SUB_NONE, ++ psPVRScreen->psImpl); ++ ++ *piMaxGLES2Version = PVRDRIAPIVersion(PVRDRI_API_GLES2, ++ PVRDRI_API_SUB_NONE, ++ psPVRScreen->psImpl); ++ ++ *pppsConfigs = ppsConfigs; ++ ++ return psPVRScreen; ++ ++ErrorDestroyFormatInfo: ++ PVRDRIDestroyFormatInfo(psPVRScreen); ++ ++ErrorScreenImplDeinit: ++ PVRDRIDestroyScreenImpl(psPVRScreen->psImpl); ++ ++ErrorScreenFree: ++ PVRDRIFreeMesaFormats(psPVRScreen); ++ ++ free(psPVRScreen); ++ ++ return NULL; ++} ++ ++void ++DRIMODDestroyScreen(struct DRISUPScreen *psPVRScreen) ++{ ++ PVRDRIDestroyFormatInfo(psPVRScreen); ++ PVRDRIDestroyScreenImpl(psPVRScreen->psImpl); ++ PVRDRIFreeMesaFormats(psPVRScreen); ++ free(psPVRScreen); ++} ++ ++unsigned int ++DRIMODCreateContext(PVRDRIAPIType eAPI, PVRDRIConfig *psPVRDRIConfig, ++ struct PVRDRIContextConfig *psCtxConfig, ++ struct __DRIcontextRec *psDRIContext, ++ struct DRISUPContext *psPVRSharedContext, ++ struct DRISUPScreen *psPVRScreen, ++ struct DRISUPContext **ppsPVRContext) ++{ ++ struct DRISUPContext *psPVRContext; ++ PVRDRIContextImpl *psSharedImpl; ++ bool bNotifyReset; ++ unsigned int uError; ++ ++ psSharedImpl = psPVRSharedContext ? psPVRSharedContext->psImpl : NULL, ++ psPVRContext = calloc(1, sizeof(*psPVRContext)); ++ if (psPVRContext == NULL) { ++ __driUtilMessage("%s: Couldn't allocate PVRDRIContext", __func__); ++ return PVRDRI_CONTEXT_ERROR_NO_MEMORY; ++ } ++ ++ psPVRContext->psDRIContext = psDRIContext; ++ psPVRContext->psPVRScreen = psPVRScreen; ++ ++ switch (eAPI) { ++ case PVRDRI_API_GLES1: ++ case PVRDRI_API_GLES2: ++ break; ++ default: ++ __driUtilMessage("%s: Unsupported API: %d", __func__, (int) eAPI); ++ uError = PVRDRI_CONTEXT_ERROR_BAD_API; ++ goto ErrorContextFree; ++ } ++ psPVRContext->eAPI = eAPI; ++ ++ switch (psCtxConfig->iResetStrategy) { ++ case PVRDRI_CONTEXT_RESET_NO_NOTIFICATION: ++ bNotifyReset = false; ++ break; ++ case PVRDRI_CONTEXT_RESET_LOSE_CONTEXT: ++ bNotifyReset = true; ++ break; ++ default: ++ __driUtilMessage("%s: Unsupported reset strategy: %d", ++ __func__, psCtxConfig->iResetStrategy); ++ uError = PVRDRI_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE; ++ goto ErrorContextFree; ++ } ++ ++ switch (psCtxConfig->iReleaseBehavior) { ++ case PVRDRI_CONTEXT_RELEASE_BEHAVIOR_NONE: ++ psPVRContext->bMakeUncurrentNoFlush = true; ++ break; ++ case PVRDRI_CONTEXT_RELEASE_BEHAVIOR_FLUSH: ++ psPVRContext->bMakeUncurrentNoFlush = false; ++ break; ++ default: ++ __driUtilMessage("%s: Unsupported release behaviour: %d", ++ __func__, psCtxConfig->iReleaseBehavior); ++ uError = PVRDRI_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE; ++ goto ErrorContextFree; ++ } ++ ++ uError = PVRDRICreateContextV1(psPVRScreen->psImpl, psSharedImpl, ++ psPVRDRIConfig, psPVRContext->eAPI, ++ PVRDRI_API_SUB_NONE, ++ psCtxConfig->uMajorVersion, ++ psCtxConfig->uMinorVersion, ++ psCtxConfig->uFlags, bNotifyReset, ++ psCtxConfig->uPriority, ++ &psPVRContext->psImpl); ++ if (uError != PVRDRI_CONTEXT_ERROR_SUCCESS) ++ goto ErrorContextFree; ++ ++ *ppsPVRContext = psPVRContext; ++ ++ return uError; ++ ++ErrorContextFree: ++ free(psPVRContext); ++ ++ return uError; ++} ++ ++void ++DRIMODDestroyContext(struct DRISUPContext *psPVRContext) ++{ ++ struct DRISUPScreen *psPVRScreen = psPVRContext->psPVRScreen; ++ ++ PVRContextUnbind(psPVRContext, false, false); ++ PVRDRIDestroyContextImpl(psPVRContext->psImpl, psPVRContext->eAPI, ++ psPVRScreen->psImpl); ++ free(psPVRContext); ++} ++ ++static IMG_PIXFMT ++PVRDRIGetPixelFormat(PVRDRIConfig *psPVRDRIConfig) ++{ ++ unsigned int uRGBBits; ++ unsigned int uRedMask, uGreenMask, uBlueMask, uAlphaMask; ++ unsigned int uSRGBCapable; ++ bool bRes; ++ ++ bRes = MODSUPConfigQuery(psPVRDRIConfig, ++ PVRDRI_CONFIG_ATTRIB_RGB_BITS, &uRGBBits); ++ ++ bRes &= MODSUPConfigQuery(psPVRDRIConfig, ++ PVRDRI_CONFIG_ATTRIB_RED_MASK, &uRedMask); ++ ++ bRes &= MODSUPConfigQuery(psPVRDRIConfig, ++ PVRDRI_CONFIG_ATTRIB_GREEN_MASK, ++ &uGreenMask); ++ ++ bRes &= MODSUPConfigQuery(psPVRDRIConfig, ++ PVRDRI_CONFIG_ATTRIB_BLUE_MASK, &uBlueMask); ++ ++ bRes &= MODSUPConfigQuery(psPVRDRIConfig, ++ PVRDRI_CONFIG_ATTRIB_ALPHA_MASK, ++ &uAlphaMask); ++ ++ bRes &= MODSUPConfigQuery(psPVRDRIConfig, ++ PVRDRI_CONFIG_ATTRIB_SRGB_CAPABLE, ++ &uSRGBCapable); ++ ++ if (!bRes) { ++ __driUtilMessage("%s: Config query failed", __func__); ++ return IMG_PIXFMT_UNKNOWN; ++ } ++ ++ switch (uRGBBits) { ++ case 32: ++ case 24: ++ if (uRedMask == 0x00FF0000 && ++ uGreenMask == 0x0000FF00 && uBlueMask == 0x000000FF) { ++ if (uAlphaMask == 0xFF000000) { ++ if (uSRGBCapable) ++ return IMG_PIXFMT_B8G8R8A8_UNORM_SRGB; ++ else ++ return IMG_PIXFMT_B8G8R8A8_UNORM; ++ } else if (uAlphaMask == 0) { ++ return IMG_PIXFMT_B8G8R8X8_UNORM; ++ } ++ } ++ ++ if (uRedMask == 0x000000FF && ++ uGreenMask == 0x0000FF00 && uBlueMask == 0x00FF0000) { ++ if (uAlphaMask == 0xFF000000) { ++ if (uSRGBCapable) ++ return IMG_PIXFMT_R8G8B8A8_UNORM_SRGB; ++ else ++ return IMG_PIXFMT_R8G8B8A8_UNORM; ++ } else if (uAlphaMask == 0) { ++ return IMG_PIXFMT_R8G8B8X8_UNORM; ++ } ++ } ++ ++ __driUtilMessage("%s: Unsupported format", __func__); ++ ++ return IMG_PIXFMT_UNKNOWN; ++ case 16: ++ if (uRedMask == 0xF800 && ++ uGreenMask == 0x07E0 && uBlueMask == 0x001F) { ++ return IMG_PIXFMT_B5G6R5_UNORM; ++ } ++ ++ __driUtilMessage("%s: Unsupported format", __func__); ++ ++ return IMG_PIXFMT_UNKNOWN; ++ default: ++ __driUtilMessage("%s: Unsupported format", __func__); ++ ++ return IMG_PIXFMT_UNKNOWN; ++ } ++} ++ ++struct DRISUPDrawable * ++DRIMODCreateDrawable(struct __DRIdrawableRec *psDRIDrawable, ++ struct DRISUPScreen *psPVRScreen, void *pvLoaderPrivate, ++ PVRDRIConfig *psPVRDRIConfig) ++{ ++ struct DRISUPDrawable *psPVRDrawable; ++ IMG_PIXFMT ePixelFormat; ++ unsigned int uDoubleBufferMode; ++ ++ psPVRDrawable = calloc(1, sizeof(*psPVRDrawable)); ++ if (!psPVRDrawable) { ++ __driUtilMessage("%s: Couldn't allocate PVR drawable", __func__); ++ goto ErrorDrawableFree; ++ } ++ ++ psPVRDrawable->psDRIDrawable = psDRIDrawable; ++ psPVRDrawable->psPVRScreen = psPVRScreen; ++ psPVRDrawable->pvLoaderPrivate = pvLoaderPrivate; ++ psPVRDrawable->psConfig = psPVRDRIConfig; ++ ++ ePixelFormat = PVRDRIGetPixelFormat(psPVRDRIConfig); ++ if (ePixelFormat == IMG_PIXFMT_UNKNOWN) { ++ __driUtilMessage("%s: Couldn't determine IMG pixel format", __func__); ++ goto ErrorDrawableFree; ++ } ++ ++ psPVRDrawable->psFormat = ++ PVRDRIIMGPixelFormatToImageFormat(psPVRScreen, ePixelFormat); ++ if (!psPVRDrawable->psFormat) { ++ __driUtilMessage("%s: Unsupported IMG pixel format (format = %u)", ++ __func__, ePixelFormat); ++ return false; ++ } ++ ++ if (!MODSUPConfigQuery(psPVRDRIConfig, ++ PVRDRI_CONFIG_ATTRIB_DOUBLE_BUFFER_MODE, ++ &uDoubleBufferMode)) { ++ __driUtilMessage("%s: Couldn't query double buffer mode", __func__); ++ goto ErrorDrawableFree; ++ } ++ psPVRDrawable->bDoubleBufferMode = (uDoubleBufferMode != 0); ++ ++ /* ++ * We aren't told the type of the drawable so treat double buffered ++ * drawables as windows and single buffered drawables as pixmaps (although ++ * these could actually be pbuffers). ++ */ ++ if (psPVRDrawable->bDoubleBufferMode) ++ psPVRDrawable->eType = PVRDRI_DRAWABLE_WINDOW; ++ else ++ psPVRDrawable->eType = PVRDRI_DRAWABLE_PIXMAP; ++ ++ psPVRDrawable->psImpl = ++ PVRDRICreateDrawableWithConfig((PVRDRIDrawable *) psPVRDrawable, ++ psPVRDRIConfig); ++ if (!psPVRDrawable->psImpl) { ++ __driUtilMessage("%s: Couldn't create PVR drawable", __func__); ++ goto ErrorDrawableFree; ++ } ++ ++ return psPVRDrawable; ++ ++ErrorDrawableFree: ++ PVRDRIDestroyDrawableImpl(psPVRDrawable->psImpl); ++ free(psPVRDrawable); ++ ++ return NULL; ++} ++ ++void ++DRIMODDestroyDrawable(struct DRISUPDrawable *psPVRDrawable) ++{ ++ PVRDrawableUnbindContext(psPVRDrawable); ++ PVRDRIDrawableDeinit(psPVRDrawable); ++ PVREGLDrawableDestroyConfig(psPVRDrawable->psImpl); ++ PVRDRIDestroyDrawableImpl(psPVRDrawable->psImpl); ++ free(psPVRDrawable); ++} ++ ++bool ++DRIMODMakeCurrent(struct DRISUPContext *psPVRContext, ++ struct DRISUPDrawable *psPVRWrite, ++ struct DRISUPDrawable *psPVRRead) ++{ ++ struct DRISUPDrawable *psPVRDrawableOld = psPVRContext->psPVRDrawable; ++ ++ if (psPVRWrite != NULL) { ++ if (!PVRDRIDrawableInit(psPVRWrite)) { ++ __driUtilMessage("%s: Couldn't initialise write drawable", __func__); ++ return false; ++ } ++ } ++ ++ if (psPVRRead != NULL) { ++ if (!PVRDRIDrawableInit(psPVRRead)) { ++ __driUtilMessage("%s: Couldn't initialise read drawable", __func__); ++ return false; ++ } ++ } ++ ++ if (!PVRDRIMakeCurrentGC(psPVRContext->eAPI, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, ++ psPVRWrite == NULL ? NULL : psPVRWrite->psImpl, ++ psPVRRead == NULL ? NULL : psPVRRead->psImpl)) ++ return false; ++ ++ if (psPVRDrawableOld != NULL) ++ psPVRDrawableOld->psPVRContext = NULL; ++ ++ if (psPVRWrite != NULL) ++ psPVRWrite->psPVRContext = psPVRContext; ++ ++ psPVRContext->psPVRDrawable = psPVRWrite; ++ ++ DRIMODThreadSetCurrentScreen(psPVRContext->psPVRScreen); ++ ++ return true; ++} ++ ++bool ++DRIMODUnbindContext(struct DRISUPContext *psPVRContext) ++{ ++ PVRContextUnbind(psPVRContext, true, false); ++ DRIMODThreadSetCurrentScreen(NULL); ++ ++ return true; ++} ++ ++struct DRISUPBuffer * ++DRIMODAllocateBuffer(struct DRISUPScreen *psPVRScreen, ++ unsigned int uAttachment, unsigned int uFormat, ++ int iWidth, int iHeight, unsigned int *puName, ++ unsigned int *puPitch, unsigned int *puCPP, ++ unsigned int *puFlags) ++{ ++ PVRDRIBufferImpl *psPVRBufferImpl; ++ unsigned int uBPP; ++ unsigned int uPitch; ++ ++ (void) uAttachment; ++ ++ /* GEM names are only supported on primary nodes */ ++ if (drmGetNodeTypeFromFd(psPVRScreen->iFD) != DRM_NODE_PRIMARY) { ++ __driUtilMessage("%s: Cannot allocate buffer", __func__); ++ return NULL; ++ } ++ ++ /* This is based upon PVRDRIGetPixelFormat */ ++ switch (uFormat) { ++ case 32: ++ case 16: ++ /* Format (depth) and bpp match */ ++ uBPP = uFormat; ++ break; ++ case 24: ++ uBPP = 32; ++ break; ++ default: ++ __driUtilMessage("%s: Unsupported format '%u'", __func__, uFormat); ++ return NULL; ++ } ++ ++ psPVRBufferImpl = PVRDRIBufferCreate(psPVRScreen->psImpl, iWidth, iHeight, ++ uBPP, PVDRI_BUFFER_USE_SHARE, &uPitch); ++ if (!psPVRBufferImpl) { ++ __driUtilMessage("%s: Failed to create backing buffer", __func__); ++ return NULL; ++ } ++ ++ *puName = PVRDRIBufferGetName(psPVRBufferImpl); ++ *puPitch = uPitch; ++ *puCPP = uBPP / 8; ++ *puFlags = 0; ++ ++ return (struct DRISUPBuffer *) psPVRBufferImpl; ++} ++ ++void ++DRIMODReleaseBuffer(struct DRISUPScreen *psPVRScreen, ++ struct DRISUPBuffer *psPVRBuffer) ++{ ++ PVRDRIBufferImpl *psPVRBufferImpl = (PVRDRIBufferImpl *) psPVRBuffer; ++ ++ (void) psPVRScreen; ++ ++ PVRDRIBufferDestroy(psPVRBufferImpl); ++} ++ ++/*************************************************************************//*! ++ Global functions ++ *//**************************************************************************/ ++ ++void ++DRIMODThreadSetCurrentScreen(struct DRISUPScreen *psPVRScreen) ++{ ++ gpsPVRScreen = psPVRScreen; ++} ++ ++struct DRISUPScreen * ++DRIMODThreadGetCurrentScreen(void) ++{ ++ return gpsPVRScreen; ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrdri_mod.h b/src/mesa/drivers/dri/pvr/pvrdri_mod.h +new file mode 100644 +index 00000000000..e46b7b083e1 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrdri_mod.h +@@ -0,0 +1,450 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#if !defined(__PVRDRI_MOD_H__) ++#define __PVRDRI_MOD_H__ ++ ++#include ++#include ++ ++#include "pvrdri.h" ++ ++/* This should match EGL_MAX_PLANES */ ++#define DRI_PLANES_MAX 3 ++ ++#define DRI2_BUFFERS_MAX 3 ++ ++struct PVRDRIModifiers { ++ /* Number of modifiers for a given format */ ++ int iNumModifiers; ++ ++ /* Array of modifiers */ ++ uint64_t *puModifiers; ++ ++ /* ++ * Array of booleans that indicates which modifiers in the above array can ++ * only be used for EGL Image External (and so not for scanout). ++ */ ++ unsigned int *puExternalOnly; ++}; ++ ++/** Our PVR related screen data */ ++struct DRISUPScreen { ++ /* DRI screen structure pointer */ ++ struct __DRIscreenRec *psDRIScreen; ++ ++ /* Use invalidate events */ ++ bool bUseInvalidate; ++ ++ int iFD; ++ ++ void *pvLoaderPrivate; ++ ++ PVRDRIScreenImpl *psImpl; ++ ++ /* ++ * Number of supported formats: ++ * -1 -> couldn't be queried (pvr_dri_support too old) ++ * 0 -> uninitialised or initialisation failed ++ */ ++ int iNumFormats; ++ ++ /* Indicates which entries in the image format array are supported */ ++ bool *pbHasFormat; ++ ++ /* Array of modifiers for each image format array entry */ ++ struct PVRDRIModifiers *psModifiers; ++ ++ /* Supported Mesa formats */ ++ unsigned int *puMesaFormats; ++ unsigned int uNumMesaFormats; ++}; ++ ++/** Our PVR related context data */ ++struct DRISUPContext { ++ /* Pointer to DRI context */ ++ struct __DRIcontextRec *psDRIContext; ++ ++ /* Pointer to PVRDRIScreen structure */ ++ struct DRISUPScreen *psPVRScreen; ++ ++ /* Pointer to currently bound drawable */ ++ struct DRISUPDrawable *psPVRDrawable; ++ ++ /* API */ ++ PVRDRIAPIType eAPI; ++ ++ PVRDRIContextImpl *psImpl; ++ ++ /* Don't flush when the context is made uncurrent */ ++ bool bMakeUncurrentNoFlush; ++}; ++ ++typedef struct PVRDRIImageFormat_TAG { ++ /* ++ * IMG pixel format for the entire/overall image, e.g. ++ * IMG_PIXFMT_B8G8R8A8_UNORM or IMG_PIXFMT_YUV420_2PLANE. ++ */ ++ IMG_PIXFMT eIMGPixelFormat; ++ ++ /* ++ * DRI fourcc for the entire/overall image (defined by dri_interface.h), ++ * e.g. __DRI_IMAGE_FOURCC_ARGB8888 or __DRI_IMAGE_FOURCC_NV12. ++ */ ++ int iDRIFourCC; ++ ++ /* ++ * DRI components for the entire/overall image (defined by ++ * dri_interface.h), e.g. __DRI_IMAGE_COMPONENTS_RGBA or ++ * __DRI_IMAGE_COMPONENTS_Y_UV. ++ * ++ * This specifies the image components and their groupings, in terms of ++ * sub-images/planes, but not the order in which they appear. ++ * ++ * For example: ++ * - any combination of BGRA channels would correspond to ++ * __DRI_IMAGE_COMPONENTS_RGBA ++ * - any combination of BGR or BGRX would correspond to ++ * __DRI_IMAGE_COMPONENTS_RGB ++ * - any combination of YUV with 2 planes would correspond to ++ * __DRI_IMAGE_COMPONENTS_Y_UV ++ */ ++ int iDRIComponents; ++ ++ /* ++ * True if the format represents an sRGB colour space and false if it ++ * represents a linear one. ++ */ ++ bool bIsSRGB; ++ ++ /* The number of sub-images/planes that make up the overall image */ ++ unsigned int uiNumPlanes; ++ ++ /* Per-plane information */ ++ struct { ++ /* IMG pixel format for the plane */ ++ IMG_PIXFMT eIMGPixelFormat; ++ ++ /* ++ * This is the amount that the image width should be bit-shifted in ++ * order to give the plane width. This value can be determined from the ++ * YUV sub-sampling ratios and should either be 0 (full * width), 1 ++ * (half width) or 2 (quarter width). ++ */ ++ unsigned int uiWidthShift; ++ ++ /* ++ * This is the amount that the image height should be bit-shifted in ++ * order to give the plane height. This value can be determined from the ++ * YUV sub-sampling ratios and should either be 0 (full * height) or 1 ++ * (half height). ++ */ ++ unsigned int uiHeightShift; ++ } sPlanes[DRI_PLANES_MAX]; ++} PVRDRIImageFormat; ++ ++/** Our PVR related drawable data */ ++struct DRISUPDrawable { ++ /** Ptr to PVR screen, that spawned this drawable */ ++ struct DRISUPScreen *psPVRScreen; ++ ++ /** DRI drawable data */ ++ struct __DRIdrawableRec *psDRIDrawable; ++ ++ void *pvLoaderPrivate; ++ ++ bool bDoubleBufferMode; ++ PVRDRIDrawableType eType; ++ ++ PVRDRIConfig *psConfig; ++ ++ /** Are surface/buffers created? */ ++ bool bInitialised; ++ ++ /* Width and height */ ++ uint32_t uWidth; ++ uint32_t uHeight; ++ ++ /** Buffer stride */ ++ unsigned int uStride; ++ ++ /* Number of bytes per pixel */ ++ unsigned int uBytesPerPixel; ++ ++ /* Context bound to this drawable */ ++ struct DRISUPContext *psPVRContext; ++ ++ /* Format of this drawable */ ++ const PVRDRIImageFormat *psFormat; ++ ++ /* Indicates the drawable info is invalid */ ++ int iInfoInvalid; ++ ++ /* Indicates the drawable is currently being updated */ ++ bool bDrawableUpdating; ++ ++ /* Indicates a flush is in progress */ ++ bool bFlushInProgress; ++ ++ __DRIimage *psDRI; ++ __DRIimage *psImage; ++ ++ __DRIimage *psDRIAccum; ++ __DRIimage *psImageAccum; ++ ++ PVRDRIDrawableImpl *psImpl; ++}; ++ ++/*************************************************************************//*! ++ pvrdri_mod.c ++ *//**************************************************************************/ ++ ++struct DRISUPScreen *DRIMODThreadGetCurrentScreen(void); ++void DRIMODThreadSetCurrentScreen(struct DRISUPScreen *psPVRScreen); ++ ++void PVRDRIFlushBuffersForSwap(struct DRISUPContext *psPVRContext, ++ struct DRISUPDrawable *psPVRDrawable); ++ ++/*************************************************************************//*! ++ pvrutil_mod.c ++ *//**************************************************************************/ ++ ++const struct __DRIconfigRec **PVRDRICreateConfigs(const struct DRISUPScreen ++ *psPVRScreen); ++const PVRDRIImageFormat *PVRDRIFourCCToImageFormat(struct DRISUPScreen ++ *psPVRScreen, ++ int iDRIFourCC); ++const PVRDRIImageFormat *PVRDRIIMGPixelFormatToImageFormat(struct DRISUPScreen *psPVRScreen, ++ IMG_PIXFMT eIMGPixelFormat); ++IMG_YUV_COLORSPACE PVRDRIToIMGColourSpace(const PVRDRIImageFormat *psFormat, ++ unsigned int uDRIColourSpace, ++ unsigned int uDRISampleRange); ++IMG_YUV_CHROMA_INTERP PVRDRIChromaSittingToIMGInterp(const PVRDRIImageFormat *psFormat, ++ unsigned int uChromaSitting); ++bool PVRDRIGetSupportedFormats(struct DRISUPScreen *psPVRScreen); ++void PVRDRIDestroyFormatInfo(struct DRISUPScreen *psPVRScreen); ++bool PVRDRIValidateImageModifier(struct DRISUPScreen *psPVRScreen, ++ const int iFourCC, const uint64_t uiModifier); ++bool PVRDRIGetMesaFormats(struct DRISUPScreen *psPVRScreen); ++void PVRDRIFreeMesaFormats(struct DRISUPScreen *psPVRScreen); ++ ++/*************************************************************************//*! ++ pvrdrawable_mod.c ++ *//**************************************************************************/ ++ ++bool PVRDRIDrawableInit(struct DRISUPDrawable *psPVRDrawable); ++void PVRDRIDrawableDeinit(struct DRISUPDrawable *psPVRDrawable); ++bool PVRDRIDrawableQuery(const PVRDRIDrawable *psPVRDRIDrawable, ++ PVRDRIBufferAttrib eBufferAttrib, ++ uint32_t *uiValueOut); ++bool PVRDRIDrawableGetParametersV2(PVRDRIDrawable *psPVRDRIDrawable, ++ uint32_t uiFlags, ++ PVRDRIBufferImpl **ppsDstBuffer, ++ PVRDRIBufferImpl **ppsAccumBuffer); ++ ++/*************************************************************************//*! ++pvrimage_mod.c ++ *//**************************************************************************/ ++ ++__DRIimage *PVRDRIScreenGetDRIImage(void *hEGLImage); ++void PVRDRIRefImage(__DRIimage *psImage); ++void PVRDRIUnrefImage(__DRIimage *psImage); ++PVRDRIImageType PVRDRIImageGetSharedType(__DRIimage *psImage); ++PVRDRIBufferImpl *PVRDRIImageGetSharedBuffer(__DRIimage *psImage); ++IMGEGLImage *PVRDRIImageGetSharedEGLImage(__DRIimage *psImage); ++IMGEGLImage *PVRDRIImageGetEGLImage(__DRIimage *psImage); ++ ++/*************************************************************************//*! ++ Functions to implement PVRDRISupportInterfaceV2, for backwards compatibility ++ With DRI Support libraries that only provide PVRDRISupportInterface. ++ *//**************************************************************************/ ++ ++struct DRISUPScreen *DRIMODCreateScreen(struct __DRIscreenRec *psDRIScreen, ++ int iFD, bool bUseInvalidate, ++ void *pvLoaderPrivate, ++ const struct __DRIconfigRec ***pppsConfigs, ++ int *piMaxGLES1Version, ++ int *piMaxGLES2Version); ++void DRIMODDestroyScreen(struct DRISUPScreen *psDRISUPScreen); ++ ++unsigned int DRIMODCreateContext(PVRDRIAPIType eAPI, ++ PVRDRIConfig *psPVRDRIConfig, ++ struct PVRDRIContextConfig *psCtxConfig, ++ struct __DRIcontextRec *psDRIContext, ++ struct DRISUPContext *psDRISUPSharedContext, ++ struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPContext **ppsDRISUPContext); ++void DRIMODDestroyContext(struct DRISUPContext *psDRISUPContext); ++ ++struct DRISUPDrawable *DRIMODCreateDrawable(struct __DRIdrawableRec *psDRIDrawable, ++ struct DRISUPScreen *psDRISUPScreen, ++ void *pvLoaderPrivate, ++ PVRDRIConfig *psPVRDRIConfig); ++void DRIMODDestroyDrawable(struct DRISUPDrawable *psDRISUPDrawable); ++ ++bool DRIMODMakeCurrent(struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPWrite, ++ struct DRISUPDrawable *psDRISUPRead); ++bool DRIMODUnbindContext(struct DRISUPContext *psDRISUPContext); ++ ++struct DRISUPBuffer *DRIMODAllocateBuffer(struct DRISUPScreen *psDRISUPScreen, ++ unsigned int uAttchment, ++ unsigned int uFormat, ++ int iWidth, int iHeight, ++ unsigned int *puName, ++ unsigned int *puPitch, ++ unsigned int *puCPP, ++ unsigned int *puFlags); ++void DRIMODReleaseBuffer(struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPBuffer *psDRISUPBuffer); ++void DRIMODSetTexBuffer2(struct DRISUPContext *psDRISUPContext, int iTarget, ++ int iFormat, struct DRISUPDrawable *psDRISUPDrawable); ++void DRIMODReleaseTexBuffer(struct DRISUPContext *psDRISUPContext, ++ int iTarget, ++ struct DRISUPDrawable *psDRISUPDrawable); ++ ++void DRIMODFlush(struct DRISUPDrawable *psDRISUPDrawable); ++void DRIMODInvalidate(struct DRISUPDrawable *psDRISUPDrawable); ++void DRIMODFlushWithFlags(struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uFlags, unsigned int uThrottleReason); ++ ++__DRIimage *DRIMODCreateImageFromName(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int iName, int iPitch, ++ void *pvLoaderPrivate); ++__DRIimage *DRIMODCreateImageFromRenderbuffer(struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, ++ void *pvLoaderPrivate); ++void DRIMODDestroyImage(__DRIimage *psImage); ++__DRIimage *DRIMODCreateImage(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ unsigned int uUse, void *pvLoaderPrivate); ++bool DRIMODQueryImage(__DRIimage *psImage, int iAttrib, int *iValue); ++__DRIimage *DRIMODDupImage(__DRIimage *psImage, void *pvLoaderPrivate); ++bool DRIMODValidateImageUsage(__DRIimage *psImage, unsigned int uUse); ++__DRIimage *DRIMODCreateImageFromNames(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piNames, int iNumNames, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate); ++__DRIimage *DRIMODFromPlanar(__DRIimage *psImage, int iPlane, ++ void *pvLoaderPrivate); ++__DRIimage *DRIMODCreateImageFromTexture(struct DRISUPContext *psDRISUPContext, ++ int iTarget, unsigned int uTexture, ++ int iDepth, int iLevel, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++__DRIimage *DRIMODCreateImageFromFDs(struct DRISUPScreen *psDRISUPcreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate); ++__DRIimage *DRIMODCreateImageFromDMABufs(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++int DRIMODGetImageCapabilities(struct DRISUPScreen *psDRISUPScreen); ++void DRIMODBlitImage(struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psDst, __DRIimage *psSrc, ++ int iDstX0, int iDstY0, int iDstWidth, int iDstHeight, ++ int iSrcX0, int iSrcY0, int iSrcWidth, int iSrcHeight, ++ int iFlushFlag); ++void *DRIMODMapImage(struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psImage, ++ int iX0, int iY0, int iWidth, int iHeight, ++ unsigned int iFlags, int *iStride, void **ppvData); ++void DRIMODUnmapImage(struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psImage, void *pvData); ++__DRIimage *DRIMODCreateImageWithModifiers(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, ++ int iFourCC, ++ const uint64_t *puModifiers, ++ const unsigned int uModifierCount, ++ void *pvLoaderPrivate); ++__DRIimage *DRIMODCreateImageFromDMABufs2(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, ++ int iFourCC, uint64_t uModifier, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++bool DRIMODQueryDMABufFormats(struct DRISUPScreen *psDRISUPScreen, int iMax, ++ int *piFormats, int *piCount); ++bool DRIMODQueryDMABufModifiers(struct DRISUPScreen *psDRISUPScreen, ++ int iFourCC, int iMax, uint64_t *puModifiers, ++ unsigned int *piExternalOnly, int *piCount); ++bool DRIMODQueryDMABufFormatModifierAttribs(struct DRISUPScreen *psDRISUPScreen, ++ uint32_t uFourCC, ++ uint64_t uModifier, ++ int iAttribute, ++ uint64_t *puValue); ++ ++__DRIimage *DRIMODCreateImageFromRenderBuffer2(struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, ++ void *pvLoaderPrivate, ++ unsigned int *puError); ++__DRIimage *DRIMODCreateImageFromBuffer(struct DRISUPContext *psDRISUPContext, ++ int iTarget, void *pvBuffer, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++int DRIMODQueryRendererInteger(struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, unsigned int *puValue); ++int DRIMODQueryRendererString(struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, const char **ppszValue); ++ ++void *DRIMODCreateFence(struct DRISUPContext *psDRISUPContext); ++void DRIMODDestroyFence(struct DRISUPScreen *psDRISUPScreen, void *pvFence); ++bool DRIMODClientWaitSync(struct DRISUPContext *psDRISUPContext, ++ void *pvFence, unsigned int uFlags, ++ uint64_t uTimeout); ++void DRIMODServerWaitSync(struct DRISUPContext *psDRISUPContext, ++ void *pvFence, unsigned int uFlags); ++unsigned int DRIMODGetFenceCapabilities(struct DRISUPScreen *psDRISUPScreen); ++void *DRIMODCreateFenceFD(struct DRISUPContext *psDRISUPContext, int iFD); ++int DRIMODGetFenceFD(struct DRISUPScreen *psDRISUPScreen, void *pvFence); ++ ++unsigned int DRIMODGetNumAPIProcs(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI); ++const char *DRIMODGetAPIProcName(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI, unsigned int uIndex); ++void *DRIMODGetAPIProcAddress(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI, unsigned int uIndex); ++ ++void DRIMODSetDamageRegion(struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uNRects, int *piRects); ++ ++#endif /* defined(__PVRDRI_MOD_H__) */ +diff --git a/src/mesa/drivers/dri/pvr/pvrdri_support.h b/src/mesa/drivers/dri/pvr/pvrdri_support.h +new file mode 100644 +index 00000000000..ced4f80ccc6 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrdri_support.h +@@ -0,0 +1,439 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#if !defined(__PVRDRI_SUPPORT_H__) ++#define __PVRDRI_SUPPORT_H__ ++ ++#include ++#include ++ ++#include "dri_support.h" ++ ++struct DRISUPScreen *DRISUPCreateScreen(struct __DRIscreenRec *psDRIScreen, ++ int iFD, bool bUseInvalidate, ++ void *pvLoaderPrivate, ++ const struct __DRIconfigRec ***pppsConfigs, ++ int *piMaxGLES1Version, ++ int *piMaxGLES2Version); ++void DRISUPDestroyScreen(struct DRISUPScreen *psDRISUPScreen); ++ ++unsigned int DRISUPCreateContext(PVRDRIAPIType eAPI, ++ PVRDRIConfig *psPVRDRIConfig, ++ struct PVRDRIContextConfig *psCtxConfig, ++ struct __DRIcontextRec *psDRIContext, ++ struct DRISUPContext *psDRISUPSharedContext, ++ struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPContext **ppsDRISUPContext); ++void DRISUPDestroyContext(struct DRISUPContext *psDRISUPContext); ++ ++struct DRISUPDrawable *DRISUPCreateDrawable(struct __DRIdrawableRec *psDRIDrawable, ++ struct DRISUPScreen *psDRISUPScreen, ++ void *pvLoaderPrivate, ++ PVRDRIConfig *psPVRDRIConfig); ++void DRISUPDestroyDrawable(struct DRISUPDrawable *psDRISUPDrawable); ++ ++bool DRISUPMakeCurrent(struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPWrite, ++ struct DRISUPDrawable *psDRISUPRead); ++bool DRISUPUnbindContext(struct DRISUPContext *psDRISUPContext); ++ ++struct DRISUPBuffer *DRISUPAllocateBuffer(struct DRISUPScreen *psDRISUPScreen, ++ unsigned int uAttchment, ++ unsigned int uFormat, ++ int iWidth, int iHeight, ++ unsigned int *puName, ++ unsigned int *puPitch, ++ unsigned int *puCPP, ++ unsigned int *puFlags); ++void DRISUPReleaseBuffer(struct DRISUPScreen *psDRISUPScreen, ++ struct DRISUPBuffer *psDRISUPBuffer); ++void DRISUPSetTexBuffer2(struct DRISUPContext *psDRISUPContext, ++ int iTarget, int iFormat, ++ struct DRISUPDrawable *psDRISUPDrawable); ++void DRISUPReleaseTexBuffer(struct DRISUPContext *psDRISUPContext, ++ int iTarget, ++ struct DRISUPDrawable *psDRISUPDrawable); ++ ++void DRISUPFlush(struct DRISUPDrawable *psDRISUPDrawable); ++void DRISUPInvalidate(struct DRISUPDrawable *psDRISUPDrawable); ++void DRISUPFlushWithFlags(struct DRISUPContext *psDRISUPContext, ++ struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uFlags, unsigned int uThrottleReason); ++ ++__DRIimage *DRISUPCreateImageFromName(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int iName, int iPitch, ++ void *pvLoaderPrivate); ++__DRIimage *DRISUPCreateImageFromRenderbuffer(struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, ++ void *pvLoaderPrivate); ++void DRISUPDestroyImage(__DRIimage *psImage); ++__DRIimage *DRISUPCreateImage(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ unsigned int uUse, void *pvLoaderPrivate); ++bool DRISUPQueryImage(__DRIimage *psImage, int iAttrib, int *piValue); ++__DRIimage *DRISUPDupImage(__DRIimage *psImage, void *pvLoaderPrivate); ++bool DRISUPValidateImageUsage(__DRIimage *psImage, unsigned int uUse); ++__DRIimage *DRISUPCreateImageFromNames(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piNames, int iNumNames, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate); ++__DRIimage *DRISUPFromPlanar(__DRIimage *psImage, int iPlane, ++ void *pvLoaderPrivate); ++__DRIimage *DRISUPCreateImageFromTexture(struct DRISUPContext *psDRISUPContext, ++ int iTarget, unsigned int uTexture, ++ int iDepth, int iLevel, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++__DRIimage *DRISUPCreateImageFromFDs(struct DRISUPScreen *psDRISUPcreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate); ++__DRIimage *DRISUPCreateImageFromDmaBufs(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++int DRISUPGetImageCapabilities(struct DRISUPScreen *psDRISUPScreen); ++void DRISUPBlitImage(struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psDst, __DRIimage *psSrc, ++ int iDstX0, int iDstY0, int iDstWidth, int iDstHeight, ++ int iSrcX0, int iSrcY0, int iSrcWidth, int iSrcHeight, ++ int iFlushFlag); ++void *DRISUPMapImage(struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psImage, ++ int iX0, int iY0, int iWidth, int iHeight, ++ unsigned int uFlags, int *piStride, void **ppvData); ++void DRISUPUnmapImage(struct DRISUPContext *psDRISUPContext, ++ __DRIimage *psImage, void *pvData); ++__DRIimage *DRISUPCreateImageWithModifiers(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, int iFourCC, ++ const uint64_t *puModifiers, ++ const unsigned int uModifierCount, ++ void *pvLoaderPrivate); ++__DRIimage *DRISUPCreateImageFromDMABufs2(struct DRISUPScreen *psDRISUPScreen, ++ int iWidth, int iHeight, ++ int iFourCC, uint64_t uModifier, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++bool DRISUPQueryDMABufFormats(struct DRISUPScreen *psDRISUPScreen, int iMax, ++ int *piFormats, int *piCount); ++bool DRISUPQueryDMABufModifiers(struct DRISUPScreen *psDRISUPScreen, ++ int iFourCC, int iMax, uint64_t *puModifiers, ++ unsigned int *piExternalOnly, int *piCount); ++bool DRISUPQueryDMABufFormatModifierAttribs(struct DRISUPScreen *psDRISUPScreen, ++ uint32_t uFourcc, ++ uint64_t uModifier, ++ int iAttrib, uint64_t *puValue); ++ ++__DRIimage *DRISUPCreateImageFromRenderBuffer2(struct DRISUPContext *psDRISUPContext, ++ int iRenderBuffer, ++ void *pvLoaderPrivate, ++ unsigned int *puError); ++ ++__DRIimage *DRISUPCreateImageFromBuffer(struct DRISUPContext *psDRISUPContext, ++ int iTarget, void *pvBuffer, ++ unsigned int *puError, ++ void *pvLoaderPrivate); ++ ++int DRISUPQueryRendererInteger(struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, unsigned int *puValue); ++int DRISUPQueryRendererString(struct DRISUPScreen *psDRISUPScreen, ++ int iAttribute, const char **ppszValue); ++ ++void *DRISUPCreateFence(struct DRISUPContext *psDRISUPContext); ++void DRISUPDestroyFence(struct DRISUPScreen *psDRISUPScreen, void *pvFence); ++bool DRISUPClientWaitSync(struct DRISUPContext *psDRISUPContext, ++ void *pvFence, unsigned int uFlags, ++ uint64_t uTimeout); ++void DRISUPServerWaitSync(struct DRISUPContext *psDRISUPContext, ++ void *pvFence, unsigned int uFlags); ++unsigned int DRISUPGetFenceCapabilities(struct DRISUPScreen *psDRISUPScreen); ++void *DRISUPCreateFenceFD(struct DRISUPContext *psDRISUPContext, int iFD); ++int DRISUPGetFenceFD(struct DRISUPScreen *psDRISUPScreen, void *pvFence); ++void *DRISUPGetFenceFromCLEvent(struct DRISUPScreen *psDRISUPScreen, ++ intptr_t iCLEvent); ++int DRISUPGetAPIVersion(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI); ++ ++unsigned int DRISUPGetNumAPIProcs(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI); ++const char *DRISUPGetAPIProcName(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI, unsigned int uIndex); ++void *DRISUPGetAPIProcAddress(struct DRISUPScreen *psDRISUPScreen, ++ PVRDRIAPIType eAPI, unsigned int uIndex); ++ ++void DRISUPSetDamageRegion(struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uNRects, int *piRects); ++ ++/****************************************************************************** ++ * PVR DRI Support interface, version 1. ++ * Everything below this point is deprecated. ++ *****************************************************************************/ ++ ++#include "imgpixfmts.h" ++#include "imgyuv.h" ++ ++PVRDRIDeviceType PVRDRIGetDeviceTypeFromFd(int iFd); ++bool PVRDRIIsFirstScreen(PVRDRIScreenImpl *psScreenImpl); ++ ++uint32_t PVRDRIPixFmtGetDepth(IMG_PIXFMT eFmt); ++uint32_t PVRDRIPixFmtGetBPP(IMG_PIXFMT eFmt); ++uint32_t PVRDRIPixFmtGetBlockSize(IMG_PIXFMT eFmt); ++ ++/* ScreenImpl functions */ ++PVRDRIScreenImpl *PVRDRICreateScreenImpl(int iFd); ++void PVRDRIDestroyScreenImpl(PVRDRIScreenImpl *psScreenImpl); ++ ++int PVRDRIAPIVersion(PVRDRIAPIType eAPI, PVRDRIAPISubType eAPISub, ++ PVRDRIScreenImpl *psScreenImpl); ++ ++void *PVRDRIEGLGetLibHandle(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl); ++PVRDRIGLAPIProc PVRDRIEGLGetProcAddress(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ const char *psProcName); ++ ++bool PVRDRIEGLFlushBuffers(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl, ++ bool bFlushAllSurfaces, bool bSwapBuffers, ++ bool bWaitForHW); ++void PVRDRIEGLMarkRendersurfaceInvalid(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl); ++ ++unsigned int PVRDRICreateContextV1(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psSharedContextImpl, ++ PVRDRIConfig *psConfig, ++ PVRDRIAPIType eAPI, ++ PVRDRIAPISubType eAPISub, ++ unsigned int uMajorVersion, ++ unsigned int uMinorVersion, ++ uint32_t uFlags, bool bNotifyReset, ++ unsigned int uPriority, ++ PVRDRIContextImpl **ppsContextImpl); ++void PVRDRIDestroyContextImpl(PVRDRIContextImpl *psContextImpl, ++ PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl); ++ ++bool PVRDRIMakeCurrentGC(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psWriteImpl, ++ PVRDRIDrawableImpl *psReadImpl); ++void PVRDRIMakeUnCurrentGC(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl); ++ ++unsigned int PVRDRIGetImageSource(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ uint32_t uiTarget, uintptr_t uiBuffer, ++ uint32_t uiLevel, IMGEGLImage *psEGLImage); ++ ++bool PVRDRI2BindTexImage(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++void PVRDRI2ReleaseTexImage(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++ ++/* DrawableImpl functions */ ++PVRDRIDrawableImpl *PVRDRICreateDrawableWithConfig(PVRDRIDrawable *psPVRDrawable, ++ PVRDRIConfig *psConfig); ++void PVRDRIDestroyDrawableImpl(PVRDRIDrawableImpl *psScreenImpl); ++bool PVREGLDrawableCreate(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++bool PVREGLDrawableRecreate(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++bool PVREGLDrawableDestroy(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIDrawableImpl *psDrawableImpl); ++void PVREGLDrawableDestroyConfig(PVRDRIDrawableImpl *psDrawableImpl); ++ ++/* Buffer functions */ ++PVRDRIBufferImpl *PVRDRIBufferCreate(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, int iHeight, ++ unsigned int uiBpp, ++ unsigned int uiUseFlags, ++ unsigned int *puiStride); ++PVRDRIBufferImpl *PVRDRIBufferCreateWithModifiers(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, int iHeight, ++ int iFormat, ++ IMG_PIXFMT eIMGPixelFormat, ++ const uint64_t *puiModifiers, ++ unsigned int uiModifierCount, ++ unsigned int *puiStride); ++PVRDRIBufferImpl *PVRDRIBufferCreateFromNames(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, int iHeight, ++ unsigned int uiNumPlanes, ++ const int *piName, ++ const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift); ++PVRDRIBufferImpl *PVRDRIBufferCreateFromFds(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, int iHeight, ++ unsigned int uiNumPlanes, ++ const int *piFd, ++ const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift); ++PVRDRIBufferImpl *PVRDRIBufferCreateFromFdsWithModifier(PVRDRIScreenImpl *psScreenImpl, ++ int iWidth, ++ int iHeight, ++ uint64_t uiModifier, ++ unsigned int uiNumPlanes, ++ const int *piFd, ++ const int *piStride, ++ const int *piOffset, ++ const unsigned int *puiWidthShift, ++ const unsigned int *puiHeightShift); ++PVRDRIBufferImpl *PVRDRISubBufferCreate(PVRDRIScreenImpl *psScreen, ++ PVRDRIBufferImpl *psParent, ++ int plane); ++void PVRDRIBufferDestroy(PVRDRIBufferImpl *psBuffer); ++ ++int PVRDRIBufferGetFd(PVRDRIBufferImpl *psBuffer); ++int PVRDRIBufferGetHandle(PVRDRIBufferImpl *psBuffer); ++uint64_t PVRDRIBufferGetModifier(PVRDRIBufferImpl *psBuffer); ++int PVRDRIBufferGetName(PVRDRIBufferImpl *psBuffer); ++int PVRDRIBufferGetOffset(PVRDRIBufferImpl *psBuffer); ++ ++/* Image functions */ ++IMGEGLImage *PVRDRIEGLImageCreate(void); ++IMGEGLImage *PVRDRIEGLImageCreateFromBuffer(int iWidth, int iHeight, ++ int iStride, ++ IMG_PIXFMT ePixelFormat, ++ IMG_YUV_COLORSPACE eColourSpace, ++ IMG_YUV_CHROMA_INTERP eChromaUInterp, ++ IMG_YUV_CHROMA_INTERP eChromaVInterp, ++ PVRDRIBufferImpl *psBuffer); ++IMGEGLImage *PVRDRIEGLImageCreateFromSubBuffer(IMG_PIXFMT ePixelFormat, ++ PVRDRIBufferImpl *psSubBuffer); ++IMGEGLImage *PVRDRIEGLImageDup(IMGEGLImage *psIn); ++ ++void PVRDRIEGLImageSetCallbackData(IMGEGLImage *psEGLImage, ++ __DRIimage *image); ++ ++void PVRDRIEGLImageDestroyExternal(PVRDRIScreenImpl *psScreenImpl, ++ IMGEGLImage *psEGLImage, ++ PVRDRIEGLImageType eglImageType); ++void PVRDRIEGLImageFree(IMGEGLImage *psEGLImage); ++ ++void PVRDRIEGLImageGetAttribs(IMGEGLImage *psEGLImage, ++ PVRDRIBufferAttribs *psAttribs); ++ ++/* Sync functions */ ++void *PVRDRICreateFenceImpl(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl); ++void PVRDRIDestroyFenceImpl(void *pvFence); ++ ++bool PVRDRIClientWaitSyncImpl(PVRDRIAPIType eAPI, ++ PVRDRIContextImpl *psContextImpl, ++ void *pvFence, bool bFlushCommands, ++ bool bTimeout, uint64_t uiTimeout); ++bool PVRDRIServerWaitSyncImpl(PVRDRIAPIType eAPI, ++ PVRDRIContextImpl *psContextImpl, ++ void *pvFence); ++ ++/* Blit functions */ ++bool PVRDRIBlitEGLImage(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psDstImage, ++ PVRDRIBufferImpl *psDstBuffer, ++ IMGEGLImage *psSrcImage, ++ PVRDRIBufferImpl *psSrcBuffer, ++ int iDstX, int iDstY, int iDstWidth, int iDstHeight, ++ int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, ++ int iFlushFlag); ++ ++/* Mapping functions */ ++void *PVRDRIMapEGLImage(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psImage, PVRDRIBufferImpl *psBuffer, ++ int iX, int iY, int iWidth, int iHeight, ++ unsigned int uiFlags, int *piStride, void **ppvData); ++bool PVRDRIUnmapEGLImage(PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, ++ IMGEGLImage *psImage, PVRDRIBufferImpl *psBuffer, ++ void *pvData); ++ ++/* Fence functions */ ++void *PVRDRICreateFenceImpl(PVRDRIAPIType eAPI, ++ PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl); ++void *PVRDRICreateFenceFd(PVRDRIAPIType eAPI, PVRDRIScreenImpl *psScreenImpl, ++ PVRDRIContextImpl *psContextImpl, int iFd); ++unsigned int PVRDRIGetFenceCapabilities(PVRDRIScreenImpl *psScreenImpl); ++int PVRDRIGetFenceFd(void *pvFence); ++void PVRDRIDestroyFenceImpl(void *pvFence); ++ ++bool PVRDRIClientWaitSyncImpl(PVRDRIAPIType eAPI, ++ PVRDRIContextImpl *psContextImpl, void *pvFence, ++ bool bFlushCommands, ++ bool bTimeout, uint64_t uiTimeout); ++ ++bool PVRDRIServerWaitSyncImpl(PVRDRIAPIType eAPI, ++ PVRDRIContextImpl *psContextImpl, ++ void *pvFence); ++ ++/* PVR utility support functions */ ++bool PVRDRIMesaFormatSupported(unsigned int iFormat); ++unsigned int PVRDRIDepthStencilBitArraySize(void); ++const uint8_t *PVRDRIDepthBitsArray(void); ++const uint8_t *PVRDRIStencilBitsArray(void); ++unsigned int PVRDRIMSAABitArraySize(void); ++const uint8_t *PVRDRIMSAABitsArray(void); ++uint32_t PVRDRIMaxPBufferWidth(void); ++uint32_t PVRDRIMaxPBufferHeight(void); ++ ++unsigned int PVRDRIGetNumAPIFuncs(PVRDRIAPIType eAPI); ++const char *PVRDRIGetAPIFunc(PVRDRIAPIType eAPI, unsigned int index); ++ ++int PVRDRIQuerySupportedFormats(PVRDRIScreenImpl *psScreenImpl, ++ unsigned int uNumFormats, ++ const int *piFormats, ++ const IMG_PIXFMT *peImgFormats, ++ bool *pbSupported); ++int PVRDRIQueryModifiers(PVRDRIScreenImpl *psScreenImpl, ++ int iFormat, IMG_PIXFMT eImgFormat, ++ uint64_t *puModifiers, unsigned int *puExternalOnly); ++ ++#endif /* defined(__PVRDRI_SUPPORT_H__) */ +diff --git a/src/mesa/drivers/dri/pvr/pvrext.c b/src/mesa/drivers/dri/pvr/pvrext.c +new file mode 100644 +index 00000000000..eb94f3f50c5 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrext.c +@@ -0,0 +1,698 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++/* ++ * EXTENSION SUPPORT ++ * ++ * As the driver supports a range of Mesa versions it can be the case that it ++ * needs to support different extensions and extension versions depending on ++ * the version of Mesa that it's built against. As a guide the following rules ++ * should be followed: ++ * ++ * 1) If an extension appears in some supported versions of Mesa but not others ++ * then it should be protected by the extension define, e.g.: ++ * #if defined(__DRI_IMAGE) ++ * ++ * #endif ++ * ++ * However, if it appears in all versions then there's no need for it to ++ * be protected. ++ * ++ * 2) Each driver supported extension should have a define for the maximum ++ * version supported by the driver. This should be used when initialising ++ * the corresponding extension structure. The Mesa extension version define ++ * should *NOT* be used. ++ * ++ * 3) If the driver supports a range of versions for a given extension then ++ * it should protect the extension code based on the Mesa extension version ++ * define. For example, if the driver has to support versions 7 to 8 of the ++ * __DRI_IMAGE extension then any fields, in the __DRIimageExtension ++ * structure, that appear in version 8 but not 7 should be protected as ++ * follows: ++ * #if (__DRI_IMAGE_VERSION >= 8) ++ * .createImageFromDmaBufs = PVRDRICreateImageFromDmaBufs, ++ * #endif ++ * ++ * Obviously any other associated code should also be protected in the same ++ * way. ++ */ ++ ++#include "dri_util.h" ++#include "utils.h" ++ ++#include "dri_support.h" ++#include "pvrdri.h" ++ ++#include "EGL/egl.h" ++#include "EGL/eglext.h" ++#include "EGL/eglmesaext.h" ++ ++/* Maximum version numbers for each supported extension */ ++#define PVR_DRI_TEX_BUFFER_VERSION 3 ++#define PVR_DRI2_FLUSH_VERSION 4 ++#define PVR_DRI_IMAGE_VERSION 17 ++#define PVR_DRI2_ROBUSTNESS_VERSION 1 ++#define PVR_DRI2_FENCE_VERSION 2 ++#define PVR_DRI2_RENDERER_QUERY_VERSION 1 ++#define PVR_DRI2_BUFFER_DAMAGE_VERSION 1 ++ ++static void ++PVRDRIExtSetTexBuffer(__DRIcontext *psDRIContext, GLint iTarget, ++ GLint iFormat, __DRIdrawable *psDRIDrawable) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ DRISUPSetTexBuffer2(psPVRContext->psDRISUPContext, ++ iTarget, iFormat, psPVRDrawable->psDRISUPDrawable); ++} ++ ++static void ++PVRDRIExtReleaseTexBuffer(__DRIcontext *psDRIContext, GLint iTarget, ++ __DRIdrawable *psDRIDrawable) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ DRISUPReleaseTexBuffer(psPVRContext->psDRISUPContext, ++ iTarget, psPVRDrawable->psDRISUPDrawable); ++ ++} ++ ++static __DRItexBufferExtension pvrDRITexBufferExtension = { ++ .base = { ++ .name = __DRI_TEX_BUFFER, ++ .version = PVR_DRI_TEX_BUFFER_VERSION, ++ }, ++ .setTexBuffer = NULL, ++ .setTexBuffer2 = PVRDRIExtSetTexBuffer, ++ .releaseTexBuffer = PVRDRIExtReleaseTexBuffer, ++}; ++ ++static void ++PVRDRI2Flush(__DRIdrawable *psDRIDrawable) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ ++ DRISUPFlush(psPVRDrawable->psDRISUPDrawable); ++} ++ ++static void ++PVRDRI2Invalidate(__DRIdrawable *psDRIDrawable) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ ++ DRISUPInvalidate(psPVRDrawable->psDRISUPDrawable); ++} ++ ++static void ++PVRDRI2FlushWithFlags(__DRIcontext *psDRIContext, ++ __DRIdrawable *psDRIDrawable, ++ unsigned int uFlags, ++ enum __DRI2throttleReason eThrottleReason) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ struct DRISUPDrawable *psDRISUPDrawable; ++ ++ if ((uFlags & __DRI2_FLUSH_DRAWABLE) != 0) { ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ ++ psDRISUPDrawable = psPVRDrawable->psDRISUPDrawable; ++ } else { ++ psDRISUPDrawable = NULL; ++ } ++ ++ DRISUPFlushWithFlags(psPVRContext->psDRISUPContext, psDRISUPDrawable, ++ uFlags, (unsigned int) eThrottleReason); ++} ++ ++static __DRI2flushExtension pvrDRI2FlushExtension = { ++ .base = { ++ .name = __DRI2_FLUSH, ++ .version = PVR_DRI2_FLUSH_VERSION, ++ }, ++ .flush = PVRDRI2Flush, ++ .invalidate = PVRDRI2Invalidate, ++ .flush_with_flags = PVRDRI2FlushWithFlags, ++}; ++ ++static __DRIimage * ++PVRDRICreateImageFromName(__DRIscreen *psDRIScreen, int iWidth, int iHeight, ++ int iFormat, int iName, int iPitch, ++ void *pvLoaderPrivate) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ int iFourCC = PVRDRIFormatToFourCC(iFormat); ++ ++ return DRISUPCreateImageFromName(psPVRScreen->psDRISUPScreen, ++ iWidth, iHeight, iFourCC, iName, iPitch, ++ pvLoaderPrivate); ++} ++ ++static __DRIimage * ++PVRDRICreateImageFromRenderbuffer(__DRIcontext *psDRIContext, ++ int iRenderBuffer, void *pvLoaderPrivate) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPCreateImageFromRenderbuffer(psPVRContext->psDRISUPContext, ++ iRenderBuffer, pvLoaderPrivate); ++} ++ ++static void ++PVRDRIDestroyImage(__DRIimage *psImage) ++{ ++ DRISUPDestroyImage(psImage); ++} ++ ++static __DRIimage * ++PVRDRICreateImage(__DRIscreen *psDRIScreen, int iWidth, int iHeight, ++ int iFormat, unsigned int uUse, void *pvLoaderPrivate) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ int iFourCC = PVRDRIFormatToFourCC(iFormat); ++ ++ return DRISUPCreateImage(psPVRScreen->psDRISUPScreen, iWidth, iHeight, ++ iFourCC, uUse, pvLoaderPrivate); ++} ++ ++static GLboolean ++PVRDRIQueryImage(__DRIimage *psImage, int iAttrib, int *piValue) ++{ ++ int iFourCC; ++ ++ switch (iAttrib) { ++ case PVRDRI_IMAGE_ATTRIB_FORMAT: ++ if (DRISUPQueryImage(psImage, ++ PVRDRI_IMAGE_ATTRIB_FOURCC, &iFourCC)) { ++ *piValue = PVRDRIFourCCToDRIFormat(iFourCC); ++ return GL_TRUE; ++ } ++ return GL_FALSE; ++ default: ++ return DRISUPQueryImage(psImage, iAttrib, piValue); ++ } ++ ++} ++ ++static __DRIimage * ++PVRDRIDupImage(__DRIimage *psImage, void *pvLoaderPrivate) ++{ ++ return DRISUPDupImage(psImage, pvLoaderPrivate); ++} ++ ++static GLboolean ++PVRDRIValidateImageUsage(__DRIimage *psImage, unsigned int uUse) ++{ ++ return DRISUPValidateImageUsage(psImage, uUse); ++} ++ ++static __DRIimage * ++PVRDRICreateImageFromNames(__DRIscreen *psDRIScreen, int iWidth, int iHeight, ++ int iFourCC, int *piNames, int iNumNames, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPCreateImageFromNames(psPVRScreen->psDRISUPScreen, ++ iWidth, iHeight, iFourCC, ++ piNames, iNumNames, ++ piStrides, piOffsets, pvLoaderPrivate); ++} ++ ++static __DRIimage * ++PVRDRIFromPlanar(__DRIimage *psImage, int iPlane, void *pvLoaderPrivate) ++{ ++ return DRISUPFromPlanar(psImage, iPlane, pvLoaderPrivate); ++} ++ ++static __DRIimage * ++PVRDRICreateImageFromTexture(__DRIcontext *psDRIContext, int iTarget, ++ unsigned int uTexture, int iDepth, int iLevel, ++ unsigned int *puError, void *pvLoaderPrivate) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ int iEGLTarget; ++ ++ switch (iTarget) { ++ case GL_TEXTURE_2D: ++ iEGLTarget = PVRDRI_GL_TEXTURE_2D; ++ break; ++ case GL_TEXTURE_3D: ++ iEGLTarget = PVRDRI_GL_TEXTURE_3D; ++ break; ++ case GL_TEXTURE_CUBE_MAP: ++ iEGLTarget = PVRDRI_GL_TEXTURE_CUBE_MAP_POSITIVE_X; ++ break; ++ default: ++ errorMessage("%s: GL Target %d is not supported", ++ __func__, iTarget); ++ *puError = __DRI_IMAGE_ERROR_BAD_PARAMETER; ++ return NULL; ++ } ++ ++ return DRISUPCreateImageFromTexture(psPVRContext->psDRISUPContext, ++ iEGLTarget, uTexture, iDepth, iLevel, ++ puError, pvLoaderPrivate); ++} ++ ++static __DRIimage * ++PVRDRICreateImageFromFds(__DRIscreen *psDRIScreen, int iWidth, int iHeight, ++ int iFourCC, int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPCreateImageFromFDs(psPVRScreen->psDRISUPScreen, ++ iWidth, iHeight, iFourCC, piFDs, iNumFDs, ++ piStrides, piOffsets, pvLoaderPrivate); ++} ++ ++static __DRIimage * ++PVRDRICreateImageFromDmaBufs(__DRIscreen *psDRIScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ enum __DRIYUVColorSpace eColorSpace, ++ enum __DRISampleRange eSampleRange, ++ enum __DRIChromaSiting eHorizSiting, ++ enum __DRIChromaSiting eVertSiting, ++ unsigned int *puError, void *pvLoaderPrivate) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPCreateImageFromDmaBufs(psPVRScreen->psDRISUPScreen, ++ iWidth, iHeight, iFourCC, ++ piFDs, iNumFDs, piStrides, piOffsets, ++ (unsigned int) eColorSpace, ++ (unsigned int) eSampleRange, ++ (unsigned int) eHorizSiting, ++ (unsigned int) eVertSiting, ++ puError, pvLoaderPrivate); ++} ++ ++static void ++PVRDRIBlitImage(__DRIcontext *psDRIContext, ++ __DRIimage *psDst, __DRIimage *psSrc, ++ int iDstX0, int iDstY0, int iDstWidth, int iDstHeight, ++ int iSrcX0, int iSrcY0, int iSrcWidth, int iSrcHeight, ++ int iFlushFlag) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPBlitImage(psPVRContext->psDRISUPContext, ++ psDst, psSrc, ++ iDstX0, iDstY0, iDstWidth, iDstHeight, ++ iSrcX0, iSrcY0, iSrcWidth, iSrcHeight, ++ iFlushFlag); ++} ++ ++static int ++PVRDRIGetCapabilities(__DRIscreen *psDRIScreen) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPGetImageCapabilities(psPVRScreen->psDRISUPScreen); ++} ++ ++static void * ++PVRDRIMapImage(__DRIcontext *psDRIContext, __DRIimage *psImage, ++ int iX0, int iY0, int iWidth, int iHeight, ++ unsigned int iFlags, int *piStride, void **ppvData) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPMapImage(psPVRContext->psDRISUPContext, psImage, ++ iX0, iY0, iWidth, iHeight, iFlags, piStride, ++ ppvData); ++} ++ ++static void ++PVRDRIUnmapImage(__DRIcontext *psDRIContext, __DRIimage *psImage, ++ void *pvData) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPUnmapImage(psPVRContext->psDRISUPContext, psImage, pvData); ++} ++ ++static __DRIimage * ++PVRDRICreateImageWithModifiers(__DRIscreen *psDRIScreen, ++ int iWidth, int iHeight, int iFormat, ++ const uint64_t *puModifiers, ++ const unsigned int uModifierCount, ++ void *pvLoaderPrivate) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ int iFourCC = PVRDRIFormatToFourCC(iFormat); ++ ++ return DRISUPCreateImageWithModifiers(psPVRScreen->psDRISUPScreen, ++ iWidth, iHeight, iFourCC, ++ puModifiers, uModifierCount, ++ pvLoaderPrivate); ++} ++ ++static __DRIimage * ++PVRDRICreateImageFromDmaBufs2(__DRIscreen *psDRIScreen, ++ int iWidth, int iHeight, ++ int iFourCC, uint64_t uModifier, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ enum __DRIYUVColorSpace eColorSpace, ++ enum __DRISampleRange eSampleRange, ++ enum __DRIChromaSiting eHorizSiting, ++ enum __DRIChromaSiting eVertSiting, ++ unsigned int *puError, void *pvLoaderPrivate) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPCreateImageFromDMABufs2(psPVRScreen->psDRISUPScreen, ++ iWidth, iHeight, iFourCC, uModifier, ++ piFDs, iNumFDs, piStrides, piOffsets, ++ (unsigned int) eColorSpace, ++ (unsigned int) eSampleRange, ++ (unsigned int) eHorizSiting, ++ (unsigned int) eVertSiting, ++ puError, pvLoaderPrivate); ++} ++ ++static GLboolean ++PVRDRIQueryDmaBufFormats(__DRIscreen *psDRIScreen, int iMax, ++ int *piFormats, int *piCount) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPQueryDMABufFormats(psPVRScreen->psDRISUPScreen, iMax, ++ piFormats, piCount); ++} ++ ++static GLboolean ++PVRDRIQueryDmaBufModifiers(__DRIscreen *psDRIScreen, int iFourCC, int iMax, ++ uint64_t *puModifiers, ++ unsigned int *puExternalOnly, int *piCount) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPQueryDMABufModifiers(psPVRScreen->psDRISUPScreen, iFourCC, ++ iMax, ++ puModifiers, puExternalOnly, piCount); ++} ++ ++static GLboolean ++PVRDRIQueryDmaBufFormatModifierAttribs(__DRIscreen *psDRIScreen, ++ uint32_t uFourCC, uint64_t uModifier, ++ int iAttrib, uint64_t *puValue) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ struct DRISUPScreen *psDRISUPScreen = psPVRScreen->psDRISUPScreen; ++ ++ return DRISUPQueryDMABufFormatModifierAttribs(psDRISUPScreen, uFourCC, ++ uModifier, iAttrib, puValue); ++} ++ ++static __DRIimage * ++PVRDRICreateImageFromRenderbuffer2(__DRIcontext *psDRIContext, ++ int iRenderBuffer, void *pvLoaderPrivate, ++ unsigned int *puError) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ struct DRISUPContext *psDRISUPContext = psPVRContext->psDRISUPContext; ++ ++ return DRISUPCreateImageFromRenderBuffer2(psDRISUPContext, iRenderBuffer, ++ pvLoaderPrivate, puError); ++} ++ ++#if defined(EGL_IMG_cl_image) ++static __DRIimage * ++PVRDRICreateImageFromBuffer(__DRIcontext *psDRIContext, int iTarget, ++ void *pvBuffer, unsigned int *puError, ++ void *pvLoaderPrivate) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPCreateImageFromBuffer(psPVRContext->psDRISUPContext, iTarget, ++ pvBuffer, puError, pvLoaderPrivate); ++} ++#endif ++ ++static __DRIimageExtension pvrDRIImage = { ++ .base = { ++ .name = __DRI_IMAGE, ++ .version = PVR_DRI_IMAGE_VERSION, ++ }, ++ .createImageFromName = PVRDRICreateImageFromName, ++ .createImageFromRenderbuffer = PVRDRICreateImageFromRenderbuffer, ++ .destroyImage = PVRDRIDestroyImage, ++ .createImage = PVRDRICreateImage, ++ .queryImage = PVRDRIQueryImage, ++ .dupImage = PVRDRIDupImage, ++ .validateUsage = PVRDRIValidateImageUsage, ++ .createImageFromNames = PVRDRICreateImageFromNames, ++ .fromPlanar = PVRDRIFromPlanar, ++ .createImageFromTexture = PVRDRICreateImageFromTexture, ++ .createImageFromFds = PVRDRICreateImageFromFds, ++ .createImageFromDmaBufs = PVRDRICreateImageFromDmaBufs, ++ .blitImage = PVRDRIBlitImage, ++ .getCapabilities = PVRDRIGetCapabilities, ++ .mapImage = PVRDRIMapImage, ++ .unmapImage = PVRDRIUnmapImage, ++ .createImageWithModifiers = PVRDRICreateImageWithModifiers, ++ .createImageFromDmaBufs2 = PVRDRICreateImageFromDmaBufs2, ++ .queryDmaBufFormats = PVRDRIQueryDmaBufFormats, ++ .queryDmaBufModifiers = PVRDRIQueryDmaBufModifiers, ++ .queryDmaBufFormatModifierAttribs = ++ PVRDRIQueryDmaBufFormatModifierAttribs, ++ .createImageFromRenderbuffer2 = PVRDRICreateImageFromRenderbuffer2, ++#if defined(EGL_IMG_cl_image) ++ .createImageFromBuffer = PVRDRICreateImageFromBuffer, ++#endif ++}; ++ ++static __DRIrobustnessExtension pvrDRIRobustness = { ++ .base = { ++ .name = __DRI2_ROBUSTNESS, ++ .version = PVR_DRI2_ROBUSTNESS_VERSION, ++ } ++}; ++ ++static int ++PVRDRIQueryRendererInteger(__DRIscreen *psDRIScreen, int iAttribute, ++ unsigned int *puValue) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ int res; ++ ++ res = DRISUPQueryRendererInteger(psPVRScreen->psDRISUPScreen, ++ iAttribute, puValue); ++ if (res == -1) ++ return driQueryRendererIntegerCommon(psDRIScreen, iAttribute, puValue); ++ ++ return res; ++} ++ ++static int ++PVRDRIQueryRendererString(__DRIscreen *psDRIScreen, int iAttribute, ++ const char **ppszValue) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPQueryRendererString(psPVRScreen->psDRISUPScreen, iAttribute, ++ ppszValue); ++} ++ ++static const __DRI2rendererQueryExtension pvrDRIRendererQueryExtension = { ++ .base = { ++ .name = __DRI2_RENDERER_QUERY, ++ .version = PVR_DRI2_RENDERER_QUERY_VERSION, ++ }, ++ .queryInteger = PVRDRIQueryRendererInteger, ++ .queryString = PVRDRIQueryRendererString, ++}; ++ ++ ++static void * ++PVRDRICreateFenceEXT(__DRIcontext *psDRIContext) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPCreateFence(psPVRContext->psDRISUPContext); ++} ++ ++static void ++PVRDRIDestroyFenceEXT(__DRIscreen *psDRIScreen, void *pvFence) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPDestroyFence(psPVRScreen->psDRISUPScreen, pvFence); ++} ++ ++static GLboolean ++PVRDRIClientWaitSyncEXT(__DRIcontext *psDRIContext, void *pvFence, ++ unsigned int uFlags, uint64_t uTimeout) ++{ ++ struct DRISUPContext *psDRISUPContext; ++ ++ if (psDRIContext) { ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ psDRISUPContext = psPVRContext->psDRISUPContext; ++ } else { ++ psDRISUPContext = NULL; ++ } ++ ++ return DRISUPClientWaitSync(psDRISUPContext, pvFence, uFlags, uTimeout); ++} ++ ++static void ++PVRDRIServerWaitSyncEXT(__DRIcontext *psDRIContext, void *pvFence, ++ unsigned int uFlags) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPServerWaitSync(psPVRContext->psDRISUPContext, pvFence, uFlags); ++} ++ ++static unsigned int ++PVRDRIGetFenceCapabilitiesEXT(__DRIscreen *psDRIScreen) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPGetFenceCapabilities(psPVRScreen->psDRISUPScreen); ++} ++ ++static void * ++PVRDRICreateFenceFdEXT(__DRIcontext *psDRIContext, int iFD) ++{ ++ PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; ++ ++ return DRISUPCreateFenceFD(psPVRContext->psDRISUPContext, iFD); ++} ++ ++static int ++PVRDRIGetFenceFdEXT(__DRIscreen *psDRIScreen, void *pvFence) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPGetFenceFD(psPVRScreen->psDRISUPScreen, pvFence); ++} ++ ++static void * ++PVRDRIGetFenceFromClEventEXT(__DRIscreen *psDRIScreen, intptr_t iClEvent) ++{ ++ PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate; ++ ++ return DRISUPGetFenceFromCLEvent(psPVRScreen->psDRISUPScreen, iClEvent); ++} ++ ++__DRI2fenceExtension pvrDRIFenceExtension = { ++ .base = { ++ .name = __DRI2_FENCE, ++ .version = PVR_DRI2_FENCE_VERSION, ++ }, ++ .create_fence = PVRDRICreateFenceEXT, ++ .get_fence_from_cl_event = PVRDRIGetFenceFromClEventEXT, ++ .destroy_fence = PVRDRIDestroyFenceEXT, ++ .client_wait_sync = PVRDRIClientWaitSyncEXT, ++ .server_wait_sync = PVRDRIServerWaitSyncEXT, ++ .get_capabilities = PVRDRIGetFenceCapabilitiesEXT, ++ .create_fence_fd = PVRDRICreateFenceFdEXT, ++ .get_fence_fd = PVRDRIGetFenceFdEXT, ++}; ++ ++static void ++PVRDRISetDamageRegion(__DRIdrawable *psDRIDrawable, ++ unsigned int uNRects, int *piRects) ++{ ++ PVRDRIDrawable *psPVRDrawable = psDRIDrawable->driverPrivate; ++ ++ DRISUPSetDamageRegion(psPVRDrawable->psDRISUPDrawable, uNRects, piRects); ++} ++ ++const __DRI2bufferDamageExtension pvrDRIbufferDamageExtension = { ++ .base = { ++ .name = __DRI2_BUFFER_DAMAGE, ++ .version = PVR_DRI2_BUFFER_DAMAGE_VERSION, ++ }, ++ .set_damage_region = PVRDRISetDamageRegion, ++}; ++ ++/* ++ * Extension lists ++ * ++ * NOTE: When adding a new screen extension asScreenExtensionVersionInfo ++ * should also be updated accordingly. ++ */ ++static const __DRIextension *apsScreenExtensions[] = { ++ &pvrDRITexBufferExtension.base, ++ &pvrDRI2FlushExtension.base, ++ &pvrDRIImage.base, ++ &pvrDRIRobustness.base, ++ &pvrDRIRendererQueryExtension.base, ++ &pvrDRIFenceExtension.base, ++ &pvrDRIbufferDamageExtension.base, ++ &dri2ConfigQueryExtension.base, ++ NULL ++}; ++ ++static const __DRIextension asScreenExtensionVersionInfo[] = { ++ {.name = __DRI_TEX_BUFFER,.version = __DRI_TEX_BUFFER_VERSION}, ++ {.name = __DRI2_FLUSH,.version = __DRI2_FLUSH_VERSION}, ++ {.name = __DRI_IMAGE,.version = __DRI_IMAGE_VERSION}, ++ {.name = __DRI2_ROBUSTNESS,.version = __DRI2_ROBUSTNESS_VERSION}, ++ {.name = __DRI2_RENDERER_QUERY,.version = __DRI2_RENDERER_QUERY_VERSION}, ++ {.name = __DRI2_FENCE,.version = __DRI2_FENCE_VERSION}, ++ {.name = __DRI2_BUFFER_DAMAGE,.version = __DRI2_BUFFER_DAMAGE_VERSION}, ++ {.name = __DRI2_CONFIG_QUERY,.version = __DRI2_CONFIG_QUERY_VERSION}, ++ {.name = NULL,.version = 0}, ++}; ++ ++const __DRIextension ** ++PVRDRIScreenExtensions(void) ++{ ++ return apsScreenExtensions; ++} ++ ++const __DRIextension * ++PVRDRIScreenExtensionVersionInfo(void) ++{ ++ return asScreenExtensionVersionInfo; ++} ++ ++void ++PVRDRIAdjustExtensions(unsigned int uVersion, unsigned int uMinVersion) ++{ ++ switch (uVersion) { ++ default: ++ case 3: ++ break; ++ case 2: ++ case 1: ++ case 0: ++ /* The KHR_cl_event2 EGL extension is not supported */ ++ pvrDRIFenceExtension.get_fence_from_cl_event = NULL; ++ break; ++ } ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrext_mod.c b/src/mesa/drivers/dri/pvr/pvrext_mod.c +new file mode 100644 +index 00000000000..dfb5c79eeb4 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrext_mod.c +@@ -0,0 +1,276 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++ ++#include "util/u_atomic.h" ++#include "pvrdri_mod.h" ++ ++static void ++PVRDRIFlushDrawableContext(struct DRISUPDrawable *psPVRDrawable, ++ struct DRISUPContext *psPVRContext) ++{ ++ struct DRISUPContext *psPVRDrawContext = psPVRDrawable->psPVRContext; ++ ++ if (psPVRDrawContext) { ++ PVRDRIEGLFlushBuffers(psPVRDrawContext->eAPI, ++ psPVRDrawContext->psPVRScreen->psImpl, ++ psPVRDrawContext->psImpl, ++ psPVRDrawable->psImpl, ++ false, ++ false, (psPVRDrawContext != psPVRContext)); ++ } ++} ++ ++void ++DRIMODSetTexBuffer2(struct DRISUPContext *psPVRContext, int iTarget, ++ int iFormat, struct DRISUPDrawable *psPVRDrawable) ++{ ++ (void) iTarget; ++ (void) iFormat; ++ ++ if (!psPVRDrawable->bInitialised) { ++ if (!PVRDRIDrawableInit(psPVRDrawable)) { ++ __driUtilMessage("%s: Couldn't initialise pixmap", __func__); ++ return; ++ } ++ } ++ ++ PVRDRIFlushDrawableContext(psPVRDrawable, psPVRContext); ++ PVRDRI2BindTexImage(psPVRContext->eAPI, psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, psPVRDrawable->psImpl); ++} ++ ++void ++DRIMODReleaseTexBuffer(struct DRISUPContext *psPVRContext, int iTarget, ++ struct DRISUPDrawable *psPVRDrawable) ++{ ++ (void) iTarget; ++ ++ PVRDRI2ReleaseTexImage(psPVRContext->eAPI, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, psPVRDrawable->psImpl); ++} ++ ++void ++DRIMODFlush(struct DRISUPDrawable *psPVRDrawable) ++{ ++ struct DRISUPContext *psPVRContext = psPVRDrawable->psPVRContext; ++ ++ PVRDRIFlushBuffersForSwap(psPVRContext, psPVRDrawable); ++} ++ ++void ++DRIMODInvalidate(struct DRISUPDrawable *psPVRDrawable) ++{ ++ if (psPVRDrawable->psPVRScreen->bUseInvalidate) ++ p_atomic_inc(&psPVRDrawable->iInfoInvalid); ++} ++ ++void ++DRIMODFlushWithFlags(struct DRISUPContext *psPVRContext, ++ struct DRISUPDrawable *psPVRDrawable, ++ unsigned int uFlags, unsigned int uThrottleReason) ++{ ++ (void) uThrottleReason; ++ ++ if ((uFlags & PVRDRI_FLUSH_DRAWABLE) != 0) { ++ PVRDRIFlushBuffersForSwap(psPVRContext, psPVRDrawable); ++ } else if ((uFlags & PVRDRI_FLUSH_CONTEXT) != 0) { ++ /* ++ * PVRDRI_FLUSH__CONTEXT means "glFlush". Most callers also specify ++ * PVRDRI_FLUSH_DRAWABLE. An exception is GBM, which flushes after an ++ * unmap, when there doesn't appear to be a need to flush outstanding ++ * GPU operations. ++ */ ++ } ++} ++ ++int ++DRIMODQueryRendererInteger(struct DRISUPScreen *psPVRScreen, int iAttribute, ++ unsigned int *puValue) ++{ ++ (void) psPVRScreen; ++ ++ switch (iAttribute) { ++ case PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY: ++ puValue[0] = 0; ++ puValue[0] |= PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY_HIGH; ++ puValue[0] |= PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY_MEDIUM; ++ puValue[0] |= PVRDRI_RENDERER_HAS_CONTEXT_PRIORITY_LOW; ++ return 0; ++ case PVRDRI_RENDERER_HAS_FRAMEBUFFER_SRGB: ++ puValue[0] = 1; ++ return 0; ++ default: ++ return -1; ++ } ++} ++ ++int ++DRIMODQueryRendererString(struct DRISUPScreen *psPVRScreen, int iAttribute, ++ const char **ppszValue) ++{ ++ (void) psPVRScreen; ++ (void) iAttribute; ++ (void) ppszValue; ++ ++ return -1; ++} ++ ++void * ++DRIMODCreateFence(struct DRISUPContext *psPVRContext) ++{ ++ return PVRDRICreateFenceImpl(psPVRContext->eAPI, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl); ++} ++ ++void ++DRIMODDestroyFence(struct DRISUPScreen *psPVRScreen, void *pvFence) ++{ ++ (void) psPVRScreen; ++ ++ PVRDRIDestroyFenceImpl(pvFence); ++} ++ ++bool ++DRIMODClientWaitSync(struct DRISUPContext *psPVRContext, void *pvFence, ++ unsigned int uFlags, uint64_t uTimeout) ++{ ++ bool bFlushCommands = (uFlags & PVRDRI_FENCE_FLAG_FLUSH_COMMANDS); ++ bool bTimeout = (uTimeout != PVRDRI_FENCE_TIMEOUT_INFINITE); ++ ++ if (psPVRContext && bFlushCommands) { ++ struct DRISUPDrawable *psPVRDrawable; ++ PVRDRIDrawableImpl *psDrawableImpl; ++ ++ psPVRDrawable = psPVRContext->psPVRDrawable; ++ psDrawableImpl = psPVRDrawable ? psPVRDrawable->psImpl : NULL; ++ ++ (void) PVRDRIEGLFlushBuffers(psPVRContext->eAPI, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, ++ psDrawableImpl, true, false, false); ++ } ++ ++ return PVRDRIClientWaitSyncImpl(PVRDRI_API_NONE, NULL, pvFence, false, ++ bTimeout, uTimeout); ++} ++ ++void ++DRIMODServerWaitSync(struct DRISUPContext *psPVRContext, void *pvFence, ++ unsigned int uFlags) ++{ ++ assert(uFlags == 0); ++ (void) uFlags; ++ ++ if (pvFence) { ++ if (!PVRDRIServerWaitSyncImpl(psPVRContext->eAPI, ++ psPVRContext->psImpl, pvFence)) { ++ __driUtilMessage("%s: Server wait sync failed", __func__); ++ } ++ } ++} ++ ++unsigned int ++DRIMODGetFenceCapabilities(struct DRISUPScreen *psPVRScreen) ++{ ++ return PVRDRIGetFenceCapabilities(psPVRScreen->psImpl); ++} ++ ++void * ++DRIMODCreateFenceFD(struct DRISUPContext *psPVRContext, int iFD) ++{ ++ return PVRDRICreateFenceFd(psPVRContext->eAPI, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, iFD); ++} ++ ++int ++DRIMODGetFenceFD(struct DRISUPScreen *psPVRScreen, void *pvFence) ++{ ++ (void) psPVRScreen; ++ ++ return PVRDRIGetFenceFd(pvFence); ++} ++ ++unsigned int ++DRIMODGetNumAPIProcs(struct DRISUPScreen *psPVRScreen, PVRDRIAPIType eAPI) ++{ ++ (void) psPVRScreen; ++ ++ return PVRDRIGetNumAPIFuncs(eAPI); ++} ++ ++const char * ++DRIMODGetAPIProcName(struct DRISUPScreen *psPVRScreen, PVRDRIAPIType eAPI, ++ unsigned int uIndex) ++{ ++ (void) psPVRScreen; ++ ++ return PVRDRIGetAPIFunc(eAPI, uIndex); ++} ++ ++void * ++DRIMODGetAPIProcAddress(struct DRISUPScreen *psPVRScreen, PVRDRIAPIType eAPI, ++ unsigned int uIndex) ++{ ++ const char *pszFunc; ++ void *pvHandle; ++ void *pvFunc; ++ const char *pszError; ++ ++ pszFunc = PVRDRIGetAPIFunc(eAPI, uIndex); ++ if (!pszFunc) { ++ __driUtilMessage("%s: No Proc for API %u at index %u", ++ __func__, (unsigned int) eAPI, uIndex); ++ return NULL; ++ } ++ ++ pvHandle = PVRDRIEGLGetLibHandle(eAPI, psPVRScreen->psImpl); ++ if (!pvHandle) { ++ __driUtilMessage("%s: No library handle for API %u", ++ __func__, (unsigned int) eAPI); ++ return NULL; ++ } ++ ++ (void) dlerror(); ++ pvFunc = dlsym(pvHandle, pszFunc); ++ pszError = dlerror(); ++ if (pszError) ++ pvFunc = PVRDRIEGLGetProcAddress(eAPI, psPVRScreen->psImpl, pszFunc); ++ ++ return pvFunc; ++} ++ ++void ++DRIMODSetDamageRegion(struct DRISUPDrawable *psDRISUPDrawable, ++ unsigned int uNRects, int *piRects) ++{ ++ (void) psDRISUPDrawable; ++ (void) uNRects; ++ (void) piRects; ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrimage_mod.c b/src/mesa/drivers/dri/pvr/pvrimage_mod.c +new file mode 100644 +index 00000000000..df4a7f4d6fb +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrimage_mod.c +@@ -0,0 +1,1282 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++ ++#include "util/u_atomic.h" ++#include ++ ++#include "img_drm_fourcc.h" ++#include "pvrdri_mod.h" ++ ++struct PVRDRIImageShared { ++ int iRefCount; ++ ++ struct DRISUPScreen *psPVRScreen; ++ ++ PVRDRIImageType eType; ++ const PVRDRIImageFormat *psFormat; ++ IMG_YUV_COLORSPACE eColourSpace; ++ IMG_YUV_CHROMA_INTERP eChromaUInterp; ++ IMG_YUV_CHROMA_INTERP eChromaVInterp; ++ ++ PVRDRIBufferImpl *psBuffer; ++ IMGEGLImage *psEGLImage; ++ PVRDRIEGLImageType eglImageType; ++ struct PVRDRIImageShared *psAncestor; ++}; ++ ++struct __DRIimageRec { ++ int iRefCount; ++ ++ void *pvLoaderPrivate; ++ ++ struct PVRDRIImageShared *psShared; ++ ++ IMGEGLImage *psEGLImage; ++}; ++ ++ ++static struct PVRDRIImageShared * ++CommonImageSharedSetup(struct DRISUPScreen *psPVRScreen, ++ PVRDRIImageType eType) ++{ ++ struct PVRDRIImageShared *psShared; ++ ++ psShared = calloc(1, sizeof(*psShared)); ++ if (!psShared) ++ return NULL; ++ ++ psShared->psPVRScreen = psPVRScreen; ++ psShared->eType = eType; ++ psShared->iRefCount = 1; ++ ++ assert(psShared->eColourSpace == IMG_COLORSPACE_UNDEFINED && ++ psShared->eChromaUInterp == IMG_CHROMA_INTERP_UNDEFINED && ++ psShared->eChromaVInterp == IMG_CHROMA_INTERP_UNDEFINED); ++ ++ return psShared; ++} ++ ++static void ++DestroyImageShared(struct PVRDRIImageShared *psShared) ++{ ++ int iRefCount = p_atomic_dec_return(&psShared->iRefCount); ++ ++ assert(iRefCount >= 0); ++ ++ if (iRefCount > 0) ++ return; ++ ++ switch (psShared->eType) { ++ case PVRDRI_IMAGE_FROM_NAMES: ++ case PVRDRI_IMAGE_FROM_DMABUFS: ++ case PVRDRI_IMAGE: ++ if (psShared->psBuffer) ++ PVRDRIBufferDestroy(psShared->psBuffer); ++ ++ assert(!psShared->psAncestor); ++ break; ++ case PVRDRI_IMAGE_FROM_EGLIMAGE: { ++ PVRDRIScreenImpl *psScreenImpl; ++ ++ psScreenImpl = psShared->psPVRScreen->psImpl; ++ ++ PVRDRIEGLImageDestroyExternal(psScreenImpl, ++ psShared->psEGLImage, ++ psShared->eglImageType); ++ break; ++ } ++ case PVRDRI_IMAGE_SUBIMAGE: ++ if (psShared->psBuffer) ++ PVRDRIBufferDestroy(psShared->psBuffer); ++ ++ if (psShared->psAncestor) ++ DestroyImageShared(psShared->psAncestor); ++ break; ++ default: ++ errorMessage("%s: Unknown image type: %d", ++ __func__, (int) psShared->eType); ++ break; ++ } ++ ++ free(psShared); ++} ++ ++static struct PVRDRIImageShared * ++CreateImageSharedFromEGLImage(struct DRISUPScreen *psPVRScreen, ++ IMGEGLImage *psEGLImage, ++ PVRDRIEGLImageType eglImageType) ++{ ++ struct PVRDRIImageShared *psShared; ++ PVRDRIBufferAttribs sAttribs; ++ const PVRDRIImageFormat *psFormat; ++ ++ PVRDRIEGLImageGetAttribs(psEGLImage, &sAttribs); ++ ++ psFormat = PVRDRIIMGPixelFormatToImageFormat(psPVRScreen, ++ sAttribs.ePixFormat); ++ if (!psFormat) ++ return NULL; ++ ++ psShared = CommonImageSharedSetup(psPVRScreen, PVRDRI_IMAGE_FROM_EGLIMAGE); ++ if (!psShared) ++ return NULL; ++ ++ psShared->psEGLImage = psEGLImage; ++ psShared->psFormat = psFormat; ++ psShared->eglImageType = eglImageType; ++ ++ return psShared; ++} ++ ++static struct PVRDRIImageShared * ++CreateImageSharedFromNames(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piNames, int iNumNames, ++ int *piStrides, int *piOffsets) ++{ ++ struct PVRDRIImageShared *psShared; ++ const PVRDRIImageFormat *psFormat; ++ int aiPlaneNames[DRI_PLANES_MAX]; ++ unsigned int auiWidthShift[DRI_PLANES_MAX]; ++ unsigned int auiHeightShift[DRI_PLANES_MAX]; ++ unsigned int i; ++ ++ psFormat = PVRDRIFourCCToImageFormat(psPVRScreen, iFourCC); ++ if (!psFormat) { ++ errorMessage("%s: Unsupported DRI FourCC (fourcc = 0x%X)", ++ __func__, iFourCC); ++ return NULL; ++ } ++ ++ if (iNumNames != 1 && iNumNames != (int) psFormat->uiNumPlanes) { ++ errorMessage("%s: Unexpected number of names (%d) for fourcc " ++ "(#%x) - expected 1 or %u", ++ __func__, iNumNames, iFourCC, psFormat->uiNumPlanes); ++ return NULL; ++ } ++ ++ for (i = 0; i < psFormat->uiNumPlanes; i++) { ++ if (piOffsets[i] < 0) { ++ errorMessage("%s: Offset %d unsupported (value = %d)", ++ __func__, i, piOffsets[i]); ++ return NULL; ++ } ++ ++ aiPlaneNames[i] = iNumNames == 1 ? piNames[0] : piNames[i]; ++ auiWidthShift[i] = psFormat->sPlanes[i].uiWidthShift; ++ auiHeightShift[i] = psFormat->sPlanes[i].uiHeightShift; ++ } ++ ++ psShared = ++ CommonImageSharedSetup(psPVRScreen, PVRDRI_IMAGE_FROM_NAMES); ++ if (!psShared) ++ return NULL; ++ ++ psShared->psBuffer = PVRDRIBufferCreateFromNames(psPVRScreen->psImpl, ++ iWidth, iHeight, ++ psFormat->uiNumPlanes, ++ aiPlaneNames, ++ piStrides, piOffsets, ++ auiWidthShift, ++ auiHeightShift); ++ if (!psShared->psBuffer) { ++ errorMessage("%s: Failed to create buffer for shared image", ++ __func__); ++ goto ErrorDestroyImage; ++ } ++ ++ psShared->psFormat = psFormat; ++ psShared->eColourSpace = ++ PVRDRIToIMGColourSpace(psFormat, ++ PVRDRI_YUV_COLOR_SPACE_UNDEFINED, ++ PVRDRI_YUV_RANGE_UNDEFINED); ++ psShared->eChromaUInterp = ++ PVRDRIChromaSittingToIMGInterp(psFormat, ++ PVRDRI_YUV_CHROMA_SITING_UNDEFINED); ++ psShared->eChromaVInterp = ++ PVRDRIChromaSittingToIMGInterp(psFormat, ++ PVRDRI_YUV_CHROMA_SITING_UNDEFINED); ++ ++ return psShared; ++ ++ErrorDestroyImage: ++ DestroyImageShared(psShared); ++ ++ return NULL; ++} ++ ++static struct PVRDRIImageShared * ++CreateImageSharedFromDMABufs(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, ++ int iFourCC, uint64_t uModifier, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError) ++{ ++ struct PVRDRIImageShared *psShared; ++ const PVRDRIImageFormat *psFormat; ++ int aiPlaneFDs[DRI_PLANES_MAX]; ++ unsigned int auiWidthShift[DRI_PLANES_MAX]; ++ unsigned int auiHeightShift[DRI_PLANES_MAX]; ++ unsigned int i; ++ ++ psFormat = PVRDRIFourCCToImageFormat(psPVRScreen, iFourCC); ++ if (!psFormat) { ++ errorMessage("%s: Unsupported DRI FourCC (fourcc = 0x%X)", ++ __func__, iFourCC); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_MATCH; ++ return NULL; ++ } ++ ++ /* When a modifier isn't specified, skip the validation */ ++ if (uModifier != DRM_FORMAT_MOD_INVALID) { ++ /* ++ * The modifier validation has to be done in this "higher" level ++ * function instead of pvr_dri_support. The support for modifiers is ++ * done on per format basis, but there is no way to pass the format ++ * information down to the plane creation API in pvr_dri_support. ++ */ ++ if (!PVRDRIValidateImageModifier(psPVRScreen, iFourCC, uModifier)) { ++ errorMessage("%s: Unsupported mod (fmt = %#x, mod = %#llx", ++ __func__, iFourCC, ++ (long long unsigned int) uModifier); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_MATCH; ++ return NULL; ++ } ++ } ++ ++ if (iNumFDs != 1 && iNumFDs != (int) psFormat->uiNumPlanes) { ++ errorMessage("%s: Unexpected number of FDs (%d) for fourcc " ++ "(#%x) - expected 1 or %u", ++ __func__, iNumFDs, iFourCC, psFormat->uiNumPlanes); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_MATCH; ++ return NULL; ++ } ++ ++ for (i = 0; i < psFormat->uiNumPlanes; i++) { ++ if (piOffsets[i] < 0) { ++ errorMessage("%s: Offset %d unsupported (value = %d)", ++ __func__, i, piOffsets[i]); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ACCESS; ++ return NULL; ++ } ++ ++ aiPlaneFDs[i] = iNumFDs == 1 ? piFDs[0] : piFDs[i]; ++ auiWidthShift[i] = psFormat->sPlanes[i].uiWidthShift; ++ auiHeightShift[i] = psFormat->sPlanes[i].uiHeightShift; ++ } ++ ++ psShared = CommonImageSharedSetup(psPVRScreen, ++ PVRDRI_IMAGE_FROM_DMABUFS); ++ if (!psShared) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psShared->psBuffer = ++ PVRDRIBufferCreateFromFdsWithModifier(psPVRScreen->psImpl, ++ iWidth, iHeight, uModifier, ++ psFormat->uiNumPlanes, aiPlaneFDs, ++ piStrides, piOffsets, ++ auiWidthShift, auiHeightShift); ++ if (!psShared->psBuffer) { ++ errorMessage("%s: Failed to create buffer for shared image", ++ __func__); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ goto ErrorDestroyImage; ++ } ++ ++ psShared->psFormat = psFormat; ++ psShared->eColourSpace = PVRDRIToIMGColourSpace(psFormat, uColorSpace, ++ uSampleRange); ++ psShared->eChromaUInterp = PVRDRIChromaSittingToIMGInterp(psFormat, ++ uHorizSiting); ++ psShared->eChromaVInterp = PVRDRIChromaSittingToIMGInterp(psFormat, ++ uVertSiting); ++ ++ *puError = PVRDRI_IMAGE_ERROR_SUCCESS; ++ ++ return psShared; ++ ++ErrorDestroyImage: ++ DestroyImageShared(psShared); ++ ++ return NULL; ++} ++ ++static struct PVRDRIImageShared * ++CreateImageShared(struct DRISUPScreen *psPVRScreen, int iWidth, int iHeight, ++ int iFourCC, unsigned int use, int *piStride) ++{ ++ struct PVRDRIImageShared *psShared; ++ const PVRDRIImageFormat *psFormat; ++ unsigned int uStride; ++ unsigned int uBPP; ++ ++ if ((use & PVDRI_BUFFER_USE_CURSOR) ++ && (use & PVDRI_BUFFER_USE_SCANOUT)) { ++ return NULL; ++ } ++ ++ psFormat = PVRDRIFourCCToImageFormat(psPVRScreen, iFourCC); ++ if (!psFormat) { ++ errorMessage("%s: Unsupported DRI image format (format = 0x%X)", ++ __func__, iFourCC); ++ return NULL; ++ } ++ ++ if (psFormat->uiNumPlanes != 1) { ++ errorMessage("%s: Only single plane formats are supported (format 0x%X has %u planes)", ++ __func__, iFourCC, psFormat->uiNumPlanes); ++ return NULL; ++ } ++ ++ uBPP = PVRDRIPixFmtGetBPP(psFormat->eIMGPixelFormat); ++ ++ psShared = CommonImageSharedSetup(psPVRScreen, PVRDRI_IMAGE); ++ if (!psShared) ++ return NULL; ++ ++ psShared->psBuffer = ++ PVRDRIBufferCreate(psPVRScreen->psImpl, iWidth, iHeight, uBPP, use, ++ &uStride); ++ if (!psShared->psBuffer) { ++ errorMessage("%s: Failed to create buffer", __func__); ++ goto ErrorDestroyImage; ++ } ++ ++ psShared->psFormat = psFormat; ++ ++ *piStride = uStride; ++ ++ return psShared; ++ ++ErrorDestroyImage: ++ DestroyImageShared(psShared); ++ ++ return NULL; ++} ++ ++static struct PVRDRIImageShared * ++CreateImageSharedWithModifiers(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, int iFourCC, ++ const uint64_t *puModifiers, ++ unsigned int uModifierCount, int *piStride) ++{ ++ struct PVRDRIImageShared *psShared; ++ const PVRDRIImageFormat *psFormat; ++ unsigned int uStride; ++ ++ psFormat = PVRDRIFourCCToImageFormat(psPVRScreen, iFourCC); ++ if (!psFormat) { ++ errorMessage("%s: Unsupported DRI image format (format = 0x%X)", ++ __func__, iFourCC); ++ return NULL; ++ } ++ ++ psShared = CommonImageSharedSetup(psPVRScreen, PVRDRI_IMAGE); ++ if (!psShared) ++ return NULL; ++ ++ psShared->psBuffer = ++ PVRDRIBufferCreateWithModifiers(psPVRScreen->psImpl, iWidth, iHeight, ++ psFormat->iDRIFourCC, ++ psFormat->eIMGPixelFormat, ++ puModifiers, uModifierCount, &uStride); ++ if (!psShared->psBuffer) { ++ errorMessage("%s: Failed to create buffer", __func__); ++ goto ErrorDestroyImage; ++ } ++ ++ psShared->psFormat = psFormat; ++ ++ *piStride = uStride; ++ ++ return psShared; ++ ++ErrorDestroyImage: ++ DestroyImageShared(psShared); ++ ++ return NULL; ++} ++ ++static struct PVRDRIImageShared * ++RefImageShared(struct PVRDRIImageShared *psShared) ++{ ++ int iRefCount = p_atomic_inc_return(&psShared->iRefCount); ++ ++ (void) iRefCount; ++ assert(iRefCount > 1); ++ ++ return psShared; ++} ++ ++static struct PVRDRIImageShared * ++CreateImageSharedForSubImage(struct PVRDRIImageShared *psParent, int iPlane) ++{ ++ struct PVRDRIImageShared *psShared; ++ struct PVRDRIImageShared *psAncestor; ++ PVRDRIBufferImpl *psBuffer = NULL; ++ IMG_PIXFMT eIMGPixelFormat; ++ ++ /* Sub-images represent a single plane in the parent image */ ++ if (!psParent->psBuffer) ++ return NULL; ++ ++ /* ++ * The ancestor image is the owner of the original buffer that will back ++ * the new image. The parent image may be a child of that image itself. The ++ * ancestor image must not be destroyed until all the child images that ++ * refer to it have been destroyed. A reference will be taken on the ++ * ancestor to ensure that is the case. We must distinguish between the ++ * parent's buffer and the ancestor's buffer. For example, plane 0 in the ++ * parent is not necessarily plane 0 in the ancestor. ++ */ ++ psAncestor = psParent; ++ if (psAncestor->psAncestor) { ++ psAncestor = psAncestor->psAncestor; ++ ++ assert(!psAncestor->psAncestor); ++ } ++ ++ psBuffer = PVRDRISubBufferCreate(psParent->psPVRScreen->psImpl, ++ psParent->psBuffer, iPlane); ++ if (!psBuffer) ++ return NULL; ++ ++ psShared = CommonImageSharedSetup(NULL, PVRDRI_IMAGE_SUBIMAGE); ++ if (!psShared) ++ goto ErrorDestroyBuffer; ++ ++ psShared->psAncestor = RefImageShared(psAncestor); ++ psShared->psBuffer = psBuffer; ++ psShared->psPVRScreen = psParent->psPVRScreen; ++ ++ eIMGPixelFormat = psParent->psFormat->sPlanes[iPlane].eIMGPixelFormat; ++ ++ psShared->psFormat = ++ PVRDRIIMGPixelFormatToImageFormat(psParent->psPVRScreen, ++ eIMGPixelFormat); ++ ++ assert(psShared->psFormat); ++ ++ return psShared; ++ ++ErrorDestroyBuffer: ++ PVRDRIBufferDestroy(psBuffer); ++ return NULL; ++} ++ ++static __DRIimage * ++CommonImageSetup(void *pvLoaderPrivate) ++{ ++ __DRIimage *psImage; ++ ++ psImage = calloc(1, sizeof(*psImage)); ++ if (!psImage) ++ return NULL; ++ ++ psImage->pvLoaderPrivate = pvLoaderPrivate; ++ psImage->iRefCount = 1; ++ ++ return psImage; ++} ++ ++void ++DRIMODDestroyImage(__DRIimage *psImage) ++{ ++ int iRefCount = p_atomic_dec_return(&psImage->iRefCount); ++ ++ assert(iRefCount >= 0); ++ ++ if (iRefCount > 0) ++ return; ++ ++ if (psImage->psShared) ++ DestroyImageShared(psImage->psShared); ++ ++ PVRDRIEGLImageFree(psImage->psEGLImage); ++ free(psImage); ++} ++ ++__DRIimage * ++DRIMODCreateImageFromName(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, int iFourCC, int iName, ++ int iPitch, void *pvLoaderPrivate) ++{ ++ const PVRDRIImageFormat *psFormat; ++ int iStride; ++ int iOffset; ++ ++ psFormat = PVRDRIFourCCToImageFormat(psPVRScreen, iFourCC); ++ if (!psFormat) { ++ errorMessage("%s: Unsupported DRI image FourCC (format = 0x%X)", ++ __func__, iFourCC); ++ return NULL; ++ } ++ ++ iStride = iPitch * PVRDRIPixFmtGetBlockSize(psFormat->eIMGPixelFormat); ++ iOffset = 0; ++ ++ return DRIMODCreateImageFromNames(psPVRScreen, iWidth, iHeight, iFourCC, ++ &iName, 1, &iStride, &iOffset, ++ pvLoaderPrivate); ++} ++ ++__DRIimage * ++DRIMODCreateImageFromRenderBuffer2(struct DRISUPContext *psPVRContext, ++ int iRenderBuffer, void *pvLoaderPrivate, ++ unsigned int *puError) ++{ ++ struct DRISUPScreen *psPVRScreen = psPVRContext->psPVRScreen; ++ unsigned int uError; ++ IMGEGLImage *psEGLImage; ++ __DRIimage *psImage; ++ ++ psImage = CommonImageSetup(pvLoaderPrivate); ++ if (!psImage) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psEGLImage = PVRDRIEGLImageCreate(); ++ if (!psEGLImage) { ++ DRIMODDestroyImage(psImage); ++ ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ uError = PVRDRIGetImageSource(psPVRContext->eAPI, psPVRScreen->psImpl, ++ psPVRContext->psImpl, PVRDRI_GL_RENDERBUFFER, ++ (uintptr_t) iRenderBuffer, 0, psEGLImage); ++ if (uError != PVRDRI_IMAGE_ERROR_SUCCESS) { ++ PVRDRIEGLImageFree(psEGLImage); ++ DRIMODDestroyImage(psImage); ++ ++ *puError = uError; ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psEGLImage, psImage); ++ ++ /* ++ * We can't destroy the image after this point, as the ++ * renderbuffer now has a reference to it. ++ */ ++ psImage->psShared = ++ CreateImageSharedFromEGLImage(psPVRScreen, psEGLImage, ++ PVRDRI_EGLIMAGE_IMGEGL); ++ if (!psImage->psShared) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psImage->psEGLImage = PVRDRIEGLImageDup(psImage->psShared->psEGLImage); ++ if (!psImage->psEGLImage) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psImage->iRefCount++; ++ ++ *puError = PVRDRI_IMAGE_ERROR_SUCCESS; ++ return psImage; ++} ++ ++ ++__DRIimage * ++DRIMODCreateImageFromRenderbuffer(struct DRISUPContext *psPVRContext, ++ int iRenderBuffer, void *pvLoaderPrivate) ++{ ++ unsigned int uError; ++ ++ return DRIMODCreateImageFromRenderBuffer2(psPVRContext, iRenderBuffer, ++ pvLoaderPrivate, &uError); ++} ++ ++__DRIimage * ++DRIMODCreateImage(struct DRISUPScreen *psPVRScreen, int iWidth, int iHeight, ++ int iFourCC, unsigned int uUse, void *pvLoaderPrivate) ++{ ++ __DRIimage *psImage; ++ struct PVRDRIImageShared *psShared; ++ IMG_PIXFMT eIMGPixelFormat; ++ int iStride; ++ ++ psImage = CommonImageSetup(pvLoaderPrivate); ++ if (!psImage) ++ return NULL; ++ ++ psShared = CreateImageShared(psPVRScreen, iWidth, iHeight, iFourCC, uUse, ++ &iStride); ++ if (!psShared) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ psImage->psShared = psShared; ++ eIMGPixelFormat = psShared->psFormat->eIMGPixelFormat; ++ ++ psImage->psEGLImage = ++ PVRDRIEGLImageCreateFromBuffer(iWidth, iHeight, iStride, ++ eIMGPixelFormat, psShared->eColourSpace, ++ psShared->eChromaUInterp, ++ psShared->eChromaVInterp, ++ psShared->psBuffer); ++ if (!psImage->psEGLImage) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psImage->psEGLImage, psImage); ++ ++ return psImage; ++} ++ ++__DRIimage * ++DRIMODCreateImageWithModifiers(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, int iFourCC, ++ const uint64_t *puModifiers, ++ const unsigned int uModifierCount, ++ void *pvLoaderPrivate) ++{ ++ __DRIimage *psImage; ++ struct PVRDRIImageShared *psShared; ++ IMG_PIXFMT eIMGPixelFormat; ++ int iStride; ++ ++ psImage = CommonImageSetup(pvLoaderPrivate); ++ if (!psImage) ++ return NULL; ++ ++ psShared = CreateImageSharedWithModifiers(psPVRScreen, ++ iWidth, iHeight, iFourCC, ++ puModifiers, uModifierCount, ++ &iStride); ++ if (!psShared) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ psImage->psShared = psShared; ++ eIMGPixelFormat = psShared->psFormat->eIMGPixelFormat; ++ ++ psImage->psEGLImage = ++ PVRDRIEGLImageCreateFromBuffer(iWidth, iHeight, iStride, ++ eIMGPixelFormat, psShared->eColourSpace, ++ psShared->eChromaUInterp, ++ psShared->eChromaVInterp, ++ psShared->psBuffer); ++ if (!psImage->psEGLImage) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psImage->psEGLImage, psImage); ++ ++ return psImage; ++} ++ ++bool ++DRIMODQueryImage(__DRIimage *psImage, int attrib, int *value_ptr) ++{ ++ struct PVRDRIImageShared *psShared = psImage->psShared; ++ PVRDRIBufferAttribs sAttribs; ++ int value; ++ uint64_t ulValue; ++ ++ PVRDRIEGLImageGetAttribs(psImage->psEGLImage, &sAttribs); ++ ++ if (attrib == PVRDRI_IMAGE_ATTRIB_HANDLE || ++ attrib == PVRDRI_IMAGE_ATTRIB_NAME || ++ attrib == PVRDRI_IMAGE_ATTRIB_FD || ++ attrib == PVRDRI_IMAGE_ATTRIB_OFFSET) { ++ if (!psShared->psFormat) ++ return false; ++ ++ switch (psShared->psFormat->iDRIComponents) { ++ case PVRDRI_IMAGE_COMPONENTS_R: ++ case PVRDRI_IMAGE_COMPONENTS_RG: ++ case PVRDRI_IMAGE_COMPONENTS_RGB: ++ case PVRDRI_IMAGE_COMPONENTS_RGBA: ++ case PVRDRI_IMAGE_COMPONENTS_EXTERNAL: ++ break; ++ default: ++ return false; ++ } ++ } ++ ++ switch (attrib) { ++ case PVRDRI_IMAGE_ATTRIB_STRIDE: ++ *value_ptr = sAttribs.uiStrideInBytes; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_HANDLE: ++ value = PVRDRIBufferGetHandle(psShared->psBuffer); ++ if (value == -1) ++ return false; ++ ++ *value_ptr = value; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_NAME: ++ value = PVRDRIBufferGetName(psShared->psBuffer); ++ if (value == -1) ++ return false; ++ ++ *value_ptr = value; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_FORMAT: ++ /* The caller should use PVRDRI_IMAGE_ATTRIB_FOURCC, and convert. */ ++ return false; ++ case PVRDRI_IMAGE_ATTRIB_WIDTH: ++ *value_ptr = sAttribs.uiWidth; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_HEIGHT: ++ *value_ptr = sAttribs.uiHeight; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_COMPONENTS: ++ if (!psShared->psFormat || !psShared->psFormat->iDRIComponents) ++ return false; ++ ++ *value_ptr = psShared->psFormat->iDRIComponents; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_FD: ++ value = PVRDRIBufferGetFd(psShared->psBuffer); ++ if (value == -1) ++ return false; ++ ++ *value_ptr = value; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_FOURCC: ++ *value_ptr = psShared->psFormat->iDRIFourCC; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_NUM_PLANES: ++ *value_ptr = (int) psShared->psFormat->uiNumPlanes; ++ break; ++ case PVRDRI_IMAGE_ATTRIB_OFFSET: ++ *value_ptr = PVRDRIBufferGetOffset(psShared->psBuffer); ++ break; ++ case PVRDRI_IMAGE_ATTRIB_MODIFIER_LOWER: ++ ulValue = PVRDRIBufferGetModifier(psShared->psBuffer); ++ *value_ptr = (int) (ulValue & 0xffffffff); ++ break; ++ case PVRDRI_IMAGE_ATTRIB_MODIFIER_UPPER: ++ ulValue = PVRDRIBufferGetModifier(psShared->psBuffer); ++ *value_ptr = (int) ((ulValue >> 32) & 0xffffffff); ++ break; ++ default: ++ return false; ++ } ++ ++ return true; ++} ++ ++__DRIimage * ++DRIMODDupImage(__DRIimage *psSrc, void *pvLoaderPrivate) ++{ ++ __DRIimage *psDst; ++ ++ psDst = CommonImageSetup(pvLoaderPrivate); ++ if (!psDst) ++ return NULL; ++ ++ psDst->psShared = RefImageShared(psSrc->psShared); ++ ++ psDst->psEGLImage = PVRDRIEGLImageDup(psSrc->psEGLImage); ++ if (!psDst->psEGLImage) { ++ DRIMODDestroyImage(psDst); ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psDst->psEGLImage, psDst); ++ ++ return psDst; ++} ++ ++bool ++DRIMODValidateImageUsage(__DRIimage *psImage, unsigned int uUse) ++{ ++ struct PVRDRIImageShared *psShared = psImage->psShared; ++ ++ if (uUse & (PVDRI_BUFFER_USE_SCANOUT | PVDRI_BUFFER_USE_CURSOR)) { ++ uint64_t uModifier; ++ ++ /* ++ * We are extra strict in this case as an application may ask for a ++ * handle so that the memory can be wrapped as a framebuffer/used as a ++ * cursor and this can only be done on a card node. ++ */ ++ if (drmGetNodeTypeFromFd(psShared->psPVRScreen->iFD) != DRM_NODE_PRIMARY) ++ return false; ++ ++ uModifier = PVRDRIBufferGetModifier(psShared->psBuffer); ++ if (uModifier != DRM_FORMAT_MOD_INVALID && ++ uModifier != DRM_FORMAT_MOD_LINEAR) ++ return false; ++ } else if (uUse & (PVDRI_BUFFER_USE_SHARE)) { ++ /* ++ * We are less strict in this case as it's possible to share buffers ++ * using prime (but not flink) on a render node so we only need to know ++ * whether or not the FD belongs to the display. ++ */ ++ if (PVRDRIGetDeviceTypeFromFd(psShared->psPVRScreen->iFD) != ++ PVRDRI_DEVICE_TYPE_DISPLAY) ++ return false; ++ } ++ ++ return true; ++} ++ ++__DRIimage * ++DRIMODCreateImageFromNames(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piNames, int iNumNames, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate) ++{ ++ __DRIimage *psImage; ++ struct PVRDRIImageShared *psShared; ++ IMG_PIXFMT eIMGPixelFormat; ++ int iStride; ++ ++ psImage = CommonImageSetup(pvLoaderPrivate); ++ if (!psImage) ++ return NULL; ++ ++ psShared = CreateImageSharedFromNames(psPVRScreen, ++ iWidth, iHeight, iFourCC, ++ piNames, iNumNames, ++ piStrides, piOffsets); ++ if (!psShared) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ psImage->psShared = psShared; ++ eIMGPixelFormat = psShared->psFormat->eIMGPixelFormat; ++ ++ if (psShared->psFormat->uiNumPlanes == 1) ++ iStride = piStrides[0]; ++ else ++ iStride = iWidth * PVRDRIPixFmtGetBlockSize(eIMGPixelFormat); ++ ++ psImage->psEGLImage = ++ PVRDRIEGLImageCreateFromBuffer(iWidth, iHeight, iStride, ++ eIMGPixelFormat, psShared->eColourSpace, ++ psShared->eChromaUInterp, ++ psShared->eChromaVInterp, ++ psShared->psBuffer); ++ if (!psImage->psEGLImage) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psImage->psEGLImage, psImage); ++ ++ return psImage; ++} ++ ++__DRIimage * ++DRIMODFromPlanar(__DRIimage *psSrc, int iPlane, void *pvLoaderPrivate) ++{ ++ __DRIimage *psDst; ++ struct PVRDRIImageShared *psShared; ++ ++ psDst = CommonImageSetup(pvLoaderPrivate); ++ if (!psDst) ++ return NULL; ++ ++ psShared = CreateImageSharedForSubImage(psSrc->psShared, iPlane); ++ if (!psShared) { ++ if (iPlane != 0) { ++ errorMessage("%s: plane %d not supported", __func__, iPlane); ++ } else { ++ psDst->psShared = RefImageShared(psSrc->psShared); ++ psDst->psEGLImage = PVRDRIEGLImageDup(psSrc->psEGLImage); ++ } ++ } else { ++ IMG_PIXFMT eIMGPixelFormat; ++ ++ psDst->psShared = psShared; ++ eIMGPixelFormat = psShared->psFormat->eIMGPixelFormat; ++ ++ psDst->psEGLImage = ++ PVRDRIEGLImageCreateFromSubBuffer(eIMGPixelFormat, psShared->psBuffer); ++ } ++ ++ if (!psDst->psEGLImage) { ++ DRIMODDestroyImage(psDst); ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psDst->psEGLImage, psDst); ++ ++ return psDst; ++} ++ ++__DRIimage * ++DRIMODCreateImageFromTexture(struct DRISUPContext *psPVRContext, int iTarget, ++ unsigned int uTexture, int iDepth, int iLevel, ++ unsigned int *puError, void *pvLoaderPrivate) ++{ ++ IMGEGLImage *psEGLImage; ++ __DRIimage *psImage; ++ uint32_t iEGLTarget; ++ unsigned int uError; ++ ++ switch (iTarget) { ++ case PVRDRI_GL_TEXTURE_2D: ++ iEGLTarget = iTarget; ++ break; ++ case PVRDRI_GL_TEXTURE_CUBE_MAP_POSITIVE_X: ++ iEGLTarget = iTarget + iDepth; ++ break; ++ default: ++ errorMessage("%s: EGL GL texture %d is not supported", ++ __func__, iTarget); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_PARAMETER; ++ return NULL; ++ } ++ ++ psImage = CommonImageSetup(pvLoaderPrivate); ++ if (!psImage) ++ return NULL; ++ ++ psEGLImage = PVRDRIEGLImageCreate(); ++ if (!psEGLImage) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ uError = PVRDRIGetImageSource(psPVRContext->eAPI, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, iEGLTarget, uTexture, ++ iLevel, psEGLImage); ++ *puError = uError; ++ ++ if (uError != PVRDRI_IMAGE_ERROR_SUCCESS) { ++ PVRDRIEGLImageFree(psEGLImage); ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psEGLImage, psImage); ++ ++ /* ++ * We can't destroy the image after this point, as the texture now has a ++ * reference to it. ++ */ ++ psImage->psShared = ++ CreateImageSharedFromEGLImage(psPVRContext->psPVRScreen, psEGLImage, ++ PVRDRI_EGLIMAGE_IMGEGL); ++ if (!psImage->psShared) ++ return NULL; ++ ++ psImage->psEGLImage = PVRDRIEGLImageDup(psImage->psShared->psEGLImage); ++ if (!psImage->psEGLImage) ++ return NULL; ++ ++ psImage->iRefCount++; ++ ++ return psImage; ++} ++ ++__DRIimage * ++DRIMODCreateImageFromFDs(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ void *pvLoaderPrivate) ++{ ++ unsigned int uError; ++ ++ return DRIMODCreateImageFromDMABufs(psPVRScreen, iWidth, iHeight, iFourCC, ++ piFDs, iNumFDs, piStrides, piOffsets, ++ PVRDRI_YUV_COLOR_SPACE_UNDEFINED, ++ PVRDRI_YUV_RANGE_UNDEFINED, ++ PVRDRI_YUV_CHROMA_SITING_UNDEFINED, ++ PVRDRI_YUV_CHROMA_SITING_UNDEFINED, ++ &uError, pvLoaderPrivate); ++} ++ ++__DRIimage * ++DRIMODCreateImageFromBuffer(struct DRISUPContext *psPVRContext, int iTarget, ++ void *pvBuffer, unsigned int *puError, ++ void *pvLoaderPrivate) ++{ ++ IMGEGLImage *psEGLImage; ++ __DRIimage *psImage; ++ ++ switch (iTarget) { ++ case PVRDRI_CL_IMAGE_IMG: ++ break; ++ default: ++ errorMessage("%s: Target %d is not supported", __func__, iTarget); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_PARAMETER; ++ return NULL; ++ } ++ ++ psImage = CommonImageSetup(pvLoaderPrivate); ++ if (!psImage) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psEGLImage = PVRDRIEGLImageCreate(); ++ if (!psEGLImage) { ++ DRIMODDestroyImage(psImage); ++ ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ *puError = PVRDRIGetImageSource(PVRDRI_API_CL, ++ psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, iTarget, ++ (uintptr_t) pvBuffer, 0, psEGLImage); ++ if (*puError != PVRDRI_IMAGE_ERROR_SUCCESS) { ++ PVRDRIEGLImageFree(psEGLImage); ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psEGLImage, psImage); ++ ++ /* ++ * We can't destroy the image after this point, as the OCL image now has a ++ * reference to it. ++ */ ++ psImage->psShared = ++ CreateImageSharedFromEGLImage(psPVRContext->psPVRScreen, psEGLImage, ++ PVRDRI_EGLIMAGE_IMGOCL); ++ if (!psImage->psShared) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psImage->psEGLImage = PVRDRIEGLImageDup(psImage->psShared->psEGLImage); ++ if (!psImage->psEGLImage) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psImage->iRefCount++; ++ ++ *puError = PVRDRI_IMAGE_ERROR_SUCCESS; ++ ++ return psImage; ++} ++ ++__DRIimage * ++DRIMODCreateImageFromDMABufs2(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, ++ int iFourCC, uint64_t uModifier, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate) ++{ ++ __DRIimage *psImage; ++ struct PVRDRIImageShared *psShared; ++ IMG_PIXFMT eIMGPixelFormat; ++ ++ psImage = CommonImageSetup(pvLoaderPrivate); ++ if (!psImage) { ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ psShared = CreateImageSharedFromDMABufs(psPVRScreen, iWidth, iHeight, ++ iFourCC, uModifier, piFDs, iNumFDs, ++ piStrides, piOffsets, ++ uColorSpace, uSampleRange, ++ uHorizSiting, uVertSiting, ++ puError); ++ if (!psShared) { ++ DRIMODDestroyImage(psImage); ++ return NULL; ++ } ++ ++ psImage->psShared = psShared; ++ eIMGPixelFormat = psShared->psFormat->eIMGPixelFormat; ++ ++ psImage->psEGLImage = ++ PVRDRIEGLImageCreateFromBuffer(iWidth, iHeight, piStrides[0], ++ eIMGPixelFormat, psShared->eColourSpace, ++ psShared->eChromaUInterp, ++ psShared->eChromaVInterp, ++ psShared->psBuffer); ++ if (!psImage->psEGLImage) { ++ DRIMODDestroyImage(psImage); ++ *puError = PVRDRI_IMAGE_ERROR_BAD_ALLOC; ++ return NULL; ++ } ++ ++ PVRDRIEGLImageSetCallbackData(psImage->psEGLImage, psImage); ++ ++ *puError = PVRDRI_IMAGE_ERROR_SUCCESS; ++ ++ return psImage; ++} ++ ++__DRIimage * ++DRIMODCreateImageFromDMABufs(struct DRISUPScreen *psPVRScreen, ++ int iWidth, int iHeight, int iFourCC, ++ int *piFDs, int iNumFDs, ++ int *piStrides, int *piOffsets, ++ unsigned int uColorSpace, ++ unsigned int uSampleRange, ++ unsigned int uHorizSiting, ++ unsigned int uVertSiting, ++ unsigned int *puError, ++ void *pvLoaderPrivate) ++{ ++ return DRIMODCreateImageFromDMABufs2(psPVRScreen, iWidth, iHeight, ++ iFourCC, DRM_FORMAT_MOD_INVALID, ++ piFDs, iNumFDs, ++ piStrides, piOffsets, ++ uColorSpace, uSampleRange, ++ uHorizSiting, uVertSiting, ++ puError, pvLoaderPrivate); ++} ++ ++void ++PVRDRIRefImage(__DRIimage *psImage) ++{ ++ int iRefCount = p_atomic_inc_return(&psImage->iRefCount); ++ ++ (void) iRefCount; ++ assert(iRefCount > 1); ++} ++ ++void ++PVRDRIUnrefImage(__DRIimage *psImage) ++{ ++ DRIMODDestroyImage(psImage); ++} ++ ++PVRDRIImageType ++PVRDRIImageGetSharedType(__DRIimage *psImage) ++{ ++ return psImage->psShared->eType; ++} ++ ++PVRDRIBufferImpl * ++PVRDRIImageGetSharedBuffer(__DRIimage *psImage) ++{ ++ assert(psImage->psShared->eType != PVRDRI_IMAGE_FROM_EGLIMAGE); ++ ++ return psImage->psShared->psBuffer; ++} ++ ++IMGEGLImage * ++PVRDRIImageGetSharedEGLImage(__DRIimage *psImage) ++{ ++ assert(psImage->psShared->eType == PVRDRI_IMAGE_FROM_EGLIMAGE); ++ ++ return psImage->psShared->psEGLImage; ++} ++ ++IMGEGLImage * ++PVRDRIImageGetEGLImage(__DRIimage *psImage) ++{ ++ return psImage->psEGLImage; ++} ++ ++__DRIimage * ++PVRDRIScreenGetDRIImage(void *hEGLImage) ++{ ++ struct DRISUPScreen *psPVRScreen; ++ ++ psPVRScreen = DRIMODThreadGetCurrentScreen(); ++ if (!psPVRScreen) ++ return NULL; ++ ++ return MODSUPLookupEGLImage(psPVRScreen->psDRIScreen, hEGLImage, ++ psPVRScreen->pvLoaderPrivate); ++} ++ ++void ++DRIMODBlitImage(struct DRISUPContext *psPVRContext, ++ __DRIimage *psDst, __DRIimage *psSrc, ++ int iDstX0, int iDstY0, int iDstWidth, int iDstHeight, ++ int iSrcX0, int iSrcY0, int iSrcWidth, int iSrcHeight, ++ int iFlushFlag) ++{ ++ bool bRes; ++ ++ bRes = PVRDRIBlitEGLImage(psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, ++ psDst->psEGLImage, psDst->psShared->psBuffer, ++ psSrc->psEGLImage, psSrc->psShared->psBuffer, ++ iDstX0, iDstY0, iDstWidth, iDstHeight, ++ iSrcX0, iSrcY0, iSrcWidth, iSrcHeight, ++ iFlushFlag); ++ if (!bRes) ++ __driUtilMessage("%s: PVRDRIBlitEGLImage failed", __func__); ++} ++ ++int ++DRIMODGetImageCapabilities(struct DRISUPScreen *psPVRScreen) ++{ ++ (void) psPVRScreen; ++ ++ return PVRDRI_IMAGE_CAP_GLOBAL_NAMES; ++} ++ ++void * ++DRIMODMapImage(struct DRISUPContext *psPVRContext, __DRIimage *psImage, ++ int iX0, int iY0, int iWidth, int iHeight, ++ unsigned int iFlags, int *iStride, void **ppvData) ++{ ++ return PVRDRIMapEGLImage(psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, ++ psImage->psEGLImage, psImage->psShared->psBuffer, ++ iX0, iY0, iWidth, iHeight, iFlags, iStride, ++ ppvData); ++} ++ ++void ++DRIMODUnmapImage(struct DRISUPContext *psPVRContext, __DRIimage *psImage, ++ void *pvData) ++{ ++ bool bRes; ++ ++ bRes = PVRDRIUnmapEGLImage(psPVRContext->psPVRScreen->psImpl, ++ psPVRContext->psImpl, psImage->psEGLImage, ++ psImage->psShared->psBuffer, pvData); ++ if (!bRes) ++ __driUtilMessage("%s: PVRDRIUnmapEGLImage failed", __func__); ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrmesa.h b/src/mesa/drivers/dri/pvr/pvrmesa.h +new file mode 100644 +index 00000000000..5e1c9c1b2e6 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrmesa.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#if !defined(__PVRMESA_H__) ++#define __PVRMESA_H__ ++ ++#include "pvrdri.h" ++ ++void pvrdri_free_dispatch_tables(PVRDRIScreen *psPVRScreen); ++bool pvrdri_create_dispatch_table(PVRDRIScreen *psPVRScreen, ++ PVRDRIAPIType eAPI); ++void pvrdri_set_null_dispatch_table(void); ++void pvrdri_set_dispatch_table(PVRDRIContext *psPVRContext); ++ ++#endif /* !defined(__PVRMESA_H__) */ +diff --git a/src/mesa/drivers/dri/pvr/pvrutil.c b/src/mesa/drivers/dri/pvr/pvrutil.c +new file mode 100644 +index 00000000000..945e18cf220 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrutil.c +@@ -0,0 +1,239 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "drm-uapi/drm_fourcc.h" ++ ++#include "utils.h" ++#include "dri_util.h" ++#include "pvrdri.h" ++ ++#define MESSAGE_LENGTH_MAX 1024 ++ ++/* ++ * Define before including android/log.h and dlog.h as this is used by these ++ * headers. ++ */ ++#define LOG_TAG "PVR-MESA" ++ ++#if defined(HAVE_ANDROID_PLATFORM) ++#include ++#define err_printf(f, args...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, f, ##args)) ++#define dbg_printf(f, args...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, f, ##args)) ++#elif defined(HAVE_TIZEN_PLATFORM) ++#include ++#define err_printf(f, args...) LOGE(f, ##args) ++#define dbg_printf(f, args...) LOGD(f, ##args) ++#else ++#define err_printf(f, args...) fprintf(stderr, f "\n", ##args) ++#define dbg_printf(f, args...) fprintf(stderr, "LibGL: " f "\n", ##args) ++#endif /* HAVE_ANDROID_PLATFORM */ ++ ++/* Standard error message */ ++void PRINTFLIKE(1, 2) ++errorMessage(const char *f, ...) ++{ ++ char message[MESSAGE_LENGTH_MAX]; ++ va_list args; ++ ++ va_start(args, f); ++ vsnprintf(message, sizeof message, f, args); ++ va_end(args); ++ ++ err_printf("%s", message); ++} ++ ++void PRINTFLIKE(1, 2) ++__driUtilMessage(const char *f, ...) ++{ ++ char message[MESSAGE_LENGTH_MAX]; ++ va_list args; ++ ++ /* ++ * On Android and Tizen, always print messages; otherwise, only print if ++ * the environment variable LIBGL_DEBUG=verbose. ++ */ ++#if !defined(HAVE_ANDROID_PLATFORM) && !defined(HAVE_TIZEN_PLATFORM) ++ char *ev = getenv("LIBGL_DEBUG"); ++ ++ if (!ev || strcmp(ev, "verbose") != 0) ++ return; ++#endif ++ ++ va_start(args, f); ++ vsnprintf(message, sizeof message, f, args); ++ va_end(args); ++ ++ dbg_printf("%s", message); ++} ++ ++mesa_format ++PVRDRIMesaFormatToMesaFormat(int pvrdri_mesa_format) ++{ ++ switch (pvrdri_mesa_format) { ++ case PVRDRI_MESA_FORMAT_NONE: ++ return MESA_FORMAT_NONE; ++ case PVRDRI_MESA_FORMAT_B8G8R8A8_UNORM: ++ return MESA_FORMAT_B8G8R8A8_UNORM; ++ case PVRDRI_MESA_FORMAT_B8G8R8X8_UNORM: ++ return MESA_FORMAT_B8G8R8X8_UNORM; ++ case PVRDRI_MESA_FORMAT_B5G6R5_UNORM: ++ return MESA_FORMAT_B5G6R5_UNORM; ++ case PVRDRI_MESA_FORMAT_R8G8B8A8_UNORM: ++ return MESA_FORMAT_R8G8B8A8_UNORM; ++ case PVRDRI_MESA_FORMAT_R8G8B8X8_UNORM: ++ return MESA_FORMAT_R8G8B8X8_UNORM; ++ case PVRDRI_MESA_FORMAT_YCBCR: ++ return MESA_FORMAT_YCBCR; ++ case PVRDRI_MESA_FORMAT_YUV420_2PLANE: ++ return MESA_FORMAT_YUV420_2PLANE; ++ case PVRDRI_MESA_FORMAT_YVU420_2PLANE: ++ return MESA_FORMAT_YVU420_2PLANE; ++ case PVRDRI_MESA_FORMAT_B8G8R8A8_SRGB: ++ return MESA_FORMAT_B8G8R8A8_SRGB; ++ case PVRDRI_MESA_FORMAT_R8G8B8A8_SRGB: ++ return MESA_FORMAT_R8G8B8A8_SRGB; ++ default: ++ __driUtilMessage("%s: Unknown format: %d", __func__, pvrdri_mesa_format); ++ break; ++ } ++ ++ return MESA_FORMAT_NONE; ++} ++ ++int ++PVRDRIFormatToFourCC(int dri_format) ++{ ++ switch (dri_format) { ++ case __DRI_IMAGE_FORMAT_RGB565: ++ return DRM_FORMAT_RGB565; ++ case __DRI_IMAGE_FORMAT_XRGB8888: ++ return DRM_FORMAT_XRGB8888; ++ case __DRI_IMAGE_FORMAT_ARGB8888: ++ return DRM_FORMAT_ARGB8888; ++ case __DRI_IMAGE_FORMAT_ABGR8888: ++ return DRM_FORMAT_ABGR8888; ++ case __DRI_IMAGE_FORMAT_XBGR8888: ++ return DRM_FORMAT_XBGR8888; ++ case __DRI_IMAGE_FORMAT_R8: ++ return DRM_FORMAT_R8; ++ case __DRI_IMAGE_FORMAT_GR88: ++ return DRM_FORMAT_GR88; ++ case __DRI_IMAGE_FORMAT_NONE: ++ return 0; ++ case __DRI_IMAGE_FORMAT_XRGB2101010: ++ return DRM_FORMAT_XRGB2101010; ++ case __DRI_IMAGE_FORMAT_ARGB2101010: ++ return DRM_FORMAT_ARGB2101010; ++ case __DRI_IMAGE_FORMAT_SARGB8: ++ return __DRI_IMAGE_FOURCC_SARGB8888; ++ case __DRI_IMAGE_FORMAT_ARGB1555: ++ return DRM_FORMAT_ARGB1555; ++ case __DRI_IMAGE_FORMAT_R16: ++ return DRM_FORMAT_R16; ++ case __DRI_IMAGE_FORMAT_GR1616: ++ return DRM_FORMAT_GR1616; ++ case __DRI_IMAGE_FORMAT_YUYV: ++ return DRM_FORMAT_YUYV; ++ case __DRI_IMAGE_FORMAT_XBGR2101010: ++ return DRM_FORMAT_XBGR2101010; ++ case __DRI_IMAGE_FORMAT_ABGR2101010: ++ return DRM_FORMAT_ABGR2101010; ++ case __DRI_IMAGE_FORMAT_SABGR8: ++ return __DRI_IMAGE_FOURCC_SABGR8888; ++ case __DRI_IMAGE_FORMAT_UYVY: ++ return DRM_FORMAT_UYVY; ++ case __DRI_IMAGE_FORMAT_ARGB4444: ++ return DRM_FORMAT_ARGB4444; ++ case __DRI_IMAGE_FORMAT_YVU444_PACK10_IMG: ++ return DRM_FORMAT_YVU444_PACK10_IMG; ++ case __DRI_IMAGE_FORMAT_BGR888: ++ return DRM_FORMAT_BGR888; ++ default: ++ __driUtilMessage("%s: Unknown format: %d", __func__, dri_format); ++ break; ++ } ++ ++ return 0; ++} ++ ++int ++PVRDRIFourCCToDRIFormat(int iFourCC) ++{ ++ switch (iFourCC) { ++ case 0: ++ return __DRI_IMAGE_FORMAT_NONE; ++ case DRM_FORMAT_RGB565: ++ return __DRI_IMAGE_FORMAT_RGB565; ++ case DRM_FORMAT_XRGB8888: ++ return __DRI_IMAGE_FORMAT_XRGB8888; ++ case DRM_FORMAT_ARGB8888: ++ return __DRI_IMAGE_FORMAT_ARGB8888; ++ case DRM_FORMAT_ABGR8888: ++ return __DRI_IMAGE_FORMAT_ABGR8888; ++ case DRM_FORMAT_XBGR8888: ++ return __DRI_IMAGE_FORMAT_XBGR8888; ++ case DRM_FORMAT_R8: ++ return __DRI_IMAGE_FORMAT_R8; ++ case DRM_FORMAT_GR88: ++ return __DRI_IMAGE_FORMAT_GR88; ++ case DRM_FORMAT_XRGB2101010: ++ return __DRI_IMAGE_FORMAT_XRGB2101010; ++ case DRM_FORMAT_ARGB2101010: ++ return __DRI_IMAGE_FORMAT_ARGB2101010; ++ case __DRI_IMAGE_FOURCC_SARGB8888: ++ return __DRI_IMAGE_FORMAT_SARGB8; ++ case DRM_FORMAT_ARGB1555: ++ return __DRI_IMAGE_FORMAT_ARGB1555; ++ case DRM_FORMAT_R16: ++ return __DRI_IMAGE_FORMAT_R16; ++ case DRM_FORMAT_GR1616: ++ return __DRI_IMAGE_FORMAT_GR1616; ++ case DRM_FORMAT_YUYV: ++ return __DRI_IMAGE_FORMAT_YUYV; ++ case DRM_FORMAT_XBGR2101010: ++ return __DRI_IMAGE_FORMAT_XBGR2101010; ++ case DRM_FORMAT_ABGR2101010: ++ return __DRI_IMAGE_FORMAT_ABGR2101010; ++ case __DRI_IMAGE_FOURCC_SABGR8888: ++ return __DRI_IMAGE_FORMAT_SABGR8; ++ case DRM_FORMAT_UYVY: ++ return __DRI_IMAGE_FORMAT_UYVY; ++ case DRM_FORMAT_ARGB4444: ++ return __DRI_IMAGE_FORMAT_ARGB4444; ++ case DRM_FORMAT_YVU444_PACK10_IMG: ++ return __DRI_IMAGE_FORMAT_YVU444_PACK10_IMG; ++ case DRM_FORMAT_BGR888: ++ return __DRI_IMAGE_FORMAT_BGR888; ++ default: ++ __driUtilMessage("%s: Unknown format: %d", __func__, iFourCC); ++ break; ++ } ++ ++ return 0; ++} +diff --git a/src/mesa/drivers/dri/pvr/pvrutil_mod.c b/src/mesa/drivers/dri/pvr/pvrutil_mod.c +new file mode 100644 +index 00000000000..5b05eb76b01 +--- /dev/null ++++ b/src/mesa/drivers/dri/pvr/pvrutil_mod.c +@@ -0,0 +1,921 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * 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 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. ++ */ ++ ++#include ++#include ++#include ++ ++#include "img_drm_fourcc.h" ++#include "pvrdri_mod.h" ++ ++/* ++ * The following sRGB formats defined may not be defined in drm_fourcc.h, but ++ * match the corresponding __DRI_IMAGE_FOURCC formats in Mesa. ++ */ ++#if !defined(DRM_FORMAT_SARGB8888) ++#define DRM_FORMAT_SARGB8888 0x83324258 ++#endif ++ ++#if !defined(DRM_FORMAT_SABGR8888) ++#define DRM_FORMAT_SABGR8888 0x84324258 ++#endif ++ ++#if !defined(DRM_FORMAT_SBGR888) ++#define DRM_FORMAT_SBGR888 0xff324742 ++#endif ++ ++static const PVRDRIImageFormat g_asFormats[] = { ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R10G10B10A2_UNORM, ++ .iDRIFourCC = DRM_FORMAT_ABGR2101010, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGBA, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R10G10B10A2_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_B8G8R8A8_UNORM, ++ .iDRIFourCC = DRM_FORMAT_ARGB8888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGBA, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_B8G8R8A8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_B8G8R8A8_UNORM_SRGB, ++ .iDRIFourCC = DRM_FORMAT_SARGB8888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGBA, ++ .bIsSRGB = true, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_B8G8R8A8_UNORM_SRGB, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8A8_UNORM, ++ .iDRIFourCC = DRM_FORMAT_ABGR8888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGBA, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8A8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8A8_UNORM_SRGB, ++ .iDRIFourCC = DRM_FORMAT_SABGR8888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGBA, ++ .bIsSRGB = true, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8A8_UNORM_SRGB, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_B8G8R8X8_UNORM, ++ .iDRIFourCC = DRM_FORMAT_XRGB8888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGB, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_B8G8R8X8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8X8_UNORM, ++ .iDRIFourCC = DRM_FORMAT_XBGR8888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGB, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8X8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8_UNORM, ++ .iDRIFourCC = DRM_FORMAT_BGR888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGB, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++#if defined(DRM_FORMAT_SBGR888) ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8_UNORM_SRGB, ++ .iDRIFourCC = DRM_FORMAT_SBGR888, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGB, ++ .bIsSRGB = true, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8B8_UNORM_SRGB, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++#endif ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_B5G6R5_UNORM, ++ .iDRIFourCC = DRM_FORMAT_RGB565, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGB, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_B5G6R5_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8_UNORM, ++ .iDRIFourCC = DRM_FORMAT_GR88, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RG, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .iDRIFourCC = DRM_FORMAT_R8, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_R, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_L8A8_UNORM, ++ .iDRIFourCC = 0, ++ .iDRIComponents = 0, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_L8A8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_L8_UNORM, ++ .iDRIFourCC = 0, ++ .iDRIComponents = 0, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_L8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_D32_FLOAT, ++ .iDRIFourCC = 0, ++ .iDRIComponents = 0, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_D32_FLOAT, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_S8_UINT, ++ .iDRIFourCC = 0, ++ .iDRIComponents = 0, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_S8_UINT, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++#if defined(DRM_FORMAT_ARGB4444) ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_B4G4R4A4_UNORM, ++ .iDRIFourCC = DRM_FORMAT_ARGB4444, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGBA, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_B4G4R4A4_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++#endif ++#if defined(DRM_FORMAT_ARGB1555) ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_B5G5R5A1_UNORM, ++ .iDRIFourCC = DRM_FORMAT_ARGB1555, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_RGBA, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_B5G5R5A1_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++#endif ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_YUYV, ++ .iDRIFourCC = DRM_FORMAT_YUYV, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_EXTERNAL, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_YUYV, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++#if defined(DRM_FORMAT_YVU444_PACK10_IMG) ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_YVU10_444_1PLANE_PACK10, ++ .iDRIFourCC = DRM_FORMAT_YVU444_PACK10_IMG, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_EXTERNAL, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_YVU10_444_1PLANE_PACK10, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0, ++ }, ++ }, ++#endif ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_YUV420_2PLANE, ++ .iDRIFourCC = DRM_FORMAT_NV12, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_Y_UV, ++ .uiNumPlanes = 2, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ .sPlanes[1] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8_UNORM, ++ .uiWidthShift = 1, ++ .uiHeightShift = 1}, ++ }, ++#if defined(DRM_FORMAT_NV21) ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_YVU420_2PLANE, ++ .iDRIFourCC = DRM_FORMAT_NV21, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_Y_UV, ++ .uiNumPlanes = 2, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ .sPlanes[1] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8G8_UNORM, ++ .uiWidthShift = 1, ++ .uiHeightShift = 1}, ++ }, ++#endif ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_YUV420_3PLANE, ++ .iDRIFourCC = DRM_FORMAT_YUV420, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_Y_U_V, ++ .uiNumPlanes = 3, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ .sPlanes[1] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 1, ++ .uiHeightShift = 1}, ++ .sPlanes[2] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 1, ++ .uiHeightShift = 1}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_YVU420_3PLANE, ++ .iDRIFourCC = DRM_FORMAT_YVU420, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_Y_U_V, ++ .uiNumPlanes = 3, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ .sPlanes[1] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 1, ++ .uiHeightShift = 1}, ++ .sPlanes[2] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 1, ++ .uiHeightShift = 1}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_YUV8_444_3PLANE_PACK8, ++ .iDRIFourCC = DRM_FORMAT_YUV444, ++ .iDRIComponents = PVRDRI_IMAGE_COMPONENTS_Y_U_V, ++ .uiNumPlanes = 3, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ .sPlanes[1] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ .sPlanes[2] = { ++ .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_D16_UNORM, ++ .iDRIFourCC = 0, ++ .iDRIComponents = 0, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_D16_UNORM, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++ { ++ .eIMGPixelFormat = IMG_PIXFMT_D24_UNORM_X8_TYPELESS, ++ .iDRIFourCC = 0, ++ .iDRIComponents = 0, ++ .uiNumPlanes = 1, ++ .sPlanes[0] = { ++ .eIMGPixelFormat = IMG_PIXFMT_D24_UNORM_X8_TYPELESS, ++ .uiWidthShift = 0, ++ .uiHeightShift = 0}, ++ }, ++}; ++ ++/* ++ * Check if a PVR Screen has support for a particular format based upon its ++ * position in g_asFormats. If querying of this information isn't supported by ++ * pvr_dri_support then assume the format is supported. ++ */ ++static inline bool ++PVRDRIScreenHasFormatFromIdx(const struct DRISUPScreen *const psPVRScreen, ++ const unsigned int uiFormatIdx) ++{ ++ if (psPVRScreen->iNumFormats > 0) { ++ if (uiFormatIdx < ARRAY_SIZE(g_asFormats)) ++ return psPVRScreen->pbHasFormat[uiFormatIdx]; ++ return false; ++ } ++ ++ assert(psPVRScreen->iNumFormats == -1); ++ return true; ++} ++ ++const struct __DRIconfigRec ** ++PVRDRICreateConfigs(const struct DRISUPScreen *psPVRScreen) ++{ ++ static const unsigned int auBackBufferModes[] = { ++ PVRDRI_ATTRIB_SWAP_NONE, ++ PVRDRI_ATTRIB_SWAP_UNDEFINED, ++ }; ++ const uint8_t *puDepthBits = PVRDRIDepthBitsArray(); ++ const uint8_t *puStencilBits = PVRDRIStencilBitsArray(); ++ const uint8_t *puMSAASamples = PVRDRIMSAABitsArray(); ++ const unsigned int uNumBackBufferModes = ARRAY_SIZE(auBackBufferModes); ++ const unsigned int uNumDepthStencilBits = ++ PVRDRIDepthStencilBitArraySize(); ++ const unsigned int uNumMSAASamples = PVRDRIMSAABitArraySize(); ++ struct __DRIconfigRec **ppsConfigs = NULL; ++ struct __DRIconfigRec **ppsNewConfigs; ++ unsigned int i; ++ ++ for (i = 0; i < psPVRScreen->uNumMesaFormats; i++) { ++ if (!MODSUPCreateConfigs(&ppsNewConfigs, psPVRScreen->psDRIScreen, ++ psPVRScreen->puMesaFormats[i], ++ puDepthBits, puStencilBits, ++ uNumDepthStencilBits, ++ auBackBufferModes, uNumBackBufferModes, ++ puMSAASamples, uNumMSAASamples, ++ false, false, false, ++ PVRDRI_YUV_DEPTH_RANGE_NONE, ++ PVRDRI_YUV_CSC_STANDARD_NONE, ++ PVRDRIMaxPBufferWidth(), ++ PVRDRIMaxPBufferHeight())) { ++ __driUtilMessage("%s: Couldn't create DRI configs", __func__); ++ return NULL; ++ } ++ ++ ppsConfigs = MODSUPConcatConfigs(psPVRScreen->psDRIScreen, ++ ppsConfigs, ppsNewConfigs); ++ } ++ ++ return (const struct __DRIconfigRec **) ppsConfigs; ++} ++ ++const PVRDRIImageFormat * ++PVRDRIFourCCToImageFormat(struct DRISUPScreen *psPVRScreen, int iDRIFourCC) ++{ ++ unsigned int i; ++ ++ if (!iDRIFourCC) ++ return NULL; ++ ++ for (i = 0; i < ARRAY_SIZE(g_asFormats); i++) { ++ if (g_asFormats[i].iDRIFourCC != iDRIFourCC) ++ continue; ++ ++ if (!PVRDRIScreenHasFormatFromIdx(psPVRScreen, i)) ++ break; ++ ++ return &g_asFormats[i]; ++ } ++ ++ return NULL; ++} ++ ++const PVRDRIImageFormat * ++PVRDRIIMGPixelFormatToImageFormat(struct DRISUPScreen *psPVRScreen, ++ IMG_PIXFMT eIMGPixelFormat) ++{ ++ unsigned int i; ++ ++ assert(eIMGPixelFormat != IMG_PIXFMT_UNKNOWN); ++ ++ for (i = 0; i < ARRAY_SIZE(g_asFormats); i++) { ++ if (g_asFormats[i].eIMGPixelFormat != eIMGPixelFormat) ++ continue; ++ ++ /* ++ * Assume that the screen has the format, i.e. it's supported by the ++ * HW+SW, since we can only have an IMG_PIXFMT from having called one of ++ * the other PVRDRI*ToImageFormat functions or one of the ++ * pvr_dri_support functions. ++ */ ++ assert(PVRDRIScreenHasFormatFromIdx(psPVRScreen, i)); ++ return &g_asFormats[i]; ++ } ++ ++ return NULL; ++} ++ ++/* ++ * The EGL_EXT_image_dma_buf_import says that if a hint is unspecified then ++ * the implementation may guess based on the pixel format or may fallback to ++ * some default value. Furthermore, if a hint is unsupported then the ++ * implementation may use whichever settings it wants to achieve the closest ++ * match. ++ */ ++IMG_YUV_COLORSPACE ++PVRDRIToIMGColourSpace(const PVRDRIImageFormat *psFormat, ++ unsigned int uDRIColourSpace, ++ unsigned int uDRISampleRange) ++{ ++ switch (psFormat->iDRIComponents) { ++ case PVRDRI_IMAGE_COMPONENTS_R: ++ case PVRDRI_IMAGE_COMPONENTS_RG: ++ case PVRDRI_IMAGE_COMPONENTS_RGB: ++ case PVRDRI_IMAGE_COMPONENTS_RGBA: ++ return IMG_COLORSPACE_UNDEFINED; ++ case PVRDRI_IMAGE_COMPONENTS_Y_U_V: ++ case PVRDRI_IMAGE_COMPONENTS_Y_UV: ++ case PVRDRI_IMAGE_COMPONENTS_Y_XUXV: ++ case PVRDRI_IMAGE_COMPONENTS_EXTERNAL: ++ break; ++ default: ++ errorMessage("%s: Unrecognised DRI components (components = 0x%X)", ++ __func__, psFormat->iDRIComponents); ++ unreachable("unhandled DRI component"); ++ return IMG_COLORSPACE_UNDEFINED; ++ } ++ ++ switch (uDRIColourSpace) { ++ case PVRDRI_YUV_COLOR_SPACE_UNDEFINED: ++ case PVRDRI_YUV_COLOR_SPACE_ITU_REC601: ++ switch (uDRISampleRange) { ++ case PVRDRI_YUV_RANGE_UNDEFINED: ++ case PVRDRI_YUV_NARROW_RANGE: ++ return IMG_COLORSPACE_BT601_CONFORMANT_RANGE; ++ case PVRDRI_YUV_FULL_RANGE: ++ return IMG_COLORSPACE_BT601_FULL_RANGE; ++ default: ++ errorMessage ("%s: Unrecognised DRI sample range (sample range = 0x%X)", ++ __func__, uDRISampleRange); ++ unreachable("unhandled sample range"); ++ return IMG_COLORSPACE_UNDEFINED; ++ } ++ case PVRDRI_YUV_COLOR_SPACE_ITU_REC709: ++ switch (uDRISampleRange) { ++ case PVRDRI_YUV_RANGE_UNDEFINED: ++ case PVRDRI_YUV_NARROW_RANGE: ++ return IMG_COLORSPACE_BT709_CONFORMANT_RANGE; ++ case PVRDRI_YUV_FULL_RANGE: ++ return IMG_COLORSPACE_BT709_FULL_RANGE; ++ default: ++ errorMessage ("%s: Unrecognised DRI sample range (sample range = 0x%X)", ++ __func__, uDRISampleRange); ++ unreachable("unhandled sample range"); ++ return IMG_COLORSPACE_UNDEFINED; ++ } ++ case PVRDRI_YUV_COLOR_SPACE_ITU_REC2020: ++ switch (uDRISampleRange) { ++ case PVRDRI_YUV_RANGE_UNDEFINED: ++ case PVRDRI_YUV_NARROW_RANGE: ++ return IMG_COLORSPACE_BT2020_CONFORMANT_RANGE; ++ case PVRDRI_YUV_FULL_RANGE: ++ return IMG_COLORSPACE_BT2020_FULL_RANGE; ++ default: ++ errorMessage ("%s: Unrecognised DRI sample range (sample range = 0x%X)", ++ __func__, uDRISampleRange); ++ assert(0); ++ return IMG_COLORSPACE_UNDEFINED; ++ } ++ default: ++ errorMessage ("%s: Unrecognised DRI color space (color space = 0x%X)", ++ __func__, uDRIColourSpace); ++ unreachable("unhandled color space"); ++ return IMG_COLORSPACE_UNDEFINED; ++ } ++} ++ ++IMG_YUV_CHROMA_INTERP ++PVRDRIChromaSittingToIMGInterp(const PVRDRIImageFormat *psFormat, ++ unsigned int uChromaSitting) ++{ ++ switch (psFormat->iDRIComponents) { ++ case PVRDRI_IMAGE_COMPONENTS_R: ++ case PVRDRI_IMAGE_COMPONENTS_RG: ++ case PVRDRI_IMAGE_COMPONENTS_RGB: ++ case PVRDRI_IMAGE_COMPONENTS_RGBA: ++ return IMG_CHROMA_INTERP_UNDEFINED; ++ case PVRDRI_IMAGE_COMPONENTS_Y_U_V: ++ case PVRDRI_IMAGE_COMPONENTS_Y_UV: ++ case PVRDRI_IMAGE_COMPONENTS_Y_XUXV: ++ case PVRDRI_IMAGE_COMPONENTS_EXTERNAL: ++ break; ++ default: ++ errorMessage("%s: Unrecognised DRI components (components = 0x%X)", ++ __func__, psFormat->iDRIComponents); ++ unreachable("unhandled dri component"); ++ return IMG_CHROMA_INTERP_UNDEFINED; ++ } ++ ++ switch (uChromaSitting) { ++ case PVRDRI_YUV_CHROMA_SITING_UNDEFINED: ++ case PVRDRI_YUV_CHROMA_SITING_0: ++ return IMG_CHROMA_INTERP_ZERO; ++ case PVRDRI_YUV_CHROMA_SITING_0_5: ++ return IMG_CHROMA_INTERP_HALF; ++ default: ++ errorMessage ("%s: Unrecognised DRI chroma sitting (chroma sitting = 0x%X)", ++ __func__, uChromaSitting); ++ unreachable("unhandled chroma sitting"); ++ return IMG_CHROMA_INTERP_UNDEFINED; ++ } ++} ++ ++bool ++PVRDRIGetSupportedFormats(struct DRISUPScreen *psPVRScreen) ++{ ++ int *piFormats; ++ IMG_PIXFMT *peImgFormats; ++ bool bRet = false; ++ unsigned int i; ++ ++ piFormats = malloc(ARRAY_SIZE(g_asFormats) * sizeof(*piFormats)); ++ peImgFormats = malloc(ARRAY_SIZE(g_asFormats) * sizeof(*peImgFormats)); ++ ++ psPVRScreen->pbHasFormat = malloc(ARRAY_SIZE(g_asFormats) * ++ sizeof(*psPVRScreen->pbHasFormat)); ++ ++ psPVRScreen->psModifiers = calloc(ARRAY_SIZE(g_asFormats), ++ sizeof(*psPVRScreen->psModifiers)); ++ ++ if (!piFormats || !peImgFormats || ++ !psPVRScreen->pbHasFormat || !psPVRScreen->psModifiers) { ++ errorMessage("%s: Out of memory", __func__); ++ goto err_free; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(g_asFormats); i++) { ++ piFormats[i] = g_asFormats[i].iDRIFourCC; ++ peImgFormats[i] = g_asFormats[i].eIMGPixelFormat; ++ ++ psPVRScreen->psModifiers[i].iNumModifiers = -1; ++ } ++ ++ psPVRScreen->iNumFormats = ++ PVRDRIQuerySupportedFormats(psPVRScreen->psImpl, ARRAY_SIZE(g_asFormats), ++ piFormats, peImgFormats, ++ psPVRScreen->pbHasFormat); ++ if (psPVRScreen->iNumFormats == 0) { ++ __driUtilMessage("%s: Couldn't query supported pixel formats", ++ __func__); ++ goto err_free; ++ } ++ ++ bRet = true; ++ goto cleanup; ++ ++err_free: ++ free(psPVRScreen->psModifiers); ++ psPVRScreen->psModifiers = NULL; ++ ++ free(psPVRScreen->pbHasFormat); ++ psPVRScreen->pbHasFormat = NULL; ++cleanup: ++ free(peImgFormats); ++ free(piFormats); ++ return bRet; ++} ++ ++bool ++DRIMODQueryDMABufFormats(struct DRISUPScreen *psPVRScreen, int iMax, ++ int *piFormats, int *piCount) ++{ ++ int iLim; ++ unsigned int i; ++ int j; ++ ++ assert(psPVRScreen->iNumFormats != 0); ++ ++ if (psPVRScreen->iNumFormats < 0) ++ return false; ++ ++ iLim = (iMax) ? iMax : psPVRScreen->iNumFormats; ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(g_asFormats) && j < iLim; i++) { ++ /* ++ * SRGB formats don't map to DRM formats, as defined by drm_fourcc.h, so ++ * should not be returned. ++ */ ++ if (g_asFormats[i].bIsSRGB) ++ continue; ++ ++ if (psPVRScreen->pbHasFormat[i] && g_asFormats[i].iDRIFourCC) { ++ if (iMax) ++ piFormats[j] = g_asFormats[i].iDRIFourCC; ++ j++; ++ } ++ } ++ ++ *piCount = j; ++ ++ return true; ++} ++ ++static bool ++PVRDRIGetSupportedModifiers(struct DRISUPScreen *psPVRScreen, ++ struct PVRDRIModifiers *psModifiers, ++ const PVRDRIImageFormat *psFormat) ++{ ++ int iNumModifiers; ++ ++ iNumModifiers = PVRDRIQueryModifiers(psPVRScreen->psImpl, ++ psFormat->iDRIFourCC, ++ psFormat->eIMGPixelFormat, ++ NULL, NULL); ++ if (iNumModifiers < 0) { ++ errorMessage("%s: Couldn't query modifiers for format 0x%x", ++ __func__, psFormat->iDRIFourCC); ++ return false; ++ } ++ ++ psModifiers->puModifiers = malloc(iNumModifiers * ++ sizeof(*psModifiers->puModifiers)); ++ psModifiers->puExternalOnly = malloc(iNumModifiers * ++ sizeof(*psModifiers-> ++ puExternalOnly)); ++ if (!psModifiers->puModifiers || !psModifiers->puExternalOnly) { ++ free(psModifiers->puModifiers); ++ psModifiers->puModifiers = NULL; ++ ++ free(psModifiers->puExternalOnly); ++ psModifiers->puExternalOnly = NULL; ++ ++ errorMessage("%s: Out of memory", __func__); ++ ++ return false; ++ } ++ psModifiers->iNumModifiers = iNumModifiers; ++ ++ iNumModifiers = PVRDRIQueryModifiers(psPVRScreen->psImpl, ++ psFormat->iDRIFourCC, ++ psFormat->eIMGPixelFormat, ++ psModifiers->puModifiers, ++ psModifiers->puExternalOnly); ++ ++ assert(iNumModifiers == psModifiers->iNumModifiers); ++ ++ return true; ++} ++ ++static bool ++PVRDRIGetModifiersForFormat(struct DRISUPScreen *psPVRScreen, int iFourCC, ++ const PVRDRIImageFormat **ppsFormat, ++ const struct PVRDRIModifiers **ppsModifiers) ++{ ++ const PVRDRIImageFormat *psFormat; ++ struct PVRDRIModifiers *psModifiers; ++ unsigned int uIdx; ++ ++ assert(psPVRScreen->iNumFormats != 0); ++ ++ if (psPVRScreen->iNumFormats < 0) ++ return false; ++ ++ psFormat = PVRDRIFourCCToImageFormat(psPVRScreen, iFourCC); ++ if (!psFormat) ++ return false; ++ ++ uIdx = psFormat - g_asFormats; ++ psModifiers = &psPVRScreen->psModifiers[uIdx]; ++ ++ if (psModifiers->iNumModifiers < 0) ++ if (!PVRDRIGetSupportedModifiers(psPVRScreen, psModifiers, psFormat)) ++ return false; ++ ++ *ppsFormat = psFormat; ++ *ppsModifiers = psModifiers; ++ ++ return true; ++} ++ ++bool ++PVRDRIValidateImageModifier(struct DRISUPScreen *psPVRScreen, ++ const int iFourCC, const uint64_t uiModifier) ++{ ++ const PVRDRIImageFormat *psFormat; ++ const struct PVRDRIModifiers *psModifiers; ++ ++ if (!PVRDRIGetModifiersForFormat(psPVRScreen, iFourCC, &psFormat, ++ &psModifiers)) ++ return false; ++ ++ for (int i = 0; i < psModifiers->iNumModifiers; i++) ++ if (psModifiers->puModifiers[i] == uiModifier) ++ return true; ++ ++ return false; ++} ++ ++bool ++DRIMODQueryDMABufModifiers(struct DRISUPScreen *psPVRScreen, int iFourCC, ++ int iMax, uint64_t *puModifiers, ++ unsigned int *puExternalOnly, int *piCount) ++{ ++ const PVRDRIImageFormat *psFormat; ++ const struct PVRDRIModifiers *psModifiers; ++ int iNumCopy; ++ ++ if (!PVRDRIGetModifiersForFormat(psPVRScreen, iFourCC, &psFormat, ++ &psModifiers)) ++ return false; ++ ++ if (!iMax) { ++ *piCount = psModifiers->iNumModifiers; ++ return true; ++ } ++ ++ iNumCopy = (iMax < psModifiers->iNumModifiers) ? ++ iMax : psModifiers->iNumModifiers; ++ ++ if (puModifiers) ++ (void) memcpy(puModifiers, psModifiers->puModifiers, ++ sizeof(*puModifiers) * iNumCopy); ++ ++ if (puExternalOnly) ++ (void) memcpy(puExternalOnly, psModifiers->puExternalOnly, ++ sizeof(*puExternalOnly) * iNumCopy); ++ ++ *piCount = iNumCopy; ++ ++ return true; ++} ++ ++bool ++DRIMODQueryDMABufFormatModifierAttribs(struct DRISUPScreen *psPVRScreen, ++ uint32_t uFourCC, uint64_t uModifier, ++ int iAttribute, uint64_t *puValue) ++{ ++ const PVRDRIImageFormat *psFormat; ++ const struct PVRDRIModifiers *psModifiers; ++ int i; ++ ++ if (!PVRDRIGetModifiersForFormat(psPVRScreen, uFourCC, &psFormat, ++ &psModifiers)) ++ return false; ++ ++ for (i = 0; i < psModifiers->iNumModifiers; i++) ++ if (psModifiers->puModifiers[i] == uModifier) ++ break; ++ ++ if (i == psModifiers->iNumModifiers) ++ return false; ++ ++ switch (iAttribute) { ++ case PVRDRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: ++ *puValue = psFormat->uiNumPlanes; ++ break; ++ default: ++ return false; ++ } ++ ++ return true; ++} ++ ++void ++PVRDRIDestroyFormatInfo(struct DRISUPScreen *psPVRScreen) ++{ ++ unsigned int i; ++ ++ if (psPVRScreen->psModifiers) { ++ for (i = 0; i < ARRAY_SIZE(g_asFormats); i++) { ++ free(psPVRScreen->psModifiers[i].puModifiers); ++ free(psPVRScreen->psModifiers[i].puExternalOnly); ++ } ++ free(psPVRScreen->psModifiers); ++ } ++ ++ free(psPVRScreen->pbHasFormat); ++} ++ ++bool ++PVRDRIGetMesaFormats(struct DRISUPScreen *psPVRScreen) ++{ ++ const unsigned int auMesaFormatsBase[] = { ++ PVRDRI_MESA_FORMAT_B8G8R8A8_UNORM, ++ PVRDRI_MESA_FORMAT_B8G8R8A8_SRGB, ++ PVRDRI_MESA_FORMAT_B8G8R8X8_UNORM, ++ PVRDRI_MESA_FORMAT_B5G6R5_UNORM, ++ }; ++ const unsigned int auMesaFormatsRGB[] = { ++ PVRDRI_MESA_FORMAT_R8G8B8A8_UNORM, ++ PVRDRI_MESA_FORMAT_R8G8B8A8_SRGB, ++ PVRDRI_MESA_FORMAT_R8G8B8X8_UNORM, ++ }; ++ unsigned int uSizeMesaFormats; ++ bool bCapRGB; ++ unsigned int i, j; ++ ++ bCapRGB = MODSUPGetCapability(psPVRScreen->psDRIScreen, ++ PVRDRI_LOADER_CAP_RGBA_ORDERING) != 0; ++ ++ uSizeMesaFormats = sizeof(auMesaFormatsBase); ++ if (bCapRGB) ++ uSizeMesaFormats += sizeof(auMesaFormatsRGB); ++ ++ /* ++ * We haven't checked if any of the Mesa formats are supported by the DDK ++ * at this point, so we may allocate more memory than we need. ++ */ ++ psPVRScreen->puMesaFormats = malloc(uSizeMesaFormats); ++ if (psPVRScreen->puMesaFormats == NULL) { ++ __driUtilMessage("%s: Out of memory", __func__); ++ return false; ++ } ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(auMesaFormatsBase); i++) { ++ unsigned int uMesaFormat = auMesaFormatsBase[i]; ++ ++ if (!PVRDRIMesaFormatSupported(uMesaFormat)) ++ continue; ++ ++ psPVRScreen->puMesaFormats[j++] = uMesaFormat; ++ } ++ ++ if (bCapRGB) { ++ for (i = 0; i < ARRAY_SIZE(auMesaFormatsRGB); i++) { ++ unsigned int uMesaFormat = auMesaFormatsRGB[i]; ++ ++ if (!PVRDRIMesaFormatSupported(uMesaFormat)) ++ continue; ++ ++ psPVRScreen->puMesaFormats[j++] = uMesaFormat; ++ } ++ } ++ ++ assert((j * sizeof(psPVRScreen->puMesaFormats[0])) <= ++ uSizeMesaFormats); ++ ++ psPVRScreen->uNumMesaFormats = j; ++ ++ return true; ++} ++ ++void ++PVRDRIFreeMesaFormats(struct DRISUPScreen *psPVRScreen) ++{ ++ free(psPVRScreen->puMesaFormats); ++} +diff --git a/src/meson.build b/src/meson.build +index 84a990358a3..d96c754a63d 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -25,6 +25,7 @@ inc_gallium = include_directories('gallium/include') + inc_gallium_aux = include_directories('gallium/auxiliary') + inc_amd_common = include_directories('amd/common') + inc_amd_common_llvm = include_directories('amd/llvm') ++inc_pvr = include_directories('mesa/main', 'mapi/glapi') + + libglsl_util = static_library( + 'glsl_util', +-- +2.17.1 + diff --git a/package/mesa3d/0001-c99_math-import-isinf-for-uclibc-based-toolchains.patch b/package/mesa3d/0001-c99_math-import-isinf-for-uclibc-based-toolchains.patch deleted file mode 100644 index 5acbaa4d..00000000 --- a/package/mesa3d/0001-c99_math-import-isinf-for-uclibc-based-toolchains.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 705490763fcc052defa2d49a5c5200775cd12c54 Mon Sep 17 00:00:00 2001 -From: Peter Seiderer -Date: Wed, 4 Mar 2020 08:27:24 +0100 -Subject: [PATCH] c99_math: import isinf for uclibc based toolchains - -The same fix as for glibc >= 2.23 is needed for uclibc -based toolchains. - -[Upstream suggested: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4042] -Signed-off-by: Peter Seiderer ---- - include/c99_math.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/c99_math.h b/include/c99_math.h -index e906c26aa54..c8a73a2d2c7 100644 ---- a/include/c99_math.h -+++ b/include/c99_math.h -@@ -190,7 +190,7 @@ fpclassify(double x) - * undefines those functions, which in glibc 2.23, are defined as macros rather - * than functions as in glibc 2.22. - */ --#if __cplusplus >= 201103L && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 23)) -+#if __cplusplus >= 201103L && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 23) || defined(__UCLIBC__)) - #include - - using std::fpclassify; --- -2.25.1 - diff --git a/package/mesa3d/0002-Force-Mesa-to-use-the-PVR-driver-for-platform-device.patch b/package/mesa3d/0002-Force-Mesa-to-use-the-PVR-driver-for-platform-device.patch new file mode 100644 index 00000000..7139dbf4 --- /dev/null +++ b/package/mesa3d/0002-Force-Mesa-to-use-the-PVR-driver-for-platform-device.patch @@ -0,0 +1,34 @@ +From dbbfc6aadf0c6b40c47b325bf9bb35cf1d552d9c Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Wed, 17 Jun 2015 15:37:18 +0100 +Subject: [PATCH 02/50] 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 d64bc7c10f2..cfadecf02b4 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.17.1 + diff --git a/package/mesa3d/0002-meson-Set-proper-value-for-LIBCLC_INCLUDEDIR.patch b/package/mesa3d/0002-meson-Set-proper-value-for-LIBCLC_INCLUDEDIR.patch deleted file mode 100644 index e3c70c3f..00000000 --- a/package/mesa3d/0002-meson-Set-proper-value-for-LIBCLC_INCLUDEDIR.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 7b46756a99aca7f27a45c3b99460f088570f6f53 Mon Sep 17 00:00:00 2001 -From: Romain Naour -Date: Wed, 17 Apr 2019 23:07:42 +0200 -Subject: [PATCH] meson: Set proper value for LIBCLC_INCLUDEDIR - -LIBCLC_INCLUDEDIR is the location where mesa3d OpenCL implementation -will look for OpenCL "headers" on the target, when building the OpenCL -kernels. - -The value returned by pkg-config for includedir is relevant when -cross-compiling, on the build machine. But in this specific case, we -really need a value that is valid on the target. - -Those headers are installed by the libclc package in /usr/share so -that they are not removed by Buildroot target-finalize logic. - -Based on the patch for autotools provided by Valentin Korenblit. - -Signed-off-by: Romain Naour -Signed-off-by: Bernd Kuhls -[rebased for 20.2.0 & 20.3.0] ---- - src/gallium/frontends/clover/meson.build | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/gallium/frontends/clover/meson.build b/src/gallium/frontends/clover/meson.build -index 62ac5f5278d..ecdeb39669c 100644 ---- a/src/gallium/frontends/clover/meson.build -+++ b/src/gallium/frontends/clover/meson.build -@@ -27,7 +27,7 @@ - '-DCL_USE_DEPRECATED_OPENCL_2_0_APIS', - '-DCL_USE_DEPRECATED_OPENCL_2_1_APIS', - '-DCL_USE_DEPRECATED_OPENCL_2_2_APIS', -- '-DLIBCLC_INCLUDEDIR="@0@/"'.format(dep_clc.get_variable(pkgconfig : 'includedir')), -+ '-DLIBCLC_INCLUDEDIR="/usr/share"', - '-DLIBCLC_LIBEXECDIR="@0@/"'.format(dep_clc.get_variable(pkgconfig : 'libexecdir')) - ] - clover_spirv_cpp_args = [] --- -2.20.1 - diff --git a/package/mesa3d/0003-dri-Add-some-new-DRI-formats-and-fourccs.patch b/package/mesa3d/0003-dri-Add-some-new-DRI-formats-and-fourccs.patch new file mode 100644 index 00000000..01721620 --- /dev/null +++ b/package/mesa3d/0003-dri-Add-some-new-DRI-formats-and-fourccs.patch @@ -0,0 +1,80 @@ +From 94cfbd20ea72aac430abf5097133b1356c0a52a1 Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Thu, 5 Jun 2014 12:07:01 +0100 +Subject: [PATCH 03/50] 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 9b85e67ce49..e668798e87f 100644 +--- a/include/GL/internal/dri_interface.h ++++ b/include/GL/internal/dri_interface.h +@@ -1366,6 +1366,9 @@ struct __DRIdri2ExtensionRec { + #define __DRI_IMAGE_FORMAT_XBGR16161616F 0x1014 + #define __DRI_IMAGE_FORMAT_ABGR16161616F 0x1015 + #define __DRI_IMAGE_FORMAT_SXRGB8 0x1016 ++#define __DRI_IMAGE_FORMAT_ARGB4444 0x1017 ++#define __DRI_IMAGE_FORMAT_YVU444_PACK10_IMG 0x1018 ++#define __DRI_IMAGE_FORMAT_BGR888 0x1019 + + #define __DRI_IMAGE_USE_SHARE 0x0001 + #define __DRI_IMAGE_USE_SCANOUT 0x0002 +@@ -1395,6 +1398,7 @@ struct __DRIdri2ExtensionRec { + #define __DRI_IMAGE_FOURCC_SARGB8888 0x83324258 + #define __DRI_IMAGE_FOURCC_SABGR8888 0x84324258 + #define __DRI_IMAGE_FOURCC_SXRGB8888 0x85324258 ++#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 3f9c8110355..8af9b16ff88 100644 +--- a/include/drm-uapi/drm_fourcc.h ++++ b/include/drm-uapi/drm_fourcc.h +@@ -307,6 +307,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 62fc7fb7783..4f52985c48e 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -2659,6 +2659,7 @@ dri2_num_fourcc_format_planes(EGLint format) + case DRM_FORMAT_VYUY: + case DRM_FORMAT_AYUV: + case DRM_FORMAT_XYUV8888: ++ 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.17.1 + diff --git a/package/mesa3d/0003-vc4-add-meson-option-to-disable-optional-neon-suppor.patch b/package/mesa3d/0003-vc4-add-meson-option-to-disable-optional-neon-suppor.patch deleted file mode 100644 index bb5ef00a..00000000 --- a/package/mesa3d/0003-vc4-add-meson-option-to-disable-optional-neon-suppor.patch +++ /dev/null @@ -1,84 +0,0 @@ -From e3b47c1b84964c62b3e1fa782f1ffa4be0ae62f9 Mon Sep 17 00:00:00 2001 -From: Peter Seiderer -Date: Mon, 9 Mar 2020 13:01:14 +0100 -Subject: [PATCH] vc4: add meson option to disable optional neon support - -Not all toolchains are able to compile the runtime -optional vc4 neon support, so add an meson option -to force disabling it at compile time. - -[Upstream: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4114] -Signed-off-by: Peter Seiderer -Signed-off-by: Bernd Kuhls -[rebased for 20.2.0, 20.3.0 & 21.1.0] ---- - meson_options.txt | 7 +++++++ - src/gallium/drivers/vc4/meson.build | 4 ++-- - src/gallium/drivers/vc4/vc4_tiling.h | 4 ++-- - 3 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/meson_options.txt b/meson_options.txt -index a39596a6f19..0f6b6c62b55 100644 ---- a/meson_options.txt -+++ b/meson_options.txt -@@ -123,6 +123,13 @@ option( - choices : ['auto', 'true', 'false', 'enabled', 'disabled'], - description : 'enable gallium va frontend.', - ) -+option( -+ 'gallium-vc4-neon', -+ type : 'combo', -+ value : 'auto', -+ choices : ['auto', 'disabled'], -+ description : 'enable gallium vc4 optional neon support.', -+) - option( - 'va-libs-path', - type : 'string', -diff --git a/src/gallium/drivers/vc4/meson.build b/src/gallium/drivers/vc4/meson.build -index 5ce5af5f6b4..e3f7d8d62ae 100644 ---- a/src/gallium/drivers/vc4/meson.build -+++ b/src/gallium/drivers/vc4/meson.build -@@ -84,7 +84,7 @@ files_libvc4 = files( - vc4_c_args = [] - - libvc4_neon = [] --if host_machine.cpu_family() == 'arm' -+if host_machine.cpu_family() == 'arm' and get_option('gallium-vc4-neon') != 'disabled' - libvc4_neon = static_library( - 'vc4_neon', - 'vc4_tiling_lt_neon.c', -@@ -93,7 +93,7 @@ if host_machine.cpu_family() == 'arm' - ], - c_args : '-mfpu=neon', - ) -- vc4_c_args += '-DUSE_ARM_ASM' -+ vc4_c_args += '-DVC4_TILING_LT_NEON' - endif - - if dep_simpenrose.found() -diff --git a/src/gallium/drivers/vc4/vc4_tiling.h b/src/gallium/drivers/vc4/vc4_tiling.h -index 66767e7f1f8..7446f1c3d0c 100644 ---- a/src/gallium/drivers/vc4/vc4_tiling.h -+++ b/src/gallium/drivers/vc4/vc4_tiling.h -@@ -89,7 +89,7 @@ vc4_load_lt_image(void *dst, uint32_t dst_stride, - void *src, uint32_t src_stride, - int cpp, const struct pipe_box *box) - { --#ifdef USE_ARM_ASM -+#ifdef VC4_TILING_LT_NEON - if (util_get_cpu_caps()->has_neon) { - vc4_load_lt_image_neon(dst, dst_stride, src, src_stride, - cpp, box); -@@ -105,7 +105,7 @@ vc4_store_lt_image(void *dst, uint32_t dst_stride, - void *src, uint32_t src_stride, - int cpp, const struct pipe_box *box) - { --#ifdef USE_ARM_ASM -+#ifdef VC4_TILING_LT_NEON - if (util_get_cpu_caps()->has_neon) { - vc4_store_lt_image_neon(dst, dst_stride, src, src_stride, - cpp, box); --- -2.25.1 - diff --git a/package/mesa3d/0004-GL_EXT_sparse_texture-entry-points.patch b/package/mesa3d/0004-GL_EXT_sparse_texture-entry-points.patch new file mode 100644 index 00000000..d810176e --- /dev/null +++ b/package/mesa3d/0004-GL_EXT_sparse_texture-entry-points.patch @@ -0,0 +1,104 @@ +From c9723120dbbe1d73c258d1aa119e05a24ab98b8a Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Wed, 12 Aug 2015 09:11:51 +0100 +Subject: [PATCH 04/50] 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 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml +index 4386375940f..d8a80995d92 100644 +--- a/src/mapi/glapi/gen/es_EXT.xml ++++ b/src/mapi/glapi/gen/es_EXT.xml +@@ -1433,6 +1433,9 @@ + + + ++ ++ ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index 5b51c222d79..a151a5d5fb4 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1677,6 +1677,8 @@ offsets = { + "SecondaryColor3hNV": 1641, + "SecondaryColor3hvNV": 1642, + "InternalSetError": 1643, ++ "TexPageCommitmentEXT": 1644, ++ "TexturePageCommitmentEXT" : 1645, + } + + functions = [ +-- +2.17.1 + diff --git a/package/mesa3d/0004-src-util-rand_xor-Include-stddef.h-to-fix-build-erro.patch b/package/mesa3d/0004-src-util-rand_xor-Include-stddef.h-to-fix-build-erro.patch deleted file mode 100644 index 538aa74e..00000000 --- a/package/mesa3d/0004-src-util-rand_xor-Include-stddef.h-to-fix-build-erro.patch +++ /dev/null @@ -1,40 +0,0 @@ -From fdc8b5a205e2116408aeb9fd305e57f656e2e89d Mon Sep 17 00:00:00 2001 -From: Bernd Kuhls -Date: Sun, 9 Aug 2020 17:06:26 +0200 -Subject: [PATCH] src/util/rand_xor: Include stddef.h to fix build error -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fixes - -In file included from ../src/util/rand_xor.c:29: -output/host/x86_64-buildroot-linux-uclibc/sysroot/usr/include/sys/random.h:27:35: - error: unknown type name ‘size_t’ - extern int getrandom(void *__buf, size_t count, unsigned int flags) - -seen with gcc version 8.3.0 (Buildroot 2020.02) and uClibc. - -Patch sent upstream: -https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6248 - -Signed-off-by: Bernd Kuhls ---- - src/util/rand_xor.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/util/rand_xor.c b/src/util/rand_xor.c -index 81b64f1ea71..fcb481487fa 100644 ---- a/src/util/rand_xor.c -+++ b/src/util/rand_xor.c -@@ -25,6 +25,7 @@ - #include "detect_os.h" - - #if !DETECT_OS_WINDOWS -+#include - #if defined(HAVE_GETRANDOM) - #include - #endif --- -2.27.0 - diff --git a/package/mesa3d/0005-Add-support-for-various-GLES-extensions.patch b/package/mesa3d/0005-Add-support-for-various-GLES-extensions.patch new file mode 100644 index 00000000..a6a96eed --- /dev/null +++ b/package/mesa3d/0005-Add-support-for-various-GLES-extensions.patch @@ -0,0 +1,106 @@ +From 329dd07729514a93a298e8ab6485822444ed4b28 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Mon, 10 Mar 2014 12:27:03 +0000 +Subject: [PATCH 05/50] 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 d8a80995d92..42f4b2b80fb 100644 +--- a/src/mapi/glapi/gen/es_EXT.xml ++++ b/src/mapi/glapi/gen/es_EXT.xml +@@ -285,28 +285,25 @@ + + + +- ++ + + + +- +- ++ + + +- ++ + + + +- ++ + + +- ++ + + + +- ++ + + + +@@ -680,6 +677,32 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index a151a5d5fb4..b23ae713f6f 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1679,6 +1679,12 @@ offsets = { + "InternalSetError": 1643, + "TexPageCommitmentEXT": 1644, + "TexturePageCommitmentEXT" : 1645, ++ "CurrentPaletteMatrixOES" : 1646, ++ "LoadPaletteFromModelViewMatrixOES" : 1647, ++ "MatrixIndexPointerOES" : 1648, ++ "WeightPointerOES" : 1649, ++ "RenderbufferStorageMultisampleIMG" : 1650, ++ "FramebufferTexture2DMultisampleIMG" : 1651, + } + + functions = [ +-- +2.17.1 + diff --git a/package/mesa3d/0005-src-util-futex.h-fix-build-on-32-bit-architectures-u.patch b/package/mesa3d/0005-src-util-futex.h-fix-build-on-32-bit-architectures-u.patch deleted file mode 100644 index b01db8a4..00000000 --- a/package/mesa3d/0005-src-util-futex.h-fix-build-on-32-bit-architectures-u.patch +++ /dev/null @@ -1,43 +0,0 @@ -From e501b7c17ada9c694d3f8302622b78d733485b38 Mon Sep 17 00:00:00 2001 -From: Fabrice Fontaine -Date: Sat, 21 Aug 2021 17:55:33 +0200 -Subject: [PATCH] src/util/futex.h: fix build on 32-bit architectures using - 64-bit time_t - -Fix the following build failure on 32-bit architectures using 64-bit -time_t (e.g. riscv32): - -../src/util/futex.h: In function 'sys_futex': -../src/util/futex.h:39:19: error: 'SYS_futex' undeclared (first use in this function); did you mean 'sys_futex'? - 39 | return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3); - | ^~~~~~~~~ - | sys_futex - -Fixes: - - http://autobuild.buildroot.org/results/692700a5f967760a0b8cd358b1712f1d5a7b681e - -Signed-off-by: Fabrice Fontaine -[Upstream status: -https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12496] ---- - src/util/futex.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/util/futex.h b/src/util/futex.h -index 43097f4cd5b..221eda9db0c 100644 ---- a/src/util/futex.h -+++ b/src/util/futex.h -@@ -34,6 +34,10 @@ - #include - #include - -+#ifndef SYS_futex -+#define SYS_futex SYS_futex_time64 -+#endif -+ - static inline long sys_futex(void *addr1, int op, int val1, const struct timespec *timeout, void *addr2, int val3) - { - return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3); --- -2.32.0 - diff --git a/package/mesa3d/0006-Add-EGL_IMG_cl_image-extension.patch b/package/mesa3d/0006-Add-EGL_IMG_cl_image-extension.patch new file mode 100644 index 00000000..ce4d2cfe --- /dev/null +++ b/package/mesa3d/0006-Add-EGL_IMG_cl_image-extension.patch @@ -0,0 +1,187 @@ +From e89ccf17b6a484d74fc1f0a45266ffc8f7fc3fec Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Tue, 11 Mar 2014 11:50:53 +0000 +Subject: [PATCH 06/50] 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 e668798e87f..06eab0da5aa 100644 +--- a/include/GL/internal/dri_interface.h ++++ b/include/GL/internal/dri_interface.h +@@ -1807,6 +1807,19 @@ struct __DRIimageExtensionRec { + uint32_t flags, + unsigned *error, + 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 4f52985c48e..fb5d5617511 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -1008,6 +1008,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) +@@ -2373,17 +2377,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 * +@@ -2462,7 +2462,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); +@@ -2923,7 +2965,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; +@@ -3159,6 +3201,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 df0a0011dbf..e08b525c319 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.17.1 + diff --git a/package/mesa3d/0007-egl_dri2-set-pbuffer-config-attribs-to-0-for-non-pbu.patch b/package/mesa3d/0007-egl_dri2-set-pbuffer-config-attribs-to-0-for-non-pbu.patch new file mode 100644 index 00000000..5b10912b --- /dev/null +++ b/package/mesa3d/0007-egl_dri2-set-pbuffer-config-attribs-to-0-for-non-pbu.patch @@ -0,0 +1,66 @@ +From 090a4c570fb58b5cd55a7628e6805cf16b36b030 Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Wed, 4 Jun 2014 13:43:03 +0100 +Subject: [PATCH 07/50] 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 fb5d5617511..a47589d929f 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -415,6 +415,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 }; +@@ -536,11 +537,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; +@@ -553,6 +560,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.17.1 + diff --git a/package/mesa3d/0008-egl-Be-stricter-when-making-a-context-current-withou.patch b/package/mesa3d/0008-egl-Be-stricter-when-making-a-context-current-withou.patch new file mode 100644 index 00000000..de11b134 --- /dev/null +++ b/package/mesa3d/0008-egl-Be-stricter-when-making-a-context-current-withou.patch @@ -0,0 +1,51 @@ +From 9aab53e750f23aa9e2d8f1bfb2d9f6ff4ac3155a Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Wed, 18 Jun 2014 17:10:28 +0100 +Subject: [PATCH 08/50] egl: Be stricter when making a context current without + any surfaces + +The EGL_KHR_surfaceless_context extension spec states for eglMakeCurrent: + "If does not support being bound without read and draw + surfaces, and both and 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 e08b525c319..9d90f503cc5 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.17.1 + diff --git a/package/mesa3d/0009-egl-optimise-eglMakeCurrent-for-the-case-where-nothi.patch b/package/mesa3d/0009-egl-optimise-eglMakeCurrent-for-the-case-where-nothi.patch new file mode 100644 index 00000000..d2339659 --- /dev/null +++ b/package/mesa3d/0009-egl-optimise-eglMakeCurrent-for-the-case-where-nothi.patch @@ -0,0 +1,46 @@ +From 0b65066319eff5c482614574d4a4192454837835 Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Tue, 15 Sep 2015 14:15:31 +0100 +Subject: [PATCH 09/50] 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 9d90f503cc5..bc7014ef8ed 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.17.1 + diff --git a/package/mesa3d/0010-GL_EXT_shader_pixel_local_storage2-entry-points.patch b/package/mesa3d/0010-GL_EXT_shader_pixel_local_storage2-entry-points.patch new file mode 100644 index 00000000..fa27b5a8 --- /dev/null +++ b/package/mesa3d/0010-GL_EXT_shader_pixel_local_storage2-entry-points.patch @@ -0,0 +1,84 @@ +From 921ab82e655c9a3ffab6e39847a7d2d61338221e Mon Sep 17 00:00:00 2001 +From: Rufus Hamade +Date: Thu, 4 Feb 2016 14:09:26 +0000 +Subject: [PATCH 10/50] 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 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml +index 42f4b2b80fb..c7fde29732a 100644 +--- a/src/mapi/glapi/gen/es_EXT.xml ++++ b/src/mapi/glapi/gen/es_EXT.xml +@@ -1459,6 +1459,9 @@ + + + ++ ++ ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index b23ae713f6f..1ace5e201d8 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1685,6 +1685,9 @@ offsets = { + "WeightPointerOES" : 1649, + "RenderbufferStorageMultisampleIMG" : 1650, + "FramebufferTexture2DMultisampleIMG" : 1651, ++ "ClearPixelLocalStorageuiEXT" : 1652, ++ "FramebufferPixelLocalStorageSizeEXT" : 1653, ++ "GetFramebufferPixelLocalStorageSizeEXT" : 1654, + } + + functions = [ +-- +2.17.1 + diff --git a/package/mesa3d/0011-GL_IMG_framebuffer_downsample-entry-points.patch b/package/mesa3d/0011-GL_IMG_framebuffer_downsample-entry-points.patch new file mode 100644 index 00000000..6d8c842b --- /dev/null +++ b/package/mesa3d/0011-GL_IMG_framebuffer_downsample-entry-points.patch @@ -0,0 +1,85 @@ +From 67428e8b27839095214419dabccaeffab923a89b Mon Sep 17 00:00:00 2001 +From: Rufus Hamade +Date: Thu, 4 Feb 2016 14:09:26 +0000 +Subject: [PATCH 11/50] 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 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml +index c7fde29732a..6aea8c55fac 100644 +--- a/src/mapi/glapi/gen/es_EXT.xml ++++ b/src/mapi/glapi/gen/es_EXT.xml +@@ -1462,6 +1462,9 @@ + + + ++ ++ ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index 1ace5e201d8..2838a4451a2 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1688,6 +1688,8 @@ offsets = { + "ClearPixelLocalStorageuiEXT" : 1652, + "FramebufferPixelLocalStorageSizeEXT" : 1653, + "GetFramebufferPixelLocalStorageSizeEXT" : 1654, ++ "FramebufferTexture2DDownsampleIMG" : 1655, ++ "FramebufferTextureLayerDownsampleIMG" : 1656, + } + + functions = [ +-- +2.17.1 + diff --git a/package/mesa3d/0012-GL_OVR_multiview-entry-points.patch b/package/mesa3d/0012-GL_OVR_multiview-entry-points.patch new file mode 100644 index 00000000..3d0c9194 --- /dev/null +++ b/package/mesa3d/0012-GL_OVR_multiview-entry-points.patch @@ -0,0 +1,53 @@ +From 5aed29849109fcb20934186b9f4ffc0606b40f8e Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Mon, 11 Jul 2016 12:45:30 +0100 +Subject: [PATCH 12/50] 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 dcdbe80290c..d6fae3b1988 100644 +--- a/src/mapi/glapi/gen/gl_API.xml ++++ b/src/mapi/glapi/gen/gl_API.xml +@@ -13101,6 +13101,23 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index 2838a4451a2..015e4efed7a 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1690,6 +1690,7 @@ offsets = { + "GetFramebufferPixelLocalStorageSizeEXT" : 1654, + "FramebufferTexture2DDownsampleIMG" : 1655, + "FramebufferTextureLayerDownsampleIMG" : 1656, ++ "FramebufferTextureMultiviewOVR" : 1657, + } + + functions = [ +-- +2.17.1 + diff --git a/package/mesa3d/0013-Add-OVR_multiview_multisampled_render_to_texture.patch b/package/mesa3d/0013-Add-OVR_multiview_multisampled_render_to_texture.patch new file mode 100644 index 00000000..5b4b6a97 --- /dev/null +++ b/package/mesa3d/0013-Add-OVR_multiview_multisampled_render_to_texture.patch @@ -0,0 +1,68 @@ +From 95383627bc57aa19f0e5d40ae8c91f4d91230708 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Mon, 11 Jul 2016 13:29:51 +0100 +Subject: [PATCH 13/50] 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 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml +index 6aea8c55fac..359cc9ca8cf 100644 +--- a/src/mapi/glapi/gen/es_EXT.xml ++++ b/src/mapi/glapi/gen/es_EXT.xml +@@ -1459,6 +1459,9 @@ + + + ++ ++ ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index 015e4efed7a..d13dc915d6f 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1691,6 +1691,7 @@ offsets = { + "FramebufferTexture2DDownsampleIMG" : 1655, + "FramebufferTextureLayerDownsampleIMG" : 1656, + "FramebufferTextureMultiviewOVR" : 1657, ++ "FramebufferTextureMultisampleMultiviewOVR" : 1658, + } + + functions = [ +-- +2.17.1 + diff --git a/package/mesa3d/0014-wayland-drm-install-wayland-drm.xml-to-the-configure.patch b/package/mesa3d/0014-wayland-drm-install-wayland-drm.xml-to-the-configure.patch new file mode 100644 index 00000000..ec193ed7 --- /dev/null +++ b/package/mesa3d/0014-wayland-drm-install-wayland-drm.xml-to-the-configure.patch @@ -0,0 +1,57 @@ +From 2d7c499fe386f83e6f77ddc1e9dbd437e5dbe59a Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Thu, 18 Aug 2016 15:52:28 +0100 +Subject: [PATCH 14/50] 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.17.1 + diff --git a/package/mesa3d/0015-Enable-buffer-sharing-in-the-kms_swrast-driver.patch b/package/mesa3d/0015-Enable-buffer-sharing-in-the-kms_swrast-driver.patch new file mode 100644 index 00000000..4ca56a92 --- /dev/null +++ b/package/mesa3d/0015-Enable-buffer-sharing-in-the-kms_swrast-driver.patch @@ -0,0 +1,27 @@ +From 2cc857d6ae366e5599a7d39b975ab030ec915001 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Wed, 26 Oct 2016 16:24:28 +0100 +Subject: [PATCH 15/50] 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 b0c0d7eafbe..d78e1638d1d 100644 +--- a/src/gallium/frontends/dri/dri2.c ++++ b/src/gallium/frontends/dri/dri2.c +@@ -2300,7 +2300,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.17.1 + diff --git a/package/mesa3d/0016-egl-wayland-add-support-for-RGB565-back-buffers.patch b/package/mesa3d/0016-egl-wayland-add-support-for-RGB565-back-buffers.patch new file mode 100644 index 00000000..5e34e537 --- /dev/null +++ b/package/mesa3d/0016-egl-wayland-add-support-for-RGB565-back-buffers.patch @@ -0,0 +1,46 @@ +From 39233fe0599c68e7b20e4074b0aa7c8e639f648b Mon Sep 17 00:00:00 2001 +From: James Glanville +Date: Tue, 28 Feb 2017 16:08:47 +0000 +Subject: [PATCH 16/50] 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 f65d9e45d8f..6eb2c7cbdf6 100644 +--- a/src/egl/drivers/dri2/platform_wayland.c ++++ b/src/egl/drivers/dri2/platform_wayland.c +@@ -647,18 +647,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.17.1 + diff --git a/package/mesa3d/0017-egl-dri3-fix-segfault-in-eglCopyBuffers.patch b/package/mesa3d/0017-egl-dri3-fix-segfault-in-eglCopyBuffers.patch new file mode 100644 index 00000000..68136982 --- /dev/null +++ b/package/mesa3d/0017-egl-dri3-fix-segfault-in-eglCopyBuffers.patch @@ -0,0 +1,49 @@ +From ef372bd8c5ee377bac81f22174b9e01a30cffe53 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Thu, 13 Apr 2017 10:12:40 +0100 +Subject: [PATCH 17/50] 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 ccf8d1795e7..0f7cf0d186c 100644 +--- a/src/loader/loader_dri3_helper.c ++++ b/src/loader/loader_dri3_helper.c +@@ -858,15 +858,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.17.1 + diff --git a/package/mesa3d/0018-egl-automatically-call-eglReleaseThread-on-thread-te.patch b/package/mesa3d/0018-egl-automatically-call-eglReleaseThread-on-thread-te.patch new file mode 100644 index 00000000..5c0709ba --- /dev/null +++ b/package/mesa3d/0018-egl-automatically-call-eglReleaseThread-on-thread-te.patch @@ -0,0 +1,78 @@ +From ce5d9f5a0a95658e2c9d54726bcd8986d7e2be4a Mon Sep 17 00:00:00 2001 +From: Iosif Antochi +Date: Wed, 14 Jun 2017 14:49:55 +0100 +Subject: [PATCH 18/50] 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 29be4268025..e93793a6073 100644 +--- a/src/egl/main/eglcurrent.c ++++ b/src/egl/main/eglcurrent.c +@@ -43,6 +43,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 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.17.1 + diff --git a/package/mesa3d/0019-egl-add-Tizen-platform-support.patch b/package/mesa3d/0019-egl-add-Tizen-platform-support.patch new file mode 100644 index 00000000..a72ceee3 --- /dev/null +++ b/package/mesa3d/0019-egl-add-Tizen-platform-support.patch @@ -0,0 +1,1637 @@ +From bbef8a8f66f7f5ac6714a2d3f77a323a2d38a493 Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Fri, 6 Jan 2017 16:35:00 +0000 +Subject: [PATCH 19/50] egl: add Tizen platform support + +Add a new "tizen" platform to support drm/gbm and Wayland on Tizen. +The platform can be enabled by passing "-Dplatforms=tizen" to Meson. +--- + meson.build | 27 +- + meson_options.txt | 2 +- + src/egl/drivers/dri2/egl_dri2.c | 182 ++++- + src/egl/drivers/dri2/egl_dri2.h | 59 +- + src/egl/drivers/dri2/platform_tizen.c | 980 ++++++++++++++++++++++++++ + src/egl/main/eglapi.c | 7 + + src/egl/main/egldisplay.c | 32 +- + src/egl/main/egldisplay.h | 7 + + src/egl/main/egllog.c | 27 +- + src/egl/meson.build | 9 +- + 10 files changed, 1316 insertions(+), 16 deletions(-) + create mode 100644 src/egl/drivers/dri2/platform_tizen.c + +diff --git a/meson.build b/meson.build +index 15e08dfea1c..c90e44254d2 100644 +--- a/meson.build ++++ b/meson.build +@@ -346,6 +346,11 @@ with_platform_x11 = _platforms.contains('x11') + with_platform_wayland = _platforms.contains('wayland') + with_platform_haiku = _platforms.contains('haiku') + with_platform_windows = _platforms.contains('windows') ++with_platform_tizen = _platforms.contains('tizen') ++ ++if with_platform_tizen and _platforms.length() != 1 ++ error('tizen cannot be enabled at the same time as other platforms') ++endif + + if _platforms.length() != 0 + egl_native_platform = _platforms[0] +@@ -859,7 +864,7 @@ else + pre_args += '-DEGL_NO_X11' + gl_pkgconfig_c_flags += '-DEGL_NO_X11' + endif +-if with_gbm ++if with_gbm and not with_platform_tizen + pre_args += '-DHAVE_DRM_PLATFORM' + endif + +@@ -889,6 +894,15 @@ endif + if with_platform_haiku + pre_args += '-DHAVE_HAIKU_PLATFORM' + endif ++if with_platform_tizen ++ dep_dlog = dependency('dlog') ++ dep_tizen = [ ++ dep_dlog, ++ dependency('libtbm'), ++ dependency('tpl-egl'), ++ ] ++ pre_args += '-DHAVE_TIZEN_PLATFORM' ++endif + + prog_python = import('python').find_installation('python3') + has_mako = run_command( +@@ -1487,7 +1501,8 @@ with_gallium_drisw_kms = false + dep_libdrm = dependency( + 'libdrm', version : '>=' + _drm_ver, + # GNU/Hurd includes egl_dri2, without drm. +- required : (with_dri2 and host_machine.system() != 'gnu') or with_dri3 ++ required : (with_dri2 and host_machine.system() != 'gnu') or with_dri3 or ++ with_platform_tizen + ) + if dep_libdrm.found() + pre_args += '-DHAVE_LIBDRM' +@@ -2028,9 +2043,11 @@ if with_egl + endif + lines += 'GBM: ' + (with_gbm ? 'yes' : 'no') + if with_egl or with_any_vk +- _platforms += 'surfaceless' +- if with_gbm +- _platforms += 'drm' ++ if not with_platform_tizen ++ _platforms += 'surfaceless' ++ if with_gbm ++ _platforms += 'drm' ++ endif + endif + lines += 'EGL/Vulkan/VL platforms: ' + ' '.join(_platforms) + endif +diff --git a/meson_options.txt b/meson_options.txt +index 6f001343ae6..b2ba2d8d979 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -23,7 +23,7 @@ option( + type : 'array', + value : ['auto'], + choices : [ +- 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', ++ 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', 'tizen', + ], + description : 'window systems to support. If this is set to `auto`, all platforms applicable will be enabled.' + ) +diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c +index a47589d929f..e9f745e4258 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -1208,6 +1208,11 @@ dri2_initialize(_EGLDisplay *disp) + case _EGL_PLATFORM_ANDROID: + ret = dri2_initialize_android(disp); + break; ++#ifdef HAVE_TIZEN_PLATFORM ++ case _EGL_PLATFORM_TIZEN: ++ ret = dri2_initialize_tizen(disp); ++ break; ++#endif + default: + unreachable("Callers ensure we cannot get here."); + return EGL_FALSE; +@@ -1282,6 +1287,12 @@ dri2_display_destroy(_EGLDisplay *disp) + case _EGL_PLATFORM_WAYLAND: + dri2_teardown_wayland(dri2_dpy); + break; ++#ifdef HAVE_TIZEN_PLATFORM ++ case _EGL_PLATFORM_TIZEN: ++ if (dri2_dpy->tpl_dpy) ++ tpl_object_unreference((tpl_object_t *) dri2_dpy->tpl_dpy); ++ break; ++#endif + default: + /* TODO: add teardown for other platforms */ + break; +@@ -2322,8 +2333,96 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, + return dri2_create_image_from_dri(disp, dri_image); + } + +-#ifdef HAVE_WAYLAND_PLATFORM ++#ifdef HAVE_TIZEN_PLATFORM ++int ++dri2_fourcc_from_tbm_format(tbm_format format) ++{ ++ switch (format) { ++ case TBM_FORMAT_ARGB8888: ++ return DRM_FORMAT_ARGB8888; ++ case TBM_FORMAT_XRGB8888: ++ return DRM_FORMAT_XRGB8888; ++ case TBM_FORMAT_RGB565: ++ return DRM_FORMAT_RGB565; ++ default: ++ _eglLog(_EGL_DEBUG, "%s: unsupported tbm format %#x", __func__, format); ++ return 0; ++ } ++} + ++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); ++ if (!tbm_surf) { ++ _eglError(EGL_BAD_PARAMETER, "tpl_display_get_buffer_from_native_pixmap"); ++ return NULL; ++ } ++ ++ if (!_eglParseImageAttribList(&attrs, disp, attr_list)) { ++ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer_tizen"); ++ return NULL; ++ } ++ ++ if (tbm_surface_get_info(tbm_surf, &info)) { ++ _eglError(EGL_BAD_PARAMETER, "tbm_surface_get_info"); ++ return NULL; ++ } ++ ++ if (info.num_planes > 1) { ++ _eglError(EGL_BAD_PARAMETER, ++ "dri2_create_image_wayland_wl_buffer_tizen (multi-plane format)"); ++ return NULL; ++ } ++ ++ if (attrs.PlaneWL < 0 || attrs.PlaneWL >= info.num_planes) { ++ _eglError(EGL_BAD_PARAMETER, ++ "dri2_create_image_wayland_wl_buffer_tizen (plane out of bounds)"); ++ 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); ++} ++#endif ++ ++#ifdef HAVE_WAYLAND_PLATFORM + /* This structure describes how a wl_buffer maps to one or more + * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the + * offsets and strides of the planes in the buffer. This table maps a +@@ -3216,6 +3315,10 @@ dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, + #ifdef HAVE_WAYLAND_PLATFORM + case EGL_WAYLAND_BUFFER_WL: + return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); ++#endif ++#ifdef HAVE_TIZEN_PLATFORM ++ case EGL_WAYLAND_BUFFER_WL: ++ return dri2_create_image_wayland_wl_buffer_tizen(disp, ctx, buffer, attr_list); + #endif + case EGL_CL_IMAGE_IMG: + return dri2_create_image_img_buffer(disp, ctx, target, buffer, attr_list); +@@ -3237,6 +3340,78 @@ dri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image) + return EGL_TRUE; + } + ++#ifdef HAVE_TIZEN_PLATFORM ++ ++static EGLint get_texture_format_from_gbm_format(tbm_format format) ++{ ++ switch (format) { ++ case TBM_FORMAT_ARGB8888: ++ return EGL_TEXTURE_RGBA; ++ default: ++ _eglLog(_EGL_DEBUG, "%s: unsupported tbm format %#x", __func__, format); ++ return 0; ++ } ++} ++ ++static EGLBoolean ++dri2_bind_wayland_display_wl_tizen(_EGLDisplay *disp, struct wl_display *wl_dpy) ++{ ++ (void) disp; ++ (void) wl_dpy; ++ ++ return EGL_TRUE; ++} ++ ++static EGLBoolean ++dri2_unbind_wayland_display_wl_tizen(_EGLDisplay *disp, ++ struct wl_display *wl_dpy) ++{ ++ (void) disp; ++ (void) wl_dpy; ++ ++ return EGL_TRUE; ++} ++ ++static EGLBoolean ++dri2_query_wayland_buffer_wl_tizen(_EGLDisplay *disp, ++ struct wl_resource *buffer_resource, ++ EGLint attribute, EGLint *value) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); ++ tpl_handle_t pixmap = (tpl_handle_t) buffer_resource; ++ tbm_surface_h tbm_surf; ++ tbm_format format; ++ EGLint tex_format; ++ ++ tbm_surf = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_dpy, ++ pixmap); ++ if (!tbm_surf) ++ return EGL_FALSE; ++ ++ switch (attribute) { ++ case EGL_TEXTURE_FORMAT: ++ format = tbm_surface_get_format(tbm_surf); ++ tex_format = get_texture_format_from_gbm_format(format); ++ if (!tex_format) ++ return EGL_FALSE; ++ ++ *value = tex_format; ++ break; ++ case EGL_WIDTH: ++ *value = tbm_surface_get_width(tbm_surf); ++ break; ++ case EGL_HEIGHT: ++ *value = tbm_surface_get_height(tbm_surf); ++ break; ++ default: ++ return EGL_FALSE; ++ } ++ ++ return EGL_TRUE; ++} ++ ++#endif ++ + #ifdef HAVE_WAYLAND_PLATFORM + + static void +@@ -3767,6 +3942,11 @@ const _EGLDriver _eglDriver = { + .BindWaylandDisplayWL = dri2_bind_wayland_display_wl, + .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl, + .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl, ++#endif ++#ifdef HAVE_TIZEN_PLATFORM ++ .BindWaylandDisplayWL = dri2_bind_wayland_display_wl_tizen, ++ .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl_tizen, ++ .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl_tizen, + #endif + .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium, + .CreateSyncKHR = dri2_create_sync, +diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h +index d7f9696da93..4d66936da28 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -62,13 +62,19 @@ struct zwp_linux_dmabuf_v1; + #include + #endif + +-#ifdef HAVE_ANDROID_PLATFORM + #define LOG_TAG "EGL-DRI2" + ++#ifdef HAVE_ANDROID_PLATFORM + #include + #include + #endif /* HAVE_ANDROID_PLATFORM */ + ++#ifdef HAVE_TIZEN_PLATFORM ++#include ++#include ++#include ++#endif ++ + #include "eglconfig.h" + #include "eglcontext.h" + #include "egldevice.h" +@@ -251,6 +257,10 @@ struct dri2_egl_display + + bool is_render_node; + bool is_different_gpu; ++ ++#ifdef HAVE_TIZEN_PLATFORM ++ tpl_display_t *tpl_dpy; ++#endif + }; + + struct dri2_egl_context +@@ -268,6 +278,18 @@ enum wayland_buffer_type { + }; + #endif + ++#define DRI2_SURFACE_NUM_COLOR_BUFFERS 4 ++ ++#ifdef HAVE_TIZEN_PLATFORM ++struct tpl_swap_queue_elem ++{ ++ tbm_surface_h tbm_surf; ++ EGLint *rects; ++ EGLint n_rects_max; ++ EGLint n_rects; ++}; ++#endif ++ + struct dri2_egl_surface + { + _EGLSurface base; +@@ -300,15 +322,33 @@ struct dri2_egl_surface + struct gbm_dri_surface *gbm_surf; + #endif + ++#ifdef HAVE_TIZEN_PLATFORM ++ tpl_surface_t *tpl_surf; ++ bool reset; ++ /* ++ * 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]; ++ int swap_queue_idx_head; ++ int swap_queue_idx_tail; ++ pthread_t swap_queue_processor; ++#endif ++ + /* EGL-owned buffers */ + __DRIbuffer *local_buffers[__DRI_BUFFER_COUNT]; + +-#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM) ++#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM) || \ ++ defined(HAVE_TIZEN_PLATFORM) + struct { ++#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_TIZEN_PLATFORM) ++ __DRIimage *dri_image; ++#endif + #ifdef HAVE_WAYLAND_PLATFORM + struct wl_buffer *wl_buffer; + bool wl_release; +- __DRIimage *dri_image; + /* for is_different_gpu case. NULL else */ + __DRIimage *linear_copy; + /* for swrast */ +@@ -317,6 +357,9 @@ struct dri2_egl_surface + #endif + #ifdef HAVE_DRM_PLATFORM + struct gbm_bo *bo; ++#endif ++#ifdef HAVE_TIZEN_PLATFORM ++ tbm_surface_h tbm_surf; + #endif + bool locked; + int age; +@@ -516,6 +559,11 @@ dri2_initialize_android(_EGLDisplay *disp) + EGLBoolean + dri2_initialize_surfaceless(_EGLDisplay *disp); + ++#ifdef HAVE_TIZEN_PLATFORM ++EGLBoolean ++dri2_initialize_tizen(_EGLDisplay *disp); ++#endif ++ + EGLBoolean + dri2_initialize_device(_EGLDisplay *disp); + static inline void +@@ -550,6 +598,11 @@ dri2_set_WL_bind_wayland_display(_EGLDisplay *disp) + #endif + } + ++#ifdef HAVE_TIZEN_PLATFORM ++int ++dri2_fourcc_from_tbm_format(tbm_format format); ++#endif ++ + void + dri2_display_destroy(_EGLDisplay *disp); + +diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c +new file mode 100644 +index 00000000000..a08bc8c07bf +--- /dev/null ++++ b/src/egl/drivers/dri2/platform_tizen.c +@@ -0,0 +1,980 @@ ++/* ++ * Mesa 3-D graphics library ++ * ++ * Copyright (c) Imagination Technologies Ltd. ++ * Copyright © 2011 Intel Corporation ++ * ++ * 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 ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "egl_dri2.h" ++#include "loader.h" ++ ++#define TIZEN_DRM_RENDER_MINOR_START 128 ++#define TIZEN_DRM_RENDER_MINOR_MAX 191 ++ ++#define TIZEN_SWAP_N_RECTS_MIN 32 ++ ++struct rgba_shifts_and_sizes { ++ int shifts[4]; ++ unsigned int sizes[4]; ++}; ++ ++static void *swap_queue_processor_worker(void *data) ++{ ++ struct dri2_egl_surface *dri2_surf = data; ++ ++ pthread_mutex_lock(&dri2_surf->mutex); ++ while (1) { ++ struct tpl_swap_queue_elem *queue_elem; ++ int i; ++ tpl_result_t res; ++ ++ if (dri2_surf->swap_queue_idx_head == dri2_surf->swap_queue_idx_tail) { ++ /* Wait for new swaps to be added to the queue */ ++ pthread_cond_wait(&dri2_surf->swap_queue_cond, &dri2_surf->mutex); ++ continue; ++ } ++ ++ queue_elem = &dri2_surf->swap_queue[dri2_surf->swap_queue_idx_head]; ++ pthread_mutex_unlock(&dri2_surf->mutex); ++ ++ res = tpl_surface_enqueue_buffer_with_damage(dri2_surf->tpl_surf, ++ queue_elem->tbm_surf, ++ queue_elem->n_rects, ++ queue_elem->rects); ++ if (res != TPL_ERROR_NONE) ++ return NULL; ++ ++ pthread_mutex_lock(&dri2_surf->mutex); ++ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { ++ if (dri2_surf->color_buffers[i].tbm_surf == queue_elem->tbm_surf) { ++ dri2_surf->color_buffers[i].locked = false; ++ break; ++ } ++ } ++ ++ 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, reset_surface_cb ++ * that it may be able to reset the surface or dri2_tizen_destroy_surface ++ * that it may be able to proceed with surface destruction. ++ */ ++ pthread_cond_signal(&dri2_surf->swap_queue_cond); ++ } ++ pthread_mutex_unlock(&dri2_surf->mutex); ++ ++ return NULL; ++} ++ ++static __DRIimage * ++create_image_from_native(struct dri2_egl_surface *dri2_surf, ++ tbm_surface_h tbm_surf, ++ int *width, int *height, ++ void *loaderPrivate) ++{ ++ _EGLSurface *surf = &dri2_surf->base; ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(surf->Resource.Display); ++ tbm_bo tbm_buf; ++ tbm_surface_info_s info; ++ int fd, fourcc, offset, pitch; ++ __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; ++ } ++ ++ 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); ++ ++ if (!dri_image) { ++ _eglLog(_EGL_DEBUG, "%s: failed to create dri image from tbm bo", __func__); ++ return NULL; ++ } ++ ++ if (width) ++ *width = info.width; ++ ++ if (height) ++ *height = info.height; ++ ++ return dri_image; ++} ++ ++static int ++get_back_bo(struct dri2_egl_surface *dri2_surf, bool allow_update) ++{ ++ struct dri2_egl_display *dri2_dpy = ++ dri2_egl_display(dri2_surf->base.Resource.Display); ++ tbm_surface_h tbm_surf; ++ tpl_bool_t tpl_surf_valid; ++ int i; ++ ++ if (dri2_surf->base.Type == EGL_PIXMAP_BIT) { ++ _eglLog(_EGL_DEBUG, "%s: can't get back bo for pixmap surface", __func__); ++ return -1; ++ } ++ ++ if (dri2_surf->back && !allow_update) ++ return 0; ++ ++ /* ++ * If the tpl surface is no longer valid, e.g. it has been resized, then ++ * we should get a new back buffer. ++ */ ++ tpl_surf_valid = tpl_surface_validate(dri2_surf->tpl_surf); ++ if (dri2_surf->back && tpl_surf_valid == TPL_TRUE) ++ return 0; ++ ++ tbm_surf = tpl_surface_dequeue_buffer(dri2_surf->tpl_surf); ++ if (!tbm_surf) { ++ _eglLog(_EGL_DEBUG, "%s: surface buffer dequeue failed", __func__); ++ return -1; ++ } ++ ++ pthread_mutex_lock(&dri2_surf->mutex); ++ /* ++ * If the tpl surface is no longer valid, e.g. it has been resized, then the ++ * call to tpl_surface should've resulted in a call to reset_surface_cb, ++ * which sets the dri2_surf reset flag. In this case we need to reset the ++ * color_buffer state. ++ * ++ * Note: we can't rely on the return value of tpl_surface_validate ++ * since the surface may have become invalid between this call and ++ * tpl_surface_dequeue_buffer. ++ */ ++ if (dri2_surf->reset) { ++ /* 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_queue_cond, &dri2_surf->mutex); ++ ++ /* Cancel the old back buffer */ ++ if (dri2_surf->back) { ++ tbm_surface_internal_unref(dri2_surf->back->tbm_surf); ++ dri2_surf->back->locked = false; ++ dri2_surf->back = NULL; ++ } ++ ++ /* Reset the color buffers */ ++ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { ++ assert(!dri2_surf->color_buffers[i].locked); ++ ++ if (dri2_surf->color_buffers[i].dri_image) { ++ dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image); ++ dri2_surf->color_buffers[i].dri_image = NULL; ++ } ++ ++ dri2_surf->color_buffers[i].tbm_surf = NULL; ++ dri2_surf->color_buffers[i].age = 0; ++ } ++ ++ dri2_surf->back = NULL; ++ dri2_surf->current = NULL; ++ dri2_surf->reset = false; ++ } ++ ++ assert(!dri2_surf->back); ++ ++ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { ++ if (dri2_surf->color_buffers[i].tbm_surf == tbm_surf) { ++ dri2_surf->back = &dri2_surf->color_buffers[i]; ++ assert(!dri2_surf->back->locked); ++ break; ++ } ++ } ++ ++ while (!dri2_surf->back) { ++ int age; ++ ++ /* ++ * Search for a free color buffer. Free the oldest buffer if one ++ * cannot be found. ++ */ ++ for (i = 0, age = -1; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { ++ if (dri2_surf->color_buffers[i].locked) ++ continue; ++ if (!dri2_surf->color_buffers[i].dri_image) { ++ dri2_surf->back = &dri2_surf->color_buffers[i]; ++ break; ++ } ++ ++ if (dri2_surf->color_buffers[i].age > age) { ++ dri2_surf->back = &dri2_surf->color_buffers[i]; ++ age = dri2_surf->color_buffers[i].age; ++ } ++ } ++ ++ if (!dri2_surf->back) { ++ /* ++ * There aren't any available back buffers so wait for ++ * swap_queue_processor_worker to make one available. ++ */ ++ pthread_cond_wait(&dri2_surf->swap_queue_cond, &dri2_surf->mutex); ++ continue; ++ } ++ ++ if (dri2_surf->back->dri_image) ++ dri2_dpy->image->destroyImage(dri2_surf->back->dri_image); ++ ++ dri2_surf->back->dri_image = ++ create_image_from_native(dri2_surf, tbm_surf, ++ &dri2_surf->base.Width, ++ &dri2_surf->base.Height, ++ dri2_surf); ++ if (!dri2_surf->back->dri_image) { ++ dri2_surf->back = NULL; ++ pthread_mutex_unlock(&dri2_surf->mutex); ++ return -1; ++ } ++ } ++ ++ dri2_surf->back->tbm_surf = tbm_surf; ++ dri2_surf->back->locked = true; ++ ++ if (dri2_surf->base.SwapBehavior == EGL_BUFFER_PRESERVED && ++ dri2_surf->current) { ++ _EGLContext *ctx = _eglGetCurrentContext(); ++ struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); ++ ++ if (dri2_ctx) ++ { ++ dri2_dpy->image->blitImage(dri2_ctx->dri_context, ++ dri2_surf->back->dri_image, ++ dri2_surf->current->dri_image, ++ 0, 0, dri2_surf->base.Width, ++ dri2_surf->base.Height, ++ 0, 0, dri2_surf->base.Width, ++ dri2_surf->base.Height, ++ __BLIT_FLAG_FLUSH); ++ } ++ } ++ ++ pthread_mutex_unlock(&dri2_surf->mutex); ++ ++ return 0; ++} ++ ++static int ++get_front_bo(struct dri2_egl_surface *dri2_surf) ++{ ++ struct dri2_egl_display *dri2_dpy = ++ dri2_egl_display(dri2_surf->base.Resource.Display); ++ ++ if (dri2_surf->front) ++ return 0; ++ ++ if (dri2_surf->base.Type == EGL_PIXMAP_BIT) { ++ tbm_surface_h tbm_surf; ++ ++ tbm_surf = tpl_surface_dequeue_buffer(dri2_surf->tpl_surf); ++ if (!tbm_surf) ++ return -1; ++ ++ dri2_surf->front = create_image_from_native(dri2_surf, tbm_surf, ++ &dri2_surf->base.Width, ++ &dri2_surf->base.Height, ++ dri2_surf); ++ } else { ++ dri2_surf->front = dri2_dpy->image->createImage(dri2_dpy->dri_screen, ++ dri2_surf->base.Width, ++ dri2_surf->base.Height, ++ dri2_surf->visual, ++ 0, ++ dri2_surf); ++ } ++ ++ return dri2_surf->front ? 0 : -1; ++} ++ ++static _EGLSurface * ++create_surface(_EGLDisplay *dpy, _EGLConfig *config, EGLint type, ++ const EGLint *attrib_list) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); ++ struct dri2_egl_config *dri2_config = dri2_egl_config(config); ++ struct dri2_egl_surface *dri2_surf; ++ const __DRIconfig *dri_config; ++ ++ dri2_surf = calloc(1, sizeof(*dri2_surf)); ++ if (!dri2_surf) { ++ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create surface"); ++ return NULL; ++ } ++ ++ if (!dri2_init_surface(&dri2_surf->base, dpy, type, config, attrib_list, ++ false, NULL)) ++ goto err_free_surface; ++ ++ dri_config = dri2_get_dri_config(dri2_config, type, ++ dri2_surf->base.GLColorspace); ++ if (!dri_config) { ++ _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); ++ goto err_free_surface; ++ } ++ ++ dri2_surf->dri_drawable = ++ dri2_dpy->image_driver->createNewDrawable(dri2_dpy->dri_screen, ++ dri_config, dri2_surf); ++ if (!dri2_surf->dri_drawable) { ++ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create drawable"); ++ goto err_free_surface; ++ } ++ ++ pthread_mutex_init(&dri2_surf->mutex, NULL); ++ pthread_cond_init(&dri2_surf->swap_queue_cond, NULL); ++ ++ return &dri2_surf->base; ++ ++err_free_surface: ++ free(dri2_surf); ++ return NULL; ++} ++ ++static void ++destroy_surface(_EGLSurface *surf) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(surf->Resource.Display); ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); ++ ++ pthread_cond_destroy(&dri2_surf->swap_queue_cond); ++ pthread_mutex_destroy(&dri2_surf->mutex); ++ dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); ++ free(dri2_surf); ++} ++ ++static void ++reset_surface_cb(void *data) ++{ ++ struct dri2_egl_surface *dri2_surf = data; ++ ++ dri2_surf->reset = true; ++} ++ ++static _EGLSurface * ++dri2_tizen_create_window_surface(_EGLDisplay *dpy, _EGLConfig *config, ++ void *native_window, const EGLint *attrib_list) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); ++ struct dri2_egl_surface *dri2_surf; ++ _EGLSurface *surf; ++ int width, height; ++ tbm_format format; ++ tpl_result_t res; ++ int err; ++ ++ surf = create_surface(dpy, config, EGL_WINDOW_BIT, attrib_list); ++ if (!surf) ++ return NULL; ++ ++ res = tpl_display_get_native_window_info(dri2_dpy->tpl_dpy, native_window, ++ &width, &height, &format, ++ config->RedSize + ++ config->GreenSize + ++ config->BlueSize + ++ config->AlphaSize, ++ config->AlphaSize); ++ if (res != TPL_ERROR_NONE) { ++ _eglError(EGL_BAD_NATIVE_WINDOW, "DRI2: failed to get window info"); ++ goto err_destroy_surface; ++ } ++ ++ dri2_surf = dri2_egl_surface(surf); ++ dri2_surf->base.Width = width; ++ dri2_surf->base.Height = height; ++ ++ dri2_surf->tpl_surf = tpl_surface_create(dri2_dpy->tpl_dpy, native_window, ++ TPL_SURFACE_TYPE_WINDOW, format); ++ if (!dri2_surf->tpl_surf) { ++ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create TPL window surface"); ++ goto err_destroy_surface; ++ } ++ ++ res = tpl_surface_set_reset_cb(dri2_surf->tpl_surf, dri2_surf, ++ reset_surface_cb); ++ if (res != TPL_ERROR_NONE) { ++ _eglError(EGL_BAD_NATIVE_WINDOW, ++ "DRI2: failed to register TPL window surface reset callback"); ++ goto err_tpl_surface_destroy; ++ } ++ ++ err = pthread_create(&dri2_surf->swap_queue_processor, NULL, ++ swap_queue_processor_worker, dri2_surf); ++ if (err) { ++ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create TPL window thread"); ++ goto err_tpl_surface_destroy; ++ } ++ ++ return surf; ++ ++err_tpl_surface_destroy: ++ tpl_object_unreference((tpl_object_t *) dri2_surf->tpl_surf); ++err_destroy_surface: ++ destroy_surface(surf); ++ return NULL; ++} ++ ++static _EGLSurface * ++dri2_tizen_create_pixmap_surface(_EGLDisplay *dpy, _EGLConfig *config, ++ void *native_pixmap, const EGLint *attrib_list) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); ++ struct dri2_egl_surface *dri2_surf; ++ _EGLSurface *surf; ++ int width, height; ++ tbm_format format; ++ tpl_result_t res; ++ ++ surf = create_surface(dpy, config, EGL_PIXMAP_BIT, attrib_list); ++ if (!surf) ++ return NULL; ++ ++ res = tpl_display_get_native_pixmap_info(dri2_dpy->tpl_dpy, native_pixmap, ++ &width, &height, &format); ++ if (res != TPL_ERROR_NONE) { ++ _eglError(EGL_BAD_NATIVE_PIXMAP, "DRI2: failed to get pixmap info"); ++ goto err_destroy_surface; ++ } ++ ++ dri2_surf = dri2_egl_surface(surf); ++ dri2_surf->base.Width = width; ++ dri2_surf->base.Height = height; ++ ++ dri2_surf->tpl_surf = tpl_surface_create(dri2_dpy->tpl_dpy, native_pixmap, ++ TPL_SURFACE_TYPE_PIXMAP, format); ++ if (!dri2_surf->tpl_surf) { ++ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create TPL pixmap surface"); ++ goto err_destroy_surface; ++ } ++ ++ return surf; ++ ++err_destroy_surface: ++ destroy_surface(surf); ++ return NULL; ++} ++ ++static _EGLSurface * ++dri2_tizen_create_pbuffer_surface(_EGLDisplay *dpy, _EGLConfig *config, ++ const EGLint *attrib_list) ++{ ++ struct dri2_egl_surface *dri2_surf; ++ _EGLSurface *surf; ++ ++ surf = create_surface(dpy, config, EGL_PBUFFER_BIT, attrib_list); ++ if (!surf) ++ return NULL; ++ ++ dri2_surf = dri2_egl_surface(surf); ++ ++ if (config->RedSize == 5) ++ dri2_surf->visual = __DRI_IMAGE_FORMAT_RGB565; ++ else if (config->AlphaSize) ++ dri2_surf->visual = __DRI_IMAGE_FORMAT_ARGB8888; ++ else ++ dri2_surf->visual = __DRI_IMAGE_FORMAT_XRGB8888; ++ ++ return surf; ++} ++ ++static EGLBoolean ++dri2_tizen_destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); ++ int i; ++ ++ if (dri2_surf->swap_queue_processor) { ++ /* Wait for any outstanding swaps to complete */ ++ 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); ++ pthread_mutex_unlock(&dri2_surf->mutex); ++ ++ pthread_cancel(dri2_surf->swap_queue_processor); ++ pthread_join(dri2_surf->swap_queue_processor, NULL); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(dri2_surf->swap_queue); i++) ++ free(dri2_surf->swap_queue[i].rects); ++ ++ if (dri2_surf->front) ++ dri2_dpy->image->destroyImage(dri2_surf->front); ++ ++ if (dri2_surf->back) { ++ tbm_surface_internal_unref(dri2_surf->back->tbm_surf); ++ dri2_surf->back->locked = false; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { ++ if (dri2_surf->color_buffers[i].dri_image) ++ dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image); ++ assert(!dri2_surf->color_buffers[i].locked); ++ } ++ ++ if (dri2_surf->tpl_surf) ++ tpl_object_unreference((tpl_object_t *) dri2_surf->tpl_surf); ++ ++ destroy_surface(surf); ++ ++ return EGL_TRUE; ++} ++ ++static EGLBoolean ++dri2_tizen_swap_interval(_EGLDisplay *dpy, _EGLSurface *surf, EGLint interval) ++{ ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); ++ tpl_result_t res; ++ ++ if (interval > surf->Config->MaxSwapInterval) ++ interval = surf->Config->MaxSwapInterval; ++ else if (interval < surf->Config->MinSwapInterval) ++ interval = surf->Config->MinSwapInterval; ++ ++ if (interval == surf->SwapInterval) ++ return EGL_TRUE; ++ ++ res = tpl_surface_set_post_interval(dri2_surf->tpl_surf, interval); ++ if (res == TPL_ERROR_NONE) { ++ surf->SwapInterval = interval; ++ return EGL_TRUE; ++ } ++ ++ return EGL_FALSE; ++} ++ ++static EGLBoolean ++dri2_tizen_swap_buffers_with_damage(_EGLDisplay *dpy, _EGLSurface *draw, ++ const EGLint *rects, EGLint n_rects) ++{ ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); ++ struct tpl_swap_queue_elem *queue_elem; ++ int i; ++ ++ if (dri2_surf->base.Type != EGL_WINDOW_BIT) ++ return EGL_TRUE; ++ ++ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { ++ if (draw->SwapBehavior == EGL_BUFFER_PRESERVED) ++ dri2_surf->color_buffers[i].age = 1; ++ else if (dri2_surf->color_buffers[i].age > 0) ++ dri2_surf->color_buffers[i].age++; ++ } ++ ++ /* ++ * Make sure we have a back buffer in case we're swapping without ever ++ * rendering. ++ */ ++ if (get_back_bo(dri2_surf, false) < 0) { ++ _eglError(EGL_BAD_ALLOC, "DRI2: failed to get back buffer"); ++ return EGL_FALSE; ++ } ++ ++ dri2_flush_drawable_for_swapbuffers(dpy, draw); ++ ++ pthread_mutex_lock(&dri2_surf->mutex); ++ queue_elem = ++ &dri2_surf->swap_queue[dri2_surf->swap_queue_idx_tail]; ++ ++ queue_elem->tbm_surf = dri2_surf->back->tbm_surf; ++ ++ /* Allocate space for damage rectangles in swap queue element if necessary */ ++ if (queue_elem->n_rects_max < n_rects) { ++ free(queue_elem->rects); ++ ++ if (!queue_elem->n_rects_max) ++ queue_elem->n_rects_max = TIZEN_SWAP_N_RECTS_MIN; ++ ++ while (queue_elem->n_rects_max <= n_rects) ++ queue_elem->n_rects_max *= 2; ++ ++ queue_elem->rects = ++ malloc(sizeof(*queue_elem->rects) * queue_elem->n_rects_max); ++ if (!queue_elem->rects) { ++ _eglError(EGL_BAD_ALLOC, ++ "DRI2: failed to allocate space for damage rects"); ++ queue_elem->n_rects_max = 0; ++ pthread_mutex_unlock(&dri2_surf->mutex); ++ return EGL_FALSE; ++ } ++ } ++ ++ /* Copy damage rectangles into swap queue element */ ++ STATIC_ASSERT(sizeof(*queue_elem->rects) == sizeof(*rects)); ++ memcpy(&queue_elem->rects[0], &rects[0], sizeof(*rects) * n_rects); ++ queue_elem->n_rects = n_rects; ++ ++ dri2_surf->swap_queue_idx_tail++; ++ dri2_surf->swap_queue_idx_tail %= ARRAY_SIZE(dri2_surf->color_buffers); ++ ++ /* Notify swap_queue_processor_worker that there's new work */ ++ pthread_cond_signal(&dri2_surf->swap_queue_cond); ++ pthread_mutex_unlock(&dri2_surf->mutex); ++ ++ dri2_surf->back->age = 1; ++ dri2_surf->current = dri2_surf->back; ++ dri2_surf->back = NULL; ++ ++ return EGL_TRUE; ++} ++ ++static EGLBoolean ++dri2_tizen_swap_buffers(_EGLDisplay *dpy, _EGLSurface *draw) ++{ ++ return dri2_tizen_swap_buffers_with_damage(dpy, draw, NULL, 0); ++} ++ ++static EGLint ++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) { ++ _eglError(EGL_BAD_ALLOC, "DRI2: failed to get back buffer"); ++ return -1; ++ } ++ ++ return dri2_surf->back->age; ++} ++ ++ ++static EGLBoolean ++dri2_tizen_query_surface(_EGLDisplay *dpy, _EGLSurface *surf, ++ EGLint attribute, EGLint *value) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); ++ ++ switch (attribute) { ++ case EGL_WIDTH: ++ case EGL_HEIGHT: ++ if (dri2_surf->base.Type == EGL_WINDOW_BIT) { ++ tpl_handle_t window; ++ int width, height; ++ tbm_format format; ++ tpl_result_t res; ++ ++ window = tpl_surface_get_native_handle(dri2_surf->tpl_surf); ++ ++ res = tpl_display_get_native_window_info(dri2_dpy->tpl_dpy, window, ++ &width, &height, &format, ++ surf->Config->RedSize + ++ surf->Config->GreenSize + ++ surf->Config->BlueSize + ++ surf->Config->AlphaSize, ++ surf->Config->AlphaSize); ++ if (res == TPL_ERROR_NONE) { ++ surf->Width = width; ++ surf->Height = height; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return _eglQuerySurface(dpy, surf, attribute, value); ++} ++ ++ ++static struct dri2_egl_display_vtbl dri2_tizen_display_vtbl = { ++ .create_window_surface = dri2_tizen_create_window_surface, ++ .create_pixmap_surface = dri2_tizen_create_pixmap_surface, ++ .create_pbuffer_surface = dri2_tizen_create_pbuffer_surface, ++ .destroy_surface = dri2_tizen_destroy_surface, ++ .create_image = dri2_create_image_khr, ++ .swap_interval = dri2_tizen_swap_interval, ++ .swap_buffers = dri2_tizen_swap_buffers, ++ .swap_buffers_with_damage = dri2_tizen_swap_buffers_with_damage, ++ .query_buffer_age = dri2_tizen_query_buffer_age, ++ .query_surface = dri2_tizen_query_surface, ++ .get_dri_drawable = dri2_surface_get_dri_drawable, ++}; ++ ++static int ++dri2_tizen_get_buffers(__DRIdrawable *driDrawable, ++ unsigned int format, ++ uint32_t *stamp, ++ void *loaderPrivate, ++ uint32_t buffer_mask, ++ struct __DRIimageList *buffers) ++{ ++ struct dri2_egl_surface *dri2_surf = loaderPrivate; ++ ++ buffers->image_mask = 0; ++ buffers->front = NULL; ++ buffers->back = 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) ++ return 0; ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) { ++ buffers->front = dri2_surf->front; ++ buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT; ++ } ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) { ++ buffers->back = dri2_surf->back->dri_image; ++ buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK; ++ } ++ ++ return 1; ++} ++ ++static void ++dri2_tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) ++{ ++} ++ ++static const __DRIimageLoaderExtension tizen_image_loader_extension = { ++ .base = { __DRI_IMAGE_LOADER, 1 }, ++ .getBuffers = dri2_tizen_get_buffers, ++ .flushFrontBuffer = dri2_tizen_flush_front_buffer, ++}; ++ ++static const __DRIextension *image_loader_extensions[] = { ++ &tizen_image_loader_extension.base, ++ &image_lookup_extension.base, ++ NULL, ++}; ++ ++static EGLBoolean ++dri2_tizen_add_configs(_EGLDisplay *dpy) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(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 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); ++ ++ dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], ++ __DRI_ATTRIB_CONFIG_CAVEAT, &caveat); ++ ++ 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; ++ ++ if (is_slow) ++ caveat |= __DRI_ATTRIB_SLOW_BIT; ++ ++ 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; ++ } ++ ++ 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; ++ ++ if (caveat & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) ++ attr_list[3] = EGL_NON_CONFORMANT_CONFIG; ++ else if (caveat & __DRI_ATTRIB_SLOW_BIT) ++ attr_list[3] = EGL_SLOW_CONFIG; ++ ++ dri2_cfg = dri2_add_config(dpy, dri2_dpy->driver_configs[i], count + 1, ++ surface_type, &attr_list[0], NULL, NULL); ++ if (dri2_cfg) ++ count++; ++ } ++ ++ return count != 0; ++} ++ ++EGLBoolean ++dri2_initialize_tizen(_EGLDisplay *dpy) ++{ ++ struct dri2_egl_display *dri2_dpy; ++ int i; ++ ++ dri2_dpy = calloc(1, sizeof(*dri2_dpy)); ++ if (!dri2_dpy) ++ return _eglError(EGL_BAD_ALLOC, "DRI2: failed to create display"); ++ ++ dpy->DriverData = (void *) dri2_dpy; ++ dri2_dpy->fd = -1; ++ ++ dri2_dpy->tpl_dpy = ++ tpl_display_create(TPL_BACKEND_UNKNOWN, dpy->PlatformDisplay); ++ if (!dri2_dpy->tpl_dpy) { ++ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to create tpl display"); ++ goto cleanup; ++ } ++ ++ for (i = TIZEN_DRM_RENDER_MINOR_START; i <= TIZEN_DRM_RENDER_MINOR_MAX; i++) { ++ char *render_path; ++ ++ if (asprintf(&render_path, DRM_RENDER_DEV_NAME, DRM_DIR_NAME, i) < 0) ++ continue; ++ ++ dri2_dpy->fd = loader_open_device(render_path); ++ free(render_path); ++ if (dri2_dpy->fd < 0) ++ continue; ++ ++ dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); ++ if (dri2_dpy->driver_name) { ++ if (dri2_load_driver_dri3(dpy)) { ++ _EGLDevice *dev = _eglAddDevice(dri2_dpy->fd, false); ++ if (!dev) { ++ dlclose(dri2_dpy->driver); ++ _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice"); ++ } else { ++ dri2_dpy->own_device = 1; ++ dpy->Device = dev; ++ break; ++ } ++ } ++ ++ free(dri2_dpy->driver_name); ++ dri2_dpy->driver_name = NULL; ++ } ++ ++ close(dri2_dpy->fd); ++ dri2_dpy->fd = -1; ++ } ++ ++ if (dri2_dpy->fd < 0) { ++ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to load driver"); ++ goto cleanup; ++ } ++ ++ dri2_dpy->loader_extensions = &image_loader_extensions[0]; ++ ++ if (!dri2_create_screen(dpy)) { ++ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to create screen"); ++ goto cleanup; ++ } ++ ++ if (!dri2_setup_extensions(dpy)) ++ goto cleanup; ++ ++ dri2_setup_screen(dpy); ++ ++ if (!dri2_tizen_add_configs(dpy)) { ++ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to add configs"); ++ goto cleanup; ++ } ++ ++ dpy->Extensions.EXT_buffer_age = EGL_TRUE; ++ dpy->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE; ++ dpy->Extensions.KHR_image_base = EGL_TRUE; ++ dpy->Extensions.WL_bind_wayland_display = EGL_TRUE; ++ ++ /* ++ * Fill vtbl last to prevent accidentally calling virtual function during ++ * initialization. ++ */ ++ dri2_dpy->vtbl = &dri2_tizen_display_vtbl; ++ ++ return EGL_TRUE; ++ ++cleanup: ++ dri2_display_destroy(dpy); ++ return EGL_FALSE; ++} +diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c +index bc7014ef8ed..4c29eedb684 100644 +--- a/src/egl/main/eglapi.c ++++ b/src/egl/main/eglapi.c +@@ -416,6 +416,13 @@ _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display, + case EGL_PLATFORM_DEVICE_EXT: + disp = _eglGetDeviceDisplay(native_display, attrib_list); + break; ++#ifdef HAVE_TIZEN_PLATFORM ++ case EGL_PLATFORM_GBM_MESA: ++ case EGL_PLATFORM_WAYLAND_EXT: ++ disp = _eglGetTizenDisplay((struct gbm_device*) native_display, ++ attrib_list); ++ break; ++#endif + default: + RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL); + } +diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c +index 765618f0dd0..486ac3b0557 100644 +--- a/src/egl/main/egldisplay.c ++++ b/src/egl/main/egldisplay.c +@@ -77,6 +77,7 @@ static const struct { + { _EGL_PLATFORM_HAIKU, "haiku" }, + { _EGL_PLATFORM_SURFACELESS, "surfaceless" }, + { _EGL_PLATFORM_DEVICE, "device" }, ++ { _EGL_PLATFORM_TIZEN, "tizen" }, + }; + + +@@ -107,6 +108,17 @@ _eglGetNativePlatformFromEnv(void) + } + } + ++#ifdef HAVE_TIZEN_PLATFORM ++ switch (plat) { ++ case _EGL_PLATFORM_DRM: ++ case _EGL_PLATFORM_WAYLAND: ++ plat = _EGL_PLATFORM_TIZEN; ++ break; ++ default: ++ break; ++ } ++#endif ++ + if (plat == _EGL_INVALID_PLATFORM) + _eglLog(_EGL_WARNING, "invalid EGL_PLATFORM given"); + +@@ -120,6 +132,7 @@ _eglGetNativePlatformFromEnv(void) + static _EGLPlatformType + _eglNativePlatformDetectNativeDisplay(void *nativeDisplay) + { ++#ifndef HAVE_TIZEN_PLATFORM + if (nativeDisplay == EGL_DEFAULT_DISPLAY) + return _EGL_INVALID_PLATFORM; + +@@ -141,7 +154,7 @@ _eglNativePlatformDetectNativeDisplay(void *nativeDisplay) + return _EGL_PLATFORM_DRM; + #endif + } +- ++#endif + return _EGL_INVALID_PLATFORM; + } + +@@ -595,6 +608,23 @@ _eglGetAndroidDisplay(void *native_display, + } + #endif /* HAVE_ANDROID_PLATFORM */ + ++#ifdef HAVE_TIZEN_PLATFORM ++_EGLDisplay* ++_eglGetTizenDisplay(void *native_display, ++ const EGLint *attrib_list) ++{ ++ /* EGL_MESA_platform_gbm and EGL_EXT_platform_wayland recognizes no ++ * attributes. */ ++ if (attrib_list != NULL && attrib_list[0] != EGL_NONE) { ++ _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); ++ return NULL; ++ } ++ ++ return _eglFindDisplay(_EGL_PLATFORM_TIZEN, native_display, ++ attrib_list); ++} ++#endif /* HAVE_TIZEN_PLATFORM */ ++ + _EGLDisplay* + _eglGetDeviceDisplay(void *native_display, + const EGLAttrib *attrib_list) +diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h +index 5b05dcc1e6d..cbb098331bf 100644 +--- a/src/egl/main/egldisplay.h ++++ b/src/egl/main/egldisplay.h +@@ -52,6 +52,7 @@ enum _egl_platform_type { + _EGL_PLATFORM_HAIKU, + _EGL_PLATFORM_SURFACELESS, + _EGL_PLATFORM_DEVICE, ++ _EGL_PLATFORM_TIZEN, + + _EGL_NUM_PLATFORMS, + _EGL_INVALID_PLATFORM = -1 +@@ -329,6 +330,12 @@ _eglGetAndroidDisplay(void *native_display, + const EGLAttrib *attrib_list); + #endif + ++#ifdef HAVE_TIZEN_PLATFORM ++_EGLDisplay* ++_eglGetTizenDisplay(void *native_display, ++ const EGLint *attrib_list); ++#endif ++ + _EGLDisplay* + _eglGetDeviceDisplay(void *native_display, + const EGLAttrib *attrib_list); +diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c +index 6a91952577f..973b7600ab1 100644 +--- a/src/egl/main/egllog.c ++++ b/src/egl/main/egllog.c +@@ -46,15 +46,17 @@ + + #include "egllog.h" + +-#ifdef HAVE_ANDROID_PLATFORM + #define LOG_TAG "EGL-MAIN" ++ ++#ifdef HAVE_ANDROID_PLATFORM + #if ANDROID_API_LEVEL >= 26 + #include + #else + #include + #endif /* use log/log.h start from android 8 major version */ +- +-#endif /* HAVE_ANDROID_PLATFORM */ ++#elif defined(HAVE_TIZEN_PLATFORM) ++#include ++#endif /* HAVE_TIZEN_PLATFORM */ + + #define MAXSTRING 1000 + #define FALLBACK_LOG_LEVEL _EGL_WARNING +@@ -93,9 +95,26 @@ _eglDefaultLogger(EGLint level, const char *msg) + [_EGL_DEBUG] = ANDROID_LOG_DEBUG, + }; + LOG_PRI(egl2alog[level], LOG_TAG, "%s", msg); ++#elif defined(HAVE_TIZEN_PLATFORM) ++ switch (level) { ++ case _EGL_DEBUG: ++ LOGD("%s", msg); ++ break; ++ case _EGL_INFO: ++ LOGI("%s", msg); ++ break; ++ case _EGL_WARNING: ++ LOGW("%s", msg); ++ break; ++ case _EGL_FATAL: ++ LOGF("%s", msg); ++ break; ++ default: ++ break; ++ } + #else + fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg); +-#endif /* HAVE_ANDROID_PLATFORM */ ++#endif /* HAVE_TIZEN_PLATFORM */ + } + + +diff --git a/src/egl/meson.build b/src/egl/meson.build +index 599a66706b7..17e9c690b82 100644 +--- a/src/egl/meson.build ++++ b/src/egl/meson.build +@@ -106,7 +106,9 @@ if with_dri2 + deps_for_egl += [dep_x11_xcb, dep_xcb_dri2, dep_xcb_xfixes] + endif + if with_gbm +- files_egl += files('drivers/dri2/platform_drm.c') ++ if not with_platform_tizen ++ files_egl += files('drivers/dri2/platform_drm.c') ++ endif + link_for_egl += libgbm + incs_for_egl += [inc_gbm, include_directories('../gbm/main')] + deps_for_egl += dep_libdrm +@@ -135,6 +137,11 @@ elif with_platform_haiku + link_for_egl += libgl + deps_for_egl += cpp.find_library('be') + endif ++if with_platform_tizen ++ files_egl += files('drivers/dri2/platform_tizen.c') ++ incs_for_egl += [inc_loader] ++ deps_for_egl += [dep_tizen, dep_libdrm] ++endif + + if cc.has_function('mincore') + c_args_for_egl += '-DHAVE_MINCORE' +-- +2.17.1 + diff --git a/package/mesa3d/0020-egl-add-support-for-EGL_TIZEN_image_native_surface.patch b/package/mesa3d/0020-egl-add-support-for-EGL_TIZEN_image_native_surface.patch new file mode 100644 index 00000000..d97623c9 --- /dev/null +++ b/package/mesa3d/0020-egl-add-support-for-EGL_TIZEN_image_native_surface.patch @@ -0,0 +1,231 @@ +From 072528e4c6b37df46499a87478f535f6235ffde5 Mon Sep 17 00:00:00 2001 +From: Eric Engestrom +Date: Mon, 6 Feb 2017 15:54:00 +0000 +Subject: [PATCH 20/50] 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 e9f745e4258..04e05567acb 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 ++#endif ++ + #include "egldefines.h" + #include "egl_dri2.h" + #include "GL/mesa_glinterop.h" +@@ -2340,28 +2344,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); +@@ -2392,33 +2483,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 + +@@ -3319,6 +3384,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 4c29eedb684..c4dcc015941 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.17.1 + diff --git a/package/mesa3d/0021-egl-wayland-post-maximum-damage-when-blitting.patch b/package/mesa3d/0021-egl-wayland-post-maximum-damage-when-blitting.patch new file mode 100644 index 00000000..7fb85079 --- /dev/null +++ b/package/mesa3d/0021-egl-wayland-post-maximum-damage-when-blitting.patch @@ -0,0 +1,33 @@ +From 66118837ec11358ea86373c343c147e9659c19b8 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Wed, 8 Nov 2017 15:15:20 +0000 +Subject: [PATCH 21/50] 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 6eb2c7cbdf6..b76c63f1439 100644 +--- a/src/egl/drivers/dri2/platform_wayland.c ++++ b/src/egl/drivers/dri2/platform_wayland.c +@@ -1121,7 +1121,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.17.1 + diff --git a/package/mesa3d/0022-egl-wayland-flush-the-drawable-before-blitting.patch b/package/mesa3d/0022-egl-wayland-flush-the-drawable-before-blitting.patch new file mode 100644 index 00000000..c8d24560 --- /dev/null +++ b/package/mesa3d/0022-egl-wayland-flush-the-drawable-before-blitting.patch @@ -0,0 +1,46 @@ +From d9235705f0c6ff56712577670f9b174f02400f5f Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Wed, 8 Nov 2017 15:26:25 +0000 +Subject: [PATCH 22/50] 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 b76c63f1439..3e6456234fe 100644 +--- a/src/egl/drivers/dri2/platform_wayland.c ++++ b/src/egl/drivers/dri2/platform_wayland.c +@@ -1126,6 +1126,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); +@@ -1135,10 +1137,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.17.1 + diff --git a/package/mesa3d/0023-egl-tizen-create-an-internal-_EGLImage-for-each-tbm-.patch b/package/mesa3d/0023-egl-tizen-create-an-internal-_EGLImage-for-each-tbm-.patch new file mode 100644 index 00000000..900bf338 --- /dev/null +++ b/package/mesa3d/0023-egl-tizen-create-an-internal-_EGLImage-for-each-tbm-.patch @@ -0,0 +1,380 @@ +From 201283a29b24ebff36b1616809c55c71eaf549ea Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Wed, 25 Oct 2017 18:15:00 +0100 +Subject: [PATCH 23/50] 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 04e05567acb..69da031fa00 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -1293,6 +1293,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; +@@ -1349,6 +1353,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(). + * +@@ -1361,6 +1419,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; +@@ -2338,6 +2398,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) + { +@@ -2434,14 +2497,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 * +@@ -2453,6 +2647,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); +@@ -2483,7 +2680,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 + +@@ -3400,10 +3611,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 4d66936da28..e516c54810d 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -260,6 +260,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 + }; + +@@ -404,6 +413,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.17.1 + diff --git a/package/mesa3d/0024-dri-use-a-supported-API-in-driCreateNewContext.patch b/package/mesa3d/0024-dri-use-a-supported-API-in-driCreateNewContext.patch new file mode 100644 index 00000000..b27fbef5 --- /dev/null +++ b/package/mesa3d/0024-dri-use-a-supported-API-in-driCreateNewContext.patch @@ -0,0 +1,54 @@ +From b9cce4ff02e66d6db913cd10352af61d3d81d9ad Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Thu, 23 Nov 2017 15:50:21 +0000 +Subject: [PATCH 24/50] 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.17.1 + diff --git a/package/mesa3d/0025-gbm-add-gbm_bo_blit.patch b/package/mesa3d/0025-gbm-add-gbm_bo_blit.patch new file mode 100644 index 00000000..a8562ef4 --- /dev/null +++ b/package/mesa3d/0025-gbm-add-gbm_bo_blit.patch @@ -0,0 +1,157 @@ +From 7b733f4e2b20614d9f367186810c4fcac4aa820c Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Tue, 28 Nov 2017 16:27:38 +0000 +Subject: [PATCH 25/50] 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 | 32 ++++++++++++++++++++++++++++++++ + src/gbm/main/gbm.c | 28 ++++++++++++++++++++++++++++ + src/gbm/main/gbm.h | 21 +++++++++++++++++++++ + src/gbm/main/gbmint.h | 4 ++++ + 4 files changed, 85 insertions(+) + +diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c +index b5634741554..ca865f4df9c 100644 +--- a/src/gbm/backends/dri/gbm_dri.c ++++ b/src/gbm/backends/dri/gbm_dri.c +@@ -1334,6 +1334,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) + { +@@ -1383,6 +1414,7 @@ dri_device_create(int fd) + dri->base.destroy = dri_destroy; + dri->base.surface_create = gbm_dri_surface_create; + dri->base.surface_destroy = gbm_dri_surface_destroy; ++ dri->base.bo_blit = gbm_dri_bo_blit; + + dri->base.name = "drm"; + +diff --git a/src/gbm/main/gbm.c b/src/gbm/main/gbm.c +index 954b3c35b0d..78de34286bd 100644 +--- a/src/gbm/main/gbm.c ++++ b/src/gbm/main/gbm.c +@@ -741,3 +741,31 @@ 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) ++{ ++ return dst_bo->gbm->bo_blit(dst_bo, src_bo, ++ dst_x0, dst_y0, dst_width, dst_height, ++ src_x0, src_y0, src_width, src_height, ++ flags); ++} +diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h +index 5801cd526a0..e754edd5654 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); + +@@ -422,6 +437,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/gbmint.h b/src/gbm/main/gbmint.h +index 192577431e2..fb95954ab32 100644 +--- a/src/gbm/main/gbmint.h ++++ b/src/gbm/main/gbmint.h +@@ -98,6 +98,10 @@ struct gbm_device { + struct gbm_bo *bo); + int (*surface_has_free_buffers)(struct gbm_surface *surface); + void (*surface_destroy)(struct gbm_surface *surface); ++ 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); + }; + + /** +-- +2.17.1 + diff --git a/package/mesa3d/0026-gbm-don-t-assert-if-DRI-context-creation-fails.patch b/package/mesa3d/0026-gbm-don-t-assert-if-DRI-context-creation-fails.patch new file mode 100644 index 00000000..7eae75be --- /dev/null +++ b/package/mesa3d/0026-gbm-don-t-assert-if-DRI-context-creation-fails.patch @@ -0,0 +1,44 @@ +From 5ed87bbc92b8034b14060d5170c3d82bfce54fb7 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Fri, 1 Dec 2017 08:31:15 +0000 +Subject: [PATCH 26/50] 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 ca865f4df9c..f9adbc5c001 100644 +--- a/src/gbm/backends/dri/gbm_dri.c ++++ b/src/gbm/backends/dri/gbm_dri.c +@@ -1224,8 +1224,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, +@@ -1353,8 +1356,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.17.1 + diff --git a/package/mesa3d/0027-egl-wayland-add-pbuffer-support.patch b/package/mesa3d/0027-egl-wayland-add-pbuffer-support.patch new file mode 100644 index 00000000..c8ee0943 --- /dev/null +++ b/package/mesa3d/0027-egl-wayland-add-pbuffer-support.patch @@ -0,0 +1,471 @@ +From daf743a8fdc7171dea73c390e3255b5c6e19046c Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Fri, 17 Mar 2017 16:23:07 +0000 +Subject: [PATCH 27/50] 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 e516c54810d..a33d87b23c1 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -396,6 +396,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 3e6456234fe..43ad6420174 100644 +--- a/src/egl/drivers/dri2/platform_wayland.c ++++ b/src/egl/drivers/dri2/platform_wayland.c +@@ -416,6 +416,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(). + */ +@@ -442,6 +535,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); + +@@ -451,11 +547,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); +@@ -642,20 +741,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; +@@ -670,12 +765,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->base.Width != dri2_surf->wl_win->width || + dri2_surf->base.Height != dri2_surf->wl_win->height) { + +@@ -715,12 +826,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 * +@@ -730,17 +842,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], +@@ -810,12 +930,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; + } +@@ -1066,6 +1204,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; ++ + while (dri2_surf->throttle_callback != NULL) + if (wl_display_dispatch_queue(dri2_dpy->wl_dpy, + dri2_surf->wl_queue) == -1) +@@ -1077,7 +1218,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) { +@@ -1162,9 +1303,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; + } +@@ -1385,6 +1530,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, +@@ -1427,7 +1573,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++; +@@ -1662,6 +1808,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, +@@ -1782,8 +1945,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) +@@ -1853,7 +2032,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; +@@ -1872,7 +2053,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; +@@ -1910,14 +2095,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; +@@ -1935,7 +2126,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 +@@ -2000,6 +2193,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.17.1 + diff --git a/package/mesa3d/0028-egl-tizen-support-DRI-driver-handling-of-swap-preser.patch b/package/mesa3d/0028-egl-tizen-support-DRI-driver-handling-of-swap-preser.patch new file mode 100644 index 00000000..9d97e5ea --- /dev/null +++ b/package/mesa3d/0028-egl-tizen-support-DRI-driver-handling-of-swap-preser.patch @@ -0,0 +1,121 @@ +From eeda62ee212dcd8fae6c138f4a3b27e3f2ffe8c0 Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Mon, 18 Dec 2017 19:22:50 +0000 +Subject: [PATCH 28/50] 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 06eab0da5aa..cf1cb574c41 100644 +--- a/include/GL/internal/dri_interface.h ++++ b/include/GL/internal/dri_interface.h +@@ -2049,12 +2049,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.17.1 + diff --git a/package/mesa3d/0029-egl-eglBindAPI-workaround-for-dEQP-bug.patch b/package/mesa3d/0029-egl-eglBindAPI-workaround-for-dEQP-bug.patch new file mode 100644 index 00000000..140b027b --- /dev/null +++ b/package/mesa3d/0029-egl-eglBindAPI-workaround-for-dEQP-bug.patch @@ -0,0 +1,29 @@ +From c431639246d96adce4a8807fa62b3b53cca3adf2 Mon Sep 17 00:00:00 2001 +From: Eric Engestrom +Date: Mon, 25 Sep 2017 15:58:49 +0100 +Subject: [PATCH 29/50] 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.17.1 + diff --git a/package/mesa3d/0030-GL_EXT_multi_draw_indirect-entry-points.patch b/package/mesa3d/0030-GL_EXT_multi_draw_indirect-entry-points.patch new file mode 100644 index 00000000..dc392324 --- /dev/null +++ b/package/mesa3d/0030-GL_EXT_multi_draw_indirect-entry-points.patch @@ -0,0 +1,56 @@ +From 651ae0156f4cec4dbf70eef95e1eceebe8941a20 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Tue, 30 Jan 2018 10:25:11 +0000 +Subject: [PATCH 30/50] 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 359cc9ca8cf..de2862a71a5 100644 +--- a/src/mapi/glapi/gen/es_EXT.xml ++++ b/src/mapi/glapi/gen/es_EXT.xml +@@ -1140,6 +1140,25 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index d13dc915d6f..32fb3b8f4f7 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1692,6 +1692,8 @@ offsets = { + "FramebufferTextureLayerDownsampleIMG" : 1656, + "FramebufferTextureMultiviewOVR" : 1657, + "FramebufferTextureMultisampleMultiviewOVR" : 1658, ++ "MultiDrawArraysIndirectEXT" : 1659, ++ "MultiDrawElementsIndirectEXT" : 1660, + } + + functions = [ +-- +2.17.1 + diff --git a/package/mesa3d/0031-dri-add-support-for-YUV-DRI-config.patch b/package/mesa3d/0031-dri-add-support-for-YUV-DRI-config.patch new file mode 100644 index 00000000..5c0f3b88 --- /dev/null +++ b/package/mesa3d/0031-dri-add-support-for-YUV-DRI-config.patch @@ -0,0 +1,494 @@ +From d4632fc9ce17416cd1f3019af554a320e142dc3b Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Fri, 22 Dec 2017 17:17:50 +0000 +Subject: [PATCH 31/50] 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 | 3 + + src/mesa/drivers/dri/common/utils.c | 87 +++++++++++++++++-- + src/mesa/drivers/dri/common/utils.h | 3 +- + src/mesa/drivers/dri/i915/intel_screen.c | 8 +- + src/mesa/drivers/dri/i965/intel_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 cf1cb574c41..cff3d9019dd 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 20ee86f52b7..09f13dd9b77 100644 +--- a/src/gallium/frontends/dri/dri_screen.c ++++ b/src/gallium/frontends/dri/dri_screen.c +@@ -306,7 +306,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_FALSE); ++ GL_TRUE, !mixed_color_depth, GL_FALSE, ++ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE, ++ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE); + configs = driConcatConfigs(configs, new_configs); + + /* Multi-sample configs without an accumulation buffer. */ +@@ -316,7 +318,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); ++ GL_FALSE, !mixed_color_depth, GL_FALSE, ++ __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 7c62b722e5d..a3a417ea0d8 100644 +--- a/src/gallium/include/pipe/p_format.h ++++ b/src/gallium/include/pipe/p_format.h +@@ -493,6 +493,9 @@ enum pipe_format { + + PIPE_FORMAT_R8_G8B8_420_UNORM, + ++ 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 0fdca2d9d84..85ffe2de64d 100644 +--- a/src/mesa/drivers/dri/common/utils.c ++++ b/src/mesa/drivers/dri/common/utils.c +@@ -166,6 +166,21 @@ driGetRendererString( char * buffer, const char * hardware_name, + * which translates to + * EGL_MUTABLE_RENDER_BUFFER_BIT_KHR. + * ++ * \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. +@@ -179,7 +194,8 @@ driCreateConfigs(mesa_format format, + 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 mutable_render_buffer) ++ GLboolean mutable_render_buffer, ++ GLint yuv_depth_range, GLint yuv_csc_standard) + { + static const struct { + uint32_t masks[4]; +@@ -218,6 +234,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; +@@ -231,6 +250,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; + +@@ -282,6 +306,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__, +@@ -337,8 +388,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; +@@ -355,6 +410,7 @@ driCreateConfigs(mesa_format format, + modes->transparentBlue = GLX_DONT_CARE; + modes->transparentAlpha = GLX_DONT_CARE; + modes->transparentIndex = GLX_DONT_CARE; ++ modes->rgbMode = !is_yuv; + + if (db_modes[i] == __DRI_ATTRIB_SWAP_NONE) { + modes->doubleBufferMode = GL_FALSE; +@@ -379,6 +435,13 @@ driCreateConfigs(mesa_format format, + modes->yInverted = GL_TRUE; + modes->sRGBCapable = is_srgb; + modes->mutableRenderBuffer = mutable_render_buffer; ++ ++ 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; + } + } + } +@@ -468,6 +531,12 @@ static const struct { unsigned int attrib, offset; } attribMap[] = { + __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), + __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable), + __ATTRIB(__DRI_ATTRIB_MUTABLE_RENDER_BUFFER, mutableRenderBuffer), ++ __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), + + /* The struct field doesn't matter here, these are handled by the + * switch in driGetConfigAttribIndex. We need them in the array +@@ -487,10 +556,14 @@ driGetConfigAttribIndex(const __DRIconfig *config, + { + switch (attribMap[index].attrib) { + 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.visualRating == GLX_NON_CONFORMANT_CONFIG) +diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h +index 7c9719f9f42..8159300c01d 100644 +--- a/src/mesa/drivers/dri/common/utils.h ++++ b/src/mesa/drivers/dri/common/utils.h +@@ -46,7 +46,8 @@ driCreateConfigs(mesa_format format, + 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 mutable_render_buffer); ++ GLboolean mutable_render_buffer, ++ 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 60b35d37a6e..62973d83bd5 100644 +--- a/src/mesa/drivers/dri/i915/intel_screen.c ++++ b/src/mesa/drivers/dri/i915/intel_screen.c +@@ -1067,7 +1067,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen) + num_depth_stencil_bits, + back_buffer_modes, 2, + singlesample_samples, 1, +- false, false, false); ++ false, false, false, ++ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE, ++ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE); + configs = driConcatConfigs(configs, new_configs); + } + +@@ -1089,7 +1091,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen) + depth_bits, stencil_bits, 1, + back_buffer_modes, 1, + singlesample_samples, 1, +- true, false, false); ++ true, 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/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c +index 1e34cbbca1a..8fed9c6931a 100644 +--- a/src/mesa/drivers/dri/i965/intel_screen.c ++++ b/src/mesa/drivers/dri/i965/intel_screen.c +@@ -2336,7 +2336,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen) + back_buffer_modes, 2, + singlesample_samples, 1, + false, false, +- /*mutable_render_buffer*/ true); ++ /*mutable_render_buffer*/ true, ++ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE, ++ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE); + configs = driConcatConfigs(configs, new_configs); + } + +@@ -2369,7 +2371,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen) + depth_bits, stencil_bits, 1, + back_buffer_modes, 1, + singlesample_samples, 1, +- true, false, false); ++ true, false, false, ++ __DRI_ATTRIB_YUV_DEPTH_RANGE_NONE, ++ __DRI_ATTRIB_YUV_CSC_STANDARD_NONE); + configs = driConcatConfigs(configs, new_configs); + } + +@@ -2434,7 +2438,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen) + back_buffer_modes, 1, + multisample_samples, + num_msaa_modes, +- false, false, 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 ba85aacf741..9d4c1d9bd94 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_FALSE); ++ GL_TRUE, chipset < 0x10, GL_FALSE, ++ __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 f61fe399c09..84aef8dd041 100644 +--- a/src/mesa/drivers/dri/radeon/radeon_screen.c ++++ b/src/mesa/drivers/dri/radeon/radeon_screen.c +@@ -839,7 +839,9 @@ __DRIconfig **radeonInitScreen2(__DRIscreen *psp) + ARRAY_SIZE(back_buffer_modes), + msaa_samples_array, + ARRAY_SIZE(msaa_samples_array), +- GL_TRUE, GL_FALSE, GL_FALSE); ++ GL_TRUE, GL_FALSE, 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 42c236c7a6a..e07d2d98b89 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 ac00a21306b..de7b9feb14b 100644 +--- a/src/mesa/main/formats.c ++++ b/src/mesa/main/formats.c +@@ -1450,6 +1450,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 e2b54e935bb..166c3d4830d 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 + + # Array normalized formats + MESA_FORMAT_A_UNORM8 , array , 1, 1, 1, un8 , , , , 000x, rgb +diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h +index 29c1308c383..4fcb5f73225 100644 +--- a/src/mesa/main/formats.h ++++ b/src/mesa/main/formats.h +@@ -615,6 +615,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 70e7b218197..96e55fc987d 100644 +--- a/src/mesa/main/mtypes.h ++++ b/src/mesa/main/mtypes.h +@@ -162,6 +162,7 @@ _mesa_varying_slot_in_fs(gl_varying_slot slot) + */ + struct gl_config + { ++ GLboolean rgbMode; + GLboolean floatMode; + GLuint doubleBufferMode; + GLuint stereoMode; +@@ -214,6 +215,14 @@ struct gl_config + + /* EGL_KHR_mutable_render_buffer */ + GLuint mutableRenderBuffer; /* bool */ ++ ++ /* EXT_yuv_surface */ ++ GLint YUVOrder; ++ GLint YUVNumberOfPlanes; ++ GLint YUVSubsample; ++ GLint YUVDepthRange; ++ GLint YUVCSCStandard; ++ GLint YUVPlaneBPP; + }; + + +-- +2.17.1 + diff --git a/package/mesa3d/0032-egl-add-support-for-EXT_yuv_surface.patch b/package/mesa3d/0032-egl-add-support-for-EXT_yuv_surface.patch new file mode 100644 index 00000000..9190a17b --- /dev/null +++ b/package/mesa3d/0032-egl-add-support-for-EXT_yuv_surface.patch @@ -0,0 +1,541 @@ +From cc2b278f33c3c9f5f74aa5b36ead67f89cb7a20d Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Wed, 20 Dec 2017 17:41:38 +0000 +Subject: [PATCH 32/50] 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 cff3d9019dd..89e29299840 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 69da031fa00..a0b52eab983 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -319,6 +319,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 * +@@ -446,6 +447,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; +@@ -556,6 +559,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) +@@ -612,6 +682,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; + +@@ -1043,6 +1124,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 c4dcc015941..8d9f4a76330 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.17.1 + diff --git a/package/mesa3d/0033-dri-add-missing-__DRI_IMAGE_COMPONENTS-define-for-EG.patch b/package/mesa3d/0033-dri-add-missing-__DRI_IMAGE_COMPONENTS-define-for-EG.patch new file mode 100644 index 00000000..5ee0d528 --- /dev/null +++ b/package/mesa3d/0033-dri-add-missing-__DRI_IMAGE_COMPONENTS-define-for-EG.patch @@ -0,0 +1,35 @@ +From ab2935ddffde305a6bdf49a9e928de407e04871b Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Fri, 2 Feb 2018 16:59:52 +0000 +Subject: [PATCH 33/50] 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 89e29299840..8214e7a55c3 100644 +--- a/include/GL/internal/dri_interface.h ++++ b/include/GL/internal/dri_interface.h +@@ -1459,11 +1459,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.17.1 + diff --git a/package/mesa3d/0034-egl-wayland-expose-EXT_yuv_surface-support.patch b/package/mesa3d/0034-egl-wayland-expose-EXT_yuv_surface-support.patch new file mode 100644 index 00000000..397f39d8 --- /dev/null +++ b/package/mesa3d/0034-egl-wayland-expose-EXT_yuv_surface-support.patch @@ -0,0 +1,74 @@ +From 2b9a147b073ed8ff1d52246be5c885959d859c45 Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Thu, 11 Jan 2018 09:38:47 +0000 +Subject: [PATCH 34/50] 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 a0b52eab983..d359934a818 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -2798,6 +2798,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 43ad6420174..de12ec21f53 100644 +--- a/src/egl/drivers/dri2/platform_wayland.c ++++ b/src/egl/drivers/dri2/platform_wayland.c +@@ -134,6 +134,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, +@@ -970,6 +977,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; +@@ -1561,6 +1569,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++) { +@@ -1572,8 +1581,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.17.1 + diff --git a/package/mesa3d/0035-egl-tizen-expose-EXT_yuv_surface-support.patch b/package/mesa3d/0035-egl-tizen-expose-EXT_yuv_surface-support.patch new file mode 100644 index 00000000..d9ee5390 --- /dev/null +++ b/package/mesa3d/0035-egl-tizen-expose-EXT_yuv_surface-support.patch @@ -0,0 +1,357 @@ +From daf8ff0be3c3fbfe5bfba656eca511a45720bdea Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Tue, 13 Feb 2018 14:47:48 +0000 +Subject: [PATCH 35/50] 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.17.1 + diff --git a/package/mesa3d/0036-gbm-add-some-new-GBM-formats.patch b/package/mesa3d/0036-gbm-add-some-new-GBM-formats.patch new file mode 100644 index 00000000..c4528930 --- /dev/null +++ b/package/mesa3d/0036-gbm-add-some-new-GBM-formats.patch @@ -0,0 +1,69 @@ +From 812b414afa598605ddc163d0a07f4374d1a625c9 Mon Sep 17 00:00:00 2001 +From: Silvestrs Timofejevs +Date: Thu, 30 Aug 2018 13:48:53 +0100 +Subject: [PATCH 36/50] 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 f9adbc5c001..1144e9a62d1 100644 +--- a/src/gbm/backends/dri/gbm_dri.c ++++ b/src/gbm/backends/dri/gbm_dri.c +@@ -508,11 +508,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 }, +@@ -565,6 +575,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 e754edd5654..19b601dc1f3 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.17.1 + diff --git a/package/mesa3d/0037-egl-add-null-platform.patch b/package/mesa3d/0037-egl-add-null-platform.patch new file mode 100644 index 00000000..c0f08199 --- /dev/null +++ b/package/mesa3d/0037-egl-add-null-platform.patch @@ -0,0 +1,1471 @@ +From 41dc5e009c2ad9e9db26256fbff335d04f03ccbd Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Sun, 5 Jun 2016 12:04:40 +0100 +Subject: [PATCH 37/50] egl: add "null" platform + +--- + meson.build | 25 +- + meson_options.txt | 2 +- + src/egl/drivers/dri2/egl_dri2.c | 6 + + src/egl/drivers/dri2/egl_dri2.h | 57 +- + src/egl/drivers/dri2/platform_null.c | 1176 ++++++++++++++++++++++++++ + src/egl/main/eglapi.c | 5 +- + src/egl/main/egldisplay.c | 1 + + src/egl/main/egldisplay.h | 1 + + src/egl/meson.build | 5 + + 9 files changed, 1271 insertions(+), 7 deletions(-) + create mode 100644 src/egl/drivers/dri2/platform_null.c + +diff --git a/meson.build b/meson.build +index c90e44254d2..56340b8ef3b 100644 +--- a/meson.build ++++ b/meson.build +@@ -328,7 +328,7 @@ endif + _platforms = get_option('platforms') + if _platforms.contains('auto') + if system_has_kms_drm +- _platforms = ['x11', 'wayland'] ++ _platforms = ['x11', 'wayland', 'null'] + elif ['darwin', 'cygwin'].contains(host_machine.system()) + _platforms = ['x11'] + elif ['haiku'].contains(host_machine.system()) +@@ -347,6 +347,7 @@ with_platform_wayland = _platforms.contains('wayland') + with_platform_haiku = _platforms.contains('haiku') + with_platform_windows = _platforms.contains('windows') + with_platform_tizen = _platforms.contains('tizen') ++with_platform_null = _platforms.contains('null') + + if with_platform_tizen and _platforms.length() != 1 + error('tizen cannot be enabled at the same time as other platforms') +@@ -903,6 +904,26 @@ if with_platform_tizen + ] + pre_args += '-DHAVE_TIZEN_PLATFORM' + endif ++if with_platform_null ++ pre_args += '-DHAVE_NULL_PLATFORM' ++endif ++if with_platform_android ++ dep_android = [ ++ dependency('cutils'), ++ dependency('hardware'), ++ dependency('sync'), ++ ] ++ if with_gallium ++ dep_android += dependency('backtrace') ++ endif ++ if get_option('platform-sdk-version') >= 26 ++ dep_android += dependency('nativewindow') ++ endif ++ pre_args += '-DHAVE_ANDROID_PLATFORM' ++endif ++if with_platform_haiku ++ pre_args += '-DHAVE_HAIKU_PLATFORM' ++endif + + prog_python = import('python').find_installation('python3') + has_mako = run_command( +@@ -1502,7 +1523,7 @@ dep_libdrm = dependency( + 'libdrm', version : '>=' + _drm_ver, + # GNU/Hurd includes egl_dri2, without drm. + required : (with_dri2 and host_machine.system() != 'gnu') or with_dri3 or +- with_platform_tizen ++ with_platform_tizen or with_platform_null + ) + if dep_libdrm.found() + pre_args += '-DHAVE_LIBDRM' +diff --git a/meson_options.txt b/meson_options.txt +index b2ba2d8d979..9073223e8f5 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -23,7 +23,7 @@ option( + type : 'array', + value : ['auto'], + choices : [ +- 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', 'tizen', ++ 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', 'tizen', 'null', + ], + description : 'window systems to support. If this is set to `auto`, all platforms applicable will be enabled.' + ) +diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c +index d359934a818..ee19d125675 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -1282,6 +1282,9 @@ dri2_initialize(_EGLDisplay *disp) + case _EGL_PLATFORM_DEVICE: + ret = dri2_initialize_device(disp); + break; ++ case _EGL_PLATFORM_NULL: ++ ret = dri2_initialize_null(disp); ++ break; + case _EGL_PLATFORM_X11: + case _EGL_PLATFORM_XCB: + ret = dri2_initialize_x11(disp); +@@ -1384,6 +1387,9 @@ dri2_display_destroy(_EGLDisplay *disp) + tpl_object_unreference((tpl_object_t *) dri2_dpy->tpl_dpy); + break; + #endif ++ case _EGL_PLATFORM_NULL: ++ dri2_teardown_null(dri2_dpy); ++ break; + default: + /* TODO: add teardown for other platforms */ + break; +diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h +index a33d87b23c1..95435b9ee12 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -75,6 +75,10 @@ struct zwp_linux_dmabuf_v1; + #include + #endif + ++#ifdef HAVE_NULL_PLATFORM ++#include ++#endif ++ + #include "eglconfig.h" + #include "eglcontext.h" + #include "egldevice.h" +@@ -93,6 +97,22 @@ struct zwp_linux_dmabuf_v1; + + struct wl_buffer; + ++#ifdef HAVE_NULL_PLATFORM ++struct display_output { ++ bool in_use; ++ uint32_t connector_id; ++ drmModePropertyRes **connector_prop_res; ++ uint32_t crtc_id; ++ drmModePropertyRes **crtc_prop_res; ++ uint32_t plane_id; ++ drmModePropertyRes **plane_prop_res; ++ drmModeModeInfo mode; ++ uint32_t mode_blob_id; ++ unsigned formats; ++ drmModeAtomicReq *atomic_state; ++}; ++#endif ++ + struct dri2_egl_display_vtbl { + /* mandatory on Wayland, unused otherwise */ + int (*authenticate)(_EGLDisplay *disp, uint32_t id); +@@ -251,6 +271,11 @@ struct dri2_egl_display + char *device_name; + #endif + ++#ifdef HAVE_NULL_PLATFORM ++ bool atomic_enabled; ++ struct display_output output; ++#endif ++ + #ifdef HAVE_ANDROID_PLATFORM + const gralloc_module_t *gralloc; + #endif +@@ -324,7 +349,10 @@ struct dri2_egl_surface + struct wl_display *wl_dpy_wrapper; + struct wl_drm *wl_drm_wrapper; + struct wl_callback *throttle_callback; +- int format; ++#endif ++ ++#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_NULL_PLATFORM) ++ int format; + #endif + + #ifdef HAVE_DRM_PLATFORM +@@ -350,9 +378,10 @@ struct dri2_egl_surface + __DRIbuffer *local_buffers[__DRI_BUFFER_COUNT]; + + #if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM) || \ +- defined(HAVE_TIZEN_PLATFORM) ++ defined(HAVE_TIZEN_PLATFORM) || defined(HAVE_NULL_PLATFORM) + struct { +-#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_TIZEN_PLATFORM) ++#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_TIZEN_PLATFORM) || \ ++ defined(HAVE_NULL_PLATFORM) + __DRIimage *dri_image; + #endif + #ifdef HAVE_WAYLAND_PLATFORM +@@ -369,6 +398,9 @@ struct dri2_egl_surface + #endif + #ifdef HAVE_TIZEN_PLATFORM + tbm_surface_h tbm_surf; ++#endif ++#ifdef HAVE_NULL_PLATFORM ++ uint32_t fb_id; + #endif + bool locked; + int age; +@@ -400,6 +432,10 @@ struct dri2_egl_surface + void *swrast_front; + #endif + ++#ifdef HAVE_NULL_PLATFORM ++ uint32_t front_fb_id; ++#endif ++ + int out_fence_fd; + EGLBoolean enable_out_fence; + +@@ -580,6 +616,21 @@ EGLBoolean + dri2_initialize_tizen(_EGLDisplay *disp); + #endif + ++#ifdef HAVE_NULL_PLATFORM ++EGLBoolean ++dri2_initialize_null(_EGLDisplay *disp); ++void ++dri2_teardown_null(struct dri2_egl_display *dri2_dpy); ++#else ++static inline EGLBoolean ++dri2_initialize_null(_EGLDisplay *disp) ++{ ++ return _eglError(EGL_NOT_INITIALIZED, "Null platform not built"); ++} ++static inline void ++dri2_teardown_null(struct dri2_egl_display *dri2_dpy) {} ++#endif ++ + EGLBoolean + dri2_initialize_device(_EGLDisplay *disp); + static inline void +diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c +new file mode 100644 +index 00000000000..2b3b08cc259 +--- /dev/null ++++ b/src/egl/drivers/dri2/platform_null.c +@@ -0,0 +1,1176 @@ ++/* ++ * Copyright (c) Imagination Technologies Ltd. ++ * ++ * Parts based on platform_wayland, which has: ++ * ++ * Copyright © 2011-2012 Intel Corporation ++ * Copyright © 2012 Collabora, Ltd. ++ * ++ * 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 (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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "egl_dri2.h" ++#include "loader.h" ++ ++#define NULL_CARD_MINOR_MAX 63U ++ ++/* ++ * Need at least version 4 for __DRI_IMAGE_ATTRIB_WIDTH and ++ * __DRI_IMAGE_ATTRIB_HEIGHT ++ */ ++#define NULL_IMAGE_EXTENSION_VERSION_MIN 4 ++ ++struct object_property { ++ uint32_t object_id; ++ uint32_t prop_id; ++ uint64_t prop_value; ++}; ++ ++#define object_property_set_named(output, object_type, prop_name, value) \ ++ { \ ++ .object_id = (output)->object_type##_id, \ ++ .prop_id = property_id_get_for_name((output)->object_type##_prop_res, \ ++ prop_name), \ ++ .prop_value = value, \ ++ } ++ ++/* ++ * The index of entries in this table is used as a bitmask in ++ * dri2_dpy->formats, which tracks the formats supported by the display. ++ */ ++static const struct dri2_null_format { ++ uint32_t drm_format; ++ int dri_image_format; ++ int rgba_shifts[4]; ++ unsigned int rgba_sizes[4]; ++} 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 }, ++ }, ++ { ++ .drm_format = DRM_FORMAT_ARGB8888, ++ .dri_image_format = __DRI_IMAGE_FORMAT_ARGB8888, ++ .rgba_shifts = { 16, 8, 0, 24 }, ++ .rgba_sizes = { 8, 8, 8, 8 }, ++ }, ++ { ++ .drm_format = DRM_FORMAT_RGB565, ++ .dri_image_format = __DRI_IMAGE_FORMAT_RGB565, ++ .rgba_shifts = { 11, 5, 0, -1 }, ++ .rgba_sizes = { 5, 6, 5, 0 }, ++ }, ++}; ++ ++ ++static int ++format_idx_get_from_config(struct dri2_egl_display *dri2_dpy, ++ const __DRIconfig *config) ++{ ++ int shifts[4]; ++ unsigned int sizes[4]; ++ ++ dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes); ++ ++ for (unsigned int i = 0; i < ARRAY_SIZE(dri2_null_formats); i++) { ++ const struct dri2_null_format *format = &dri2_null_formats[i]; ++ ++ if (shifts[0] == format->rgba_shifts[0] && ++ shifts[1] == format->rgba_shifts[1] && ++ shifts[2] == format->rgba_shifts[2] && ++ shifts[3] == format->rgba_shifts[3] && ++ sizes[0] == format->rgba_sizes[0] && ++ sizes[1] == format->rgba_sizes[1] && ++ sizes[2] == format->rgba_sizes[2] && ++ sizes[3] == format->rgba_sizes[3]) { ++ return i; ++ } ++ } ++ ++ return -1; ++} ++ ++static int ++format_idx_get_from_dri_image_format(uint32_t dri_image_format) ++{ ++ for (unsigned int i = 0; i < ARRAY_SIZE(dri2_null_formats); i++) ++ if (dri2_null_formats[i].dri_image_format == dri_image_format) ++ return i; ++ ++ return -1; ++} ++ ++static int ++format_idx_get_from_drm_format(uint32_t drm_format) ++{ ++ for (unsigned int i = 0; i < ARRAY_SIZE(dri2_null_formats); i++) ++ if (dri2_null_formats[i].drm_format == drm_format) ++ return i; ++ ++ return -1; ++} ++ ++static int ++atomic_state_add_object_properties(drmModeAtomicReq *atomic_state, ++ const struct object_property *props, ++ const unsigned prop_count) ++{ ++ for (unsigned i = 0; i < prop_count; i++) { ++ int err; ++ ++ if (props[i].prop_id == 0) ++ return -EINVAL; ++ ++ err = drmModeAtomicAddProperty(atomic_state, props[i].object_id, ++ props[i].prop_id, props[i].prop_value); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++ ++static uint32_t ++property_id_get_for_name(drmModePropertyRes **prop_res, const char *prop_name) ++{ ++ if (prop_res) ++ for (unsigned i = 0; prop_res[i]; i++) ++ if (!strcmp(prop_res[i]->name, prop_name)) ++ return prop_res[i]->prop_id; ++ ++ 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) ++{ ++ drmModeObjectProperties *props; ++ drmModePropertyRes **prop_res; ++ ++ props = drmModeObjectGetProperties(fd, object_id, object_type); ++ if (!props) ++ return NULL; ++ ++ prop_res = malloc((props->count_props + 1) * sizeof(*prop_res)); ++ if (prop_res) { ++ prop_res[props->count_props] = NULL; ++ ++ for (unsigned i = 0; i < props->count_props; i++) { ++ prop_res[i] = drmModeGetProperty(fd, props->props[i]); ++ if (!prop_res[i]) { ++ while (i--) { ++ drmModeFreeProperty(prop_res[i]); ++ free(prop_res); ++ prop_res = NULL; ++ } ++ break; ++ } ++ } ++ } ++ ++ drmModeFreeObjectProperties(props); ++ ++ return prop_res; ++} ++ ++static void ++object_free_property_resources(int fd, drmModePropertyRes **prop_res) ++{ ++ for (unsigned i = 0; prop_res[i]; i++) ++ drmModeFreeProperty(prop_res[i]); ++ free(prop_res); ++} ++ ++static bool ++object_property_value_for_name(int fd, uint32_t object_id, uint32_t object_type, ++ const char *prop_name, uint64_t *value_out) ++{ ++ drmModeObjectProperties *plane_props; ++ bool found = false; ++ ++ plane_props = drmModeObjectGetProperties(fd, object_id, object_type); ++ if (!plane_props) ++ return false; ++ ++ for (unsigned i = 0; i < plane_props->count_props; i++) { ++ drmModePropertyRes *prop; ++ ++ prop = drmModeGetProperty(fd, plane_props->props[i]); ++ if (!prop) ++ continue; ++ ++ found = !strcmp(prop->name, prop_name); ++ drmModeFreeProperty(prop); ++ if (found) { ++ *value_out = plane_props->prop_values[i]; ++ break; ++ } ++ } ++ ++ drmModeFreeObjectProperties(plane_props); ++ ++ return found; ++} ++ ++static int ++connector_choose_mode(drmModeConnector *connector) ++{ ++ if (!connector->count_modes) ++ return -1; ++ ++ for (unsigned i = 0; i < connector->count_modes; i++) { ++ if (connector->modes[i].flags & DRM_MODE_FLAG_INTERLACE) ++ continue; ++ ++ if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) ++ return i; ++ } ++ ++ return 0; ++} ++ ++static drmModeConnector * ++connector_get(int fd, drmModeRes *resources) ++{ ++ /* Find the first connected connector */ ++ for (unsigned i = 0; i < resources->count_connectors; i++) { ++ drmModeConnector *connector; ++ ++ connector = drmModeGetConnector(fd, resources->connectors[i]); ++ if (!connector) ++ continue; ++ ++ if (connector->connection == DRM_MODE_CONNECTED) ++ return connector; ++ ++ drmModeFreeConnector(connector); ++ } ++ ++ return NULL; ++} ++ ++static drmModeCrtc * ++crtc_get_for_connector(int fd, drmModeRes *resources, ++ drmModeConnector *connector) ++{ ++ for (unsigned i = 0; i < connector->count_encoders; i++) { ++ drmModeEncoder *encoder; ++ ++ encoder = drmModeGetEncoder(fd, connector->encoders[i]); ++ if (!encoder) ++ continue; ++ ++ for (unsigned j = 0; j < resources->count_crtcs; j++) { ++ if (encoder->possible_crtcs & (1 << j)) { ++ drmModeCrtc *crtc; ++ ++ crtc = drmModeGetCrtc(fd, resources->crtcs[j]); ++ if (crtc) { ++ drmModeFreeEncoder(encoder); ++ return crtc; ++ } ++ } ++ } ++ ++ drmModeFreeEncoder(encoder); ++ } ++ ++ return NULL; ++} ++ ++static drmModePlane * ++primary_plane_get_for_crtc(int fd, drmModeRes *resources, drmModeCrtc *crtc) ++{ ++ drmModePlaneRes *plane_resources; ++ unsigned crtc_idx; ++ ++ plane_resources = drmModeGetPlaneResources(fd); ++ if (!plane_resources) ++ return NULL; ++ ++ for (crtc_idx = 0; crtc_idx < resources->count_crtcs; crtc_idx++) ++ if (resources->crtcs[crtc_idx] == crtc->crtc_id) ++ break; ++ assert(crtc_idx != resources->count_crtcs); ++ ++ for (unsigned i = 0; i < plane_resources->count_planes; i++) { ++ const uint32_t crtc_bit = 1 << crtc_idx; ++ drmModePlane *plane; ++ ++ plane = drmModeGetPlane(fd, plane_resources->planes[i]); ++ if (!plane) ++ continue; ++ ++ if (plane->possible_crtcs & crtc_bit) { ++ uint64_t type; ++ bool res; ++ ++ res = object_property_value_for_name(fd, plane->plane_id, ++ DRM_MODE_OBJECT_PLANE, ++ "type", &type); ++ if (res && type == DRM_PLANE_TYPE_PRIMARY) { ++ drmModeFreePlaneResources(plane_resources); ++ return plane; ++ } ++ } ++ ++ drmModeFreePlane(plane); ++ } ++ ++ drmModeFreePlaneResources(plane_resources); ++ ++ return NULL; ++} ++ ++static bool ++display_output_atomic_init(int fd, struct display_output *output) ++{ ++ drmModePropertyRes **connector_prop_res; ++ drmModePropertyRes **crtc_prop_res; ++ drmModePropertyRes **plane_prop_res; ++ int err; ++ ++ connector_prop_res = object_get_property_resources(fd, output->connector_id, ++ DRM_MODE_OBJECT_CONNECTOR); ++ if (!connector_prop_res) ++ return false; ++ ++ crtc_prop_res = object_get_property_resources(fd, output->crtc_id, ++ DRM_MODE_OBJECT_CRTC); ++ if (!crtc_prop_res) ++ goto err_free_connector_prop_res; ++ ++ plane_prop_res = object_get_property_resources(fd, output->plane_id, ++ DRM_MODE_OBJECT_PLANE); ++ if (!plane_prop_res) ++ goto err_free_crtc_prop_res; ++ ++ err = drmModeCreatePropertyBlob(fd, &output->mode, sizeof(output->mode), ++ &output->mode_blob_id); ++ if (err) ++ goto err_free_plane_prop_res; ++ ++ output->atomic_state = drmModeAtomicAlloc(); ++ if (!output->atomic_state) ++ goto err_destroy_mode_prop_blob; ++ ++ output->connector_prop_res = connector_prop_res; ++ output->crtc_prop_res = crtc_prop_res; ++ output->plane_prop_res = plane_prop_res; ++ ++ return true; ++ ++err_destroy_mode_prop_blob: ++ drmModeDestroyPropertyBlob(fd, output->mode_blob_id); ++err_free_plane_prop_res: ++ object_free_property_resources(fd, plane_prop_res); ++err_free_crtc_prop_res: ++ object_free_property_resources(fd, crtc_prop_res); ++err_free_connector_prop_res: ++ object_free_property_resources(fd, connector_prop_res); ++ return false; ++} ++ ++static int ++display_output_atomic_flip(int fd, struct display_output *output, uint32_t fb_id, ++ uint32_t flags, void *flip_data) ++{ ++ const struct object_property obj_props[] = { ++ object_property_set_named(output, plane, "FB_ID", fb_id), ++ }; ++ int err; ++ ++ /* Reset atomic state */ ++ drmModeAtomicSetCursor(output->atomic_state, 0); ++ ++ err = atomic_state_add_object_properties(output->atomic_state, obj_props, ++ ARRAY_SIZE(obj_props)); ++ if (err) ++ return err; ++ ++ /* ++ * 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); ++} ++ ++static int ++display_output_atomic_modeset(int fd, struct display_output *output, uint32_t fb_id) ++{ ++ /* SRC_W and SRC_H in 16.16 fixed point */ ++ const struct object_property obj_props[] = { ++ object_property_set_named(output, connector, "CRTC_ID", output->crtc_id), ++ object_property_set_named(output, crtc, "ACTIVE", 1), ++ object_property_set_named(output, crtc, "MODE_ID", output->mode_blob_id), ++ object_property_set_named(output, plane, "FB_ID", fb_id), ++ object_property_set_named(output, plane, "CRTC_ID", output->crtc_id), ++ object_property_set_named(output, plane, "CRTC_X", 0), ++ object_property_set_named(output, plane, "CRTC_Y", 0), ++ object_property_set_named(output, plane, "CRTC_W", output->mode.hdisplay), ++ object_property_set_named(output, plane, "CRTC_H", output->mode.vdisplay), ++ object_property_set_named(output, plane, "SRC_X", 0), ++ object_property_set_named(output, plane, "SRC_Y", 0), ++ object_property_set_named(output, plane, "SRC_W", output->mode.hdisplay << 16), ++ object_property_set_named(output, plane, "SRC_H", output->mode.vdisplay << 16), ++ }; ++ int err; ++ ++ /* Reset atomic state */ ++ drmModeAtomicSetCursor(output->atomic_state, 0); ++ ++ err = atomic_state_add_object_properties(output->atomic_state, obj_props, ++ ARRAY_SIZE(obj_props)); ++ if (err) ++ return false; ++ ++ return drmModeAtomicCommit(fd, output->atomic_state, ++ DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); ++} ++ ++static bool ++display_output_init(int fd, struct display_output *output, bool use_atomic) ++{ ++ drmModeRes *resources; ++ drmModeConnector *connector; ++ drmModeCrtc *crtc; ++ drmModePlane *plane; ++ unsigned mode_idx; ++ ++ resources = drmModeGetResources(fd); ++ if (!resources) ++ return false; ++ ++ connector = connector_get(fd, resources); ++ if (!connector) ++ goto err_free_resources; ++ ++ crtc = crtc_get_for_connector(fd, resources, connector); ++ if (!crtc) ++ goto err_free_connector; ++ ++ plane = primary_plane_get_for_crtc(fd, resources, crtc); ++ if (!plane) ++ goto err_free_crtc; ++ ++ mode_idx = connector_choose_mode(connector); ++ if (mode_idx < 0) ++ 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; ++ ++ format_idx = format_idx_get_from_drm_format(plane->formats[i]); ++ if (format_idx == -1) ++ continue; ++ ++ output->formats |= (1 << format_idx); ++ } ++ if (!output->formats) ++ goto err_free_plane; ++ ++ output->connector_id = connector->connector_id; ++ output->crtc_id = crtc->crtc_id; ++ output->plane_id = plane->plane_id; ++ ++ drmModeFreePlane(plane); ++ drmModeFreeCrtc(crtc); ++ drmModeFreeConnector(connector); ++ drmModeFreeResources(resources); ++ ++ if (use_atomic) { ++ if (!display_output_atomic_init(fd, output)) { ++ _eglLog(_EGL_DEBUG, ++ "failed to initialise atomic support (using legacy mode)"); ++ } ++ } ++ ++ return true; ++ ++err_free_plane: ++ drmModeFreePlane(plane); ++err_free_crtc: ++ drmModeFreeCrtc(crtc); ++err_free_connector: ++ drmModeFreeConnector(connector); ++err_free_resources: ++ drmModeFreeResources(resources); ++ return false; ++} ++ ++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); ++ ++ return drmModePageFlip(fd, output->crtc_id, fb_id, flags, flip_data); ++} ++ ++static int ++display_output_modeset(int fd, struct display_output *output, uint32_t fb_id) ++{ ++ if (output->atomic_state) ++ return display_output_atomic_modeset(fd, output, fb_id); ++ ++ return drmModeSetCrtc(fd, output->crtc_id, fb_id, 0, 0, ++ &output->connector_id, 1, &output->mode); ++} ++ ++static bool ++add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image, ++ uint32_t *fb_id_out) ++{ ++ uint32_t handles[4] = {0}; ++ uint32_t pitches[4] = {0}; ++ uint32_t offsets[4] = {0}; ++ int handle, stride, width, height, format; ++ int format_idx; ++ ++ 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); ++ ++ return !drmModeAddFB2(dri2_dpy->fd, width, height, ++ dri2_null_formats[format_idx].drm_format, ++ handles, pitches, offsets, fb_id_out, 0); ++} ++ ++static bool ++get_front_bo(struct dri2_egl_surface *dri2_surf) ++{ ++ struct dri2_egl_display *dri2_dpy = ++ dri2_egl_display(dri2_surf->base.Resource.Display); ++ unsigned int use = 0; ++ ++ 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); ++ if (!dri2_surf->front) ++ 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; ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static bool ++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) { ++ 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; ++ } ++ } ++ if (!dri2_surf->back) ++ return false; ++ } ++ ++ 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); ++ if (!dri2_surf->back->dri_image) ++ return false; ++ } ++ ++ 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->locked = 1; ++ ++ return true; ++} ++ ++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 dri2_egl_config *dri2_config = dri2_egl_config(config); ++ struct dri2_egl_surface *dri2_surf; ++ const __DRIconfig *dri_config; ++ _EGLSurface *surf; ++ int format_idx; ++ ++ dri2_surf = calloc(1, sizeof(*dri2_surf)); ++ if (!dri2_surf) { ++ _eglError(EGL_BAD_ALLOC, "failed to create surface"); ++ return NULL; ++ } ++ surf = &dri2_surf->base; ++ ++ if (!dri2_init_surface(surf, disp, type, config, attrib_list, false, NULL)) ++ goto err_free_surface; ++ ++ dri_config = dri2_get_dri_config(dri2_config, type, ++ dri2_surf->base.GLColorspace); ++ if (!dri_config) { ++ _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); ++ goto err_free_surface; ++ } ++ ++ dri2_surf->dri_drawable = ++ dri2_dpy->image_driver->createNewDrawable(dri2_dpy->dri_screen, ++ dri_config, dri2_surf); ++ if (!dri2_surf->dri_drawable) { ++ _eglError(EGL_BAD_ALLOC, "failed to create drawable"); ++ goto err_free_surface; ++ } ++ ++ 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; ++ ++ return surf; ++ ++err_free_surface: ++ free(dri2_surf); ++ return NULL; ++} ++ ++static void ++destroy_surface(_EGLSurface *surf) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(surf->Resource.Display); ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); ++ ++ dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); ++ dri2_fini_surface(surf); ++ free(surf); ++} ++ ++static EGLBoolean ++dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf); ++ ++static _EGLSurface * ++dri2_null_create_window_surface(_EGLDisplay *disp, _EGLConfig *config, ++ void *native_window, const EGLint *attrib_list) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); ++ struct dri2_egl_surface *dri2_surf; ++ _EGLSurface *surf; ++ int err; ++ ++ if (dri2_dpy->output.in_use) { ++ _eglError(EGL_BAD_NATIVE_WINDOW, "window in use"); ++ return NULL; ++ } ++ ++ surf = create_surface(disp, config, EGL_WINDOW_BIT, attrib_list); ++ if (!surf) ++ return NULL; ++ dri2_surf = dri2_egl_surface(surf); ++ ++ dri2_surf->base.Width = dri2_dpy->output.mode.hdisplay; ++ dri2_surf->base.Height = dri2_dpy->output.mode.vdisplay; ++ ++ if (!get_front_bo(dri2_surf)) { ++ _eglError(EGL_BAD_NATIVE_WINDOW, "window get buffer"); ++ goto err_destroy_surface; ++ } ++ ++ err = display_output_modeset(dri2_dpy->fd, &dri2_dpy->output, ++ dri2_surf->front_fb_id); ++ if (err) { ++ _eglError(EGL_BAD_NATIVE_WINDOW, "window set mode"); ++ goto err_destroy_surface; ++ } ++ ++ dri2_dpy->output.in_use = true; ++ ++ return surf; ++ ++err_destroy_surface: ++ dri2_null_destroy_surface(disp, surf); ++ return NULL; ++} ++ ++static _EGLSurface * ++dri2_null_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *config, ++ const EGLint *attrib_list) ++{ ++ return create_surface(disp, config, EGL_PBUFFER_BIT, attrib_list); ++} ++ ++static EGLBoolean ++dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); ++ EGLint type = surf->Type; ++ ++ /* 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->front) ++ dri2_dpy->image->destroyImage(dri2_surf->front); ++ ++ if (dri2_surf->front_fb_id) ++ drmModeRmFB(dri2_dpy->fd, dri2_surf->front_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); ++ if (dri2_surf->color_buffers[i].dri_image) ++ dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image); ++ } ++ ++ destroy_surface(surf); ++ ++ if (type == EGL_WINDOW_BIT) ++ dri2_dpy->output.in_use = false; ++ ++ return EGL_TRUE; ++} ++ ++static EGLBoolean ++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; ++ ++ if (dri2_surf->base.Type != EGL_WINDOW_BIT) ++ 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++; ++ ++ /* Make sure we have a back buffer in case we're swapping without ++ * ever rendering. */ ++ if (!get_back_bo(dri2_surf)) { ++ _eglError(EGL_BAD_ALLOC, "dri2_null_swap_buffers"); ++ return EGL_FALSE; ++ } ++ ++ 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; ++ } ++ ++ 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; ++ } ++ ++ dri2_surf->back->age = 1; ++ dri2_surf->current = dri2_surf->back; ++ dri2_surf->back = NULL; ++ ++ return EGL_TRUE; ++} ++ ++static EGLint ++dri2_null_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface) ++{ ++ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface); ++ ++ if (!get_back_bo(dri2_surf)) { ++ _eglError(EGL_BAD_ALLOC, "failed to get back buffer to query age"); ++ return -1; ++ } ++ ++ return dri2_surf->back->age; ++} ++ ++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_buffers = dri2_null_swap_buffers, ++ .query_buffer_age = dri2_null_query_buffer_age, ++ .get_dri_drawable = dri2_surface_get_dri_drawable, ++}; ++ ++static int ++dri2_null_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format, ++ uint32_t *stamp, void *loaderPrivate, ++ uint32_t buffer_mask, struct __DRIimageList *buffers) ++{ ++ struct dri2_egl_surface *dri2_surf = loaderPrivate; ++ ++ buffers->image_mask = 0; ++ buffers->back = NULL; ++ buffers->front = NULL; ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) ++ if (!get_front_bo(dri2_surf)) ++ return 0; ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) ++ if (!get_back_bo(dri2_surf)) ++ return 0; ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) { ++ buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT; ++ buffers->front = dri2_surf->front; ++ } ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) { ++ buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK; ++ buffers->back = dri2_surf->back->dri_image; ++ } ++ ++ return 1; ++} ++ ++static void ++dri2_null_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) ++{ ++ (void) driDrawable; ++ (void) loaderPrivate; ++} ++ ++static const __DRIimageLoaderExtension image_loader_extension = { ++ .base = { __DRI_IMAGE_LOADER, 1 }, ++ ++ .getBuffers = dri2_null_image_get_buffers, ++ .flushFrontBuffer = dri2_null_flush_front_buffer, ++}; ++ ++static const __DRIextension *image_loader_extensions[] = { ++ &image_loader_extension.base, ++ &image_lookup_extension.base, ++ &use_invalidate.base, ++ NULL, ++}; ++ ++static bool ++dri2_null_device_is_kms(int fd) ++{ ++ drmModeRes *resources; ++ bool is_kms; ++ ++ resources = drmModeGetResources(fd); ++ if (!resources) ++ return false; ++ ++ is_kms = resources->count_crtcs != 0 && ++ resources->count_connectors != 0 && ++ resources->count_encoders != 0; ++ ++ drmModeFreeResources(resources); ++ ++ return is_kms; ++} ++ ++static bool ++dri2_null_probe_device(_EGLDisplay *disp) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); ++ ++ dri2_dpy->fd = -1; ++ ++ for (unsigned i = 0; i <= NULL_CARD_MINOR_MAX; i++) { ++ char *card_path; ++ ++ if (asprintf(&card_path, DRM_DEV_NAME, DRM_DIR_NAME, i) < 0) ++ continue; ++ ++ dri2_dpy->fd = loader_open_device(card_path); ++ free(card_path); ++ if (dri2_dpy->fd < 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; ++ } ++ } ++ ++ close(dri2_dpy->fd); ++ dri2_dpy->fd = -1; ++ } ++ ++ return false; ++} ++ ++static EGLBoolean ++dri2_null_add_configs_for_formats(_EGLDisplay *disp) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); ++ unsigned int count = 0; ++ ++ for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) { ++ struct dri2_egl_config *dri2_conf; ++ int format_idx; ++ ++ format_idx = format_idx_get_from_config(dri2_dpy, ++ dri2_dpy->driver_configs[i]); ++ if (format_idx == -1) ++ continue; ++ ++ if (!(dri2_dpy->output.formats & (1 << format_idx))) ++ continue; ++ ++ dri2_conf = dri2_add_config(disp, ++ dri2_dpy->driver_configs[i], count + 1, ++ EGL_WINDOW_BIT | EGL_PBUFFER_BIT, ++ NULL, NULL, NULL); ++ if (dri2_conf) ++ count++; ++ } ++ ++ return count != 0; ++} ++ ++EGLBoolean ++dri2_initialize_null(_EGLDisplay *disp) ++{ ++ struct dri2_egl_display *dri2_dpy; ++ uint64_t value; ++ int err; ++ ++ dri2_dpy = calloc(1, sizeof(*dri2_dpy)); ++ if (!dri2_dpy) ++ return _eglError(EGL_BAD_ALLOC, "eglInitialize"); ++ ++ disp->DriverData = (void *) dri2_dpy; ++ ++ if (!dri2_null_probe_device(disp)) { ++ _eglError(EGL_NOT_INITIALIZED, "failed to load driver"); ++ goto cleanup; ++ } ++ ++ /* ++ * Try to use atomic modesetting if available and fallback to legacy kernel ++ * modesetting if not. If this succeeds then universal planes will also have ++ * been enabled. ++ */ ++ err = drmSetClientCap(dri2_dpy->fd, DRM_CLIENT_CAP_ATOMIC, 1); ++ dri2_dpy->atomic_enabled = !err; ++ ++ if (!dri2_dpy->atomic_enabled) { ++ /* ++ * 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); ++ if (err) { ++ _eglError(EGL_NOT_INITIALIZED, "failed to enable universal planes"); ++ goto cleanup; ++ } ++ ++ dri2_dpy->atomic_enabled = false; ++ } ++ ++ if (!dri2_create_screen(disp)) { ++ _eglError(EGL_NOT_INITIALIZED, "failed to create screen"); ++ goto cleanup; ++ } ++ ++ if (!dri2_setup_extensions(disp)) { ++ _eglError(EGL_NOT_INITIALIZED, "failed to find required DRI extensions"); ++ goto cleanup; ++ } ++ ++ 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; ++ ++ if (dri2_dpy->image->base.version < NULL_IMAGE_EXTENSION_VERSION_MIN) { ++ _eglError(EGL_NOT_INITIALIZED, "image extension version too old"); ++ goto cleanup; ++ } ++ ++ if (!display_output_init(dri2_dpy->fd, &dri2_dpy->output, ++ dri2_dpy->atomic_enabled)) { ++ _eglError(EGL_NOT_INITIALIZED, "failed to create output"); ++ goto cleanup; ++ } ++ ++ if (!dri2_null_add_configs_for_formats(disp)) { ++ _eglError(EGL_NOT_INITIALIZED, "failed to add configs"); ++ goto cleanup; ++ } ++ ++ disp->Extensions.EXT_buffer_age = EGL_TRUE; ++ disp->Extensions.KHR_image_base = EGL_TRUE; ++ ++ /* Fill vtbl last to prevent accidentally calling virtual function during ++ * initialization. ++ */ ++ dri2_dpy->vtbl = &dri2_null_display_vtbl; ++ ++ return EGL_TRUE; ++ ++cleanup: ++ dri2_display_destroy(disp); ++ return EGL_FALSE; ++} ++ ++void ++dri2_teardown_null(struct dri2_egl_display *dri2_dpy) ++{ ++ drmModeAtomicFree(dri2_dpy->output.atomic_state); ++ ++ if (dri2_dpy->output.mode_blob_id) ++ drmModeDestroyPropertyBlob(dri2_dpy->fd, 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++) ++ drmModeFreeProperty(dri2_dpy->output.plane_prop_res[i]); ++ free(dri2_dpy->output.plane_prop_res); ++ } ++ ++ if (dri2_dpy->output.crtc_prop_res) { ++ for (unsigned i = 0; dri2_dpy->output.crtc_prop_res[i]; i++) ++ drmModeFreeProperty(dri2_dpy->output.crtc_prop_res[i]); ++ free(dri2_dpy->output.crtc_prop_res); ++ } ++ ++ if (dri2_dpy->output.connector_prop_res) { ++ for (unsigned i = 0; dri2_dpy->output.connector_prop_res[i]; i++) ++ drmModeFreeProperty(dri2_dpy->output.connector_prop_res[i]); ++ free(dri2_dpy->output.connector_prop_res); ++ } ++} +diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c +index 8d9f4a76330..893541f55b1 100644 +--- a/src/egl/main/eglapi.c ++++ b/src/egl/main/eglapi.c +@@ -989,7 +989,10 @@ _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, + + + if (native_window == NULL) +- RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); ++#ifdef HAVE_NULL_PLATFORM ++ if (disp && disp->Platform != _EGL_PLATFORM_NULL) ++#endif ++ RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + + if (disp && (disp->Platform == _EGL_PLATFORM_SURFACELESS || + disp->Platform == _EGL_PLATFORM_DEVICE)) { +diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c +index 486ac3b0557..395f38156d7 100644 +--- a/src/egl/main/egldisplay.c ++++ b/src/egl/main/egldisplay.c +@@ -78,6 +78,7 @@ static const struct { + { _EGL_PLATFORM_SURFACELESS, "surfaceless" }, + { _EGL_PLATFORM_DEVICE, "device" }, + { _EGL_PLATFORM_TIZEN, "tizen" }, ++ { _EGL_PLATFORM_NULL, "null" }, + }; + + +diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h +index 020529c57e2..8489af9dde2 100644 +--- a/src/egl/main/egldisplay.h ++++ b/src/egl/main/egldisplay.h +@@ -53,6 +53,7 @@ enum _egl_platform_type { + _EGL_PLATFORM_SURFACELESS, + _EGL_PLATFORM_DEVICE, + _EGL_PLATFORM_TIZEN, ++ _EGL_PLATFORM_NULL, + + _EGL_NUM_PLATFORMS, + _EGL_INVALID_PLATFORM = -1 +diff --git a/src/egl/meson.build b/src/egl/meson.build +index 17e9c690b82..d23d62562da 100644 +--- a/src/egl/meson.build ++++ b/src/egl/meson.build +@@ -142,6 +142,11 @@ if with_platform_tizen + incs_for_egl += [inc_loader] + deps_for_egl += [dep_tizen, dep_libdrm] + endif ++if with_platform_null ++ files_egl += files('drivers/dri2/platform_null.c') ++ incs_for_egl += [inc_loader] ++ deps_for_egl += dep_libdrm ++endif + + if cc.has_function('mincore') + c_args_for_egl += '-DHAVE_MINCORE' +-- +2.17.1 + diff --git a/package/mesa3d/0038-egl-add-config-debug-printout.patch b/package/mesa3d/0038-egl-add-config-debug-printout.patch new file mode 100644 index 00000000..93c0d720 --- /dev/null +++ b/package/mesa3d/0038-egl-add-config-debug-printout.patch @@ -0,0 +1,480 @@ +From 7065e8e6bc0c3674ae310468b95cef1d538f5f03 Mon Sep 17 00:00:00 2001 +From: Silvestrs Timofejevs +Date: Mon, 24 Sep 2018 14:14:25 +0100 +Subject: [PATCH 38/50] 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/Makefile.sources | 4 +- + src/egl/main/eglconfig.c | 20 ++- + src/egl/main/eglconfigdebug.c | 276 ++++++++++++++++++++++++++++++++++ + src/egl/main/eglconfigdebug.h | 55 +++++++ + src/egl/main/egllog.c | 9 ++ + src/egl/main/egllog.h | 4 + + src/egl/meson.build | 2 + + 7 files changed, 365 insertions(+), 5 deletions(-) + create mode 100644 src/egl/main/eglconfigdebug.c + create mode 100644 src/egl/main/eglconfigdebug.h + +diff --git a/src/egl/Makefile.sources b/src/egl/Makefile.sources +index 5f5b6d27e64..d757ba9bed4 100644 +--- a/src/egl/Makefile.sources ++++ b/src/egl/Makefile.sources +@@ -25,7 +25,9 @@ LIBEGL_C_FILES := \ + main/eglsync.c \ + main/eglsync.h \ + main/eglentrypoint.h \ +- main/egltypedefs.h ++ main/egltypedefs.h \ ++ main/eglconfigdebug.h \ ++ main/eglconfigdebug.c + + dri2_backend_core_FILES := \ + drivers/dri2/egl_dri2.c \ +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..13e0a8bc350 +--- /dev/null ++++ b/src/egl/main/eglconfigdebug.c +@@ -0,0 +1,276 @@ ++/* ++ * 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 ++#include ++#include ++#include ++ ++#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]; ++}; ++ ++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 ++ * ++ * colourbuffer ++ * 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 ++ */ ++ _eglLog(_EGL_DEBUG, "---------------"); ++ _eglLog(_EGL_DEBUG, "Configurations:"); ++ _eglLog(_EGL_DEBUG, "cho bf lv colourbuffer dp st ms vis cav bi renderable supported"); ++ _eglLog(_EGL_DEBUG, "sen id sz l r g b a th cl ns b id eat nd gl es es2 es3 vg surfaces"); ++ _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 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); ++ ++ 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); ++ ++ _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 d23d62562da..e0628c41c43 100644 +--- a/src/egl/meson.build ++++ b/src/egl/meson.build +@@ -30,6 +30,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.17.1 + diff --git a/package/mesa3d/0039-egl-add-support-for-EXT_image_gl_colorspace.patch b/package/mesa3d/0039-egl-add-support-for-EXT_image_gl_colorspace.patch new file mode 100644 index 00000000..4d04dfe4 --- /dev/null +++ b/package/mesa3d/0039-egl-add-support-for-EXT_image_gl_colorspace.patch @@ -0,0 +1,217 @@ +From 1b9ddfc2a489056311c6eff3760ad6f450d13c94 Mon Sep 17 00:00:00 2001 +From: Frank Binns +Date: Tue, 29 Jan 2019 14:36:25 +0000 +Subject: [PATCH 39/50] 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 ee19d125675..f001ee7b98f 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -1113,6 +1113,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) +@@ -2752,6 +2755,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; +@@ -2827,6 +2835,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) { +@@ -2890,6 +2903,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) { +@@ -3035,6 +3053,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; +@@ -3211,6 +3234,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) +@@ -3356,6 +3396,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; +@@ -3381,6 +3422,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; +@@ -3425,7 +3478,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, +@@ -3437,7 +3490,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 893541f55b1..431dd70d1d8 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.17.1 + diff --git a/package/mesa3d/0040-meson-force-C-2011-for-thread_local.patch b/package/mesa3d/0040-meson-force-C-2011-for-thread_local.patch new file mode 100644 index 00000000..92e7d239 --- /dev/null +++ b/package/mesa3d/0040-meson-force-C-2011-for-thread_local.patch @@ -0,0 +1,35 @@ +From 04993e64906c7481f877dd6775a935259ea2d5b9 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Mon, 24 Jun 2019 09:35:39 +0100 +Subject: [PATCH 40/50] 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 56340b8ef3b..3c55447b6eb 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.17.1 + diff --git a/package/mesa3d/0041-dri2-add-support-for-swap-intervals-other-than-1.patch b/package/mesa3d/0041-dri2-add-support-for-swap-intervals-other-than-1.patch new file mode 100644 index 00000000..44c129be --- /dev/null +++ b/package/mesa3d/0041-dri2-add-support-for-swap-intervals-other-than-1.patch @@ -0,0 +1,785 @@ +From dc031ad65131ed5de6e8dd8db21d49c0185d6e0b Mon Sep 17 00:00:00 2001 +From: Luigi Santivetti +Date: Wed, 19 Jun 2019 16:36:06 +0100 +Subject: [PATCH 41/50] 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 +--- + 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 95435b9ee12..2fdba4bd62e 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -324,6 +324,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; +@@ -362,13 +379,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; +@@ -404,7 +426,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 +@@ -433,7 +455,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 2b3b08cc259..0b20aef9e4d 100644 +--- a/src/egl/drivers/dri2/platform_null.c ++++ b/src/egl/drivers/dri2/platform_null.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -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, ¤t_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, +@@ -1059,12 +1431,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)); +@@ -1111,11 +1506,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.17.1 + diff --git a/package/mesa3d/0042-null_platform-add-support-for-explicit-synchronisati.patch b/package/mesa3d/0042-null_platform-add-support-for-explicit-synchronisati.patch new file mode 100644 index 00000000..ab394328 --- /dev/null +++ b/package/mesa3d/0042-null_platform-add-support-for-explicit-synchronisati.patch @@ -0,0 +1,214 @@ +From 58d5fa48cf14a930322b5645dd5e26c8b546f394 Mon Sep 17 00:00:00 2001 +From: Silvestrs Timofejevs +Date: Mon, 2 Sep 2019 09:32:01 +0100 +Subject: [PATCH 42/50] 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 2fdba4bd62e..3d5c9adb4f3 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -100,6 +100,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; +@@ -330,6 +331,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 0b20aef9e4d..c25ae0b2a04 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.17.1 + diff --git a/package/mesa3d/0043-dri2-add-support-for-image-modifiers.patch b/package/mesa3d/0043-dri2-add-support-for-image-modifiers.patch new file mode 100644 index 00000000..8befe7c8 --- /dev/null +++ b/package/mesa3d/0043-dri2-add-support-for-image-modifiers.patch @@ -0,0 +1,372 @@ +From ac19d1d06ea2433fed707210f4433133a58a12dc Mon Sep 17 00:00:00 2001 +From: Luigi Santivetti +Date: Thu, 26 Sep 2019 13:32:15 +0100 +Subject: [PATCH 43/50] dri2: add support for image 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 +populate all formats with associated modifiers supported by the display +for the primary drm plane in use. + +drmModePopulateFormats() is added to the DRM api in a different change +and it is not upstream at present. + +NOTES: + [1] IN_FORMATS blobs are available since kernel 4.14: + - db1689aa61bd1efb5ce9b896e7aa860a85b7f1b6 + - https://patchwork.freedesktop.org/patch/168543 + + [2] for the record, in order to test this change, it was needed to: + - edit pvrdri_impl.c, as fbc relies on the BVNC for selecting which + algorithm and fourcc code are to be used. To sidestep this, include + img_drm_fourcc_internal.h instead of powervr/img_drm_fourcc.h and + manually add the list of g_auiAll_mods[] + - edit null_disp_drv.h, by removing DRM_FORMAT_MOD_LINEAR + - edit pvrrem_conv_sw_fbdc.c, log from decompress_fb() by building + with RFB_DEBUG=1, the log file is under /var/log + + [3] 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 +--- + src/egl/drivers/dri2/egl_dri2.h | 6 + + src/egl/drivers/dri2/platform_null.c | 174 +++++++++++++++++++++++---- + 2 files changed, 159 insertions(+), 21 deletions(-) + +diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h +index 3d5c9adb4f3..6ec9ee01885 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -110,6 +110,7 @@ struct display_output { + drmModeModeInfo mode; + uint32_t mode_blob_id; + unsigned formats; ++ drmModeFormats *in_formats; + drmModeAtomicReq *atomic_state; + }; + #endif +@@ -274,6 +275,7 @@ struct dri2_egl_display + + #ifdef HAVE_NULL_PLATFORM + bool atomic_enabled; ++ bool in_formats_enabled; + struct display_output output; + #endif + +@@ -373,6 +375,10 @@ struct dri2_egl_surface + #if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_NULL_PLATFORM) + int format; + #endif ++#if defined(HAVE_NULL_PLATFORM) ++ uint64_t *modifiers; ++ uint32_t count_modifiers; ++#endif + + #ifdef HAVE_DRM_PLATFORM + struct gbm_dri_surface *gbm_surf; +diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c +index c25ae0b2a04..701460dde4e 100644 +--- a/src/egl/drivers/dri2/platform_null.c ++++ b/src/egl/drivers/dri2/platform_null.c +@@ -156,6 +156,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, +@@ -644,14 +656,45 @@ drm_event_process(int fd) + return 0; + } + ++static drmModeFormatsPtr ++plane_get_in_formats(int fd, drmModePlane *plane) ++{ ++ drmModeFormatsPtr drm_mode_fmt = NULL; ++ drmModePropertyBlobRes *blob; ++ uint64_t prop_value; ++ uint32_t blob_id; ++ int err; ++ ++ if (!plane) ++ return NULL; ++ ++ err = !object_property_value_for_name(fd, plane->plane_id, DRM_MODE_OBJECT_PLANE, ++ "IN_FORMATS", &prop_value); ++ if (err) ++ return NULL; ++ ++ blob_id = blob_id_from_property_value(prop_value); ++ blob = drmModeGetPropertyBlob(fd, blob_id); ++ ++ err = drmModePopulateFormats(blob, &drm_mode_fmt); ++ if (err) ++ _eglLog(_EGL_WARNING,"failed to populate in_formats (%d)", err); ++ ++ drmModeFreePropertyBlob(blob); ++ ++ return drm_mode_fmt; ++} ++ + static bool +-display_output_init(int fd, struct display_output *output, bool use_atomic) ++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; + drmModeCrtc *crtc; + drmModePlane *plane; + unsigned mode_idx; ++ uint32_t drm_format; + + resources = drmModeGetResources(fd); + if (!resources) +@@ -674,18 +717,41 @@ display_output_init(int fd, struct display_output *output, bool use_atomic) + goto err_free_plane; + output->mode = connector->modes[mode_idx]; + ++ assert(in_formats_enabled_out && !(*in_formats_enabled_out)); ++ ++ /* can in_formats be enabled for this display? */ ++ if (prefer_in_formats) { ++ output->in_formats = plane_get_in_formats(fd, plane); ++ if (!output->in_formats) { ++ _eglLog(_EGL_WARNING, ++ "fallback to plane formats, no in_formats found"); ++ } else if (output->in_formats->count != plane->count_formats) { ++ /* exit the process with generic failure 1 */ ++ _eglLog(_EGL_FATAL, ++ "kernel bug: formats count mismatch, exit"); ++ } else { ++ *in_formats_enabled_out = true; ++ } ++ } ++ + /* Record the display supported formats */ + for (unsigned i = 0; i < plane->count_formats; i++) { + int format_idx; + +- format_idx = format_idx_get_from_drm_format(plane->formats[i]); ++ drm_format = *in_formats_enabled_out ? ++ output->in_formats->formats[i].format : plane->formats[i]; ++ format_idx = format_idx_get_from_drm_format(drm_format); + 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; ++ goto err_free_formats; + + output->connector_id = connector->connector_id; + output->crtc_id = crtc->crtc_id; +@@ -705,6 +771,8 @@ display_output_init(int fd, struct display_output *output, bool use_atomic) + + return true; + ++err_free_formats: ++ drmModeFreeFormats(output->in_formats); + err_free_plane: + drmModeFreePlane(plane); + err_free_crtc: +@@ -983,10 +1051,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 +1071,41 @@ 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); ++ ++ if (dri2_dpy->in_formats_enabled) ++ return dri2_dpy->image->createImageWithModifiers(dri2_dpy->dri_screen, ++ dri2_surf->base.Width, ++ dri2_surf->base.Height, ++ dri2_surf->format, ++ dri2_surf->modifiers, ++ dri2_surf->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 +1118,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 +1155,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 +1186,26 @@ 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(drmModeFormats *in_formats, int drm_format, ++ uint64_t **out_modifiers, uint32_t *out_count) ++{ ++ unsigned i; ++ ++ if (!in_formats) ++ return false; ++ ++ for (i = 0; i < in_formats->count; i++) { ++ if (in_formats->formats[i].format == drm_format) { ++ *out_modifiers = in_formats->formats[i].modifiers; ++ *out_count = in_formats->formats[i].count_modifiers; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + static _EGLSurface * + create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type, + const EGLint *attrib_list) +@@ -1105,6 +1217,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 +1250,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->output.in_formats, ++ dri2_null_formats[format_idx].drm_format, ++ &dri2_surf->modifiers, ++ &dri2_surf->count_modifiers); ++ if (!ret || dri2_surf->count_modifiers <= 0) ++ goto err_free_surface; ++ } ++ + surface_swap_queue_init(dri2_surf); + + return surf; +@@ -1533,6 +1655,7 @@ EGLBoolean + dri2_initialize_null(_EGLDisplay *disp) + { + struct dri2_egl_display *dri2_dpy; ++ bool prefer_in_formats; + int err; + + dri2_dpy = calloc(1, sizeof(*dri2_dpy)); +@@ -1586,8 +1709,16 @@ dri2_initialize_null(_EGLDisplay *disp) + goto cleanup; + } + ++ /* 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; + } +@@ -1616,6 +1747,7 @@ void + dri2_teardown_null(struct dri2_egl_display *dri2_dpy) + { + drmModeAtomicFree(dri2_dpy->output.atomic_state); ++ drmModeFreeFormats(dri2_dpy->output.in_formats); + + if (dri2_dpy->output.mode_blob_id) + drmModeDestroyPropertyBlob(dri2_dpy->fd, dri2_dpy->output.mode_blob_id); +-- +2.17.1 + diff --git a/package/mesa3d/0044-egl-query-the-supported-ES2-context-version.patch b/package/mesa3d/0044-egl-query-the-supported-ES2-context-version.patch new file mode 100644 index 00000000..342692d6 --- /dev/null +++ b/package/mesa3d/0044-egl-query-the-supported-ES2-context-version.patch @@ -0,0 +1,203 @@ +From 7c21f010de28888376dcafd99d3fa43d15279dc6 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Mon, 10 Feb 2020 09:23:03 +0000 +Subject: [PATCH 44/50] 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 8214e7a55c3..302e4e08de0 100644 +--- a/include/GL/internal/dri_interface.h ++++ b/include/GL/internal/dri_interface.h +@@ -2028,6 +2028,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 f001ee7b98f..cda414f4adc 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -2083,6 +2083,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) + { +@@ -4347,6 +4367,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 8eda31c2936..6fc58371063 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 431dd70d1d8..900ef7ab4cc 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 65dc886abbb..09e7d3ee589 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.17.1 + diff --git a/package/mesa3d/0045-meson-allow-libGL-to-be-built-without-GLX.patch b/package/mesa3d/0045-meson-allow-libGL-to-be-built-without-GLX.patch new file mode 100644 index 00000000..0f347bf4 --- /dev/null +++ b/package/mesa3d/0045-meson-allow-libGL-to-be-built-without-GLX.patch @@ -0,0 +1,140 @@ +From 43662126e9973c6cff496ba32fae3cf372e0646b Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Thu, 11 Jun 2020 12:29:51 +0100 +Subject: [PATCH 45/50] 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 | 16 ++++++++++++---- + src/meson.build | 2 +- + 5 files changed, 23 insertions(+), 12 deletions(-) + +diff --git a/meson.build b/meson.build +index 3c55447b6eb..af020203752 100644 +--- a/meson.build ++++ b/meson.build +@@ -459,6 +459,10 @@ else + with_egl = false + 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 ['windows', 'freebsd', 'openbsd', 'haiku'].contains(host_machine.system()) and (not with_platform_android or get_option('platform-sdk-version') >= 29) +@@ -466,7 +470,7 @@ if not ['windows', 'freebsd', 'openbsd', 'haiku'].contains(host_machine.system() + use_elf_tls = true + 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' +@@ -528,7 +532,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 9073223e8f5..4038629544e 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -267,7 +267,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 58f9e1aa896..41ca936b8f4 100644 +--- a/src/glx/meson.build ++++ b/src/glx/meson.build +@@ -126,7 +126,11 @@ gl_lib_cargs = [ + '-D_REENTRANT', + ] + +-libglx = static_library( ++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], +@@ -143,13 +147,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 d96c754a63d..a92580b2dd5 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -104,7 +104,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.17.1 + diff --git a/package/mesa3d/0046-egl-wayland-process-non-resized-window-movement.patch b/package/mesa3d/0046-egl-wayland-process-non-resized-window-movement.patch new file mode 100644 index 00000000..9fcfb3c2 --- /dev/null +++ b/package/mesa3d/0046-egl-wayland-process-non-resized-window-movement.patch @@ -0,0 +1,38 @@ +From bc8f13db460c79ef9036e7f0983bb039ac1af777 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Tue, 25 Aug 2020 14:12:32 +0100 +Subject: [PATCH 46/50] 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 de12ec21f53..f4b43aa26a2 100644 +--- a/src/egl/drivers/dri2/platform_wayland.c ++++ b/src/egl/drivers/dri2/platform_wayland.c +@@ -265,6 +265,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; +@@ -799,8 +802,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->base.Width != dri2_surf->wl_win->attached_width || +-- +2.17.1 + diff --git a/package/mesa3d/0047-Separate-EXT_framebuffer_object-from-ARB-version.patch b/package/mesa3d/0047-Separate-EXT_framebuffer_object-from-ARB-version.patch new file mode 100644 index 00000000..0f1f2416 --- /dev/null +++ b/package/mesa3d/0047-Separate-EXT_framebuffer_object-from-ARB-version.patch @@ -0,0 +1,539 @@ +From 22afb695d4598a52198f9bbe98b359f9fcf77cfa Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Mon, 10 Mar 2014 13:43:45 +0000 +Subject: [PATCH 47/50] 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 @@ + + + +- ++ + + + +@@ -81,30 +81,30 @@ + + + +- ++ + + + + +- ++ + + + + +- ++ + + + + + + +- ++ + + + + + +- ++ + + + +@@ -115,22 +115,22 @@ + + + +- ++ + + + + +- ++ + + + + +- ++ + + + + +- ++ + + + +@@ -138,7 +138,7 @@ + + + +- ++ + + + +@@ -146,7 +146,7 @@ + + + +- ++ + + + +@@ -155,21 +155,21 @@ + + + +- ++ + + + + + + +- ++ + + + + + + +- ++ + + + +diff --git a/src/mapi/glapi/gen/static_data.py b/src/mapi/glapi/gen/static_data.py +index 32fb3b8f4f7..ecd650ab814 100644 +--- a/src/mapi/glapi/gen/static_data.py ++++ b/src/mapi/glapi/gen/static_data.py +@@ -1694,6 +1694,21 @@ offsets = { + "FramebufferTextureMultisampleMultiviewOVR" : 1658, + "MultiDrawArraysIndirectEXT" : 1659, + "MultiDrawElementsIndirectEXT" : 1660, ++ "IsRenderbufferEXT" : 1661, ++ "DeleteRenderbuffersEXT" : 1662, ++ "GenRenderbuffersEXT" : 1663, ++ "RenderbufferStorageEXT" : 1664, ++ "GetRenderbufferParameterivEXT" : 1665, ++ "IsFramebufferEXT" : 1666, ++ "DeleteFramebuffersEXT" : 1667, ++ "GenFramebuffersEXT" : 1668, ++ "CheckFramebufferStatusEXT" : 1669, ++ "FramebufferTexture1DEXT" : 1670, ++ "FramebufferTexture2DEXT" : 1671, ++ "FramebufferTexture3DEXT" : 1672, ++ "FramebufferRenderbufferEXT" : 1673, ++ "GetFramebufferAttachmentParameterivEXT" : 1674, ++ "GenerateMipmapEXT" : 1675, + } + + functions = [ +diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c +index 798f59d2499..21507ff7c19 100644 +--- a/src/mesa/main/fbobject.c ++++ b/src/mesa/main/fbobject.c +@@ -1973,6 +1973,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) +@@ -2682,6 +2687,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) + { +@@ -2712,6 +2723,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 +@@ -2744,6 +2760,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, +@@ -2945,6 +2967,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, +@@ -2978,6 +3005,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 +@@ -3212,6 +3244,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. +@@ -3258,6 +3295,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) +@@ -3297,6 +3339,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) +@@ -3909,6 +3956,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, +@@ -3949,6 +4002,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, +@@ -4059,6 +4118,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, +@@ -4312,6 +4380,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, +@@ -4713,6 +4790,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 16e2b037635..4d7b7db36a5 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.17.1 + diff --git a/package/mesa3d/0048-egl-null-add-support-for-async-flip-with-front-buffe.patch b/package/mesa3d/0048-egl-null-add-support-for-async-flip-with-front-buffe.patch new file mode 100644 index 00000000..d1a5ecf0 --- /dev/null +++ b/package/mesa3d/0048-egl-null-add-support-for-async-flip-with-front-buffe.patch @@ -0,0 +1,321 @@ +From b2bee752e8c3d4188037b0d538b86836a0ba19d3 Mon Sep 17 00:00:00 2001 +From: Luigi Santivetti +Date: Mon, 21 Oct 2019 09:21:52 +0100 +Subject: [PATCH 48/50] 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 +--- + 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 6ec9ee01885..9d60d21e8fd 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -276,6 +276,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 + +@@ -434,8 +435,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; +@@ -463,12 +468,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 701460dde4e..4969121bf37 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) { +@@ -1637,18 +1719,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.17.1 + diff --git a/package/mesa3d/0049-gbm-add-pbuffer-support.patch b/package/mesa3d/0049-gbm-add-pbuffer-support.patch new file mode 100644 index 00000000..59c6b14a --- /dev/null +++ b/package/mesa3d/0049-gbm-add-pbuffer-support.patch @@ -0,0 +1,229 @@ +From 8ea569933388752a39e859989b69ab2f09f68309 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Fri, 21 Aug 2020 12:13:28 +0100 +Subject: [PATCH 49/50] 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 9d60d21e8fd..2292f29772d 100644 +--- a/src/egl/drivers/dri2/egl_dri2.h ++++ b/src/egl/drivers/dri2/egl_dri2.h +@@ -462,6 +462,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 2944a5d7ad4..7fb8d2376d8 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_surface *surf = &dri2_surf->gbm_surf->base; ++ ++ dri2_surf->front_bo = gbm_bo_create(&dri2_dpy->gbm_dri->base, ++ surf->width, ++ surf->height, ++ surf->format, ++ surf->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); + +@@ -400,12 +470,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; + } +@@ -423,6 +508,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; +@@ -646,7 +734,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++; +@@ -670,6 +759,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.17.1 + diff --git a/package/mesa3d/0050-egl-null-expose-EXT_yuv_surface-support.patch b/package/mesa3d/0050-egl-null-expose-EXT_yuv_surface-support.patch new file mode 100644 index 00000000..eafc25e9 --- /dev/null +++ b/package/mesa3d/0050-egl-null-expose-EXT_yuv_surface-support.patch @@ -0,0 +1,84 @@ +From b8488580d9d7e034aa39426f6ef161035e56915d Mon Sep 17 00:00:00 2001 +From: Luigi Santivetti +Date: Mon, 25 Jan 2021 11:05:49 +0000 +Subject: [PATCH 50/50] egl/null: expose EXT_yuv_surface support + +--- + src/egl/drivers/dri2/platform_null.c | 28 +++++++++++++++++++++++++--- + 1 file changed, 25 insertions(+), 3 deletions(-) + +diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c +index 4969121bf37..9830b73d704 100644 +--- a/src/egl/drivers/dri2/platform_null.c ++++ b/src/egl/drivers/dri2/platform_null.c +@@ -106,6 +106,12 @@ static const struct dri2_null_format { + .rgba_shifts = { 11, 5, 0, -1 }, + .rgba_sizes = { 5, 6, 5, 0 }, + }, ++ { ++ .drm_format = DRM_FORMAT_YUYV, ++ .dri_image_format = __DRI_IMAGE_FORMAT_YUYV, ++ .rgba_shifts = { -1, -1, -1, -1 }, ++ .rgba_sizes = { 0, 0, 0, 0 }, ++ }, + }; + + +@@ -1595,6 +1601,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) + { +@@ -1603,10 +1620,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[] = { +@@ -1688,6 +1706,7 @@ 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; + int format_idx; + + format_idx = format_idx_get_from_config(dri2_dpy, +@@ -1698,10 +1717,13 @@ dri2_null_add_configs_for_formats(_EGLDisplay *disp) + if (!(dri2_dpy->output.formats & (1 << format_idx))) + continue; + ++ surface_type = EGL_WINDOW_BIT; ++ if (dri2_null_formats[format_idx].drm_format != 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, NULL, NULL); ++ surface_type, NULL, NULL, NULL); + if (dri2_conf) + count++; + } +-- +2.17.1 + diff --git a/package/mesa3d/Config.in b/package/mesa3d/Config.in index 7da9ca4f..062603f7 100644 --- a/package/mesa3d/Config.in +++ b/package/mesa3d/Config.in @@ -351,6 +351,13 @@ config BR2_PACKAGE_MESA3D_DRI_DRIVER_RADEON help Legacy Radeon driver for R100 series GPUs. +config BR2_PACKAGE_MESA3D_DRI_DRIVER_PVR + bool "DRI pvr driver" + depends on BR2_PACKAGE_IMG_GPU_POWERVR + select BR2_PACKAGE_MESA3D_DRI_DRIVER + help + Support for Imagination PowerVR GPUs. + comment "Vulkan drivers" config BR2_PACKAGE_MESA3D_VULKAN_DRIVER_INTEL diff --git a/package/mesa3d/mesa3d.hash b/package/mesa3d/mesa3d.hash index 26176b85..eb56b8c8 100644 --- a/package/mesa3d/mesa3d.hash +++ b/package/mesa3d/mesa3d.hash @@ -1,6 +1,6 @@ -# From https://lists.freedesktop.org/archives/mesa-announce/2021-September/000644.html -sha256 5cd32f5d089dca75300578a3d771a656eaed652090573a2655fe4e7022d56bfc mesa-21.1.8.tar.xz -sha512 80fcf2b1d59b49e384e9aa1ae63a3ce709833059af1ffd8eb821054c1976709134098cfc79fac1578a2f08a003223f1c96b38e2e650c5be49821c6f2fe1047af mesa-21.1.8.tar.xz +# From https://lists.freedesktop.org/archives/mesa-announce/2021-March/000624.html +sha256 379fc984459394f2ab2d84049efdc3a659869dc1328ce72ef0598506611712bb mesa-21.0.1.tar.xz +sha512 b31b78778b6092dfaf0712f90de3074217574389c4236f8379c127739874f6bd1b47883140a26445d25e58df87e6207278efd048453096ee710d334b1dcfe419 mesa-21.0.1.tar.xz # License sha256 998437f3f75f0c542046f83c1cb349408122268168fb13eb4ae6967aa18b7d98 docs/license.rst diff --git a/package/mesa3d/mesa3d.mk b/package/mesa3d/mesa3d.mk index dc63d8c9..550b0b20 100644 --- a/package/mesa3d/mesa3d.mk +++ b/package/mesa3d/mesa3d.mk @@ -5,7 +5,7 @@ ################################################################################ # When updating the version, please also update mesa3d-headers -MESA3D_VERSION = 21.1.8 +MESA3D_VERSION = 21.0.1 MESA3D_SOURCE = mesa-$(MESA3D_VERSION).tar.xz MESA3D_SITE = https://archive.mesa3d.org MESA3D_LICENSE = MIT, SGI, Khronos @@ -76,12 +76,6 @@ MESA3D_CONF_OPTS += \ -Dgallium-xa=disabled endif -ifeq ($(BR2_ARM_CPU_HAS_NEON),y) -MESA3D_CONF_OPTS += -Dgallium-vc4-neon=auto -else -MESA3D_CONF_OPTS += -Dgallium-vc4-neon=disabled -endif - # Drivers #Gallium Drivers @@ -106,6 +100,7 @@ MESA3D_DRI_DRIVERS-$(BR2_PACKAGE_MESA3D_DRI_DRIVER_I915) += i915 MESA3D_DRI_DRIVERS-$(BR2_PACKAGE_MESA3D_DRI_DRIVER_I965) += i965 MESA3D_DRI_DRIVERS-$(BR2_PACKAGE_MESA3D_DRI_DRIVER_NOUVEAU) += nouveau MESA3D_DRI_DRIVERS-$(BR2_PACKAGE_MESA3D_DRI_DRIVER_RADEON) += r100 +MESA3D_DRI_DRIVERS-$(BR2_PACKAGE_MESA3D_DRI_DRIVER_PVR) += pvr # Vulkan Drivers MESA3D_VULKAN_DRIVERS-$(BR2_PACKAGE_MESA3D_VULKAN_DRIVER_INTEL) += intel diff --git a/package/starfive/Config.in b/package/starfive/Config.in index 4e9a492e..8d055523 100644 --- a/package/starfive/Config.in +++ b/package/starfive/Config.in @@ -9,3 +9,4 @@ source "package/starfive/v4l2_test/Config.in" source "package/starfive/mailbox-test/Config.in" source "package/starfive/e24-test/Config.in" source "package/starfive/stfisp_setfile/Config.in.host" +source "package/starfive/img-gpu-powervr/Config.in" diff --git a/package/starfive/img-gpu-powervr/Config.in b/package/starfive/img-gpu-powervr/Config.in new file mode 100644 index 00000000..511d33b8 --- /dev/null +++ b/package/starfive/img-gpu-powervr/Config.in @@ -0,0 +1,97 @@ +comment "img-gpu-powervr needs a glibc toolchain" + depends on BR2_riscv + depends on !BR2_TOOLCHAIN_USES_GLIBC + +config BR2_PACKAGE_IMG_GPU_POWERVR + bool "img-gpu-powervr" + # Pre-built binaries only available for RISCV + depends on BR2_riscv + # Library binaries are linked against libc.so.6 + depends on BR2_TOOLCHAIN_USES_GLIBC + # Library binaries are linked against libdrm.so.2, except framebuffer + # output on RISCV + select BR2_PACKAGE_LIBDRM if !(BR2_riscv && BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_FB) + select BR2_PACKAGE_HAS_LIBEGL + select BR2_PACKAGE_HAS_LIBGLES + select BR2_PACKAGE_HAS_LIBOPENCL + select BR2_PACKAGE_HAS_LIBVULKAN + select BR2_PACKAGE_MESA3D + select BR2_PACKAGE_MESA3D_OPENGL_EGL + select BR2_PACKAGE_MESA3D_DRI_DRIVER_PVR + help + Userspace libraries for Imagination PowerGPU GPU on StarFive platforms + + It contains libraries and headers for GLES, OpenCL, and + Vulkan. It also contains a DRI plugin for X11. It also + contains a plugin for DirectFB-1.4.0. + + This library is provided by StarFive as-is and doesn't have + an upstream. + +if BR2_PACKAGE_IMG_GPU_POWERVR + +choice + prompt "Output option" + help + There are two versions of this library: one for + direct framebuffer access, one for X11 rendering. + Choose here which version to install. + +config BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_X11 + bool "X11" + depends on BR2_PACKAGE_XORG7 + # The i.MX8 blob doesn't support X11 output + depends on !BR2_PACKAGE_FREESCALE_IMX_PLATFORM_IMX8M + select BR2_PACKAGE_XLIB_LIBXDAMAGE + select BR2_PACKAGE_XLIB_LIBXEXT + select BR2_PACKAGE_XLIB_LIBXFIXES + +comment "X11 backend needs Xorg package" + depends on !BR2_PACKAGE_XORG7 + +config BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_FB + bool "Framebuffer" + +config BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_WL + bool "Wayland" + select BR2_PACKAGE_WAYLAND + select BR2_PACKAGE_HAS_LIBEGL_WAYLAND + +endchoice + +config BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT + string + default "x11" if BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_X11 + default "fb" if BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_FB + default "wayland" if BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_WL + +config BR2_PACKAGE_PROVIDES_LIBEGL + default "img-gpu-powervr" + +config BR2_PACKAGE_PROVIDES_LIBGLES + default "img-gpu-powervr" + +config BR2_PACKAGE_PROVIDES_LIBOPENCL + default "img-gpu-powervr" + +config BR2_PACKAGE_PROVIDES_LIBVULKAN + default "img-gpu-powervr" + +config BR2_PACKAGE_IMG_GPU_POWERVR_EXAMPLES + bool "install examples" + depends on BR2_INSTALL_LIBSTDCPP + help + Copy the PowerVR examples to the target. + + Warning: examples take approximately 150 MB of disk space. + +comment "img-gpu-powervr-examples need a toolchain w/ C++ support" + depends on !BR2_INSTALL_LIBSTDCPP + +config BR2_PACKAGE_IMG_GPU_POWERVR_GMEM_INFO + bool "install gmem_info tool" + help + Copy the gmem_info tool to the target which provides + information about GPU memory consumption. + +endif diff --git a/package/starfive/img-gpu-powervr/img-gpu-powervr.hash b/package/starfive/img-gpu-powervr/img-gpu-powervr.hash new file mode 100644 index 00000000..39ce77e7 --- /dev/null +++ b/package/starfive/img-gpu-powervr/img-gpu-powervr.hash @@ -0,0 +1,5 @@ +# Locally calculated +# sha256 1324b1aaf190110b80ad9a6f6533f4f50dce9e9ab8d49d8503f59764b151d219 imx-gpu-viv-6.4.3.p2.0-aarch32.bin +# sha256 003c30baefb1655790b475c3cdfa5cefbf81ea89ef37c6649b64f151dd23a52e imx-gpu-viv-6.4.3.p2.0-aarch64.bin +# sha256 ea58636bf34f589048fcd46e38497c47229fde8498df086ff5fb52f9ef8e15ee COPYING +# sha256 50099e283cfd307f84f159aeb1a6f462351320273dbcdb80d7f2c9db0494b71c EULA diff --git a/package/starfive/img-gpu-powervr/img-gpu-powervr.mk b/package/starfive/img-gpu-powervr/img-gpu-powervr.mk new file mode 100644 index 00000000..240c2ebd --- /dev/null +++ b/package/starfive/img-gpu-powervr/img-gpu-powervr.mk @@ -0,0 +1,99 @@ +################################################################################ +# +# img-gpu-powervr +# +# This file is for Imagination PowerVR GPU, modified from freescale-imx/imx-gpu-viv +# +# Windsome Zeng +# +################################################################################ + +# ifeq ($(BR2_aarch64),y) +# IMG_GPU_POWERVR_VERSION = 6.4.3.p2.0-aarch64 +# else +# IMG_GPU_POWERVR_VERSION = 6.4.3.p2.0-aarch32 +# endif +# IMG_GPU_POWERVR_SITE = $(FREESCALE_IMX_SITE) +# IMG_GPU_POWERVR_SOURCE = imx-gpu-viv-$(IMG_GPU_POWERVR_VERSION).bin + +IMG_GPU_POWERVR_INSTALL_STAGING = YES + +IMG_GPU_POWERVR_LICENSE = Strictly Confidential +IMG_GPU_POWERVR_REDISTRIBUTE = NO + +IMG_GPU_POWERVR_PROVIDES = libgles libopencl +IMG_GPU_POWERVR_LIB_TARGET = $(call qstrip,$(BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT)) + +ifeq ($(IMG_GPU_POWERVR_LIB_TARGET),x11) +# The libGAL.so library provided by imx-gpu-viv uses X functions. Packages +# may want to link against libGAL.so (QT5 Base with OpenGL and X support +# does so). For this to work we need build dependencies to libXdamage, +# libXext and libXfixes so that X functions used in libGAL.so are referenced. +IMG_GPU_POWERVR_DEPENDENCIES += xlib_libXdamage xlib_libXext xlib_libXfixes +endif + +# Libraries are linked against libdrm, except framebuffer output on ARM +ifneq ($(IMG_GPU_POWERVR_LIB_TARGET)$(BR2_riscv),fby) +IMG_GPU_POWERVR_DEPENDENCIES += libdrm +endif + +ifeq ($(IMG_GPU_POWERVR_LIB_TARGET),wayland) +IMG_GPU_POWERVR_DEPENDENCIES += wayland +endif + +# define IMG_GPU_POWERVR_EXTRACT_CMDS +# $(call FREESCALE_IMX_EXTRACT_HELPER,$(IMG_GPU_POWERVR_DL_DIR)/$(IMG_GPU_POWERVR_SOURCE)) +# endef + +# ifeq ($(IMG_GPU_POWERVR_LIB_TARGET),fb) +# define IMG_GPU_POWERVR_FIXUP_PKGCONFIG +# ln -sf egl_linuxfb.pc $(@D)/gpu-core/usr/lib/pkgconfig/egl.pc +# endef +# else ifeq ($(IMG_GPU_POWERVR_LIB_TARGET),wayland) +# define IMG_GPU_POWERVR_FIXUP_PKGCONFIG +# ln -sf egl_wayland.pc $(@D)/gpu-core/usr/lib/pkgconfig/egl.pc +# endef +# else ifeq ($(IMG_GPU_POWERVR_LIB_TARGET),x11) +# define IMG_GPU_POWERVR_FIXUP_PKGCONFIG +# $(foreach lib,egl gbm glesv1_cm glesv2 vg, \ +# ln -sf $(lib)_x11.pc $(@D)/gpu-core/usr/lib/pkgconfig/$(lib).pc +# ) +# endef +# endif + +# Instead of building, we fix up the inconsistencies that exist +# in the upstream archive here. We also remove unused backend files. +# Make sure these commands are idempotent. +# define IMG_GPU_POWERVR_BUILD_CMDS +# cp -dpfr $(@D)/gpu-core/usr/lib/$(IMG_GPU_POWERVR_LIB_TARGET)/* $(@D)/gpu-core/usr/lib/ +# $(foreach backend,fb x11 wayland, \ +# $(RM) -r $(@D)/gpu-core/usr/lib/$(backend) +# ) +# $(IMG_GPU_POWERVR_FIXUP_PKGCONFIG) +# endef +# +# define IMG_GPU_POWERVR_INSTALL_STAGING_CMDS +# cp -r $(@D)/gpu-core/usr/* $(STAGING_DIR)/usr +# endef + +# ifeq ($(BR2_PACKAGE_IMG_GPU_POWERVR_EXAMPLES),y) +# define IMG_GPU_POWERVR_INSTALL_EXAMPLES +# mkdir -p $(TARGET_DIR)/usr/share/examples/ +# cp -r $(@D)/gpu-demos/opt/* $(TARGET_DIR)/usr/share/examples/ +# endef +# endif +# +# ifeq ($(BR2_PACKAGE_IMG_GPU_POWERVR_GMEM_INFO),y) +# define IMG_GPU_POWERVR_INSTALL_GMEM_INFO +# cp -dpfr $(@D)/gpu-tools/gmem-info/usr/bin/* $(TARGET_DIR)/usr/bin/ +# endef +# endif + +# define IMG_GPU_POWERVR_INSTALL_TARGET_CMDS +# $(IMG_GPU_POWERVR_INSTALL_EXAMPLES) +# $(IMG_GPU_POWERVR_INSTALL_GMEM_INFO) +# cp -a $(@D)/gpu-core/usr/lib $(TARGET_DIR)/usr +# $(INSTALL) -D -m 0644 $(@D)/gpu-core/etc/Vivante.icd $(TARGET_DIR)/etc/OpenCL/vendors/Vivante.icd +# endef + +$(eval $(generic-package)) diff --git a/package/weston/0005-backend-drm-disable-bo-geometry-out-of-bounds-messag.patch b/package/weston/0005-backend-drm-disable-bo-geometry-out-of-bounds-messag.patch new file mode 100644 index 00000000..264f83f4 --- /dev/null +++ b/package/weston/0005-backend-drm-disable-bo-geometry-out-of-bounds-messag.patch @@ -0,0 +1,29 @@ +From 0f85e6d2e358c530dd1136d71bfd306cd64c4305 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Tue, 4 Sep 2018 14:59:09 +0100 +Subject: [PATCH 1/2] backend-drm: disable "bo geometry out of bounds" message + +The message was being printed repeatedly whilst running an opaque +windowed application, because the application wasn't within the +framebuffer dimension limits. +--- + libweston/backend-drm/fb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libweston/backend-drm/fb.c b/libweston/backend-drm/fb.c +index e7349c4b..da781015 100644 +--- a/libweston/backend-drm/fb.c ++++ b/libweston/backend-drm/fb.c +@@ -343,7 +343,9 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, + fb->width > backend->max_width || + backend->min_height > fb->height || + fb->height > backend->max_height) { ++#if 0 + weston_log("bo geometry out of bounds\n"); ++#endif + goto err_free; + } + +-- +2.17.1 + diff --git a/package/weston/0006-libweston-reduce-checks-for-dmabufs-with-DRM-modifie.patch b/package/weston/0006-libweston-reduce-checks-for-dmabufs-with-DRM-modifie.patch new file mode 100644 index 00000000..67d906c3 --- /dev/null +++ b/package/weston/0006-libweston-reduce-checks-for-dmabufs-with-DRM-modifie.patch @@ -0,0 +1,63 @@ +From 4a6e5e4ac0a2c63eb78e442bc34a0ee6a0f470d4 Mon Sep 17 00:00:00 2001 +From: Brendan King +Date: Thu, 15 Apr 2021 19:30:02 +0100 +Subject: [PATCH 3/3] libweston: reduce checks for dmabufs with DRM modifiers + +If the buffer associated with a dmabuf has a DRM modifier, then +checking the stride and stride*height against the size of the +dambuf may not make sense, so skip the check. + +IMG lossy framebuffers have a smaller size than that of the +equivalent linear framebuffer. +--- + libweston/linux-dmabuf.c | 33 ++++++++++++++++++--------------- + 1 file changed, 18 insertions(+), 15 deletions(-) + +diff --git a/libweston/linux-dmabuf.c b/libweston/linux-dmabuf.c +index 796e9826..0bbfe480 100644 +--- a/libweston/linux-dmabuf.c ++++ b/libweston/linux-dmabuf.c +@@ -240,22 +240,25 @@ params_create_common(struct wl_client *client, + goto err_out; + } + +- if (buffer->attributes.offset[i] + buffer->attributes.stride[i] > size) { +- wl_resource_post_error(params_resource, +- ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, +- "invalid stride %i for plane %i", +- buffer->attributes.stride[i], i); +- goto err_out; +- } ++ if (buffer->attributes.modifier[i] == DRM_FORMAT_MOD_INVALID || ++ buffer->attributes.modifier[i] == DRM_FORMAT_MOD_LINEAR) { ++ if (buffer->attributes.offset[i] + buffer->attributes.stride[i] > size) { ++ wl_resource_post_error(params_resource, ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, ++ "invalid stride %i for plane %i", ++ buffer->attributes.stride[i], i); ++ goto err_out; ++ } + +- /* Only valid for first plane as other planes might be +- * sub-sampled according to fourcc format */ +- if (i == 0 && +- buffer->attributes.offset[i] + buffer->attributes.stride[i] * height > size) { +- wl_resource_post_error(params_resource, +- ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, +- "invalid buffer stride or height for plane %i", i); +- goto err_out; ++ /* Only valid for first plane as other planes might be ++ * sub-sampled according to fourcc format */ ++ if (i == 0 && ++ buffer->attributes.offset[i] + buffer->attributes.stride[i] * height > size) { ++ wl_resource_post_error(params_resource, ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, ++ "invalid buffer stride or height for plane %i", i); ++ goto err_out; ++ } + } + } + +-- +2.17.1 + diff --git a/package/weston/Config.in b/package/weston/Config.in index 8f3dbc79..3e6d1efa 100644 --- a/package/weston/Config.in +++ b/package/weston/Config.in @@ -40,11 +40,11 @@ config BR2_PACKAGE_WESTON_DEFAULT_FBDEV config BR2_PACKAGE_WESTON_DEFAULT_DRM bool "drm" - depends on BR2_PACKAGE_MESA3D_OPENGL_EGL || BR2_PACKAGE_IMX_GPU_VIV_OUTPUT_WL + depends on BR2_PACKAGE_MESA3D_OPENGL_EGL || BR2_PACKAGE_IMX_GPU_VIV_OUTPUT_WL || BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_WL select BR2_PACKAGE_WESTON_DRM comment "drm backend needs mesa3d w/ EGL driver" - depends on !BR2_PACKAGE_MESA3D_OPENGL_EGL && !BR2_PACKAGE_IMX_GPU_VIV_OUTPUT_WL + depends on !BR2_PACKAGE_MESA3D_OPENGL_EGL && !BR2_PACKAGE_IMX_GPU_VIV_OUTPUT_WL && !BR2_PACKAGE_IMG_GPU_POWERVR_OUTPUT_WL config BR2_PACKAGE_WESTON_DEFAULT_X11 bool "X11"