diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/android/Android.mk b/android/Android.mk index 339d7f25e73..8c7616d476b 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -118,6 +118,20 @@ LOCAL_SHARED_LIBRARIES += \ MESON_GEN_PKGCONFIGS += android.hardware.graphics.mapper:4.0 endif +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 35; echo $$?), 0) +LOCAL_SHARED_LIBRARIES += \ + libbinder_ndk \ + libvndksupport \ + android.hardware.graphics.allocator-V2-ndk \ + +LOCAL_HEADER_LIBRARIES += \ + libimapper_stablec \ + libimapper_providerutils \ + libui_headers + +MESON_GEN_PKGCONFIGS += android.hardware.graphics.allocator-V2-ndk +endif + __MY_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES) ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 30; echo $$?), 0) @@ -155,7 +169,11 @@ LOCAL_PREBUILT_MODULE_FILE := $($4) LOCAL_MULTILIB := first LOCAL_CHECK_ELF_FILES := false LOCAL_MODULE_SUFFIX := .so +ifeq ($1, libgallium_dri) +LOCAL_MODULE_SYMLINKS += $1$2 iris_dri.so virtio_gpu_dri.so +else LOCAL_MODULE_SYMLINKS := $1$2 +endif LOCAL_SHARED_LIBRARIES := $(__MY_SHARED_LIBRARIES) LOCAL_EXPORT_C_INCLUDE_DIRS := $5 include $(BUILD_PREBUILT) @@ -170,7 +188,11 @@ LOCAL_PREBUILT_MODULE_FILE := $(2ND_$4) LOCAL_MULTILIB := 32 LOCAL_CHECK_ELF_FILES := false LOCAL_MODULE_SUFFIX := .so +ifeq ($1, libgallium_dri) +LOCAL_MODULE_SYMLINKS += $1$2 iris_dri.so virtio_gpu_dri.so +else LOCAL_MODULE_SYMLINKS := $1$2 +endif LOCAL_SHARED_LIBRARIES := $(__MY_SHARED_LIBRARIES) LOCAL_EXPORT_C_INCLUDE_DIRS := $5 include $(BUILD_PREBUILT) diff --git a/include/pci_ids/iris_pci_ids.h b/include/pci_ids/iris_pci_ids.h index 5ce6f00929b..2a02bc3d812 100644 --- a/include/pci_ids/iris_pci_ids.h +++ b/include/pci_ids/iris_pci_ids.h @@ -188,6 +188,8 @@ CHIPSET(0x46c3, adl_gt2, "ADL GT2", "Intel(R) Graphics") CHIPSET(0x46d0, adl_n, "ADL-N", "Intel(R) Graphics") CHIPSET(0x46d1, adl_n, "ADL-N", "Intel(R) Graphics") CHIPSET(0x46d2, adl_n, "ADL-N", "Intel(R) Graphics") +CHIPSET(0x46d3, adl_n, "ADL-N", "Intel(R) Graphics") +CHIPSET(0x46d4, adl_n, "ADL-N", "Intel(R) Graphics") CHIPSET(0x9a40, tgl_gt2, "TGL GT2", "Intel(R) Xe Graphics") CHIPSET(0x9a49, tgl_gt2, "TGL GT2", "Intel(R) Xe Graphics") @@ -242,6 +244,7 @@ CHIPSET(0x56a3, dg2_g12, "DG2", "Intel(R) Graphics") CHIPSET(0x56a4, dg2_g12, "DG2", "Intel(R) Graphics") CHIPSET(0x56a5, dg2_g11, "DG2", "Intel(R) Arc(tm) A380 Graphics") CHIPSET(0x56a6, dg2_g11, "DG2", "Intel(R) Arc(tm) A310 Graphics") +CHIPSET(0x56af, dg2_g10, "DG2", "Intel(R) Arc(tm) A760 Graphics") CHIPSET(0x56b0, dg2_g11, "DG2", "Intel(R) Arc(tm) Pro A30M Graphics") CHIPSET(0x56b1, dg2_g11, "DG2", "Intel(R) Arc(tm) Pro A40/A50 Graphics") CHIPSET(0x56b2, dg2_g12, "DG2", "Intel(R) Graphics") diff --git a/meson.build b/meson.build index de18e8272d0..a07c3602531 100644 --- a/meson.build +++ b/meson.build @@ -205,6 +205,7 @@ with_gallium_kmsro = system_has_kms_drm and [ with_gallium_panfrost, with_gallium_v3d, with_gallium_vc4, + with_gallium_iris, ].contains(true) _vulkan_drivers = get_option('vulkan-drivers') @@ -888,6 +889,7 @@ endif if with_platform_android dep_android_mapper4 = null_dep + dep_android_mapper5 = null_dep if not with_android_stub dep_android = [ dependency('cutils'), @@ -900,9 +902,12 @@ if with_platform_android if get_option('platform-sdk-version') >= 26 dep_android += dependency('nativewindow') endif - if get_option('platform-sdk-version') >= 30 + if get_option('platform-sdk-version') >= 30 and get_option('platform-sdk-version') <= 34 dep_android_mapper4 = dependency('android.hardware.graphics.mapper', version : '>= 4.0', required : false) endif + if get_option('platform-sdk-version') >= 35 + dep_android_mapper5 = dependency('android.hardware.graphics.allocator-V2-ndk', required : false) + endif endif pre_args += [ '-DANDROID', diff --git a/meson_options.txt b/meson_options.txt index 92ffd1d6c40..ed2b4ce7659 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -687,6 +687,6 @@ option( option ( 'intel-xe-kmd', type : 'feature', - value : 'disabled', + value : 'enabled', description: 'Enable Intel Xe KMD support.' ) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 510b23e4e20..a957b3dd710 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -1557,9 +1557,11 @@ dri2_create_context(_EGLDisplay *disp, _EGLConfig *conf, } else dri_config = NULL; +#ifdef HAVE_ANDROID_PLATFORM if (intel_lower_ctx_priority()) { dri2_ctx->base.ContextPriority = EGL_CONTEXT_PRIORITY_LOW_IMG; } +#endif if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs, &num_attribs)) diff --git a/src/gallium/auxiliary/pipe-loader/meson.build b/src/gallium/auxiliary/pipe-loader/meson.build index 7927515cf98..a1d9a51880f 100644 --- a/src/gallium/auxiliary/pipe-loader/meson.build +++ b/src/gallium/auxiliary/pipe-loader/meson.build @@ -56,6 +56,9 @@ endif if with_gallium_asahi renderonly_drivers_c_args += '-DGALLIUM_ASAHI' endif +if with_gallium_iris + renderonly_drivers_c_args += '-DGALLIUM_IRIS' +endif libpipe_loader_static = static_library( 'pipe_loader_static', diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c index 055c637199d..e978c65cddb 100644 --- a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c +++ b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c @@ -295,6 +295,9 @@ pipe_loader_get_compatible_render_capable_device_fd(int kms_only_fd) #endif #if defined GALLIUM_VC4 "vc4", +#endif +#if defined GALLIUM_IRIS + "i915", #endif }; @@ -303,10 +306,12 @@ pipe_loader_get_compatible_render_capable_device_fd(int kms_only_fd) is_platform_device = (dev->type == PIPE_LOADER_DEVICE_PLATFORM); pipe_loader_release(&dev, 1); +#ifndef GALLIUM_IRIS /* For display-only devices that are not on the platform bus, we can't assume * that any of the rendering devices are compatible. */ if (!is_platform_device) return -1; +#endif /* For platform display-only devices, we try to find a render-capable device * on the platform bus and that should be compatible with the display-only diff --git a/src/gallium/auxiliary/target-helpers/drm_helper.h b/src/gallium/auxiliary/target-helpers/drm_helper.h index be44b8f71df..106bac7f7e1 100644 --- a/src/gallium/auxiliary/target-helpers/drm_helper.h +++ b/src/gallium/auxiliary/target-helpers/drm_helper.h @@ -68,6 +68,7 @@ const struct drm_driver_descriptor descriptor_name = { \ #undef GALLIUM_PANFROST #undef GALLIUM_LIMA #undef GALLIUM_ASAHI +#undef GALLIUM_IRIS #endif #ifdef GALLIUM_I915 @@ -454,6 +455,9 @@ const driOptionDescription kmsro_driconf[] = { #ifdef GALLIUM_FREEDRENO #include "freedreno/driinfo_freedreno.h" #endif +#ifdef GALLIUM_IRIS + #include "iris/driinfo_iris.h" +#endif }; DRM_DRIVER_DESCRIPTOR(kmsro, kmsro_driconf, ARRAY_SIZE(kmsro_driconf)) diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index 138fd2f7771..c6a8f68e98d 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -54,6 +54,8 @@ #include "isl/isl.h" #include "drm-uapi/drm_fourcc.h" #include "drm-uapi/i915_drm.h" +#include "renderonly/renderonly.h" +#include "util/u_drm.h" enum modifier_priority { MODIFIER_PRIORITY_INVALID = 0, @@ -560,7 +562,12 @@ static void iris_resource_destroy(struct pipe_screen *screen, struct pipe_resource *p_res) { + struct iris_resource *res = (struct iris_resource *) p_res; + struct iris_screen *pscreen = (struct iris_screen *)screen; + + if (res->scanout) + renderonly_scanout_destroy(res->scanout, pscreen->ro); if (p_res->target == PIPE_BUFFER) util_range_destroy(&res->valid_buffer_range); @@ -1133,7 +1140,6 @@ iris_resource_create_for_image(struct pipe_screen *pscreen, struct iris_screen *screen = (struct iris_screen *)pscreen; const struct intel_device_info *devinfo = screen->devinfo; struct iris_resource *res = iris_alloc_resource(pscreen, templ); - if (!res) return NULL; @@ -1225,6 +1231,12 @@ iris_resource_create_for_image(struct pipe_screen *pscreen, res->base.is_shared = true; } + if (screen->ro && + (templ->bind & (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT | PIPE_BIND_SHARED))) { + res->scanout = renderonly_scanout_for_resource(&res->base.b, screen->ro, NULL); + } + return &res->base.b; fail: @@ -1394,6 +1406,17 @@ iris_resource_from_handle(struct pipe_screen *pscreen, res->offset = whandle->offset; res->surf.row_pitch_B = whandle->stride; + if (screen->ro) { + /* Make sure that renderonly has a handle to our buffer in the + * display's fd, so that a later renderonly_get_handle() + * returns correct handles or GEM names. + */ + res->scanout = + renderonly_create_gpu_import_for_resource(&res->base.b, + screen->ro, + NULL); + } + if (whandle->plane == 0) { /* All planes are present. Fill out the main plane resource(s). */ for (unsigned plane = 0; plane < util_resource_num(templ); plane++) { @@ -1904,6 +1927,9 @@ iris_resource_get_handle(struct pipe_screen *pscreen, case WINSYS_HANDLE_TYPE_KMS: { iris_gem_set_tiling(bo, &res->surf); + if (screen->ro && res->scanout) { + return renderonly_get_handle(res->scanout, whandle); + } /* Because we share the same drm file across multiple iris_screen, when * we export a GEM handle we must make sure it is valid in the DRM file * descriptor the caller is using (this is the FD given at screen diff --git a/src/gallium/drivers/iris/iris_resource.h b/src/gallium/drivers/iris/iris_resource.h index 80e079d4031..daf63f0a6d1 100644 --- a/src/gallium/drivers/iris/iris_resource.h +++ b/src/gallium/drivers/iris/iris_resource.h @@ -55,6 +55,7 @@ struct iris_format_info { struct iris_resource { struct threaded_resource base; enum pipe_format internal_format; + struct renderonly_scanout *scanout; /** * The ISL surface layout information for this resource. diff --git a/src/gallium/drivers/iris/iris_screen.c b/src/gallium/drivers/iris/iris_screen.c index 6557ef81663..cf6ba1ae3ae 100644 --- a/src/gallium/drivers/iris/iris_screen.c +++ b/src/gallium/drivers/iris/iris_screen.c @@ -59,6 +59,7 @@ #include "intel/common/intel_l3_config.h" #include "intel/common/intel_uuid.h" #include "iris_monitor.h" +#include "renderonly/renderonly.h" #define genX_call(devinfo, func, ...) \ switch ((devinfo)->verx10) { \ @@ -677,6 +678,7 @@ iris_screen_destroy(struct iris_screen *screen) iris_bufmgr_unref(screen->bufmgr); disk_cache_destroy(screen->disk_cache); close(screen->winsys_fd); + free(screen->ro); ralloc_free(screen); } diff --git a/src/gallium/drivers/iris/iris_screen.h b/src/gallium/drivers/iris/iris_screen.h index a6c4b5d0c3d..a35a82d7173 100644 --- a/src/gallium/drivers/iris/iris_screen.h +++ b/src/gallium/drivers/iris/iris_screen.h @@ -161,6 +161,7 @@ struct iris_address { struct iris_screen { struct pipe_screen base; + struct renderonly *ro; uint32_t refcount; diff --git a/src/gallium/winsys/iris/drm/iris_drm_public.h b/src/gallium/winsys/iris/drm/iris_drm_public.h index f942e05ad8b..4e4c3edaec3 100644 --- a/src/gallium/winsys/iris/drm/iris_drm_public.h +++ b/src/gallium/winsys/iris/drm/iris_drm_public.h @@ -26,8 +26,13 @@ struct pipe_screen; struct pipe_screen_config; +struct renderonly; struct pipe_screen * iris_drm_screen_create(int drm_fd, const struct pipe_screen_config *config); +struct pipe_screen * +iris_screen_create_renderonly(int fd, struct renderonly *ro, + const struct pipe_screen_config *config); + #endif /* IRIS_DRM_PUBLIC_H */ diff --git a/src/gallium/winsys/iris/drm/iris_drm_winsys.c b/src/gallium/winsys/iris/drm/iris_drm_winsys.c index 15095e2d3fa..bf6c5577c78 100644 --- a/src/gallium/winsys/iris/drm/iris_drm_winsys.c +++ b/src/gallium/winsys/iris/drm/iris_drm_winsys.c @@ -26,7 +26,11 @@ #include "util/os_file.h" +#include "renderonly/renderonly.h" +#include "kmsro/drm/kmsro_drm_public.h" #include "iris_drm_public.h" +#include "iris/iris_screen.h" + extern struct pipe_screen *iris_screen_create(int fd, const struct pipe_screen_config *config); struct pipe_screen * @@ -34,3 +38,19 @@ iris_drm_screen_create(int fd, const struct pipe_screen_config *config) { return iris_screen_create(fd, config); } + +struct pipe_screen * +iris_screen_create_renderonly(int fd, struct renderonly *ro, + const struct pipe_screen_config *config) +{ + struct iris_screen *pscreen; + + pscreen = (struct iris_screen *)iris_screen_create(os_dupfd_cloexec(fd), config); + if (!pscreen) + return NULL; + + pscreen->ro = ro; + pscreen->winsys_fd = ro->kms_fd; + + return &pscreen->base; +} diff --git a/src/gallium/winsys/iris/drm/meson.build b/src/gallium/winsys/iris/drm/meson.build index 3dcdc4a455e..aedb66543f4 100644 --- a/src/gallium/winsys/iris/drm/meson.build +++ b/src/gallium/winsys/iris/drm/meson.build @@ -18,12 +18,19 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +iris_drm_winsys_c_args = [] +if with_gallium_kmsro + iris_drm_winsys_c_args += '-DGALLIUM_KMSRO' +endif + libiriswinsys = static_library( 'iriswinsys', files('iris_drm_winsys.c'), include_directories : [ inc_src, inc_include, - inc_gallium, inc_gallium_aux, inc_gallium_drivers, + inc_gallium, inc_gallium_aux, inc_gallium_drivers, inc_gallium_winsys, inc_intel, ], + c_args : [iris_drm_winsys_c_args], + dependencies: [ idep_intel_dev ], gnu_symbol_visibility : 'hidden', ) diff --git a/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c b/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c index 3d14bce1ce7..c8d9a1c4de4 100644 --- a/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c +++ b/src/gallium/winsys/kmsro/drm/kmsro_drm_winsys.c @@ -33,6 +33,7 @@ #include "panfrost/drm/panfrost_drm_public.h" #include "lima/drm/lima_drm_public.h" #include "asahi/drm/asahi_drm_public.h" +#include "iris/drm/iris_drm_public.h" #include "xf86drm.h" #include "pipe/p_screen.h" @@ -119,6 +120,11 @@ struct pipe_screen *kmsro_drm_screen_create(int kms_fd, */ ro->create_for_resource = renderonly_create_gpu_import_for_resource; screen = vc4_drm_screen_create_renderonly(ro->gpu_fd, ro, config); +#endif + } else if (strcmp(render_dev_name, "i915") == 0) { +#if defined(GALLIUM_IRIS) + ro->create_for_resource = renderonly_create_gpu_import_for_resource, + screen = iris_screen_create_renderonly(ro->gpu_fd, ro, config); #endif } diff --git a/src/intel/common/intel_check.c b/src/intel/common/intel_check.c index 42b679251aa..6262555b989 100644 --- a/src/intel/common/intel_check.c +++ b/src/intel/common/intel_check.c @@ -40,29 +40,33 @@ get_pid_name(pid_t pid, char *task_name) static bool use_dgpu_render(char *target) { -   char dGPU_prop[BUF_SIZE]; -   char vendor_buf[PROPERTY_VALUE_MAX]; -   sprintf(dGPU_prop, "persist.vendor.intel.dGPU.%s",target); -   if (property_get(dGPU_prop, vendor_buf, NULL) > 0) { -      if (vendor_buf[0] == '1') { -         return true; -      } -   } + char dGPU_prop[BUF_SIZE]; + char vendor_buf[PROPERTY_VALUE_MAX]; + sprintf(dGPU_prop, "persist.vendor.intel.dGPU%s", target); + if (property_get(dGPU_prop, vendor_buf, NULL) > 0) { + if (vendor_buf[0] == '1') { + return true; + } + } return false; } static bool -is_target_process(char *target) +is_target_process(const char *target) { - char *str_char[] = { "k.lite:refinery", "k.lite:transfer", NULL }; - char **ptr = str_char; + static const char *str_char[] = { "k.lite:refinery", "k.lite:transfer", NULL }; + const char **ptr = str_char; - for (ptr=str_char; *ptr!=NULL; ptr++) - { - if(!strcmp(target, *ptr)) { + // Prefer dGPU for compositing in surfaceflinger since dGPU covers more + // scenarios than iGPU. + if (!strcmp(target, "surfaceflinger")) + return true; + + for (ptr = str_char; *ptr != NULL; ptr++) { + if (!strcmp(target, *ptr)) { char vendor_buf[PROPERTY_VALUE_MAX]; if (property_get("persist.vendor.intel.dGPU.ABenchMark.lite", - vendor_buf, NULL) > 0) { + vendor_buf, NULL) > 0) { if (vendor_buf[0] == '1') { return true; } @@ -72,12 +76,17 @@ is_target_process(char *target) return false; } -bool intel_is_dgpu_render(void) { +bool intel_is_dgpu_render(void) +{ pid_t process_id = getpid(); char process_name[BUF_SIZE]; get_pid_name(process_id, process_name); - return (use_dgpu_render(process_name) || is_target_process(process_name)); + char *app_name = strrchr(process_name, '.'); + if (app_name == NULL) + app_name = process_name; + + return (use_dgpu_render(app_name) || is_target_process(process_name)); } bool intel_lower_ctx_priority(void) @@ -85,19 +94,23 @@ bool intel_lower_ctx_priority(void) pid_t process_id = getpid(); char process_name[BUF_SIZE]; get_pid_name(process_id, process_name); + char *app_name = strrchr(process_name, '.'); + if (app_name == NULL) + app_name = process_name; + -   char lower_pri[BUF_SIZE]; -   char vendor_buf[PROPERTY_VALUE_MAX]; -   sprintf(lower_pri, "persist.vendor.intel.lowPir.%s",process_name); -   if (property_get(lower_pri, vendor_buf, NULL) > 0) { -      if (vendor_buf[0] == '1') { -         return true; -      } -   } + char lower_pri[BUF_SIZE]; + char vendor_buf[PROPERTY_VALUE_MAX]; + sprintf(lower_pri, "persist.vendor.intel.lowPir%s", app_name); + if (property_get(lower_pri, vendor_buf, NULL) > 0) { + if (vendor_buf[0] == '1') { + return true; + } + } return false; } -bool has_local_mem(int fd) +static bool has_local_mem(int fd) { struct drm_i915_query_item item = { .query_id = DRM_I915_QUERY_MEMORY_REGIONS, diff --git a/src/intel/common/intel_check.h b/src/intel/common/intel_check.h index a6a0e519e5d..90db0a6429c 100644 --- a/src/intel/common/intel_check.h +++ b/src/intel/common/intel_check.h @@ -8,7 +8,6 @@ extern "C" { bool intel_is_dgpu_render(void); bool intel_lower_ctx_priority(void); bool is_dgpu(int id); -bool has_local_mem(int fd); int get_intel_node_num(void); #ifdef __cplusplus } diff --git a/src/intel/common/meson.build b/src/intel/common/meson.build index 9bbcc3a5042..febbbd36e3b 100644 --- a/src/intel/common/meson.build +++ b/src/intel/common/meson.build @@ -56,8 +56,6 @@ files_libintel_common = files( 'intel_mem.c', 'intel_mem.h', 'intel_pixel_hash.h', - 'intel_check.c', - 'intel_check.h', ) files_batch_decoder = files( @@ -86,6 +84,13 @@ batch_decoder_dependencies = [] files_libintel_common += files_batch_decoder #endif +if with_platform_android + files_libintel_common += files( + 'intel_check.c', + 'intel_check.h', + ) +endif + libintel_common = static_library( 'intel_common', [files_libintel_common, genX_xml_h, sha1_h], diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index 769bbd848a7..9b83551a071 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -1388,6 +1388,10 @@ anv_bo_vma_alloc_or_close(struct anv_device *device, uint32_t align = device->physical->info.mem_alignment; + if (driQueryOptionb(&device->physical->instance->dri_options, "vk_descriptor_pool_64k_alignment") && + alloc_flags & (ANV_BO_ALLOC_DESCRIPTOR_POOL | ANV_BO_ALLOC_SAMPLER_POOL)) + align = 64 * 1024; + /* If it's big enough to store a tiled resource, we need 64K alignment */ if (bo->size >= 64 * 1024) align = MAX2(64 * 1024, align); diff --git a/src/intel/vulkan/anv_android.c b/src/intel/vulkan/anv_android.c index b3405f6c96f..e706fcbe2ce 100644 --- a/src/intel/vulkan/anv_android.c +++ b/src/intel/vulkan/anv_android.c @@ -104,6 +104,7 @@ anv_hal_close(struct hw_device_t *dev) #include /* See i915_private_android_types.h in minigbm. */ #define HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL 0x100 +#define HAL_PIXEL_FORMAT_NV12_LINEAR_CAMERA_INTEL 0x10F enum { /* Usage bit equal to GRALLOC_USAGE_HW_CAMERA_MASK */ @@ -114,10 +115,9 @@ inline VkFormat vk_format_from_android(unsigned android_format, unsigned android_usage) { switch (android_format) { - case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: - return VK_FORMAT_R8G8B8_UNORM; case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL: + case HAL_PIXEL_FORMAT_NV12_LINEAR_CAMERA_INTEL: return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; case AHARDWAREBUFFER_FORMAT_YV12: return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; @@ -318,6 +318,30 @@ anv_import_ahw_memory(VkDevice device_h, #endif } +VkResult +anv_android_get_tiling(struct anv_device *device, + struct u_gralloc_buffer_handle *gr_handle, + enum isl_tiling *tiling_out) +{ + assert(device->u_gralloc); + + struct u_gralloc_buffer_basic_info buf_info; + if (u_gralloc_get_buffer_basic_info(device->u_gralloc, gr_handle, &buf_info)) + return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE, + "failed to get tiling from gralloc buffer info"); + + const struct isl_drm_modifier_info *mod_info = + isl_drm_modifier_get_info(buf_info.modifier); + if (!mod_info) { + return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE, + "invalid drm modifier from VkNativeBufferANDROID " + "gralloc buffer info 0x%"PRIx64"", buf_info.modifier); + } + + *tiling_out = mod_info->tiling; + return VK_SUCCESS; +} + VkResult anv_image_init_from_gralloc(struct anv_device *device, struct anv_image *image, @@ -338,19 +362,13 @@ anv_image_init_from_gralloc(struct anv_device *device, */ int dma_buf = gralloc_info->handle->data[0]; - /* We need to set the WRITE flag on window system buffers so that GEM will - * know we're writing to them and synchronize uses on other rings (for - * example, if the display server uses the blitter ring). - * - * If this function fails and if the imported bo was resident in the cache, + /* If this function fails and if the imported bo was resident in the cache, * we should avoid updating the bo's flags. Therefore, we defer updating * the flags until success is certain. * */ result = anv_device_import_bo(device, dma_buf, - ANV_BO_ALLOC_EXTERNAL | - ANV_BO_ALLOC_IMPLICIT_SYNC | - ANV_BO_ALLOC_IMPLICIT_WRITE, + ANV_BO_ALLOC_EXTERNAL, 0 /* client_address */, &bo); if (result != VK_SUCCESS) { @@ -360,21 +378,14 @@ anv_image_init_from_gralloc(struct anv_device *device, enum isl_tiling tiling; if (device->u_gralloc) { - struct u_gralloc_buffer_basic_info buf_info; struct u_gralloc_buffer_handle gr_handle = { .handle = gralloc_info->handle, .hal_format = gralloc_info->format, .pixel_stride = gralloc_info->stride, }; - u_gralloc_get_buffer_basic_info(device->u_gralloc, &gr_handle, &buf_info); - const struct isl_drm_modifier_info *mod_info = - isl_drm_modifier_get_info(buf_info.modifier); - if (mod_info) { - tiling = mod_info->tiling; - } else { - return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE, - "unknown modifier of BO from VkNativeBufferANDROID"); - } + result = anv_android_get_tiling(device, &gr_handle, &tiling); + if (result != VK_SUCCESS) + return result; } else { /* Fallback to get_tiling API. */ result = anv_device_get_bo_tiling(device, bo, &tiling); @@ -440,20 +451,14 @@ anv_image_bind_from_gralloc(struct anv_device *device, */ int dma_buf = gralloc_info->handle->data[0]; - /* We need to set the WRITE flag on window system buffers so that GEM will - * know we're writing to them and synchronize uses on other rings (for - * example, if the display server uses the blitter ring). - * - * If this function fails and if the imported bo was resident in the cache, + /* If this function fails and if the imported bo was resident in the cache, * we should avoid updating the bo's flags. Therefore, we defer updating * the flags until success is certain. * */ struct anv_bo *bo = NULL; VkResult result = anv_device_import_bo(device, dma_buf, - ANV_BO_ALLOC_EXTERNAL | - ANV_BO_ALLOC_IMPLICIT_SYNC | - ANV_BO_ALLOC_IMPLICIT_WRITE, + ANV_BO_ALLOC_EXTERNAL, 0 /* client_address */, &bo); if (result != VK_SUCCESS) { @@ -461,12 +466,22 @@ anv_image_bind_from_gralloc(struct anv_device *device, "failed to import dma-buf from VkNativeBufferANDROID"); } - uint64_t img_size = image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].memory_range.size; - if (img_size < bo->size) { + VkMemoryRequirements2 mem_reqs = { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + }; + + anv_image_get_memory_requirements(device, image, image->vk.aspects, + &mem_reqs); + + VkDeviceSize aligned_image_size = + align64(mem_reqs.memoryRequirements.size, + mem_reqs.memoryRequirements.alignment); + + if (bo->size < aligned_image_size) { result = vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE, "dma-buf from VkNativeBufferANDROID is too small for " "VkImage: %"PRIu64"B < %"PRIu64"B", - bo->size, img_size); + bo->size, aligned_image_size); anv_device_release_bo(device, bo); return result; } diff --git a/src/intel/vulkan/anv_android.h b/src/intel/vulkan/anv_android.h index e1f099e1f4f..6eeff850723 100644 --- a/src/intel/vulkan/anv_android.h +++ b/src/intel/vulkan/anv_android.h @@ -34,6 +34,13 @@ struct anv_device_memory; struct anv_device; struct anv_image; +struct u_gralloc_buffer_handle; +enum isl_tiling; + +VkResult +anv_android_get_tiling(struct anv_device *device, + struct u_gralloc_buffer_handle *gr_handle, + enum isl_tiling *tiling_out); VkResult anv_image_init_from_gralloc(struct anv_device *device, struct anv_image *image, diff --git a/src/intel/vulkan/anv_android_stubs.c b/src/intel/vulkan/anv_android_stubs.c index f1b2ef6b6f8..1c095e0aa82 100644 --- a/src/intel/vulkan/anv_android_stubs.c +++ b/src/intel/vulkan/anv_android_stubs.c @@ -23,6 +23,14 @@ #include "anv_android.h" +VkResult +anv_android_get_tiling(struct anv_device *device, + struct u_gralloc_buffer_handle *gr_handle, + enum isl_tiling *tiling_out) +{ + return VK_ERROR_EXTENSION_NOT_PRESENT; +} + VkResult anv_image_init_from_gralloc(struct anv_device *device, struct anv_image *image, diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 13f534934f9..64e4aa04fa1 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -61,7 +61,9 @@ #include "common/intel_aux_map.h" #include "common/intel_uuid.h" #include "common/i915/intel_gem.h" +#ifdef ANDROID #include "common/intel_check.h" +#endif #include "perf/intel_perf.h" #include "i915/anv_device.h" @@ -107,6 +109,7 @@ static const driOptionDescription anv_dri_options[] = { #else DRI_CONF_VK_REQUIRE_ASTC(false) #endif + DRI_CONF_VK_DESCRIPTOR_POOL_64K_ALIGNMENT(false) DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY @@ -1968,12 +1971,12 @@ anv_override_engine_counts(int *gc_count, int *g_count, int *c_count, int *v_cou int g_override = -1; int c_override = -1; int v_override = -1; - char *env = getenv("ANV_QUEUE_OVERRIDE"); + const char *env_ = os_get_option("ANV_QUEUE_OVERRIDE"); - if (env == NULL) + if (env_ == NULL) return; - env = strdup(env); + char *env = strdup(env_); char *save = NULL; char *next = strtok_r(env, ",", &save); while (next != NULL) { @@ -2170,6 +2173,7 @@ anv_physical_device_try_create(struct vk_instance *vk_instance, goto fail_fd; } +#ifdef ANDROID if (get_intel_node_num() > 1) { if (!is_dgpu(fd) && intel_is_dgpu_render()) { result = VK_ERROR_INCOMPATIBLE_DRIVER; @@ -2181,6 +2185,7 @@ anv_physical_device_try_create(struct vk_instance *vk_instance, goto fail_fd; } } +#endif if (devinfo.ver == 20) { mesa_logw("Vulkan not yet supported on %s", devinfo.name); diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index 6ead10079b2..26cd62973d1 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -1638,6 +1638,15 @@ anv_image_init(struct anv_device *device, struct anv_image *image, image->n_planes = anv_get_format_planes(image->vk.format); +#ifdef VK_USE_PLATFORM_ANDROID_KHR + /* In the case of gralloc-backed swap chain image, we don't know the + * layout yet. + */ + if (vk_find_struct_const(pCreateInfo->pNext, + IMAGE_SWAPCHAIN_CREATE_INFO_KHR) != NULL) + return VK_SUCCESS; +#endif + image->from_wsi = vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA) != NULL; @@ -1863,9 +1872,9 @@ VkResult anv_CreateImage( __LINE__, pCreateInfo->flags); #ifndef VK_USE_PLATFORM_ANDROID_KHR - /* Ignore swapchain creation info on Android. Since we don't have an - * implementation in Mesa, we're guaranteed to access an Android object - * incorrectly. + /* Skip the WSI common swapchain creation here on Android. Similar to ahw, + * this case is handled by a partial image init and then resolved when the + * image is bound and gralloc info is passed. */ const VkImageSwapchainCreateInfoKHR *swapchain_info = vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR); @@ -1928,7 +1937,14 @@ resolve_ahw_image(struct anv_device *device, /* Check tiling. */ enum isl_tiling tiling; - result = anv_device_get_bo_tiling(device, mem->bo, &tiling); + const native_handle_t *handle = + AHardwareBuffer_getNativeHandle(mem->vk.ahardware_buffer); + struct u_gralloc_buffer_handle gr_handle = { + .handle = handle, + .hal_format = desc.format, + .pixel_stride = desc.stride, + }; + result = anv_android_get_tiling(device, &gr_handle, &tiling); assert(result == VK_SUCCESS); isl_tiling_flags_t isl_tiling_flags = (1u << tiling); @@ -1949,6 +1965,36 @@ resolve_ahw_image(struct anv_device *device, #endif } +static void +resolve_anb_image(struct anv_device *device, + struct anv_image *image, + const VkNativeBufferANDROID *gralloc_info) +{ +#if DETECT_OS_ANDROID && ANDROID_API_LEVEL >= 29 + VkResult result; + + /* Check tiling. */ + enum isl_tiling tiling; + struct u_gralloc_buffer_handle gr_handle = { + .handle = gralloc_info->handle, + .hal_format = gralloc_info->format, + .pixel_stride = gralloc_info->stride, + }; + result = anv_android_get_tiling(device, &gr_handle, &tiling); + assert(result == VK_SUCCESS); + + isl_tiling_flags_t isl_tiling_flags = (1u << tiling); + + /* Now we are able to fill anv_image fields properly and create + * isl_surface for it. + */ + result = add_all_surfaces_implicit_layout(device, image, NULL, gralloc_info->stride, + isl_tiling_flags, + ISL_SURF_USAGE_DISABLE_AUX_BIT); + assert(result == VK_SUCCESS); +#endif +} + void anv_image_get_memory_requirements(struct anv_device *device, struct anv_image *image, @@ -2359,6 +2405,8 @@ anv_bind_image_memory(struct anv_device *device, gralloc_info); if (result != VK_SUCCESS) return result; + + resolve_anb_image(device, image, gralloc_info); did_bind = true; break; } diff --git a/src/intel/vulkan/genX_init_state.c b/src/intel/vulkan/genX_init_state.c index da994697c7e..06e1abe024d 100644 --- a/src/intel/vulkan/genX_init_state.c +++ b/src/intel/vulkan/genX_init_state.c @@ -305,6 +305,18 @@ init_common_queue_state(struct anv_queue *queue, struct anv_batch *batch) sba.L1CacheControl = L1CC_WB; #endif } + + /* Disable the POOL_ALLOC mechanism in HW. We found that this state can get + * corrupted (likely due to leaking from another context), the default + * value should be disabled. It doesn't cost anything to set it once at + * device initialization. + */ +#if GFX_VER >= 11 && GFX_VERx10 < 125 + anv_batch_emit(batch, GENX(3DSTATE_BINDING_TABLE_POOL_ALLOC), btpa) { + btpa.MOCS = mocs; + btpa.BindingTablePoolEnable = false; + } +#endif #endif #if GFX_VERx10 >= 125 diff --git a/src/intel/vulkan/i915/anv_device.c b/src/intel/vulkan/i915/anv_device.c index 68efd4caeaa..6746957608a 100644 --- a/src/intel/vulkan/i915/anv_device.c +++ b/src/intel/vulkan/i915/anv_device.c @@ -256,6 +256,7 @@ anv_i915_set_queue_parameters( } } +#ifdef ANDROID if (intel_lower_ctx_priority()) { int ret = anv_gem_set_context_param(device->fd, device->context_id, I915_CONTEXT_PARAM_PRIORITY, @@ -263,7 +264,8 @@ anv_i915_set_queue_parameters( if (ret != 0) { return vk_error(device, VK_ERROR_INITIALIZATION_FAILED); } -} + } +#endif return VK_SUCCESS; } diff --git a/src/intel/vulkan_hasvk/anv_device.c b/src/intel/vulkan_hasvk/anv_device.c index 2819dd634b2..434d533e89e 100644 --- a/src/intel/vulkan_hasvk/anv_device.c +++ b/src/intel/vulkan_hasvk/anv_device.c @@ -875,12 +875,12 @@ anv_override_engine_counts(int *gc_count, int *g_count, int *c_count) int gc_override = -1; int g_override = -1; int c_override = -1; - char *env = getenv("ANV_QUEUE_OVERRIDE"); + const char *env_ = os_get_option("ANV_QUEUE_OVERRIDE"); - if (env == NULL) + if (env_ == NULL) return; - env = strdup(env); + char *env = strdup(env_); char *save = NULL; char *next = strtok_r(env, ",", &save); while (next != NULL) { diff --git a/src/loader/loader.c b/src/loader/loader.c index 19c456c7020..8b8047b77f2 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -154,8 +154,8 @@ loader_open_render_node_platform_device(const char * const drivers[], for (i = 0; i < num_devices; i++) { device = devices[i]; - if ((device->available_nodes & (1 << DRM_NODE_RENDER)) && - (device->bustype == DRM_BUS_PLATFORM)) { + if ((device->available_nodes & (1 << DRM_NODE_RENDER)) /* && + (device->bustype == DRM_BUS_PLATFORM) */) { drmVersionPtr version; fd = loader_open_device(device->nodes[DRM_NODE_RENDER]); diff --git a/src/util/00-mesa-defaults.conf b/src/util/00-mesa-defaults.conf index 907801a9146..1de36fbc617 100644 --- a/src/util/00-mesa-defaults.conf +++ b/src/util/00-mesa-defaults.conf @@ -1235,6 +1235,18 @@ TODO: document the other workarounds. + + + + + + + + diff --git a/src/util/driconf.h b/src/util/driconf.h index da880b27a20..5ce939fad5d 100644 --- a/src/util/driconf.h +++ b/src/util/driconf.h @@ -336,6 +336,10 @@ DRI_CONF_OPT_B(vk_require_astc, def, \ "Implement emulated ASTC on HW that does not support it") +#define DRI_CONF_VK_DESCRIPTOR_POOL_64K_ALIGNMENT(def) \ + DRI_CONF_OPT_B(vk_descriptor_pool_64k_alignment, def, \ + "Force use 64k alignment when allocate BO for descriptor pool") + /** * \brief Image quality-related options */ diff --git a/src/util/os_misc.c b/src/util/os_misc.c index 7261577488f..99d63e27aa4 100644 --- a/src/util/os_misc.c +++ b/src/util/os_misc.c @@ -142,7 +142,10 @@ os_log_message(const char *message) * * 1) convert to lowercase * 2) replace '_' with '.' - * 3) if necessary, prepend "mesa." + * 3) replace "MESA_" or prepend with "mesa." + * 4) look for "debug.mesa." prefix + * 5) look for "vendor.mesa." prefix + * 6) look for "mesa." prefix * * For example: * - MESA_EXTENSION_OVERRIDE -> mesa.extension.override @@ -167,9 +170,16 @@ os_get_android_option(const char *name) } } - int len = property_get(key, os_android_option_value, NULL); - if (len > 1) { - return os_android_option_value; + /* prefixes to search sorted by preference */ + const char *prefices[] = { "debug.", "vendor.", "" }; + char full_key[PROPERTY_KEY_MAX]; + int len = 0; + for (int i = 0; i < ARRAY_SIZE(prefices); i++) { + strlcpy(full_key, prefices[i], PROPERTY_KEY_MAX); + strlcat(full_key, key, PROPERTY_KEY_MAX); + len = property_get(full_key, os_android_option_value, NULL); + if (len > 0) + return os_android_option_value; } return NULL; } diff --git a/src/util/u_gralloc/meson.build b/src/util/u_gralloc/meson.build index 913fc7c786d..e84458e7bd2 100644 --- a/src/util/u_gralloc/meson.build +++ b/src/util/u_gralloc/meson.build @@ -22,6 +22,12 @@ if dep_android_mapper4.found() cpp_args_for_u_gralloc += '-DUSE_IMAPPER4_METADATA_API' options_for_u_gralloc += 'cpp_std=c++17' endif +if dep_android_mapper5.found() + files_u_gralloc += files('u_gralloc_imapper5_api.cpp') + c_args_for_u_gralloc += '-DUSE_IMAPPER5_METADATA_API' + cpp_args_for_u_gralloc += '-DUSE_IMAPPER5_METADATA_API' + options_for_u_gralloc += 'cpp_std=c++17' +endif _libmesa_u_gralloc = static_library( '_mesa_u_gralloc', diff --git a/src/util/u_gralloc/u_gralloc.c b/src/util/u_gralloc/u_gralloc.c index b92057c515d..2aaba2034a0 100644 --- a/src/util/u_gralloc/u_gralloc.c +++ b/src/util/u_gralloc/u_gralloc.c @@ -25,9 +25,9 @@ static const struct u_grallocs { } u_grallocs[] = { /* Prefer the CrOS API as it is significantly faster than IMapper4 */ {.type = U_GRALLOC_TYPE_CROS, .create = u_gralloc_cros_api_create}, -#ifdef USE_IMAPPER4_METADATA_API +#if defined(USE_IMAPPER4_METADATA_API) || defined(USE_IMAPPER5_METADATA_API) {.type = U_GRALLOC_TYPE_GRALLOC4, .create = u_gralloc_imapper_api_create}, -#endif /* USE_IMAPPER4_METADATA_API */ +#endif /* USE_IMAPPER4_METADATA_API || USE_IMAPPER5_METADATA_API */ {.type = U_GRALLOC_TYPE_LIBDRM, .create = u_gralloc_libdrm_create}, {.type = U_GRALLOC_TYPE_QCOM, .create = u_gralloc_qcom_create}, {.type = U_GRALLOC_TYPE_FALLBACK, .create = u_gralloc_fallback_create}, diff --git a/src/util/u_gralloc/u_gralloc_imapper5_api.cpp b/src/util/u_gralloc/u_gralloc_imapper5_api.cpp new file mode 100644 index 00000000000..b336abdf433 --- /dev/null +++ b/src/util/u_gralloc/u_gralloc_imapper5_api.cpp @@ -0,0 +1,520 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2021 GlobalLogic Ukraine + * Copyright (C) 2021-2022 Roman Stratiienko (r.stratiienko@gmail.com) + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util/log.h" +#include "u_gralloc_internal.h" + +using namespace aidl::android::hardware::graphics::allocator; +using aidl::android::hardware::graphics::common::BufferUsage; +using aidl::android::hardware::graphics::common::StandardMetadataType; +using aidl::android::hardware::graphics::common::ChromaSiting; +using aidl::android::hardware::graphics::common::Dataspace; +using aidl::android::hardware::graphics::common::ExtendableType; +using aidl::android::hardware::graphics::common::PlaneLayout; +using aidl::android::hardware::graphics::common::PlaneLayoutComponent; +using aidl::android::hardware::graphics::common::PlaneLayoutComponentType; +using android::hardware::graphics::common::V1_2::PixelFormat; +using android::hardware::graphics::mapper::StandardMetadata; +using android::hardware::hidl_handle; + +static const auto kIAllocatorServiceName = IAllocator::descriptor + std::string("/default"); +static const auto kIAllocatorMinimumVersion = 2; + +typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper *_Nullable *_Nonnull outImplementation); + +static std::shared_ptr waitForAllocator() { + if (__builtin_available(android 31, *)) { + if (!AServiceManager_isDeclared(kIAllocatorServiceName.c_str())) { + mesa_loge("AllocatorService not declared"); + return nullptr; + } + auto allocator = IAllocator::fromBinder( + ndk::SpAIBinder(AServiceManager_waitForService(kIAllocatorServiceName.c_str()))); + if (!allocator) { + mesa_loge("AIDL IAllocator declared but failed to get service"); + return nullptr; + } + + int32_t version = 0; + if (!allocator->getInterfaceVersion(&version).isOk()) { + mesa_loge("Failed to query interface version"); + return nullptr; + } + if (version < kIAllocatorMinimumVersion) { + mesa_loge("version is < kIAllocatorMinimumVersion"); + return nullptr; + } + return allocator; + } else { + mesa_loge("API level < 31"); + return nullptr; + } +} + +static void *loadIMapperLibrary() { + static void *imapperLibrary = []() -> void * { + auto allocator = waitForAllocator(); + if (allocator == nullptr) + return NULL; + + std::string mapperSuffix; + auto status = allocator->getIMapperLibrarySuffix(&mapperSuffix); + if (!status.isOk()) { + mesa_loge("Failed to get IMapper library suffix"); + return NULL; + } + std::string lib_name = "mapper." + mapperSuffix + ".so"; + mesa_logi("Loading mapper.%s.so", mapperSuffix.c_str()); + void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW); + if (!so) { + mesa_loge("Failed to load mapper.%s.so", mapperSuffix.c_str()); + } + return so; + }(); + return imapperLibrary; +} + +template +static auto getStandardMetadata(AIMapper *mapper, buffer_handle_t bufferHandle) + -> decltype(StandardMetadata::value::decode(NULL, 0)) { + using Value = typename StandardMetadata::value; + // TODO: Tune for common-case better + android::FatVector buffer; + int32_t sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, + static_cast(T), + buffer.data(), buffer.size()); + if (sizeRequired < 0) { + ALOGW_IF(-AIMAPPER_ERROR_UNSUPPORTED != sizeRequired, + "Unexpected error %d from valid getStandardMetadata call", -sizeRequired); + return std::nullopt; + } + if ((size_t)sizeRequired > buffer.size()) { + buffer.resize(sizeRequired); + sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, static_cast(T), + buffer.data(), buffer.size()); + } + if (sizeRequired < 0 || (size_t)sizeRequired > buffer.size()) { + mesa_logw("getStandardMetadata failed, received %d with buffer size %zd", sizeRequired, + buffer.size()); + // Generate a fail type + return std::nullopt; + } + return Value::decode(buffer.data(), sizeRequired); +} + +struct gralloc5 { + struct u_gralloc base; + AIMapper *mapper = NULL; +}; + +extern "C" { + +static buffer_handle_t import_buffer(struct u_gralloc *gralloc, const buffer_handle_t rawHandle) +{ + buffer_handle_t outBuffer = nullptr; + gralloc5 *gr = (gralloc5 *)gralloc; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + } else { + AIMapper_Error error = gr->mapper->v5.importBuffer(hidl_handle(rawHandle), + &outBuffer); + if (error != AIMAPPER_ERROR_NONE) { + mesa_loge("importBuffer failed"); + } + } + + return outBuffer; +} + +static int free_buffer(struct u_gralloc *gralloc, const buffer_handle_t handle) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + AIMapper_Error error = gr->mapper->v5.freeBuffer(handle); + if (error != AIMAPPER_ERROR_NONE) { + mesa_loge("freeBuffer failed"); + return - EINVAL; + } + + return 0; +} + +static int +mapper_resolve_format(struct u_gralloc *gralloc, struct u_gralloc_buffer_handle *hnd, + int32_t *format) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + int error = 0; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!hnd->handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + auto importedHandle = import_buffer(gralloc, hnd->handle); + if (nullptr == importedHandle) { + mesa_loge("import_buffer failed"); + return -EINVAL; + } + + auto value = + getStandardMetadata(gr->mapper, + importedHandle); + if (!value.has_value()) { + mesa_loge("PIXEL_FORMAT_REQUESTED get failed"); + error = -EINVAL; + } else { + *format = static_cast>(*value); + } + + (void)free_buffer(gralloc, importedHandle); + return error; +} + +static int +mapper_get_buffer_basic_info(struct u_gralloc *gralloc, + struct u_gralloc_buffer_handle *hnd, + struct u_gralloc_buffer_basic_info *out) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + int error = -EINVAL; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!hnd->handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + auto importedHandle = import_buffer(gralloc, hnd->handle); + if (nullptr == importedHandle) { + mesa_loge("import_buffer failed"); + return -EINVAL; + } + + { + auto value = + getStandardMetadata(gr->mapper, + importedHandle); + if (!value.has_value()) { + mesa_loge("PIXEL_FORMAT_FOURCC get failed"); + goto out; + } + + out->drm_fourcc = *value; + } + + { + auto value = getStandardMetadata( + gr->mapper, + importedHandle); + if (!value.has_value()) { + mesa_loge("PIXEL_FORMAT_MODIFIER get failed"); + goto out; + } + + out->modifier = *value; + } + + { + auto layouts_opt = getStandardMetadata(gr->mapper, + importedHandle); + if (!(layouts_opt.has_value())) { + mesa_loge("PLANE_LAYOUTS get failed"); + goto out; + } else { + std::vector &layouts = *layouts_opt; + int fd_index = 0; + int droid_format = 0, resolve_format = 0; + enum chroma_order chroma_order = chroma_order::YCbCr; + int chroma_step = 0; + + out->num_planes = layouts.size(); + + + for (uint32_t i = 0; i < layouts.size(); i++) { + out->strides[i] = layouts[i].strideInBytes; + out->offsets[i] = layouts[i].offsetInBytes; + + /* offset == 0 means layer is located in different dma-buf */ + if (out->offsets[i] == 0 && i > 0) + fd_index++; + + if (fd_index >= hnd->handle->numFds) + goto out; + + out->fds[i] = hnd->handle->data[fd_index]; + } + + if (mapper_resolve_format(gralloc, hnd, &droid_format)) { + mesa_loge("mapper_resolve_format failed"); + goto out; + } + + if (is_hal_format_yuv(droid_format)) { + if (layouts[1].components[0].type == android::gralloc4::PlaneLayoutComponentType_CB) + chroma_order = chroma_order::YCbCr; + else + chroma_order = chroma_order::YCrCb; + + chroma_step = layouts[1].sampleIncrementInBits / 8; + resolve_format = get_fourcc_yuv(droid_format, chroma_order, chroma_step); + out->drm_fourcc = resolve_format; + + if (layouts.size() == 2) { + out->strides[2] = out->strides[1]; + out->offsets[2] = out->offsets[1] + (chroma_step/2); + } + } + } + } + + error = 0; +out: + (void)free_buffer(gralloc, importedHandle); + return error; +} + +static __inline__ Dataspace +_legacy_dataspace_to_v0(Dataspace ds) +{ + switch((android_dataspace_t)ds) { + case HAL_DATASPACE_SRGB: + ds = Dataspace::SRGB; + break; + case HAL_DATASPACE_BT709: + ds = Dataspace::BT709; + break; + case HAL_DATASPACE_SRGB_LINEAR: + ds = Dataspace::SRGB_LINEAR; + break; + case HAL_DATASPACE_BT601_525: + ds = Dataspace::BT601_525; + break; + case HAL_DATASPACE_BT601_625: + ds = Dataspace::BT601_625; + break; + case HAL_DATASPACE_JFIF: + ds = Dataspace::JFIF; + break; + default: + break; + } + return ds; +} + +static int +mapper_get_buffer_color_info(struct u_gralloc *gralloc, + struct u_gralloc_buffer_handle *hnd, + struct u_gralloc_buffer_color_info *out) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!hnd->handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + int droid_format = 0; + + if (mapper_resolve_format(gralloc, hnd, &droid_format)) { + mesa_loge("mapper_resolve_format failed"); + return -EINVAL; + } + + if (is_hal_format_yuv(droid_format)) { + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601; + out->sample_range = __DRI_YUV_NARROW_RANGE; + out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0; + out->vertical_siting = __DRI_YUV_CHROMA_SITING_0; + + return 0; + } + + auto importedHandle = import_buffer(gralloc, hnd->handle); + if (nullptr == importedHandle) { + mesa_loge("import_buffer failed"); + return -EINVAL; + } + + /* optional attributes */ + std::optional chroma_siting; + { + auto value = getStandardMetadata(gr->mapper, + importedHandle); + if (value.has_value()) { + ExtendableType chroma_siting_ext = *value; + + chroma_siting = + android::gralloc4::getStandardChromaSitingValue(chroma_siting_ext); + } + } + + { + auto value = getStandardMetadata(gr->mapper, + importedHandle); + if (value.has_value()) { + Dataspace dataspace = static_cast(*value); + + // The dataspace value passed down might be a legacy value, + // which does not comply with the pattern: + // (Standard << 16) |(Transfer << 22) | (Range << 27) + // Just convert the legacy value to v0 value, + // according to standard “hardware/interfaces/graphics/common/1.0/types.hal”. + if ((int)dataspace & 0xffff) + dataspace = _legacy_dataspace_to_v0(dataspace); + + Dataspace standard = + (Dataspace)((int)dataspace & (uint32_t)Dataspace::STANDARD_MASK); + switch (standard) { + case Dataspace::STANDARD_BT709: + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709; + break; + case Dataspace::STANDARD_BT601_625: + case Dataspace::STANDARD_BT601_625_UNADJUSTED: + case Dataspace::STANDARD_BT601_525: + case Dataspace::STANDARD_BT601_525_UNADJUSTED: + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601; + break; + case Dataspace::STANDARD_BT2020: + case Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE: + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020; + break; + default: + break; + } + + Dataspace range = + (Dataspace)((int)dataspace & (uint32_t)Dataspace::RANGE_MASK); + switch (range) { + case Dataspace::RANGE_FULL: + out->sample_range = __DRI_YUV_FULL_RANGE; + break; + case Dataspace::RANGE_LIMITED: + out->sample_range = __DRI_YUV_NARROW_RANGE; + break; + default: + break; + } + } + } + + if (chroma_siting) { + switch (*chroma_siting) { + case ChromaSiting::SITED_INTERSTITIAL: + out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5; + out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5; + break; + case ChromaSiting::COSITED_HORIZONTAL: + out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0; + out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5; + break; + default: + break; + } + } + + (void)free_buffer(gralloc, importedHandle); + return 0; +} + +static int +mapper_get_front_rendering_usage(struct u_gralloc *gralloc, + uint64_t *out_usage) +{ + assert(out_usage); +#if ANDROID_API_LEVEL >= 33 + *out_usage = static_cast(BufferUsage::FRONT_BUFFER); + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int +destroy(struct u_gralloc *gralloc) +{ + gralloc5 *gr = (struct gralloc5 *)gralloc; + delete gr; + + return 0; +} + +struct u_gralloc * +u_gralloc_imapper_api_create() +{ + void *so = loadIMapperLibrary(); + if (!so) { + mesa_loge("loadIMapperLibrary failed"); + return NULL; + } + auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper"); + AIMapper *mapper = nullptr; + AIMapper_Error error = loadIMapper(&mapper); + if (error != AIMAPPER_ERROR_NONE) { + mesa_loge("AIMapper_loadIMapper failed %d", error); + return NULL; + } + + auto gr = new gralloc5; + gr->mapper = mapper; + gr->base.ops.get_buffer_basic_info = mapper_get_buffer_basic_info; + gr->base.ops.get_buffer_color_info = mapper_get_buffer_color_info; + gr->base.ops.get_front_rendering_usage = mapper_get_front_rendering_usage; + gr->base.ops.destroy = destroy; + + mesa_logi("Using IMapper5 API"); + + return &gr->base; +} + +} // extern "C" diff --git a/src/util/u_gralloc/u_gralloc_internal.h b/src/util/u_gralloc/u_gralloc_internal.h index e66ae7b8d43..3e9b0ac853b 100644 --- a/src/util/u_gralloc/u_gralloc_internal.h +++ b/src/util/u_gralloc/u_gralloc_internal.h @@ -37,7 +37,7 @@ struct u_gralloc { }; extern struct u_gralloc *u_gralloc_cros_api_create(void); -#ifdef USE_IMAPPER4_METADATA_API +#if defined(USE_IMAPPER4_METADATA_API) || defined(USE_IMAPPER5_METADATA_API) extern struct u_gralloc *u_gralloc_imapper_api_create(void); #endif extern struct u_gralloc *u_gralloc_qcom_create(void);