├── .clang-format ├── .gitlab-ci.yml ├── .pre-commit-config.yaml ├── CMakeLists.txt ├── DCO.txt ├── LICENSE ├── README.md ├── check_copyright.py ├── docs └── guidelines.md ├── layer ├── VkLayer_window_system_integration.json ├── layer.cpp ├── present_timing.cpp ├── private_data.cpp ├── private_data.hpp ├── surface_api.cpp ├── surface_api.hpp ├── swapchain_api.cpp ├── swapchain_api.hpp ├── swapchain_maintenance_api.cpp ├── swapchain_maintenance_api.hpp └── wsi_layer_experimental.hpp ├── util ├── custom_allocator.cpp ├── custom_allocator.hpp ├── drm │ ├── drm_utils.cpp │ ├── drm_utils.hpp │ ├── format_table.c │ └── format_table.h ├── extension_list.cpp ├── extension_list.hpp ├── file_descriptor.hpp ├── format_modifiers.cpp ├── format_modifiers.hpp ├── helpers.hpp ├── log.cpp ├── log.hpp ├── macros.hpp ├── platform_set.hpp ├── ring_buffer.hpp ├── timed_semaphore.cpp ├── timed_semaphore.hpp ├── unordered_map.hpp ├── unordered_set.hpp └── wsialloc │ ├── wsialloc.h │ └── wsialloc_ion.c └── wsi ├── README.md ├── compatible_present_modes.hpp ├── display ├── drm_display.cpp ├── drm_display.hpp ├── surface.cpp ├── surface.hpp ├── surface_properties.cpp ├── surface_properties.hpp ├── swapchain.cpp └── swapchain.hpp ├── external_memory.cpp ├── external_memory.hpp ├── frame_boundary.cpp ├── frame_boundary.hpp ├── headless ├── surface.cpp ├── surface.hpp ├── surface_properties.cpp ├── surface_properties.hpp ├── swapchain.cpp └── swapchain.hpp ├── surface.hpp ├── surface_properties.cpp ├── surface_properties.hpp ├── swapchain_base.cpp ├── swapchain_base.hpp ├── synchronization.cpp ├── synchronization.hpp ├── wayland ├── surface.cpp ├── surface.hpp ├── surface_properties.cpp ├── surface_properties.hpp ├── swapchain.cpp ├── swapchain.hpp ├── wl_helpers.cpp ├── wl_helpers.hpp └── wl_object_owner.hpp ├── wsi_factory.cpp ├── wsi_factory.hpp └── x11 ├── surface.cpp ├── surface.hpp ├── surface_properties.cpp ├── surface_properties.hpp ├── swapchain.cpp └── swapchain.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | # The style used for all options not specifically set in the configuration. 2 | BasedOnStyle: LLVM 3 | 4 | # The extra indent or outdent of access modifiers, e.g. public:. 5 | AccessModifierOffset: -3 6 | 7 | # If true, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column. 8 | AlignEscapedNewlinesLeft: true 9 | 10 | # If true, aligns trailing comments. 11 | AlignTrailingComments: true 12 | 13 | # Allow putting all parameters of a function declaration onto the next line even if BinPackParameters is false. 14 | AllowAllParametersOfDeclarationOnNextLine: false 15 | 16 | # Allows contracting simple braced statements to a single line. 17 | AllowShortBlocksOnASingleLine: false 18 | 19 | # If true, short case labels will be contracted to a single line. 20 | AllowShortCaseLabelsOnASingleLine: false 21 | 22 | # Dependent on the value, int f() { return 0; } can be put on a single line. Possible values: None, Inline, All. 23 | AllowShortFunctionsOnASingleLine: None 24 | 25 | # If true, if (a) return; can be put on a single line. 26 | AllowShortIfStatementsOnASingleLine: false 27 | 28 | # If true, while (true) continue; can be put on a single line. 29 | AllowShortLoopsOnASingleLine: false 30 | 31 | # If true, always break after function definition return types. 32 | AlwaysBreakAfterDefinitionReturnType: false 33 | 34 | # If true, always break before multiline string literals. 35 | AlwaysBreakBeforeMultilineStrings: false 36 | 37 | # If true, always break after the template<...> of a template declaration. 38 | AlwaysBreakTemplateDeclarations: true 39 | 40 | # If false, a function call's arguments will either be all on the same line or will have one line each. 41 | BinPackArguments: true 42 | 43 | # If false, a function declaration's or function definition's parameters will either all be on the same line 44 | # or will have one line each. 45 | BinPackParameters: true 46 | 47 | # The way to wrap binary operators. Possible values: None, NonAssignment, All. 48 | BreakBeforeBinaryOperators: None 49 | 50 | # The brace breaking style to use. Possible values: Attach, Linux, Stroustrup, Allman, GNU. 51 | BreakBeforeBraces: Custom 52 | # Like Allman but do not indent extern blocks 53 | BraceWrapping: 54 | AfterExternBlock: 'false' 55 | AfterCaseLabel: 'true' 56 | AfterClass: 'true' 57 | AfterEnum: 'true' 58 | AfterFunction: 'true' 59 | AfterNamespace: 'true' 60 | AfterObjCDeclaration: 'true' 61 | AfterStruct: 'true' 62 | AfterUnion: 'true' 63 | BeforeCatch: 'true' 64 | BeforeElse: 'true' 65 | AfterControlStatement: 'Always' 66 | 67 | # If true, ternary operators will be placed after line breaks. 68 | BreakBeforeTernaryOperators: false 69 | 70 | # Always break constructor initializers before commas and align the commas with the colon. 71 | BreakConstructorInitializersBeforeComma: true 72 | 73 | # The column limit. A column limit of 0 means that there is no column limit. 74 | ColumnLimit: 120 75 | 76 | # A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed. 77 | CommentPragmas: '^ *' 78 | 79 | # If the constructor initializers don't fit on a line, put each initializer on its own line. 80 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 81 | 82 | # The number of characters to use for indentation of constructor initializer lists. 83 | ConstructorInitializerIndentWidth: 3 84 | 85 | # Indent width for line continuations. 86 | ContinuationIndentWidth: 3 87 | 88 | # If true, format braced lists as best suited for C++11 braced lists. 89 | Cpp11BracedListStyle: false 90 | 91 | # Disables formatting at all. 92 | DisableFormat: false 93 | 94 | # A vector of macros that should be interpreted as foreach loops instead of as function calls. 95 | ForEachMacros: [''] 96 | 97 | # Indent case labels one level from the switch statement. 98 | # When false, use the same indentation level as for the switch statement. 99 | # Switch statement body is always indented one level more than case labels. 100 | IndentCaseLabels: false 101 | 102 | # The number of columns to use for indentation. 103 | IndentWidth: 3 104 | 105 | # Indent if a function definition or declaration is wrapped after the type. 106 | IndentWrappedFunctionNames: false 107 | 108 | # If true, empty lines at the start of blocks are kept. 109 | KeepEmptyLinesAtTheStartOfBlocks: true 110 | 111 | # Language, this format style is targeted at. Possible values: None, Cpp, Java, JavaScript, Proto. 112 | Language: Cpp 113 | 114 | # The maximum number of consecutive empty lines to keep. 115 | MaxEmptyLinesToKeep: 1 116 | 117 | # The indentation used for namespaces. Possible values: None, Inner, All. 118 | NamespaceIndentation: None 119 | 120 | # The penalty for breaking a function call after "call(". 121 | PenaltyBreakBeforeFirstCallParameter: 19 122 | 123 | # The penalty for each line break introduced inside a comment. 124 | PenaltyBreakComment: 300 125 | 126 | # The penalty for breaking before the first <<. 127 | PenaltyBreakFirstLessLess: 120 128 | 129 | # The penalty for each line break introduced inside a string literal. 130 | PenaltyBreakString: 1000 131 | 132 | # The penalty for each character outside of the column limit. 133 | PenaltyExcessCharacter: 1000000 134 | 135 | # Penalty for putting the return type of a function onto its own line. 136 | PenaltyReturnTypeOnItsOwnLine: 1000000000 137 | 138 | # Pointer and reference alignment style. Possible values: Left, Right, Middle. 139 | PointerAlignment: Right 140 | 141 | # Do not sort includes 142 | SortIncludes: false 143 | 144 | # If true, a space may be inserted after C style casts. 145 | SpaceAfterCStyleCast: false 146 | 147 | # If false, spaces will be removed before assignment operators. 148 | SpaceBeforeAssignmentOperators: true 149 | 150 | # Defines in which cases to put a space before opening parentheses. Possible values: Never, ControlStatements, Always. 151 | SpaceBeforeParens: ControlStatements 152 | 153 | # If true, spaces may be inserted into '()'. 154 | SpaceInEmptyParentheses: false 155 | 156 | # The number of spaces before trailing line comments (// - comments). 157 | SpacesBeforeTrailingComments: 1 158 | 159 | # If true, spaces will be inserted after '<' and before '>' in template argument lists. 160 | SpacesInAngles: false 161 | 162 | # If true, spaces may be inserted into C style casts. 163 | SpacesInCStyleCastParentheses: false 164 | 165 | # If true, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals). 166 | SpacesInContainerLiterals: false 167 | 168 | # If true, spaces will be inserted after '(' and before ')'. 169 | SpacesInParentheses: false 170 | 171 | # If true, spaces will be inserted after '[' and befor']'. 172 | SpacesInSquareBrackets: false 173 | 174 | # Format compatible with this standard, e.g. use A > instead of A> for LS_Cpp03. Possible values: Cpp03, Cpp11, Auto. 175 | Standard: Cpp11 176 | 177 | # The number of columns used for tab stops. 178 | TabWidth: 3 179 | 180 | # The way to use tab characters in the resulting file. Possible values: Never, ForIndentation, Always. 181 | UseTab: Never 182 | 183 | FixNamespaceComments: false 184 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2024 Arm Limited. 2 | # 3 | # SPDX-License-Identifier: MIT 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to 7 | # deal in the Software without restriction, including without limitation the 8 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | # sell copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | pre-commit: 24 | image: python:3.10.6 25 | rules: 26 | - if: $CI_MERGE_REQUEST_DIFF_BASE_SHA 27 | script: 28 | - pip install pre-commit 29 | - echo Using $CI_MERGE_REQUEST_DIFF_BASE_SHA as Pre-commit base 30 | - pre-commit run --show-diff-on-failure --from-ref $CI_MERGE_REQUEST_DIFF_BASE_SHA --to-ref HEAD 31 | 32 | build_vulkan_wsi_layer: 33 | # For now start from a standard Fedora image and install everything each time. 34 | image: "registry.fedoraproject.org/fedora" 35 | before_script: 36 | - pwd 37 | - uname -a 38 | # Install necessary packages. 39 | # Oddly the exit status of the command below is nonzero even on success, just ignore it. 40 | - yes | dnf install make cmake gcc g++ python git libxcb-devel libxkbcommon-devel wayland-devel libXrandr-devel || true 41 | # Check out and set-up the Vulkan Loader. 42 | - mkdir /build 43 | - pushd /build 44 | - git clone --depth=1 https://github.com/KhronosGroup/Vulkan-Loader.git 45 | - cd Vulkan-Loader 46 | - mkdir build 47 | - cd build/ 48 | - ../scripts/update_deps.py --cmake_var VULKAN_HEADERS_ENABLE_MODULE=OFF 49 | # Build the Vulkan loader. 50 | - cmake -C helper.cmake .. 51 | - make 52 | - make install 53 | - popd 54 | script: 55 | - pwd 56 | - mkdir build 57 | - cd build 58 | - cmake .. -DVULKAN_CXX_INCLUDE=/build/Vulkan-Loader/build/Vulkan-Headers/build/install/include 59 | - make 60 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | 4 | minimum_pre_commit_version: 2.9.0 5 | 6 | repos: 7 | - repo: https://github.com/pre-commit/mirrors-clang-format 8 | rev: v14.0.0 9 | hooks: 10 | - id: clang-format 11 | types_or: [c, c++] 12 | 13 | - repo: local 14 | hooks: 15 | - id: copyright-check 16 | name: copyright-check 17 | description: Checks for a valid copyright header 18 | entry: check_copyright.py 19 | language: script 20 | types_or: [c, c++] 21 | -------------------------------------------------------------------------------- /DCO.txt: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 1 Letterman Drive 6 | Suite D4700 7 | San Francisco, CA, 94129 8 | 9 | Everyone is permitted to copy and distribute verbatim copies of this 10 | license document, but changing it is not allowed. 11 | 12 | 13 | Developer's Certificate of Origin 1.1 14 | 15 | By making a contribution to this project, I certify that: 16 | 17 | (a) The contribution was created in whole or in part by me and I 18 | have the right to submit it under the open source license 19 | indicated in the file; or 20 | 21 | (b) The contribution is based upon previous work that, to the best 22 | of my knowledge, is covered under an appropriate open source 23 | license and I have the right under that license to submit that 24 | work with modifications, whether created in whole or in part 25 | by me, under the same open source license (unless I am 26 | permitted to submit under a different license), as indicated 27 | in the file; or 28 | 29 | (c) The contribution was provided directly to me by some other 30 | person who certified (a), (b) or (c) and I have not modified 31 | it. 32 | 33 | (d) I understand and agree that this project and the contribution 34 | are public and that a record of the contribution (including all 35 | personal information I submit with it, including my sign-off) is 36 | maintained indefinitely and may be redistributed consistent with 37 | this project or the open source license(s) involved. 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Arm Limited. 2 | 3 | SPDX-License-Identifier: MIT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to 7 | deal in the Software without restriction, including without limitation the 8 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | sell copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /check_copyright.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2022 Arm Limited. 4 | # 5 | # SPDX-License-Identifier: MIT 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to 9 | # deal in the Software without restriction, including without limitation the 10 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | # sell copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | ''' 26 | This script will check the files passed as arguments for a valid copyright 27 | header. It will run against all changed files as part of the pre-commit hook 28 | after running `pre-commit install` in the root of the repository. It can also 29 | be run manually e.g. `./check_copyright.py file1 dir1/file2` 30 | 31 | A valid copyright header includes the word 'Copyright' followed by the 32 | relevant copyright years. It also requires an SPDX licence id string identifying 33 | the license as MIT, as follows: 'SPDX-License-Identifier: MIT' 34 | ''' 35 | 36 | import datetime 37 | import re 38 | import sys 39 | from typing import List 40 | 41 | # Set the limit on number of lines at top of file to search 42 | MAX_SEARCH_LINES = 20 43 | CURRENT_YEAR = datetime.datetime.now().year 44 | 45 | # Regex for positive copyright string 46 | COPYRIGHT_YEAR_REGEX = re.compile( 47 | r".*\bCOPYRIGHT.*%s.*" % str(CURRENT_YEAR), re.IGNORECASE 48 | ) 49 | 50 | # Regex for positive SPDX id string 51 | SPDX_REGEX = re.compile(r".*SPDX-License-Identifier: MIT.*", re.IGNORECASE) 52 | 53 | # To match eg: "Copyright (C) 2014-2021" 54 | PATTERN_STRING = r"\bCopyright\b.*[0-9,)]" 55 | PATTERN_COPYRIGHT = re.compile(PATTERN_STRING, re.IGNORECASE) 56 | 57 | 58 | def generate_years_string(years: List[int]) -> str: 59 | """ 60 | Create a compacted string representation of a list of years. 61 | 62 | E.g. [1991, 2001, 2002, 2003, 2006, 2007] becomes "1991, 2001-2003, 63 | 2006-2007" 64 | """ 65 | 66 | generated_years_string = "" 67 | if len(years) > 0: 68 | y_mod_strings = ["%d" % years[0]] 69 | 70 | last_element_was_incremental = False 71 | for i in range(1, len(years)): 72 | # Are we in an incremental sequence? 73 | if years[i] == years[i - 1] + 1: 74 | 75 | last_element_was_incremental = True 76 | 77 | # Are we at the last element? 78 | if i == len(years) - 1: 79 | y_mod_strings.append("-%d" % years[i]) 80 | else: 81 | continue 82 | 83 | else: 84 | # End of a sequence? 85 | if last_element_was_incremental: 86 | y_mod_strings.append("-%d, " % years[i - 1]) 87 | else: 88 | y_mod_strings.append(", ") 89 | 90 | y_mod_strings.append("%d" % years[i]) 91 | last_element_was_incremental = False 92 | 93 | generated_years_string = "".join(y_mod_strings) 94 | 95 | return generated_years_string 96 | 97 | 98 | def parse_years_string(s: str) -> List[int]: 99 | """ 100 | Given the string "1999, 2001-2005" this function returns the list: 101 | [1999, 2001, 2002, 2003, 2004, 2005] 102 | """ 103 | singles = re.findall(r"(? None: 118 | """ 119 | Updates the Copyright header in 'filename' to hold the correct years. 120 | """ 121 | 122 | with open(filename, "r+", encoding="utf-8") as file_handle: 123 | file_data = file_handle.read() 124 | 125 | copyright_match = re.search(PATTERN_COPYRIGHT, file_data) 126 | if copyright_match: 127 | 128 | notice_years = parse_years_string(copyright_match.group(0)) 129 | 130 | if not notice_years or notice_years[-1] != CURRENT_YEAR: 131 | notice_years.append(CURRENT_YEAR) 132 | 133 | years_string = generate_years_string(notice_years) 134 | 135 | file_data = re.sub( 136 | PATTERN_COPYRIGHT, "Copyright (c) %s" % years_string, file_data, 1 137 | ) 138 | file_handle.seek(0) 139 | file_handle.write(file_data) 140 | file_handle.truncate() 141 | 142 | 143 | bad_copyright_files = [] 144 | bad_spdx_files = [] 145 | 146 | for changed_file in sys.argv[1:]: 147 | copyright_found = False 148 | spdx_found = False 149 | 150 | with open(changed_file, encoding="utf-8") as f: 151 | for line_num, line in enumerate(f): 152 | if line_num > MAX_SEARCH_LINES: 153 | break 154 | if COPYRIGHT_YEAR_REGEX.match(line): 155 | copyright_found = True 156 | if SPDX_REGEX.match(line): 157 | spdx_found = True 158 | 159 | if not copyright_found: 160 | bad_copyright_files.append(changed_file) 161 | update_header(changed_file) 162 | if not spdx_found: 163 | bad_spdx_files.append(changed_file) 164 | 165 | if bad_copyright_files: 166 | print( 167 | "The following files did not have a valid copyright header: " 168 | + str(bad_copyright_files) 169 | + "\nAn attempted fix may have been made please check the files and re-commit", 170 | file=sys.stderr, 171 | ) 172 | 173 | if bad_spdx_files: 174 | print( 175 | "The following files do not have a valid SPDX licence identifier: " 176 | + str(bad_spdx_files) 177 | + "\nPlease add the identifier as follows 'SPDX-License-Identifier: MIT'", 178 | file=sys.stderr, 179 | ) 180 | 181 | if bad_copyright_files or bad_spdx_files: 182 | sys.exit(1) 183 | -------------------------------------------------------------------------------- /docs/guidelines.md: -------------------------------------------------------------------------------- 1 | # Guidelines for development 2 | This document outlines the guidelines that should be followed when submitting changes to the WSI layer. Although these 3 | rules should not be taken as set in stone, we encourage contributors to follow them in order to make the WSI layer 4 | more maintainable and easier to review. 5 | 6 | ## Exceptions 7 | We discourage the use of exceptions in the codebase. The preferred error handling mechanism is to return 8 | error codes. This closely aligns to the way the Vulkan API returns VkResult error codes to 9 | indicate an error or success. In addition, some of the libraries used in the layer are written using C rather 10 | than C++. In order to ensure interoperability between C and C++ code in the layer we have decided to forgo exceptions 11 | as there is no way for the C code to clean up correctly when an exception is thrown in C++ code. 12 | 13 | In some cases you might find that avoiding exceptions is very difficult. As an example we can use the STL 14 | containers such as std::vector or std::map which, by design, throw exceptions for memory allocation failures. 15 | In addition, the Vulkan API allows the application to supply custom allocation callbacks for memory allocation by 16 | passing a VkAllocationCallbacks structure. We must be able to handle these exceptions, possibly caused by failures in 17 | custom allocators, STL containers, etc., in order to correctly implement the Vulkan API and return the appropriate 18 | error codes, e.g. VK_ERROR_OUT_OF_HOST_MEMORY. 19 | 20 | A good idea is to introduce a wrapper around the STL container to ensure all exceptions are caught and converted to 21 | error codes that are propagated back to the caller. It is highly recommended to use the 22 | [utility classes](https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer/-/tree/main/util) provided by the WSI layer 23 | if you need an exception-safe wrapper for STL containers: 24 | * [util::vector](https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer/-/blob/main/util/custom_allocator.hpp) 25 | * [util::unordered_map](https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer/-/blob/main/util/unordered_map.hpp) 26 | * [util::unordered_set](https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer/-/blob/main/util/unordered_set.hpp) 27 | 28 | For other helper components provided by the WSI layer please see 29 | [WSI integration document](https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer/-/blob/main/wsi/README.md#helpers). 30 | -------------------------------------------------------------------------------- /layer/VkLayer_window_system_integration.json: -------------------------------------------------------------------------------- 1 | { 2 | "file_format_version": "1.1.2", 3 | "layer": { 4 | "name": "VK_LAYER_window_system_integration", 5 | "type": "GLOBAL", 6 | "library_path": "./libVkLayer_window_system_integration.so", 7 | "api_version": "1.3.216", 8 | "implementation_version": "1", 9 | "description": "Window system integration layer", 10 | "functions": { 11 | "vkNegotiateLoaderLayerInterfaceVersion": "wsi_layer_vkNegotiateLoaderLayerInterfaceVersion" 12 | }, 13 | "instance_extensions": [ 14 | {"name" : "VK_EXT_headless_surface", "spec_version" : "1"}, 15 | {"name" : "VK_KHR_wayland_surface", "spec_version" : "6"}, 16 | {"name" : "VK_KHR_xcb_surface", "spec_version" : "1"}, 17 | {"name" : "VK_KHR_xlib_surface", "spec_version" : "1"}, 18 | {"name" : "VK_KHR_surface", "spec_version" : "25"}, 19 | {"name" : "VK_KHR_display", "spec_version" : "23"}, 20 | {"name" : "VK_KHR_get_surface_capabilities2", "spec_version" : "1"}, 21 | {"name" : "VK_EXT_surface_maintenance1", "spec_version" : "1"} 22 | ], 23 | "device_extensions": [ 24 | {"name": "VK_KHR_shared_presentable_image", "spec_version": "1", "entrypoints": ["vkGetSwapchainStatusKHR"]}, 25 | {"name": "VK_EXT_image_compression_control_swapchain", "spec_version": "1"}, 26 | { 27 | "name": "VK_KHR_swapchain", 28 | "spec_version": "70", 29 | "entrypoints": [ 30 | "vkAcquireNextImageKHR", 31 | "vkCreateSwapchainKHR", 32 | "vkDestroySwapchainKHR", 33 | "vkGetSwapchainImagesKHR", 34 | "vkQueuePresentKHR", 35 | "vkAcquireNextImage2KHR", 36 | "vkGetDeviceGroupPresentCapabilitiesKHR", 37 | "vkGetDeviceGroupSurfacePresentModesKHR", 38 | "vkGetPhysicalDevicePresentRectanglesKHR" 39 | ] 40 | }, 41 | {"name": "VK_KHR_present_id", "spec_version": "1"}, 42 | { 43 | "name": "VK_EXT_swapchain_maintenance1", 44 | "spec_version": "1", 45 | "entrypoints": [ 46 | "vkReleaseSwapchainImagesEXT" 47 | ] 48 | }, 49 | { 50 | "name": "VK_EXT_present_timing", 51 | "spec_version": "1", 52 | "entrypoints": [ 53 | "vkSetSwapchainPresentTimingQueueSizeEXT", 54 | "vkGetSwapchainTimingPropertiesEXT", 55 | "vkGetSwapchainTimeDomainPropertiesEXT", 56 | "vkGetPastPresentationTimingEXT" 57 | ] 58 | } 59 | ], 60 | "disable_environment": { 61 | "DISABLE_WSI_LAYER": "1" 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /layer/present_timing.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file present_timing.cpp 27 | * 28 | * @brief Contains the Vulkan entrypoints for the present timing. 29 | */ 30 | #include 31 | #include "wsi_layer_experimental.hpp" 32 | #include "wsi/swapchain_base.hpp" 33 | 34 | #if VULKAN_WSI_LAYER_EXPERIMENTAL 35 | 36 | /** 37 | * @brief Implements vkSetSwapchainPresentTimingQueueSizeEXT Vulkan entrypoint. 38 | */ 39 | VWL_VKAPI_CALL(VkResult) 40 | wsi_layer_vkSetSwapchainPresentTimingQueueSizeEXT(VkDevice device, VkSwapchainKHR swapchain, uint32_t size) VWL_API_POST 41 | { 42 | assert(swapchain != VK_NULL_HANDLE); 43 | auto *sc = reinterpret_cast(swapchain); 44 | return sc->presentation_timing_queue_set_size(size); 45 | } 46 | 47 | /** 48 | * @brief Implements vkGetSwapchainTimingPropertiesEXT Vulkan entrypoint. 49 | */ 50 | VWL_VKAPI_CALL(VkResult) 51 | wsi_layer_vkGetSwapchainTimingPropertiesEXT(VkDevice device, VkSwapchainKHR swapchain, 52 | uint64_t *pSwapchainTimingPropertiesCounter, 53 | VkSwapchainTimingPropertiesEXT *pSwapchainTimingProperties) VWL_API_POST 54 | { 55 | VkResult result = VK_SUCCESS; 56 | return result; 57 | } 58 | 59 | /** 60 | * @brief Implements vkGetSwapchainTimeDomainPropertiesEXT Vulkan entrypoint. 61 | */ 62 | VWL_VKAPI_CALL(VkResult) 63 | wsi_layer_vkGetSwapchainTimeDomainPropertiesEXT( 64 | VkDevice device, VkSwapchainKHR swapchain, uint64_t *pTimeDomainsCounter, 65 | VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties) VWL_API_POST 66 | { 67 | VkResult result = VK_SUCCESS; 68 | return result; 69 | } 70 | 71 | /** 72 | * @brief Implements vkGetPastPresentationTimingEXT Vulkan entrypoint. 73 | */ 74 | VWL_VKAPI_CALL(VkResult) 75 | wsi_layer_vkGetPastPresentationTimingEXT( 76 | VkDevice device, const VkPastPresentationTimingInfoEXT *pPastPresentationTimingInfo, 77 | VkPastPresentationTimingPropertiesEXT *pPastPresentationTimingProperties) VWL_API_POST 78 | { 79 | VkResult result = VK_SUCCESS; 80 | return result; 81 | } 82 | #endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ 83 | -------------------------------------------------------------------------------- /layer/surface_api.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2019, 2021-2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file surface_api.hpp 27 | * 28 | * @brief Contains the Vulkan entrypoints for the VkSurfaceKHR. 29 | */ 30 | #pragma once 31 | 32 | #include 33 | #include "util/macros.hpp" 34 | 35 | /** 36 | * @brief Implements vkGetPhysicalDeviceSurfaceCapabilitiesKHR Vulkan entrypoint. 37 | */ 38 | VWL_VKAPI_CALL(VkResult) 39 | wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 40 | VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) VWL_API_POST; 41 | 42 | /** 43 | * @brief Implements vkGetPhysicalDeviceSurfaceCapabilities2KHR Vulkan entrypoint. 44 | */ 45 | VWL_VKAPI_CALL(VkResult) 46 | wsi_layer_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, 47 | const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 48 | VkSurfaceCapabilities2KHR *pSurfaceCapabilities) VWL_API_POST; 49 | 50 | /** 51 | * @brief Implements vkGetPhysicalDeviceSurfaceFormatsKHR Vulkan entrypoint. 52 | */ 53 | VWL_VKAPI_CALL(VkResult) 54 | wsi_layer_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 55 | uint32_t *pSurfaceFormatCount, 56 | VkSurfaceFormatKHR *pSurfaceFormats) VWL_API_POST; 57 | 58 | /** 59 | * @brief Implements vkGetPhysicalDeviceSurfaceFormats2KHR Vulkan entrypoint. 60 | */ 61 | VWL_VKAPI_CALL(VkResult) 62 | wsi_layer_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, 63 | const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 64 | uint32_t *pSurfaceFormatCount, 65 | VkSurfaceFormat2KHR *pSurfaceFormats) VWL_API_POST; 66 | 67 | /** 68 | * @brief Implements vkGetPhysicalDeviceSurfacePresentModesKHR Vulkan entrypoint. 69 | */ 70 | VWL_VKAPI_CALL(VkResult) 71 | wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 72 | uint32_t *pPresentModeCount, 73 | VkPresentModeKHR *pPresentModes) VWL_API_POST; 74 | 75 | /** 76 | * @brief Implements vkGetPhysicalDeviceSurfaceSupportKHR Vulkan entrypoint. 77 | */ 78 | VWL_VKAPI_CALL(VkResult) 79 | wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, 80 | VkSurfaceKHR surface, VkBool32 *pSupported) VWL_API_POST; 81 | 82 | /** 83 | * @brief Implements vkDestroySurfaceKHR Vulkan entrypoint. 84 | */ 85 | VWL_VKAPI_CALL(void) 86 | wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, 87 | const VkAllocationCallbacks *pAllocator) VWL_API_POST; 88 | -------------------------------------------------------------------------------- /layer/swapchain_api.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2019, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file swapchain_api.hpp 27 | * 28 | * @brief Contains the Vulkan entrypoints for the swapchain. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include "util/macros.hpp" 35 | 36 | VWL_VKAPI_CALL(VkResult) 37 | wsi_layer_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo, 38 | const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) VWL_API_POST; 39 | 40 | VWL_VKAPI_CALL(void) 41 | wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc, 42 | const VkAllocationCallbacks *pAllocator) VWL_API_POST; 43 | 44 | VWL_VKAPI_CALL(VkResult) 45 | wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapc, uint32_t *pSwapchainImageCount, 46 | VkImage *pSwapchainImages) VWL_API_POST; 47 | 48 | VWL_VKAPI_CALL(VkResult) 49 | wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapc, uint64_t timeout, VkSemaphore semaphore, 50 | VkFence fence, uint32_t *pImageIndex) VWL_API_POST; 51 | 52 | VWL_VKAPI_CALL(VkResult) 53 | wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) VWL_API_POST; 54 | 55 | /* 1.1 entrypoints */ 56 | VWL_VKAPI_CALL(VkResult) 57 | wsi_layer_vkGetDeviceGroupPresentCapabilitiesKHR( 58 | VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities) VWL_API_POST; 59 | 60 | VWL_VKAPI_CALL(VkResult) 61 | wsi_layer_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, 62 | VkDeviceGroupPresentModeFlagsKHR *pModes) VWL_API_POST; 63 | 64 | VWL_VKAPI_CALL(VkResult) 65 | wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 66 | uint32_t *pRectCount, VkRect2D *pRects) VWL_API_POST; 67 | 68 | VWL_VKAPI_CALL(VkResult) 69 | wsi_layer_vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo, 70 | uint32_t *pImageIndex) VWL_API_POST; 71 | 72 | VWL_VKAPI_CALL(VkResult) 73 | wsi_layer_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 74 | VkImage *pImage) VWL_API_POST; 75 | 76 | VWL_VKAPI_CALL(VkResult) 77 | wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, 78 | const VkBindImageMemoryInfo *pBindInfos) VWL_API_POST; 79 | 80 | VWL_VKAPI_CALL(VkResult) 81 | wsi_layer_vkGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain) VWL_API_POST; 82 | -------------------------------------------------------------------------------- /layer/swapchain_maintenance_api.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file swapchain_maintenance_api.cpp 27 | * 28 | * @brief Contains the Vulkan entrypoints for the swapchain maintenance. 29 | */ 30 | 31 | #include "swapchain_maintenance_api.hpp" 32 | #include "private_data.hpp" 33 | 34 | #include 35 | #include 36 | 37 | VWL_VKAPI_CALL(VkResult) 38 | wsi_layer_vkReleaseSwapchainImagesEXT(VkDevice device, const VkReleaseSwapchainImagesInfoEXT *pReleaseInfo) VWL_API_POST 39 | { 40 | if (pReleaseInfo == nullptr || pReleaseInfo->imageIndexCount == 0) 41 | { 42 | return VK_SUCCESS; 43 | } 44 | 45 | assert(pReleaseInfo->pImageIndices != nullptr); 46 | assert(pReleaseInfo->swapchain != VK_NULL_HANDLE); 47 | 48 | auto &device_data = layer::device_private_data::get(device); 49 | if (!device_data.layer_owns_swapchain(pReleaseInfo->swapchain)) 50 | { 51 | return device_data.disp.ReleaseSwapchainImagesEXT(device, pReleaseInfo); 52 | } 53 | 54 | auto *sc = reinterpret_cast(pReleaseInfo->swapchain); 55 | sc->release_images(pReleaseInfo->imageIndexCount, pReleaseInfo->pImageIndices); 56 | 57 | return VK_SUCCESS; 58 | } -------------------------------------------------------------------------------- /layer/swapchain_maintenance_api.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file swapchain_maintenance_api.hpp 27 | * 28 | * @brief Contains the Vulkan entrypoints for the swapchain maintenance. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include "util/macros.hpp" 35 | 36 | VWL_VKAPI_CALL(VkResult) 37 | wsi_layer_vkReleaseSwapchainImagesEXT(VkDevice device, 38 | const VkReleaseSwapchainImagesInfoEXT *pReleaseInfo) VWL_API_POST; -------------------------------------------------------------------------------- /layer/wsi_layer_experimental.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file wsi_layer_experimental.hpp 27 | * 28 | * @brief Contains the Vulkan definitions for experimental features. 29 | */ 30 | #pragma once 31 | 32 | #include 33 | #include "util/macros.hpp" 34 | 35 | #if VULKAN_WSI_LAYER_EXPERIMENTAL 36 | #define VK_KHR_present_timing 1 37 | #define VK_KHR_PRESENT_TIMING_SPEC_VERSION 1 38 | #define VK_KHR_PRESENT_TIMING_EXTENSION_NAME "VK_KHR_present_timing" 39 | 40 | #define VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT ((VkResult)(-1000208000)) 41 | #define VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT ((VkTimeDomainEXT)(1000208000)) 42 | #define VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT ((VkTimeDomainEXT)(1000208001)) 43 | #define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_TIMING_FEATURES_EXT ((VkStructureType)1000208002) 44 | #define VK_STRUCTURE_TYPE_PRESENT_TIMING_SURFACE_CAPABILITIES_EXT ((VkStructureType)1000208003) 45 | #define VK_STRUCTURE_TYPE_SWAPCHAIN_TIMING_PROPERTIES_EXT ((VkStructureType)1000208004) 46 | #define VK_STRUCTURE_TYPE_SWAPCHAIN_TIME_DOMAIN_PROPERTIES_EXT ((VkStructureType)1000208005) 47 | #define VK_STRUCTURE_TYPE_SWAPCHAIN_CALIBRATED_TIMESTAMP_INFO_EXT ((VkStructureType)1000208006) 48 | #define VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_EXT ((VkStructureType)1000208007) 49 | #define VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_PROPERTIES_EXT ((VkStructureType)1000208008) 50 | #define VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_INFO_EXT ((VkStructureType)1000208009) 51 | #define VK_STRUCTURE_TYPE_PRESENT_TIMING_INFO_EXT ((VkStructureType)1000208010) 52 | #define VK_STRUCTURE_TYPE_PRESENT_TIMINGS_INFO_EXT ((VkStructureType)1000208011) 53 | 54 | typedef VkFlags VkPresentStageFlagsEXT; 55 | 56 | typedef struct VkPhysicalDevicePresentTimingFeaturesEXT 57 | { 58 | VkStructureType sType; 59 | void *pNext; 60 | VkBool32 presentTiming; 61 | VkBool32 presentAtAbsoluteTime; 62 | VkBool32 presentAtRelativeTime; 63 | } VkPhysicalDevicePresentTimingFeaturesEXT; 64 | 65 | typedef struct VkPresentTimingSurfaceCapabilitiesEXT 66 | { 67 | VkStructureType sType; 68 | void *pNext; 69 | VkBool32 presentTimingSupported; 70 | VkBool32 presentAtAbsoluteTimeSupported; 71 | VkBool32 presentAtRelativeTimeSupported; 72 | VkPresentStageFlagsEXT presentStageQueries; 73 | VkPresentStageFlagsEXT presentStageTargets; 74 | } VkPresentTimingSurfaceCapabilitiesEXT; 75 | 76 | typedef enum VkPresentStageFlagBitsEXT 77 | { 78 | VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT = 0x00000001, 79 | VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT = 0x00000002, 80 | VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT = 0x00000004, 81 | VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT = 0x00000008, 82 | } VkPresentStageFlagBitsEXT; 83 | 84 | typedef struct VkSwapchainTimingPropertiesEXT 85 | { 86 | VkStructureType sType; 87 | const void *pNext; 88 | uint64_t refreshDuration; 89 | uint64_t variableRefreshDelay; 90 | } VkSwapchainTimingPropertiesEXT; 91 | 92 | typedef struct VkSwapchainTimeDomainPropertiesEXT 93 | { 94 | VkStructureType sType; 95 | void *pNext; 96 | uint32_t timeDomainCount; 97 | VkTimeDomainEXT *pTimeDomains; 98 | uint64_t *pTimeDomainIds; 99 | } VkSwapchainTimeDomainPropertiesEXT; 100 | 101 | typedef struct VkSwapchainCalibratedTimestampInfoEXT 102 | { 103 | VkStructureType sType; 104 | const void *pNext; 105 | VkSwapchainKHR swapchain; 106 | VkPresentStageFlagsEXT presentStage; 107 | uint64_t timeDomainId; 108 | } VkSwapchainCalibratedTimestampInfoEXT; 109 | 110 | typedef struct VkPresentStageTimeEXT 111 | { 112 | VkPresentStageFlagsEXT stage; 113 | uint64_t time; 114 | } VkPresentStageTimeEXT; 115 | 116 | typedef struct VkPastPresentationTimingEXT 117 | { 118 | VkStructureType sType; 119 | const void *pNext; 120 | uint64_t presentId; 121 | uint32_t presentStageCount; 122 | VkPresentStageTimeEXT *pPresentStages; 123 | VkTimeDomainEXT timeDomain; 124 | uint64_t timeDomainId; 125 | VkBool32 reportComplete; 126 | } VkPastPresentationTimingEXT; 127 | 128 | typedef struct VkPastPresentationTimingPropertiesEXT 129 | { 130 | VkStructureType sType; 131 | const void *pNext; 132 | uint64_t timingPropertiesCounter; 133 | uint64_t timeDomainsCounter; 134 | uint32_t presentationTimingCount; 135 | VkPastPresentationTimingEXT *pPresentationTimings; 136 | } VkPastPresentationTimingPropertiesEXT; 137 | 138 | typedef struct VkPastPresentationTimingInfoEXT 139 | { 140 | VkStructureType sType; 141 | const void *pNext; 142 | VkSwapchainKHR swapchain; 143 | } VkPastPresentationTimingInfoEXT; 144 | 145 | typedef union VkPresentTimeEXT 146 | { 147 | uint64_t targetPresentTime; 148 | uint64_t presentDuration; 149 | } VkPresentTimeEXT; 150 | 151 | typedef struct VkPresentTimingInfoEXT 152 | { 153 | VkStructureType sType; 154 | const void *pNext; 155 | VkPresentTimeEXT time; 156 | uint64_t timeDomainId; 157 | VkPresentStageFlagsEXT presentStageQueries; 158 | VkPresentStageFlagsEXT targetPresentStage; 159 | VkBool32 presentAtRelativeTime; 160 | VkBool32 presentAtNearestRefreshCycle; 161 | } VkPresentTimingInfoEXT; 162 | 163 | typedef struct VkPresentTimingsInfoEXT 164 | { 165 | VkStructureType sType; 166 | const void *pNext; 167 | uint32_t swapchainCount; 168 | const VkPresentTimingInfoEXT *pTimingInfos; 169 | } VkPresentTimingsInfoEXT; 170 | 171 | VWL_VKAPI_CALL(VkResult) 172 | wsi_layer_vkSetSwapchainPresentTimingQueueSizeEXT(VkDevice device, VkSwapchainKHR swapchain, 173 | uint32_t size) VWL_API_POST; 174 | 175 | VWL_VKAPI_CALL(VkResult) 176 | wsi_layer_vkGetSwapchainTimingPropertiesEXT(VkDevice device, VkSwapchainKHR swapchain, 177 | uint64_t *pSwapchainTimingPropertiesCounter, 178 | VkSwapchainTimingPropertiesEXT *pSwapchainTimingProperties) VWL_API_POST; 179 | VWL_VKAPI_CALL(VkResult) 180 | wsi_layer_vkGetSwapchainTimeDomainPropertiesEXT( 181 | VkDevice device, VkSwapchainKHR swapchain, uint64_t *pTimeDomainsCounter, 182 | VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties) VWL_API_POST; 183 | 184 | VWL_VKAPI_CALL(VkResult) 185 | wsi_layer_vkGetPastPresentationTimingEXT( 186 | VkDevice device, const VkPastPresentationTimingInfoEXT *pPastPresentationTimingInfo, 187 | VkPastPresentationTimingPropertiesEXT *pPastPresentationTimingProperties) VWL_API_POST; 188 | #endif 189 | -------------------------------------------------------------------------------- /util/custom_allocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020-2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "custom_allocator.hpp" 26 | #include "macros.hpp" 27 | #include 28 | 29 | namespace util 30 | { 31 | 32 | VWL_VKAPI_CALL(void *) default_allocation(void *, size_t size, size_t, VkSystemAllocationScope) VWL_API_POST 33 | { 34 | return malloc(size); 35 | } 36 | 37 | VWL_VKAPI_CALL(void *) 38 | default_reallocation(void *, void *pOriginal, size_t size, size_t, VkSystemAllocationScope) VWL_API_POST 39 | { 40 | return realloc(pOriginal, size); 41 | } 42 | 43 | VWL_VKAPI_CALL(void) default_free(void *, void *pMemory) VWL_API_POST 44 | { 45 | free(pMemory); 46 | } 47 | 48 | const allocator &allocator::get_generic() 49 | { 50 | static allocator generic{ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND, nullptr }; 51 | return generic; 52 | } 53 | 54 | allocator::allocator(const allocator &other, VkSystemAllocationScope new_scope, const VkAllocationCallbacks *callbacks) 55 | : allocator{ new_scope, callbacks == nullptr ? other.get_original_callbacks() : callbacks } 56 | { 57 | } 58 | 59 | /* If callbacks is already populated by vulkan then use those specified as default. */ 60 | allocator::allocator(VkSystemAllocationScope scope, const VkAllocationCallbacks *callbacks) 61 | { 62 | m_scope = scope; 63 | if (callbacks != nullptr) 64 | { 65 | m_callbacks = *callbacks; 66 | } 67 | else 68 | { 69 | m_callbacks = {}; 70 | m_callbacks.pfnAllocation = default_allocation; 71 | m_callbacks.pfnReallocation = default_reallocation; 72 | m_callbacks.pfnFree = default_free; 73 | } 74 | } 75 | 76 | const VkAllocationCallbacks *allocator::get_original_callbacks() const 77 | { 78 | return m_callbacks.pfnAllocation == default_allocation ? nullptr : &m_callbacks; 79 | } 80 | 81 | } /* namespace util */ 82 | -------------------------------------------------------------------------------- /util/drm/drm_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, 2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "drm_utils.hpp" 26 | #include "format_table.h" 27 | 28 | namespace util 29 | { 30 | namespace drm 31 | { 32 | 33 | uint32_t vk_to_drm_format(VkFormat vk_format) 34 | { 35 | for (size_t i = 0; i < fourcc_format_table_len; i++) 36 | { 37 | if (vk_format == fourcc_format_table[i].vk_format) 38 | { 39 | return fourcc_format_table[i].drm_format; 40 | } 41 | } 42 | 43 | for (size_t i = 0; i < srgb_fourcc_format_table_len; i++) 44 | { 45 | if (vk_format == srgb_fourcc_format_table[i].vk_format) 46 | { 47 | return srgb_fourcc_format_table[i].drm_format; 48 | } 49 | } 50 | 51 | return 0; 52 | } 53 | 54 | VkFormat drm_to_vk_format(uint32_t drm_format) 55 | { 56 | for (size_t i = 0; i < fourcc_format_table_len; i++) 57 | { 58 | if (drm_format == fourcc_format_table[i].drm_format) 59 | { 60 | return fourcc_format_table[i].vk_format; 61 | } 62 | } 63 | 64 | return VK_FORMAT_UNDEFINED; 65 | } 66 | 67 | VkFormat drm_to_vk_srgb_format(uint32_t drm_format) 68 | { 69 | for (size_t i = 0; i < srgb_fourcc_format_table_len; i++) 70 | { 71 | if (drm_format == srgb_fourcc_format_table[i].drm_format) 72 | { 73 | return srgb_fourcc_format_table[i].vk_format; 74 | } 75 | } 76 | 77 | return VK_FORMAT_UNDEFINED; 78 | } 79 | 80 | /* Returns the number of planes represented by a fourcc format. */ 81 | uint32_t drm_fourcc_format_get_num_planes(uint32_t format) 82 | { 83 | switch (format) 84 | { 85 | default: 86 | return 0; 87 | 88 | case DRM_FORMAT_RGB332: 89 | case DRM_FORMAT_BGR233: 90 | case DRM_FORMAT_XRGB4444: 91 | case DRM_FORMAT_XBGR4444: 92 | case DRM_FORMAT_RGBX4444: 93 | case DRM_FORMAT_BGRX4444: 94 | case DRM_FORMAT_ARGB4444: 95 | case DRM_FORMAT_ABGR4444: 96 | case DRM_FORMAT_RGBA4444: 97 | case DRM_FORMAT_BGRA4444: 98 | case DRM_FORMAT_XRGB1555: 99 | case DRM_FORMAT_XBGR1555: 100 | case DRM_FORMAT_RGBX5551: 101 | case DRM_FORMAT_BGRX5551: 102 | case DRM_FORMAT_ARGB1555: 103 | case DRM_FORMAT_ABGR1555: 104 | case DRM_FORMAT_RGBA5551: 105 | case DRM_FORMAT_BGRA5551: 106 | case DRM_FORMAT_RGB565: 107 | case DRM_FORMAT_BGR565: 108 | case DRM_FORMAT_RGB888: 109 | case DRM_FORMAT_BGR888: 110 | case DRM_FORMAT_XRGB8888: 111 | case DRM_FORMAT_XBGR8888: 112 | case DRM_FORMAT_RGBX8888: 113 | case DRM_FORMAT_BGRX8888: 114 | case DRM_FORMAT_ARGB8888: 115 | case DRM_FORMAT_ABGR8888: 116 | case DRM_FORMAT_RGBA8888: 117 | case DRM_FORMAT_BGRA8888: 118 | return 1; 119 | } 120 | } 121 | 122 | } // namespace drm 123 | } // namespace util 124 | -------------------------------------------------------------------------------- /util/drm/drm_utils.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, 2021-2022, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace util 30 | { 31 | namespace drm 32 | { 33 | 34 | uint32_t vk_to_drm_format(VkFormat vk_format); 35 | VkFormat drm_to_vk_format(uint32_t drm_format); 36 | VkFormat drm_to_vk_srgb_format(uint32_t drm_format); 37 | uint32_t drm_fourcc_format_get_num_planes(uint32_t format); 38 | 39 | } // namespace drm 40 | } // namespace util 41 | -------------------------------------------------------------------------------- /util/drm/format_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "format_table.h" 26 | 27 | const fmt_spec fourcc_format_table[] = { 28 | /* Supported R,G,B,A formats */ 29 | { DRM_FORMAT_RGB332, 1, { 8, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 30 | { DRM_FORMAT_BGR233, 1, { 8, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 31 | { DRM_FORMAT_XRGB4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 32 | { DRM_FORMAT_XBGR4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 33 | { DRM_FORMAT_RGBX4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 34 | { DRM_FORMAT_BGRX4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 35 | { DRM_FORMAT_ARGB4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 36 | { DRM_FORMAT_ABGR4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 37 | { DRM_FORMAT_RGBA4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_R4G4B4A4_UNORM_PACK16 }, 38 | { DRM_FORMAT_BGRA4444, 1, { 16, 0, 0, 0 }, VK_FORMAT_B4G4R4A4_UNORM_PACK16 }, 39 | { DRM_FORMAT_XRGB1555, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 40 | { DRM_FORMAT_XBGR1555, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 41 | { DRM_FORMAT_RGBX5551, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 42 | { DRM_FORMAT_BGRX5551, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 43 | { DRM_FORMAT_ARGB1555, 1, { 16, 0, 0, 0 }, VK_FORMAT_A1R5G5B5_UNORM_PACK16 }, 44 | { DRM_FORMAT_ABGR1555, 1, { 16, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 45 | { DRM_FORMAT_RGBA5551, 1, { 16, 0, 0, 0 }, VK_FORMAT_R5G5B5A1_UNORM_PACK16 }, 46 | { DRM_FORMAT_BGRA5551, 1, { 16, 0, 0, 0 }, VK_FORMAT_B5G5R5A1_UNORM_PACK16 }, 47 | { DRM_FORMAT_RGB565, 1, { 16, 0, 0, 0 }, VK_FORMAT_R5G6B5_UNORM_PACK16 }, 48 | { DRM_FORMAT_BGR565, 1, { 16, 0, 0, 0 }, VK_FORMAT_B5G6R5_UNORM_PACK16 }, 49 | { DRM_FORMAT_RGB888, 1, { 24, 0, 0, 0 }, VK_FORMAT_B8G8R8_UNORM }, 50 | { DRM_FORMAT_BGR888, 1, { 24, 0, 0, 0 }, VK_FORMAT_R8G8B8_UNORM }, 51 | { DRM_FORMAT_XRGB8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 52 | { DRM_FORMAT_XBGR8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 53 | { DRM_FORMAT_RGBX8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 54 | { DRM_FORMAT_BGRX8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 55 | { DRM_FORMAT_ARGB8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_B8G8R8A8_UNORM }, 56 | { DRM_FORMAT_ABGR8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_R8G8B8A8_UNORM }, 57 | { DRM_FORMAT_RGBA8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 58 | { DRM_FORMAT_BGRA8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_UNDEFINED }, 59 | }; 60 | 61 | const fmt_spec srgb_fourcc_format_table[] = { 62 | { DRM_FORMAT_ARGB8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_B8G8R8A8_SRGB }, 63 | { DRM_FORMAT_ABGR8888, 1, { 32, 0, 0, 0 }, VK_FORMAT_R8G8B8A8_SRGB }, 64 | }; 65 | 66 | const size_t fourcc_format_table_len = NELEMS(fourcc_format_table); 67 | const size_t srgb_fourcc_format_table_len = NELEMS(srgb_fourcc_format_table); 68 | -------------------------------------------------------------------------------- /util/drm/format_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include "wsialloc.h" 30 | 31 | /* Define DRM linear modifier for compatibility with older DRM header versions. */ 32 | #ifndef DRM_FORMAT_MOD_LINEAR 33 | #define DRM_FORMAT_MOD_LINEAR 0 34 | #endif 35 | 36 | #define NELEMS(x) (sizeof(x) / sizeof(x[0])) 37 | 38 | typedef struct fmt_spec 39 | { 40 | uint32_t drm_format; 41 | uint32_t nr_planes; 42 | uint8_t bpp[WSIALLOC_MAX_PLANES]; 43 | VkFormat vk_format; 44 | } fmt_spec; 45 | 46 | extern const fmt_spec fourcc_format_table[]; 47 | extern const fmt_spec srgb_fourcc_format_table[]; 48 | 49 | extern size_t const fourcc_format_table_len; 50 | extern size_t const srgb_fourcc_format_table_len; 51 | -------------------------------------------------------------------------------- /util/extension_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, 2021-2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "extension_list.hpp" 26 | #include "util/custom_allocator.hpp" 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace util 33 | { 34 | 35 | extension_list::extension_list(const util::allocator &allocator) 36 | : m_alloc{ allocator } 37 | , m_ext_props(allocator) 38 | { 39 | } 40 | 41 | VkResult extension_list::add(const char *const *extensions, size_t count) 42 | { 43 | auto initial_size = m_ext_props.size(); 44 | if (!m_ext_props.try_resize(initial_size + count)) 45 | { 46 | return VK_ERROR_OUT_OF_HOST_MEMORY; 47 | } 48 | 49 | for (size_t i = 0; i < count; i++) 50 | { 51 | auto &dst = m_ext_props[initial_size + i]; 52 | 53 | const size_t len = strlen(extensions[i]); 54 | bool success = false; 55 | if (len < sizeof(dst.extensionName)) 56 | { 57 | int chars_printed = snprintf(dst.extensionName, len + 1, "%s", extensions[i]); 58 | if (chars_printed >= 0 && static_cast(chars_printed) == len) 59 | { 60 | success = true; 61 | } 62 | } 63 | 64 | if (!success) 65 | { 66 | abort(); 67 | } 68 | } 69 | return VK_SUCCESS; 70 | } 71 | 72 | VkResult extension_list::add(const char *const *extensions, size_t count, const char *const *extensions_subset, 73 | size_t subset_count) 74 | { 75 | util::vector extensions_to_add(m_alloc); 76 | for (size_t ext_index = 0; ext_index < count; ++ext_index) 77 | { 78 | for (size_t subset_index = 0; subset_index < subset_count; ++subset_index) 79 | { 80 | if (!strcmp(extensions[ext_index], extensions_subset[subset_index])) 81 | { 82 | if (!extensions_to_add.try_push_back(extensions[ext_index])) 83 | { 84 | return VK_ERROR_OUT_OF_HOST_MEMORY; 85 | } 86 | } 87 | } 88 | } 89 | 90 | VkResult result = add(extensions_to_add.data(), extensions_to_add.size()); 91 | if (result != VK_SUCCESS) 92 | { 93 | return result; 94 | } 95 | 96 | return VK_SUCCESS; 97 | } 98 | 99 | VkResult extension_list::add(VkExtensionProperties ext_prop) 100 | { 101 | if (!contains(ext_prop.extensionName)) 102 | { 103 | if (!m_ext_props.try_push_back(ext_prop)) 104 | { 105 | return VK_ERROR_OUT_OF_HOST_MEMORY; 106 | } 107 | } 108 | return VK_SUCCESS; 109 | } 110 | 111 | VkResult extension_list::add(const VkExtensionProperties *props, size_t count) 112 | { 113 | auto initial_size = m_ext_props.size(); 114 | if (!m_ext_props.try_resize(initial_size + count)) 115 | { 116 | return VK_ERROR_OUT_OF_HOST_MEMORY; 117 | } 118 | for (size_t i = 0; i < count; i++) 119 | { 120 | m_ext_props[initial_size + i] = props[i]; 121 | } 122 | return VK_SUCCESS; 123 | } 124 | 125 | VkResult extension_list::add(const extension_list &ext_list) 126 | { 127 | util::vector ext_vect{ m_alloc }; 128 | VkResult result = ext_list.get_extension_strings(ext_vect); 129 | if (result != VK_SUCCESS) 130 | { 131 | return result; 132 | } 133 | return add(ext_vect.data(), ext_vect.size()); 134 | } 135 | 136 | VkResult extension_list::get_extension_strings(util::vector &out) const 137 | { 138 | size_t old_size = out.size(); 139 | size_t new_size = old_size + m_ext_props.size(); 140 | if (!out.try_resize(new_size)) 141 | { 142 | return VK_ERROR_OUT_OF_HOST_MEMORY; 143 | } 144 | 145 | for (size_t i = old_size; i < new_size; i++) 146 | { 147 | out[i] = m_ext_props[i - old_size].extensionName; 148 | } 149 | return VK_SUCCESS; 150 | } 151 | 152 | bool extension_list::contains(const extension_list &req) const 153 | { 154 | for (const auto &req_ext : req.m_ext_props) 155 | { 156 | if (!contains(req_ext.extensionName)) 157 | { 158 | return false; 159 | } 160 | } 161 | return true; 162 | } 163 | 164 | bool extension_list::contains(const char *extension_name) const 165 | { 166 | for (const auto &p : m_ext_props) 167 | { 168 | if (strcmp(p.extensionName, extension_name) == 0) 169 | { 170 | return true; 171 | } 172 | } 173 | return false; 174 | } 175 | 176 | void extension_list::remove(const char *ext) 177 | { 178 | m_ext_props.erase(std::remove_if(m_ext_props.begin(), m_ext_props.end(), [&ext](VkExtensionProperties ext_prop) { 179 | return (strcmp(ext_prop.extensionName, ext) == 0); 180 | })); 181 | } 182 | } // namespace util 183 | -------------------------------------------------------------------------------- /util/extension_list.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, 2021-2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | #pragma once 25 | 26 | #include "custom_allocator.hpp" 27 | #include "helpers.hpp" 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | namespace util 35 | { 36 | 37 | /** 38 | * @brief A helper class for storing a vector of extension names 39 | * 40 | * @note This class does not store the extension versions. 41 | */ 42 | class extension_list : private noncopyable 43 | { 44 | public: 45 | extension_list(const util::allocator &allocator); 46 | 47 | /** 48 | * @brief Get the allocator used to manage the memory of this object. 49 | */ 50 | const util::allocator get_allocator() const 51 | { 52 | return m_alloc; 53 | } 54 | 55 | /** 56 | * @brief Append pointers to extension strings to the given vector. 57 | * 58 | * @warning Pointers in the vector are referring to string allocated in this extension_list and will become invalid 59 | * if the extension_list is modified (e.g. by adding/removing elements.) 60 | * 61 | * @param[out] out A vector of C strings to which all extension are appended. 62 | * 63 | * @return Indicates whether the operation was successful. If this is @c VK_ERROR_OUT_OF_HOST_MEMORY, 64 | * then @p out is unmodified. 65 | */ 66 | VkResult get_extension_strings(util::vector &out) const; 67 | 68 | /** 69 | * @brief Check if this extension list contains all the extensions listed in req. 70 | */ 71 | bool contains(const extension_list &req) const; 72 | 73 | /** 74 | * @brief Check if this extension list contains the extension specified by ext. 75 | */ 76 | bool contains(const char *ext) const; 77 | 78 | /** 79 | * @brief Remove an extension from a extension list 80 | */ 81 | void remove(const char *ext); 82 | 83 | VkResult add(VkExtensionProperties ext_prop); 84 | VkResult add(const VkExtensionProperties *props, size_t count); 85 | VkResult add(const extension_list &ext_list); 86 | VkResult add(const char *const *extensions, size_t count); 87 | 88 | VkResult add(const char *extension) 89 | { 90 | return add(&extension, 1); 91 | } 92 | 93 | /** 94 | * @brief Perform intersection between extensions and add them to the list. 95 | * 96 | * Adds the extensions from @p extensions that are also part of @p extensions_subset. 97 | * 98 | * @param extensions A list with the names of the extensions to be added. 99 | * @param count Length of the extensions list. 100 | * @param extensions_subset A list with the names of the target extensions. 101 | * @param subset_count Length of the target list. 102 | * 103 | * @return VK_SUCCESS on success, otherwise an error. 104 | */ 105 | VkResult add(const char *const *extensions, size_t count, const char *const *extensions_subset, size_t subset_count); 106 | 107 | private: 108 | util::allocator m_alloc; 109 | 110 | /** 111 | * @note We are using VkExtensionProperties to store the extension name only 112 | */ 113 | util::vector m_ext_props; 114 | }; 115 | } // namespace util 116 | -------------------------------------------------------------------------------- /util/file_descriptor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file 27 | * 28 | * @brief Contains the defintions of file descriptor utilities. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include 35 | 36 | #include "helpers.hpp" 37 | 38 | namespace util 39 | { 40 | 41 | /** 42 | * Manages a POSIX file descriptor. 43 | */ 44 | class fd_owner : private noncopyable 45 | { 46 | public: 47 | fd_owner() = default; 48 | fd_owner(int fd) 49 | : fd_handle{ fd } 50 | { 51 | } 52 | 53 | fd_owner(fd_owner &&rhs) 54 | { 55 | *this = std::move(rhs); 56 | } 57 | 58 | fd_owner &operator=(fd_owner &&rhs) 59 | { 60 | std::swap(fd_handle, rhs.fd_handle); 61 | return *this; 62 | } 63 | 64 | ~fd_owner() 65 | { 66 | if (is_valid()) 67 | { 68 | close(fd_handle); 69 | } 70 | } 71 | 72 | int get() const 73 | { 74 | return fd_handle; 75 | } 76 | 77 | bool is_valid() const 78 | { 79 | return fd_handle >= 0; 80 | } 81 | 82 | private: 83 | int fd_handle{ -1 }; 84 | }; 85 | 86 | } /* namespace util */ 87 | -------------------------------------------------------------------------------- /util/format_modifiers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "format_modifiers.hpp" 26 | #include "layer/private_data.hpp" 27 | 28 | namespace util 29 | { 30 | 31 | VkResult get_drm_format_properties(VkPhysicalDevice physical_device, VkFormat format, 32 | util::vector &format_props_list) 33 | { 34 | auto &instance_data = layer::instance_private_data::get(physical_device); 35 | 36 | VkDrmFormatModifierPropertiesListEXT format_modifier_props = {}; 37 | format_modifier_props.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT; 38 | 39 | VkFormatProperties2KHR format_props = {}; 40 | format_props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR; 41 | format_props.pNext = &format_modifier_props; 42 | 43 | instance_data.disp.GetPhysicalDeviceFormatProperties2KHR(physical_device, format, &format_props); 44 | 45 | if (!format_props_list.try_resize(format_modifier_props.drmFormatModifierCount)) 46 | { 47 | return VK_ERROR_OUT_OF_HOST_MEMORY; 48 | } 49 | 50 | format_modifier_props.pDrmFormatModifierProperties = format_props_list.data(); 51 | instance_data.disp.GetPhysicalDeviceFormatProperties2KHR(physical_device, format, &format_props); 52 | return VK_SUCCESS; 53 | } 54 | } /* namespace util */ 55 | -------------------------------------------------------------------------------- /util/format_modifiers.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include "custom_allocator.hpp" 29 | 30 | namespace util 31 | { 32 | 33 | /** 34 | * @brief Get the properties a format has when combined with a DRM modifier. 35 | * 36 | * @param physical_device The physical device 37 | * @param format The target format. 38 | * @param[out] format_props_list A vector which will store the supported properties 39 | * for every modifier. 40 | * 41 | * @return VK_SUCCESS on success. VK_ERROR_OUT_OF_HOST_MEMORY is returned when 42 | * the host gets out of memory. 43 | */ 44 | VkResult get_drm_format_properties(VkPhysicalDevice physical_device, VkFormat format, 45 | util::vector &format_props_list); 46 | 47 | } /* namespace util */ 48 | -------------------------------------------------------------------------------- /util/helpers.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2022, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file helpers.hpp 27 | * 28 | * @brief Contains common utility functions used across the project. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include "log.hpp" 35 | 36 | /* 37 | * Conditional return statement. This allows functions to return early for 38 | * failing Vulkan commands with a terse syntax. 39 | * 40 | * Example usage: 41 | * 42 | * VkResult foo() 43 | * { 44 | * TRY(vkCommand()); 45 | * return VK_SUCCESS; 46 | * } 47 | * 48 | * The above is equivalent to: 49 | * 50 | * VkResult foo() 51 | * { 52 | * VkResult result = vkCommand(); 53 | * if (result != VK_SUCCESS) 54 | * { 55 | * return result; 56 | * } 57 | * return VK_SUCCESS; 58 | * } 59 | */ 60 | #define TRY_HANDLER(expression, do_log, ...) \ 61 | do \ 62 | { \ 63 | VkResult try_result = expression; \ 64 | if (try_result != VK_SUCCESS) \ 65 | { \ 66 | if (do_log) \ 67 | { \ 68 | WSI_LOG_ERROR(__VA_ARGS__); \ 69 | } \ 70 | return try_result; \ 71 | } \ 72 | } while (0) 73 | 74 | #define TRY(expression) TRY_HANDLER(expression, false, "PLACEHOLDER") 75 | #define TRY_LOG_CALL(expression) TRY_HANDLER(expression, true, #expression) 76 | #define TRY_LOG(expression, ...) TRY_HANDLER(expression, true, __VA_ARGS__) 77 | 78 | namespace util 79 | { 80 | template 81 | const T *find_extension(VkStructureType sType, const void *pNext) 82 | { 83 | auto entry = reinterpret_cast(pNext); 84 | while (entry && entry->sType != sType) 85 | { 86 | entry = entry->pNext; 87 | } 88 | return reinterpret_cast(entry); 89 | } 90 | 91 | template 92 | T *find_extension(VkStructureType sType, void *pNext) 93 | { 94 | auto entry = reinterpret_cast(pNext); 95 | while (entry && entry->sType != sType) 96 | { 97 | entry = entry->pNext; 98 | } 99 | return reinterpret_cast(entry); 100 | } 101 | 102 | template 103 | inline T shallow_copy_extension(const T *structure_to_copy) 104 | { 105 | T shallow_copy = *structure_to_copy; 106 | shallow_copy.pNext = nullptr; 107 | 108 | return shallow_copy; 109 | } 110 | 111 | class noncopyable 112 | { 113 | protected: 114 | noncopyable() = default; 115 | ~noncopyable() = default; 116 | 117 | private: 118 | noncopyable(const noncopyable &) = delete; 119 | noncopyable &operator=(const noncopyable &) = delete; 120 | }; 121 | 122 | static constexpr uint32_t MAX_PLANES = 4; 123 | 124 | /** 125 | * @brief Helper variable for plane image aspect flag bits. 126 | */ 127 | const VkImageAspectFlagBits PLANE_FLAG_BITS[MAX_PLANES] = { 128 | VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, 129 | VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT, 130 | VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT, 131 | VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT, 132 | }; 133 | 134 | } // namespace util 135 | -------------------------------------------------------------------------------- /util/log.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2023 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "log.hpp" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | namespace util 35 | { 36 | 37 | #ifndef NDEBUG 38 | 39 | /** 40 | * @brief check if a log level is enabled, and print it 41 | */ 42 | static bool check_and_print_log_level(int level) 43 | { 44 | struct log_state 45 | { 46 | int level = WSI_DEFAULT_LOG_LEVEL; 47 | log_state() 48 | { 49 | if (const char *env = std::getenv("VULKAN_WSI_DEBUG_LEVEL")) 50 | { 51 | std::from_chars(env, env + std::strlen(env), level); 52 | } 53 | } 54 | }; 55 | static log_state state; 56 | 57 | bool result = level <= state.level; 58 | if (result) 59 | { 60 | switch (level) 61 | { 62 | case 0: 63 | /* Reserved for no logging */ 64 | break; 65 | case 1: 66 | std::fprintf(stderr, "ERROR"); 67 | break; 68 | case 2: 69 | std::fprintf(stderr, "WARNING"); 70 | break; 71 | case 3: 72 | std::fprintf(stderr, "INFO"); 73 | break; 74 | default: 75 | std::fprintf(stderr, "LEVEL_%d", level); 76 | break; 77 | } 78 | } 79 | return result; 80 | } 81 | 82 | void wsi_log_message(int level, const char *file, int line, const char *format, ...) 83 | { 84 | if (check_and_print_log_level(level)) 85 | { 86 | std::fprintf(stderr, "(%s:%d): ", file, line); 87 | std::va_list args; 88 | va_start(args, format); 89 | std::vfprintf(stderr, format, args); 90 | va_end(args); 91 | std::putc('\n', stderr); 92 | } 93 | } 94 | 95 | #endif 96 | 97 | } /* namespace util */ 98 | -------------------------------------------------------------------------------- /util/log.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2023 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | namespace util 27 | { 28 | #define WSI_DEFAULT_LOG_LEVEL 1 29 | 30 | /** 31 | * @brief Log a message to a certain log level 32 | * 33 | * @details For the log level, we use a bigger integer to represent an increased 34 | * level of verbosity. If this is not specified, the log level is default to 1. 35 | * We use a "staircase" approach with respect to printing logs. We print all log 36 | * messages equal or below the log level set, e.g. if VULKAN_WSI_DEBUG_LEVEL 37 | * is set to 2, messages with log level 1 and 2 are printed. Please note that 38 | * the newline character '\n' is automatically appended. 39 | * 40 | * @param[in] level The log level of this message, you can set an arbitary 41 | * integer however please refer to the included macros for 42 | * the sensible defaults. 43 | * @param[in] file The source file name (``__FILE__``) 44 | * @param[in] line The source file line number (``__LINE__``) 45 | * @param[in] format A C-style formatting string. 46 | */ 47 | 48 | void wsi_log_message(int level, const char *file, int line, const char *format, ...) 49 | #ifdef __GNUC__ 50 | __attribute__((format(printf, 4, 5))) 51 | #endif 52 | ; 53 | 54 | #ifdef NDEBUG 55 | static constexpr bool wsi_log_enable = false; 56 | #else 57 | static constexpr bool wsi_log_enable = true; 58 | #endif 59 | 60 | #define WSI_LOG(level, ...) \ 61 | do \ 62 | { \ 63 | if (::util::wsi_log_enable) \ 64 | ::util::wsi_log_message(level, __FILE__, __LINE__, __VA_ARGS__); \ 65 | } while (0) 66 | 67 | #define WSI_LOG_ERROR(...) WSI_LOG(1, __VA_ARGS__) 68 | #define WSI_LOG_WARNING(...) WSI_LOG(2, __VA_ARGS__) 69 | #define WSI_LOG_INFO(...) WSI_LOG(3, __VA_ARGS__) 70 | 71 | } /* namespace util */ 72 | -------------------------------------------------------------------------------- /util/macros.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, 2023-2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file macros.hpp 27 | * 28 | * @brief Contains useful utility macros used across the project. 29 | */ 30 | #include 31 | 32 | /* 33 | * Macros that are used to mark functions signatures. 34 | * 35 | * VWL_VKAPI_CALL - Replaces the return type of the function. Use to mark functions to use the expected 36 | * Vulkan calling conventions. 37 | * VWL_CAPI_CALL - Replaces the return type of the function. Use to mark other non-Vulkan functions 38 | * that should use the C calling convention, such as callbacks implemented in C++ that 39 | * are used by C code. 40 | * VWL_API_POST - Placed at the end of the function signature. These will typically be 41 | * functions that need to be callable from C. 42 | * VWL_VKAPI_EXPORT - Marks that the symbol should use the "default" visibility 43 | */ 44 | #define VWL_VKAPI_CALL(ret_type) extern "C" VKAPI_ATTR ret_type VKAPI_CALL 45 | #define VWL_CAPI_CALL(ret_type) extern "C" ret_type 46 | #define VWL_API_POST noexcept 47 | 48 | #if defined(__GNUC__) && __GNUC__ >= 4 49 | #define VWL_VKAPI_EXPORT __attribute__((visibility("default"))) 50 | #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) 51 | #define VWL_VKAPI_EXPORT __attribute__((visibility("default"))) 52 | #else 53 | #define VWL_VKAPI_EXPORT 54 | #endif 55 | 56 | /* Unused parameter macro */ 57 | #define UNUSED(x) ((void)(x)) -------------------------------------------------------------------------------- /util/platform_set.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace util 33 | { 34 | 35 | /** 36 | * @brief Set of WSI platforms. 37 | * @note This could be implemented via std::unordered_set, but would require handling allocation callbacks and would 38 | * therefore be less convenient to use. Instead, we can store all info in the bits of uint64_t. 39 | */ 40 | class wsi_platform_set 41 | { 42 | public: 43 | void add(VkIcdWsiPlatform p) 44 | { 45 | m_platforms |= (static_cast(1) << to_int(p)); 46 | } 47 | 48 | bool contains(VkIcdWsiPlatform p) const 49 | { 50 | return (m_platforms & (static_cast(1) << to_int(p))) != 0; 51 | } 52 | 53 | bool empty() const 54 | { 55 | return m_platforms == 0; 56 | } 57 | 58 | private: 59 | /** 60 | * @brief Convert a VkIcdWsiPlatform to an integer between 0-63. 61 | */ 62 | static int to_int(VkIcdWsiPlatform p) 63 | { 64 | assert(static_cast(p) >= 0 && static_cast(p) < 64); 65 | return static_cast(p); 66 | } 67 | 68 | uint64_t m_platforms = 0; 69 | }; 70 | 71 | } /* namespace util */ 72 | -------------------------------------------------------------------------------- /util/ring_buffer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace util 30 | { 31 | 32 | template 33 | class ring_buffer 34 | { 35 | public: 36 | /** 37 | * @brief Return maximum capacity of the ring buffer. 38 | */ 39 | constexpr std::size_t capacity() 40 | { 41 | return N; 42 | } 43 | 44 | /** 45 | * @brief Return current size of the ring buffer. 46 | */ 47 | std::size_t size() const 48 | { 49 | return m_size; 50 | } 51 | 52 | /** 53 | * @brief Places item into next slot of the ring buffer. 54 | * @return Boolean to indicate success or failure. 55 | */ 56 | template 57 | bool push_back(U &&item) 58 | { 59 | if (size() == capacity()) 60 | { 61 | return false; 62 | } 63 | 64 | m_data[(m_begin + m_size) % N].emplace(std::forward(item)); 65 | ++m_size; 66 | 67 | return true; 68 | } 69 | 70 | /** 71 | * @brief Gets a pointer to the item at the starting index of the ring buffer. 72 | */ 73 | T *front() 74 | { 75 | return get(m_begin); 76 | } 77 | 78 | /** 79 | * @brief Gets a pointer to the item that was last placed into the ring buffer. 80 | */ 81 | T *back() 82 | { 83 | return get((m_begin + m_size + N - 1) % N); 84 | } 85 | 86 | /** 87 | * @brief Pop the front of the ring buffer. 88 | * 89 | * Item at the starting index of the ring buffer is returned. The slot is subsequently emptied. The starting index of 90 | * the ring buffer increments by 1. 91 | * 92 | * @return Item wrapped in an optional. 93 | */ 94 | std::optional pop_front() 95 | { 96 | if (size() == 0) 97 | { 98 | return std::nullopt; 99 | } 100 | 101 | std::optional value = std::move(m_data[m_begin]); 102 | 103 | m_begin = (m_begin + 1) % N; 104 | --m_size; 105 | 106 | return value; 107 | } 108 | 109 | private: 110 | T *get(std::size_t index) 111 | { 112 | if (m_data[index].has_value()) 113 | { 114 | return std::addressof(m_data[index].value()); 115 | } 116 | else 117 | { 118 | return nullptr; 119 | } 120 | } 121 | 122 | std::array, N> m_data{}; 123 | 124 | // Marks the start index of the ring buffer. 125 | std::size_t m_begin{}; 126 | 127 | // The number of entries in the ring buffer from the start index. 128 | std::size_t m_size{}; 129 | }; 130 | 131 | } /* namespace util */ 132 | -------------------------------------------------------------------------------- /util/timed_semaphore.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2019, 2021-2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include "timed_semaphore.hpp" 29 | 30 | namespace util 31 | { 32 | 33 | VkResult timed_semaphore::init(unsigned count) 34 | { 35 | int res; 36 | 37 | m_count = count; 38 | 39 | pthread_condattr_t attr; 40 | res = pthread_condattr_init(&attr); 41 | /* the only failure that can occur is ENOMEM */ 42 | assert(res == 0 || res == ENOMEM); 43 | if (res != 0) 44 | { 45 | return VK_ERROR_OUT_OF_HOST_MEMORY; 46 | } 47 | 48 | res = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 49 | /* only programming error can cause _setclock to fail */ 50 | assert(res == 0); 51 | 52 | res = pthread_cond_init(&m_cond, &attr); 53 | /* the only failure that can occur that is not programming error is ENOMEM */ 54 | assert(res == 0 || res == ENOMEM); 55 | if (res != 0) 56 | { 57 | res = pthread_condattr_destroy(&attr); 58 | assert(res == 0); 59 | return VK_ERROR_OUT_OF_HOST_MEMORY; 60 | } 61 | 62 | res = pthread_condattr_destroy(&attr); 63 | /* only programming error can cause _destroy to fail */ 64 | assert(res == 0); 65 | 66 | res = pthread_mutex_init(&m_mutex, nullptr); 67 | /* only programming errors can result in failure */ 68 | assert(res == 0); 69 | 70 | initialized = true; 71 | 72 | return VK_SUCCESS; 73 | } 74 | 75 | timed_semaphore::~timed_semaphore() 76 | { 77 | int res; 78 | (void)res; /* unused when NDEBUG */ 79 | 80 | if (initialized) 81 | { 82 | res = pthread_cond_destroy(&m_cond); 83 | assert(res == 0); /* only programming error (EBUSY, EINVAL) */ 84 | 85 | res = pthread_mutex_destroy(&m_mutex); 86 | assert(res == 0); /* only programming error (EBUSY, EINVAL) */ 87 | } 88 | } 89 | 90 | VkResult timed_semaphore::wait(uint64_t timeout) 91 | { 92 | VkResult retval = VK_SUCCESS; 93 | int res; 94 | 95 | assert(initialized); 96 | 97 | res = pthread_mutex_lock(&m_mutex); 98 | assert(res == 0); /* only fails with programming error (EINVAL) */ 99 | 100 | if (m_count == 0) 101 | { 102 | switch (timeout) 103 | { 104 | case 0: 105 | retval = VK_NOT_READY; 106 | break; 107 | case UINT64_MAX: 108 | res = pthread_cond_wait(&m_cond, &m_mutex); 109 | assert(res == 0); /* only fails with programming error (EINVAL) */ 110 | 111 | break; 112 | default: 113 | struct timespec diff = { /* narrowing casts */ 114 | static_cast(timeout / (1000 * 1000 * 1000)), 115 | static_cast(timeout % (1000 * 1000 * 1000)) 116 | }; 117 | 118 | struct timespec now = {}; 119 | res = clock_gettime(CLOCK_MONOTONIC, &now); 120 | assert(res == 0); /* only fails with programming error (EINVAL, EFAULT, EPERM) */ 121 | 122 | /* add diff to now, handling overflow */ 123 | struct timespec end = { now.tv_sec + diff.tv_sec, now.tv_nsec + diff.tv_nsec }; 124 | 125 | if (end.tv_nsec >= 1000 * 1000 * 1000) 126 | { 127 | end.tv_nsec -= 1000 * 1000 * 1000; 128 | end.tv_sec++; 129 | } 130 | 131 | res = pthread_cond_timedwait(&m_cond, &m_mutex, &end); 132 | /* only fails with programming error, other than timeout */ 133 | assert(res == 0 || res == ETIMEDOUT); 134 | if (res != 0) 135 | { 136 | retval = VK_TIMEOUT; 137 | } 138 | } 139 | } 140 | if (retval == VK_SUCCESS) 141 | { 142 | assert(m_count > 0); 143 | m_count--; 144 | } 145 | res = pthread_mutex_unlock(&m_mutex); 146 | assert(res == 0); /* only fails with programming error (EPERM) */ 147 | 148 | return retval; 149 | } 150 | 151 | void timed_semaphore::post() 152 | { 153 | int res; 154 | (void)res; /* unused when NDEBUG */ 155 | 156 | assert(initialized); 157 | 158 | res = pthread_mutex_lock(&m_mutex); 159 | assert(res == 0); /* only fails with programming error (EINVAL) */ 160 | 161 | m_count++; 162 | 163 | res = pthread_cond_signal(&m_cond); 164 | assert(res == 0); /* only fails with programming error (EINVAL) */ 165 | 166 | res = pthread_mutex_unlock(&m_mutex); 167 | assert(res == 0); /* only fails with programming error (EPERM) */ 168 | } 169 | 170 | } /* namespace util */ 171 | -------------------------------------------------------------------------------- /util/timed_semaphore.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2019, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file timed_semaphore.hpp 27 | * 28 | * @brief Contains the class definition for a semaphore with a relative timedwait 29 | * 30 | * sem_timedwait takes an absolute time, based on CLOCK_REALTIME. Simply 31 | * taking the current time and adding on a relative timeout is not correct, 32 | * as the system time may change, resulting in an incorrect timeout period 33 | * (potentially by a significant amount). 34 | * 35 | * We therefore have to re-engineer semaphores using condition variables. 36 | * 37 | * This code does not use the C++ standard library to avoid exceptions. 38 | */ 39 | 40 | #pragma once 41 | 42 | extern "C" { 43 | #include 44 | } 45 | 46 | #include 47 | #include "helpers.hpp" 48 | 49 | namespace util 50 | { 51 | 52 | /** 53 | * brief semaphore with a safe relative timed wait 54 | * 55 | * sem_timedwait takes an absolute time, based on CLOCK_REALTIME. Simply 56 | * taking the current time and adding on a relative timeout is not correct, 57 | * as the system time may change, resulting in an incorrect timeout period 58 | * (potentially by a significant amount). 59 | * 60 | * We therefore have to re-engineer semaphores using condition variables. 61 | * 62 | * This code does not use the C++ standard library to avoid exceptions. 63 | */ 64 | class timed_semaphore : private noncopyable 65 | { 66 | public: 67 | ~timed_semaphore(); 68 | timed_semaphore() 69 | : initialized(false){}; 70 | 71 | /** 72 | * @brief initializes the semaphore 73 | * 74 | * @param count initial value of the semaphore 75 | * @retval VK_ERROR_OUT_OF_HOST_MEMORY out of memory condition from pthread calls 76 | * @retval VK_SUCCESS on success 77 | */ 78 | VkResult init(unsigned count); 79 | 80 | /** 81 | * @brief decrement semaphore, waiting (with timeout) if the value is 0 82 | * 83 | * @param timeout time to wait (ns). 0 doesn't block, UINT64_MAX waits indefinately. 84 | * @retval VK_TIMEOUT timeout was non-zero and reached the timeout 85 | * @retval VK_NOT_READY timeout was zero and count is 0 86 | * @retval VK_SUCCESS on success 87 | */ 88 | VkResult wait(uint64_t timeout); 89 | 90 | /** 91 | * @brief increment semaphore, potentially unblocking a waiting thread 92 | */ 93 | void post(); 94 | 95 | private: 96 | /** 97 | * @brief true if the semaphore has been initialized 98 | * 99 | * Determines if the destructor should cleanup the mutex and cond. 100 | */ 101 | bool initialized; 102 | /** 103 | * @brief semaphore value 104 | */ 105 | unsigned m_count; 106 | 107 | pthread_mutex_t m_mutex; 108 | pthread_cond_t m_cond; 109 | }; 110 | 111 | } /* namespace util */ 112 | -------------------------------------------------------------------------------- /util/unordered_map.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2022, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | #include "custom_allocator.hpp" 30 | #include "helpers.hpp" 31 | 32 | namespace util 33 | { 34 | /** 35 | * @brief This utility class has the same purpose as std::unordered_map, but 36 | * ensures that the operations that could result in out of memory 37 | * exceptions don't throw them and also ensures that the memory can 38 | * only be allocated by an custom_allocator. 39 | */ 40 | template , typename Comparator = std::equal_to, 41 | typename Allocator = util::custom_allocator>> 42 | class unordered_map : public std::unordered_map, private noncopyable 43 | { 44 | using base = std::unordered_map; 45 | using size_type = typename base::size_type; 46 | using iterator = typename base::iterator; 47 | 48 | public: 49 | /** 50 | * Delete all member functions that can cause allocation failure by throwing std::bad_alloc. 51 | */ 52 | Value &operator[](const Key &key) = delete; 53 | Value &operator[](Key &&key) = delete; 54 | 55 | void insert() = delete; 56 | void emplace() = delete; 57 | void emplace_hint() = delete; 58 | void reserve() = delete; 59 | void rehash() = delete; 60 | 61 | /** 62 | * @brief Construct a new unordered map object with a custom allocator. 63 | * 64 | * @param allocator The allocator that will be used. 65 | */ 66 | explicit unordered_map(util::custom_allocator> allocator) 67 | : base(allocator) 68 | { 69 | } 70 | 71 | /** 72 | * @brief Like std::unordered_map.insert but doesn't throw on out of memory errors. 73 | * 74 | * @param value The value to insert in the map. 75 | * @return std::optional> If successful, the optional will 76 | * contain the same return value as from std::unordered_map.insert, otherwise 77 | * if out of memory, the function returns std::nullopt. 78 | */ 79 | std::optional> try_insert(const std::pair &value) 80 | { 81 | try 82 | { 83 | return { base::insert(value) }; 84 | } 85 | catch (std::bad_alloc &e) 86 | { 87 | return std::nullopt; 88 | } 89 | } 90 | 91 | /** 92 | * @brief Like std::unordered_map.reserve but doesn't throw on out of memory errors. 93 | * 94 | * @param size The new capacity of the container. Same as std::unordered_map.reserve. 95 | * @return true If the container was resized successfuly. 96 | * @return false If the host has run out of memory 97 | */ 98 | bool try_reserve(size_type size) 99 | { 100 | try 101 | { 102 | base::reserve(size); 103 | return true; 104 | } 105 | catch (std::bad_alloc &e) 106 | { 107 | return false; 108 | } 109 | } 110 | 111 | /** 112 | * @brief Like std::unordered_map.rehash but doesn't throw on out of memory errors. 113 | * 114 | * @param count Number of buckets. Same as std::unordered_map.rehash. 115 | * @return true If the container was rehashed successfuly. 116 | * @return false If the host has run out of memory 117 | */ 118 | bool try_rehash(size_type count) 119 | { 120 | try 121 | { 122 | base::rehash(count); 123 | return true; 124 | } 125 | catch (std::bad_alloc &e) 126 | { 127 | return false; 128 | } 129 | } 130 | }; 131 | } /* namespace util */ 132 | -------------------------------------------------------------------------------- /util/unordered_set.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2022, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | #include "custom_allocator.hpp" 30 | #include "helpers.hpp" 31 | 32 | namespace util 33 | { 34 | /** 35 | * @brief This utility class has the same purpose as std::unordered_set, but 36 | * ensures that the operations that could result in out of memory 37 | * exceptions don't throw them and also ensures that the memory can 38 | * only be allocated by an custom_allocator. 39 | */ 40 | template , typename Comparator = std::equal_to, 41 | typename Allocator = util::custom_allocator> 42 | class unordered_set : public std::unordered_set, private noncopyable 43 | { 44 | using value_type = Key; 45 | using base = std::unordered_set; 46 | using size_type = typename base::size_type; 47 | using iterator = typename base::iterator; 48 | 49 | public: 50 | /** 51 | * Delete all member functions that can cause allocation failure by throwing std::bad_alloc. 52 | */ 53 | void insert() = delete; 54 | void emplace() = delete; 55 | void emplace_hint() = delete; 56 | void rehash() = delete; 57 | void reserve() = delete; 58 | 59 | /** 60 | * @brief Construct a new unordered set object with a custom allocator. 61 | * 62 | * @param allocator The allocator that will be used. 63 | */ 64 | explicit unordered_set(util::custom_allocator allocator) 65 | : base(allocator) 66 | { 67 | } 68 | 69 | /** 70 | * @brief Like std::unordered_set.insert but doesn't throw on out of memory errors. 71 | * 72 | * @param value The value to insert in the map. 73 | * @return std::optional> If successful, the optional will 74 | * contain the same return value as from std::unordered_set.insert, otherwise 75 | * if out of memory, the function returns std::nullopt. 76 | */ 77 | std::optional> try_insert(const value_type &value) noexcept 78 | { 79 | try 80 | { 81 | return { base::insert(value) }; 82 | } 83 | catch (const std::bad_alloc &e) 84 | { 85 | return std::nullopt; 86 | } 87 | } 88 | 89 | /** 90 | * @brief Like std::unordered_set.reserve but doesn't throw on out of memory errors. 91 | * 92 | * @param size The new capacity of the container. Same as std::unordered_set.reserve. 93 | * @return true If the container was resized successfuly. 94 | * @return false If the host has run out of memory 95 | */ 96 | bool try_reserve(size_type size) 97 | { 98 | try 99 | { 100 | base::reserve(size); 101 | return true; 102 | } 103 | catch (std::bad_alloc &e) 104 | { 105 | return false; 106 | } 107 | } 108 | 109 | /** 110 | * @brief Like std::unordered_set.rehash but doesn't throw on out of memory errors. 111 | * 112 | * @param count Number of buckets. Same as std::unordered_set.rehash. 113 | * @return true If the container was rehashed successfuly. 114 | * @return false If the host has run out of memory 115 | */ 116 | bool try_rehash(size_type count) 117 | { 118 | try 119 | { 120 | base::rehash(count); 121 | return true; 122 | } 123 | catch (std::bad_alloc &e) 124 | { 125 | return false; 126 | } 127 | } 128 | }; 129 | } // namespace util 130 | -------------------------------------------------------------------------------- /wsi/compatible_present_modes.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file compatible_present_modes.hpp 27 | * 28 | * @brief Contains functions for handling compatibility between different presentation modes 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | namespace wsi 38 | { 39 | 40 | static constexpr uint32_t MAX_PRESENT_MODES = 6; 41 | struct present_mode_compatibility 42 | { 43 | /* Presentation mode */ 44 | VkPresentModeKHR present_mode; 45 | 46 | /* Number of presentation modes compatible */ 47 | uint32_t present_mode_count; 48 | 49 | /* Stores the compatible presentation modes */ 50 | std::array compatible_present_modes; 51 | }; 52 | 53 | template 54 | class compatible_present_modes 55 | { 56 | public: 57 | compatible_present_modes() 58 | { 59 | } 60 | 61 | compatible_present_modes(std::array present_mode_compatibilites) 62 | : m_present_mode_compatibilites(present_mode_compatibilites) 63 | { 64 | } 65 | 66 | /** 67 | * @brief Common function for handling VkSurfacePresentModeCompatibilityEXT if it exists in the pNext chain of VkSurfaceCapabilities2KHR. 68 | * 69 | * If pSurfaceInfo contains a VkSurfacePresentModeEXT struct in its pNext chain, and pSurfaceCapabilities contains a VkSurfacePresentModeCompatibilityEXT struct 70 | * then this function fills the VkSurfacePresentModeCompatibilityEXT struct with the presentation modes that are compatible with the presentation mode specified 71 | * in the VkSurfacePresentModeEXT struct. 72 | * 73 | * @param pSurfaceInfo Pointer to surface info that may or may not contain a VkSurfacePresentModeEXT. 74 | * @param pSurfaceCapabilities Pointer to surface capabilities that may or may not contain a VkSurfacePresentModeCompatibilityEXT struct. 75 | * 76 | */ 77 | void get_surface_present_mode_compatibility_common(const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 78 | VkSurfaceCapabilities2KHR *pSurfaceCapabilities) 79 | { 80 | auto surface_present_mode = 81 | util::find_extension(VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT, pSurfaceInfo); 82 | auto surface_present_mode_compatibility = util::find_extension( 83 | VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT, pSurfaceCapabilities); 84 | 85 | if (surface_present_mode == nullptr || surface_present_mode_compatibility == nullptr) 86 | { 87 | return; 88 | } 89 | 90 | VkPresentModeKHR present_mode = surface_present_mode->presentMode; 91 | auto it = std::find_if(m_present_mode_compatibilites.begin(), m_present_mode_compatibilites.end(), 92 | [present_mode](present_mode_compatibility p) { return p.present_mode == present_mode; }); 93 | if (it == m_present_mode_compatibilites.end()) 94 | { 95 | WSI_LOG_ERROR("Querying compatible presentation mode support for a presentation mode that is not supported."); 96 | return; 97 | } 98 | const present_mode_compatibility &surface_supported_compatibility = *it; 99 | 100 | if (surface_present_mode_compatibility->pPresentModes == nullptr) 101 | { 102 | surface_present_mode_compatibility->presentModeCount = surface_supported_compatibility.present_mode_count; 103 | return; 104 | } 105 | 106 | surface_present_mode_compatibility->presentModeCount = std::min( 107 | surface_present_mode_compatibility->presentModeCount, surface_supported_compatibility.present_mode_count); 108 | std::copy(surface_supported_compatibility.compatible_present_modes.begin(), 109 | surface_supported_compatibility.compatible_present_modes.begin() + 110 | surface_present_mode_compatibility->presentModeCount, 111 | surface_present_mode_compatibility->pPresentModes); 112 | } 113 | 114 | /** 115 | * @brief Common function for handling checking whether a present mode is compatible with another. 116 | * 117 | * @param present_mode_a First present mode. 118 | * @param present_mode_b Second present mode to compare against. 119 | * 120 | * @return true if compatible, false otherwise. 121 | */ 122 | bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) 123 | { 124 | auto it = 125 | std::find_if(m_present_mode_compatibilites.begin(), m_present_mode_compatibilites.end(), 126 | [present_mode_a](present_mode_compatibility p) { return p.present_mode == present_mode_a; }); 127 | if (it == m_present_mode_compatibilites.end()) 128 | { 129 | WSI_LOG_ERROR("Querying compatible presentation mode support for a presentation mode that is not supported."); 130 | return false; 131 | } 132 | 133 | const present_mode_compatibility &present_mode_comp = *it; 134 | auto present_mode_it = 135 | std::find_if(present_mode_comp.compatible_present_modes.begin(), 136 | present_mode_comp.compatible_present_modes.begin() + present_mode_comp.present_mode_count, 137 | [present_mode_b](VkPresentModeKHR p) { return p == present_mode_b; }); 138 | return present_mode_it != present_mode_comp.compatible_present_modes.end(); 139 | } 140 | 141 | private: 142 | std::array m_present_mode_compatibilites; 143 | }; 144 | 145 | } // namespace wsi 146 | -------------------------------------------------------------------------------- /wsi/display/surface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** @file 26 | * @brief Implementation of a headless WSI Surface 27 | */ 28 | 29 | #include "surface.hpp" 30 | #include "swapchain.hpp" 31 | #include "surface_properties.hpp" 32 | 33 | namespace wsi 34 | { 35 | namespace display 36 | { 37 | 38 | surface::surface(drm_display_mode *display_mode, VkExtent2D extent) 39 | : m_display_mode(display_mode) 40 | , m_extent(extent) 41 | { 42 | } 43 | 44 | wsi::surface_properties &surface::get_properties() 45 | { 46 | return m_surface_properties; 47 | } 48 | 49 | util::unique_ptr surface::allocate_swapchain(layer::device_private_data &dev_data, 50 | const VkAllocationCallbacks *allocator) 51 | { 52 | util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, allocator }; 53 | return util::unique_ptr(alloc.make_unique(dev_data, allocator, *this)); 54 | } 55 | 56 | VkExtent2D surface::get_extent() const 57 | { 58 | return m_extent; 59 | } 60 | 61 | drm_display_mode *surface::get_display_mode() 62 | { 63 | return m_display_mode; 64 | } 65 | 66 | } /* namespace display */ 67 | } /* namespace wsi */ 68 | -------------------------------------------------------------------------------- /wsi/display/surface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** @file 26 | * @brief Definitions for a headless WSI Surface 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "wsi/surface.hpp" 32 | #include "surface_properties.hpp" 33 | #include "drm_display.hpp" 34 | 35 | namespace wsi 36 | { 37 | namespace display 38 | { 39 | 40 | class surface : public wsi::surface 41 | { 42 | public: 43 | /** 44 | * @brief Construct a new surface. 45 | * 46 | * @param mode The display mode to be used with the surface. 47 | * @param extent The extent of the surface. 48 | */ 49 | surface(drm_display_mode *mode, VkExtent2D extent); 50 | 51 | wsi::surface_properties &get_properties() override; 52 | util::unique_ptr allocate_swapchain(layer::device_private_data &dev_data, 53 | const VkAllocationCallbacks *allocator) override; 54 | 55 | /** 56 | * @brief Get the extent of the surface. 57 | */ 58 | VkExtent2D get_extent() const; 59 | 60 | /** 61 | * @brief Get the display mode associated with this surface. 62 | */ 63 | drm_display_mode *get_display_mode(); 64 | 65 | private: 66 | /** 67 | * @brief Pointer to the DRM display mode used with this surface. 68 | */ 69 | drm_display_mode *m_display_mode; 70 | 71 | /** 72 | * @brief The extent of this surface. 73 | */ 74 | VkExtent2D m_extent; 75 | 76 | /** 77 | * @brief Surface properties instance specific to this surface. 78 | */ 79 | surface_properties m_surface_properties; 80 | }; 81 | 82 | } /* namespace display */ 83 | } /* namespace wsi */ 84 | -------------------------------------------------------------------------------- /wsi/display/surface_properties.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #include "wsi/surface_properties.hpp" 30 | #include "drm_display.hpp" 31 | #include "wsi/compatible_present_modes.hpp" 32 | 33 | namespace wsi 34 | { 35 | 36 | namespace display 37 | { 38 | 39 | class surface; 40 | 41 | class surface_properties : public wsi::surface_properties 42 | { 43 | public: 44 | surface_properties(); 45 | 46 | surface_properties(surface *wsi_surface); 47 | 48 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 49 | VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override; 50 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 51 | const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 52 | VkSurfaceCapabilities2KHR *pSurfaceCapabilities) override; 53 | 54 | VkResult get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount, 55 | VkSurfaceFormatKHR *surfaceFormats, 56 | VkSurfaceFormat2KHR *extended_surface_formats) override; 57 | 58 | VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface, 59 | uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override; 60 | 61 | PFN_vkVoidFunction get_proc_addr(const char *name) override; 62 | 63 | VkResult get_required_instance_extensions(util::extension_list &extension_list) override; 64 | 65 | VkResult get_required_device_extensions(util::extension_list &extension_list) override; 66 | 67 | bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override; 68 | 69 | #if VULKAN_WSI_LAYER_EXPERIMENTAL 70 | void get_present_timing_surface_caps(VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; 71 | #endif 72 | 73 | static surface_properties &get_instance(); 74 | 75 | bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) override; 76 | 77 | private: 78 | surface *const m_specific_surface; 79 | 80 | /* List of supported presentation modes */ 81 | std::array m_supported_modes; 82 | 83 | /* Stores compatible presentation modes */ 84 | compatible_present_modes<1> m_compatible_present_modes; 85 | 86 | void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; 87 | void populate_present_mode_compatibilities() override; 88 | }; 89 | 90 | } /* namespace display */ 91 | 92 | } /* namespace wsi */ -------------------------------------------------------------------------------- /wsi/display/swapchain.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file swapchain.hpp 27 | * 28 | * @brief Contains the class definition for a display swapchain. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include 35 | #include 36 | #include "util/wsialloc/wsialloc.h" 37 | #include "drm_display.hpp" 38 | #include "wsi/external_memory.hpp" 39 | #include "surface.hpp" 40 | 41 | namespace wsi 42 | { 43 | 44 | namespace display 45 | { 46 | 47 | struct display_image_data 48 | { 49 | display_image_data(const VkDevice &device, const util::allocator &allocator) 50 | : external_mem(device, allocator) 51 | , fb_id(std::numeric_limits::max()) 52 | { 53 | } 54 | 55 | external_memory external_mem; 56 | uint32_t fb_id; 57 | sync_fd_fence_sync present_fence; 58 | }; 59 | 60 | struct image_creation_parameters 61 | { 62 | wsialloc_format m_allocated_format; 63 | util::vector m_image_layout; 64 | VkExternalMemoryImageCreateInfoKHR m_external_info; 65 | VkImageDrmFormatModifierExplicitCreateInfoEXT m_drm_mod_info; 66 | 67 | image_creation_parameters(wsialloc_format allocated_format, util::allocator allocator, 68 | VkExternalMemoryImageCreateInfoKHR external_info, 69 | VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info) 70 | : m_allocated_format(allocated_format) 71 | , m_image_layout(allocator) 72 | , m_external_info(external_info) 73 | , m_drm_mod_info(drm_mod_info) 74 | { 75 | } 76 | }; 77 | 78 | /** 79 | * @brief Display swapchain class. 80 | */ 81 | class swapchain : public wsi::swapchain_base 82 | { 83 | public: 84 | swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator, surface &wsi_surface); 85 | virtual ~swapchain(); 86 | virtual VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info, 87 | bool &use_presentation_thread) override; 88 | 89 | virtual VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info, 90 | const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override; 91 | 92 | VkResult allocate_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; 93 | 94 | virtual VkResult create_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; 95 | 96 | /** 97 | * @brief Method to present and image 98 | * 99 | * It sends the next image for presentation to the presentation engine. 100 | * 101 | * @param pending_present Information on the pending present request. 102 | */ 103 | void present_image(const pending_present_request &pending_present) override; 104 | 105 | virtual VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, 106 | const queue_submit_semaphores &semaphores, 107 | const void *submission_pnext) override; 108 | 109 | virtual VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override; 110 | 111 | void destroy_image(swapchain_image &image) override; 112 | 113 | private: 114 | VkResult allocate_image(VkImageCreateInfo &image_create_info, display_image_data *image_data); 115 | 116 | VkResult allocate_wsialloc(VkImageCreateInfo &image_create_info, display_image_data *image_data, 117 | util::vector &importable_formats, wsialloc_format *allocated_format, 118 | bool avoid_allocation); 119 | 120 | VkResult get_surface_compatible_formats(const VkImageCreateInfo &info, 121 | util::vector &importable_formats, 122 | util::vector &exportable_modifers, 123 | util::vector &drm_format_props); 124 | 125 | VkResult create_framebuffer(const VkImageCreateInfo &image_create_info, swapchain_image &image, 126 | display_image_data *image_data); 127 | 128 | wsialloc_allocator *m_wsi_allocator; 129 | drm_display_mode *m_display_mode; 130 | image_creation_parameters m_image_creation_parameters; 131 | }; 132 | 133 | } /* namespace display */ 134 | 135 | } /* namespace wsi*/ 136 | -------------------------------------------------------------------------------- /wsi/frame_boundary.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file frame_boundary.cpp 27 | * 28 | * @brief Contains the functionality for frame boundary handling. 29 | */ 30 | 31 | #include "frame_boundary.hpp" 32 | 33 | namespace wsi 34 | { 35 | frame_boundary_handler::frame_boundary_handler(const layer::device_private_data &device_data) 36 | : m_handle_frame_boundary_events(device_data.should_layer_handle_frame_boundary_events()) 37 | { 38 | } 39 | 40 | std::optional frame_boundary_handler::handle_frame_boundary_event( 41 | const VkPresentInfoKHR *present_info, VkImage *current_image_to_be_presented) 42 | { 43 | /* If frame boundary feature is not enabled by the application, the layer will pass its own frame boundary events back to ICD. 44 | * Otherwise, let the application handle the frame boundary events. */ 45 | return m_handle_frame_boundary_events ? create_frame_boundary(current_image_to_be_presented) : 46 | wsi::create_frame_boundary(*present_info); 47 | } 48 | 49 | std::optional create_frame_boundary(const VkPresentInfoKHR &present_info) 50 | { 51 | auto *present_frame_boundary = 52 | util::find_extension(VK_STRUCTURE_TYPE_PRESENT_ID_KHR, present_info.pNext); 53 | 54 | /* Extract the VkFrameBoundaryEXT structure to avoid passing other, unrelated structures to vkQueueSubmit */ 55 | if (present_frame_boundary != nullptr) 56 | { 57 | return util::shallow_copy_extension(present_frame_boundary); 58 | } 59 | 60 | return std::nullopt; 61 | } 62 | 63 | bool frame_boundary_handler::should_layer_handle_frame_boundary_events() const 64 | { 65 | return m_handle_frame_boundary_events; 66 | } 67 | 68 | VkFrameBoundaryEXT frame_boundary_handler::create_frame_boundary(VkImage *image) 69 | { 70 | VkFrameBoundaryEXT frame_boundary{}; 71 | frame_boundary.pNext = nullptr; 72 | frame_boundary.sType = VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT; 73 | frame_boundary.flags = VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT; 74 | /* Number of presented images by swapchain as the frame boundary 75 | * would not work as when the page flip thread is running, the 76 | * number frame ID could remain the same until the image is picked 77 | * up by the thread so we use our own counter for the frame boundary. */ 78 | frame_boundary.frameID = m_current_frame_boundary_id++; 79 | frame_boundary.imageCount = 1; 80 | frame_boundary.pImages = image; 81 | frame_boundary.pBuffers = nullptr; 82 | frame_boundary.bufferCount = 0; 83 | 84 | /* Create an unique identifier for the layer in case tools make use of it. 85 | * The number below is derived from converting characters 'WSI' into 86 | * their numerical representation from the ASCII table. */ 87 | frame_boundary.tagName = 0x575349; 88 | 89 | /* No additional data attached */ 90 | frame_boundary.tagSize = 0; 91 | frame_boundary.pTag = nullptr; 92 | 93 | return frame_boundary; 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /wsi/frame_boundary.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file frame_boundary.hpp 27 | * 28 | * @brief Contains the functionality for frame boundary handling. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include 35 | 36 | #include 37 | 38 | namespace wsi 39 | { 40 | class frame_boundary_handler 41 | { 42 | public: 43 | frame_boundary_handler(const layer::device_private_data &device_data); 44 | 45 | /** 46 | * @brief Handle frame boundary event at present time 47 | * 48 | * @param present_info Information about the swapchain and image to be presented. 49 | * @param current_image_to_be_presented Address to the currently to be presented image 50 | */ 51 | std::optional handle_frame_boundary_event(const VkPresentInfoKHR *present_info, 52 | VkImage *current_image_to_be_presented); 53 | 54 | private: 55 | /** 56 | * @brief Create a frame boundary with the current image 57 | * 58 | * @param image Address to the currently to be presented image 59 | * @return Frame boundary structure 60 | */ 61 | VkFrameBoundaryEXT create_frame_boundary(VkImage *image); 62 | 63 | /** 64 | * @brief Check whether we should handle frame boundary events. 65 | * 66 | * @return true if supported, false otherwise. 67 | */ 68 | bool should_layer_handle_frame_boundary_events() const; 69 | 70 | /** 71 | * @brief Holds the number of the current frame identifier for the swapchain 72 | */ 73 | uint64_t m_current_frame_boundary_id{ 0 }; 74 | 75 | /** 76 | * @brief Stores whether the layer should handle frame boundary events. 77 | */ 78 | const bool m_handle_frame_boundary_events; 79 | }; 80 | 81 | /** 82 | * @brief Create a frame boundary object 83 | * 84 | * @param present_info Present info 85 | * @return Frame boundary if @p present_info has passed it. 86 | */ 87 | std::optional create_frame_boundary(const VkPresentInfoKHR &present_info); 88 | 89 | } 90 | -------------------------------------------------------------------------------- /wsi/headless/surface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** @file 26 | * @brief Implementation of a headless WSI Surface 27 | */ 28 | 29 | #include "surface.hpp" 30 | #include "swapchain.hpp" 31 | #include "surface_properties.hpp" 32 | 33 | namespace wsi 34 | { 35 | namespace headless 36 | { 37 | 38 | wsi::surface_properties &surface::get_properties() 39 | { 40 | return surface_properties::get_instance(); 41 | } 42 | 43 | util::unique_ptr surface::allocate_swapchain(layer::device_private_data &dev_data, 44 | const VkAllocationCallbacks *allocator) 45 | { 46 | util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, allocator }; 47 | return util::unique_ptr(alloc.make_unique(dev_data, allocator)); 48 | } 49 | 50 | } /* namespace headless */ 51 | } /* namespace wsi */ 52 | -------------------------------------------------------------------------------- /wsi/headless/surface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** @file 26 | * @brief Definitions for a headless WSI Surface 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "wsi/surface.hpp" 32 | 33 | namespace wsi 34 | { 35 | namespace headless 36 | { 37 | 38 | class surface : public wsi::surface 39 | { 40 | public: 41 | surface() = default; 42 | wsi::surface_properties &get_properties() override; 43 | util::unique_ptr allocate_swapchain(layer::device_private_data &dev_data, 44 | const VkAllocationCallbacks *allocator) override; 45 | }; 46 | 47 | } /* namespace headless */ 48 | } /* namespace wsi */ 49 | -------------------------------------------------------------------------------- /wsi/headless/surface_properties.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019, 2022-2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | namespace wsi 32 | { 33 | namespace headless 34 | { 35 | 36 | class surface_properties : public wsi::surface_properties 37 | { 38 | public: 39 | surface_properties(); 40 | 41 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 42 | VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override; 43 | 44 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 45 | const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 46 | VkSurfaceCapabilities2KHR *pSurfaceCapabilities) override; 47 | 48 | VkResult get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount, 49 | VkSurfaceFormatKHR *surfaceFormats, 50 | VkSurfaceFormat2KHR *extended_surface_formats) override; 51 | 52 | VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface, 53 | uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override; 54 | 55 | PFN_vkVoidFunction get_proc_addr(const char *name) override; 56 | 57 | VkResult get_required_instance_extensions(util::extension_list &extension_list) override; 58 | 59 | bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override; 60 | 61 | static surface_properties &get_instance(); 62 | 63 | bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) override; 64 | 65 | #if VULKAN_WSI_LAYER_EXPERIMENTAL 66 | void get_present_timing_surface_caps(VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; 67 | #endif 68 | 69 | private: 70 | /* List of supported presentation modes */ 71 | std::array m_supported_modes; 72 | 73 | /* Stores compatible presentation modes */ 74 | compatible_present_modes<4> m_compatible_present_modes; 75 | 76 | void populate_present_mode_compatibilities() override; 77 | 78 | void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; 79 | }; 80 | 81 | } /* namespace headless */ 82 | } /* namespace wsi */ 83 | -------------------------------------------------------------------------------- /wsi/headless/swapchain.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file swapchain.hpp 27 | * 28 | * @brief Contains the class definition for a headless swapchain. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | namespace wsi 38 | { 39 | namespace headless 40 | { 41 | 42 | /** 43 | * @brief Headless swapchain class. 44 | * 45 | * This class is mostly empty, because all the swapchain stuff is handled by the swapchain class, 46 | * which we inherit. This class only provides a way to create an image and page-flip ops. 47 | */ 48 | class swapchain : public wsi::swapchain_base 49 | { 50 | public: 51 | explicit swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator); 52 | 53 | ~swapchain(); 54 | 55 | protected: 56 | /** 57 | * @brief Platform specific init 58 | */ 59 | VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info, 60 | bool &use_presentation_thread) override; 61 | 62 | /** 63 | * @brief Allocates and binds a new swapchain image. 64 | * 65 | * @param image_create_info Data to be used to create the image. 66 | * @param image Handle to the image. 67 | * 68 | * @return Returns VK_SUCCESS on success, otherwise an appropriate error code. 69 | */ 70 | VkResult allocate_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; 71 | 72 | /** 73 | * @brief Creates a new swapchain image. 74 | * 75 | * @param image_create_info Data to be used to create the image. 76 | * @param image Handle to the image. 77 | * 78 | * @return If image creation is successful returns VK_SUCCESS, otherwise 79 | * will return VK_ERROR_OUT_OF_DEVICE_MEMORY or VK_ERROR_INITIALIZATION_FAILED 80 | * depending on the error that occurred. 81 | */ 82 | VkResult create_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; 83 | 84 | /** 85 | * @brief Method to present and image 86 | * 87 | * It sends the next image for presentation to the presentation engine. 88 | * 89 | * @param pending_present Information on the pending present request. 90 | */ 91 | void present_image(const pending_present_request &pending_present) override; 92 | 93 | /** 94 | * @brief Method to release a swapchain image 95 | * 96 | * @param image Handle to the image about to be released. 97 | */ 98 | void destroy_image(wsi::swapchain_image &image); 99 | 100 | /** 101 | * @brief Sets the present payload for a swapchain image. 102 | * 103 | * @param[in] image The swapchain image for which to set a present payload. 104 | * @param queue A Vulkan queue that can be used for any Vulkan commands needed. 105 | * @param[in] sem_payload Array of Vulkan semaphores that constitute the payload. 106 | * @param[in] submission_pnext Chain of pointers to attach to the payload submission. 107 | * 108 | * @return VK_SUCCESS on success or an error code otherwise. 109 | */ 110 | VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const queue_submit_semaphores &semaphores, 111 | const void *submission_pnext) override; 112 | 113 | VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override; 114 | 115 | /** 116 | * @brief Bind image to a swapchain 117 | * 118 | * @param device is the logical device that owns the images and memory. 119 | * @param bind_image_mem_info details the image we want to bind. 120 | * @param bind_sc_info describes the swapchain memory to bind to. 121 | * 122 | * @return VK_SUCCESS on success, otherwise on failure VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY 123 | * can be returned. 124 | */ 125 | VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info, 126 | const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override; 127 | 128 | private: 129 | #if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN 130 | VkImageCompressionControlEXT m_image_compression_control; 131 | #endif 132 | }; 133 | 134 | } /* namespace headless */ 135 | } /* namespace wsi */ 136 | -------------------------------------------------------------------------------- /wsi/surface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file 27 | * @brief Vulkan WSI surface interfaces. 28 | */ 29 | 30 | #pragma once 31 | 32 | #include 33 | #include "surface_properties.hpp" 34 | #include "swapchain_base.hpp" 35 | 36 | namespace wsi 37 | { 38 | 39 | /** 40 | * @brief Struct describing a DRM format with modifier. 41 | */ 42 | struct drm_format_pair 43 | { 44 | uint32_t fourcc; 45 | uint64_t modifier; 46 | }; 47 | 48 | /** 49 | * @brief A generic WSI representation of a VkSurface. 50 | * 51 | * The association between these objects and VkSurfaces is kept in the VkInstance private data. 52 | */ 53 | class surface 54 | { 55 | public: 56 | virtual ~surface() = default; 57 | 58 | /** 59 | * @brief Returns a @ref surface_properties implementation that can be specific to the VkSurface represented. 60 | */ 61 | virtual surface_properties &get_properties() = 0; 62 | 63 | /** 64 | * @brief Allocates a swapchain for the VkSurface type represented. 65 | * 66 | * @param dev_data The VkDevice associated private date. 67 | * @param allocator Allocation callbacks to use for host memory. 68 | * 69 | * @return nullptr on failure otherwise a constructed swapchain. 70 | */ 71 | virtual util::unique_ptr allocate_swapchain(layer::device_private_data &dev_data, 72 | const VkAllocationCallbacks *allocator) = 0; 73 | }; 74 | 75 | } /* namespace wsi */ 76 | -------------------------------------------------------------------------------- /wsi/surface_properties.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "surface_properties.hpp" 26 | #include "layer/private_data.hpp" 27 | 28 | namespace wsi 29 | { 30 | 31 | VkResult surface_format_properties::check_device_support(VkPhysicalDevice phys_dev, 32 | VkPhysicalDeviceImageFormatInfo2KHR image_format_info) 33 | { 34 | VkImageFormatProperties2KHR image_format_props{ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR, nullptr }; 35 | 36 | auto &instance_data = layer::instance_private_data::get(phys_dev); 37 | 38 | return instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(phys_dev, &image_format_info, 39 | &image_format_props); 40 | } 41 | 42 | #if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN 43 | VkResult surface_format_properties::add_device_compression_support( 44 | VkPhysicalDevice phys_dev, VkPhysicalDeviceImageFormatInfo2KHR image_format_info) 45 | { 46 | auto &instance_data = layer::instance_private_data::get(phys_dev); 47 | 48 | VkImageCompressionPropertiesEXT compression_props = { VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT, nullptr, 0, 49 | 0 }; 50 | VkImageFormatProperties2KHR image_format_props{ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR, 51 | &compression_props }; 52 | 53 | VkImageCompressionControlEXT compression_control{ VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT, 54 | image_format_info.pNext, 55 | VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT }; 56 | image_format_info.pNext = &compression_control; 57 | 58 | VkResult res = 59 | instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(phys_dev, &image_format_info, &image_format_props); 60 | if (res == VK_SUCCESS) 61 | { 62 | m_compression.imageCompressionFlags |= compression_props.imageCompressionFlags; 63 | m_compression.imageCompressionFixedRateFlags |= compression_props.imageCompressionFixedRateFlags; 64 | } 65 | else if (res != VK_ERROR_FORMAT_NOT_SUPPORTED) 66 | { 67 | return res; 68 | } 69 | 70 | return VK_SUCCESS; 71 | } 72 | #endif 73 | 74 | void surface_format_properties::fill_format_properties(VkSurfaceFormat2KHR &surf_format) const 75 | { 76 | surf_format.surfaceFormat = m_surface_format; 77 | #if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN 78 | auto *compression_properties = util::find_extension( 79 | VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT, surf_format.pNext); 80 | if (compression_properties != nullptr) 81 | { 82 | /** While a format can support multiple compression control flags the returned value is only allowed to be: 83 | * VK_IMAGE_COMPRESSION_DEFAULT_EXT, VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT or 84 | * VK_IMAGE_COMPRESSION_DISABLED_EXT. 85 | * 86 | * Since currently formats that are supported with both default and disabled compression are not distinguished 87 | * from formats that would always be with disabled compression, disabled is not returned. 88 | */ 89 | compression_properties->imageCompressionFlags = VK_IMAGE_COMPRESSION_DEFAULT_EXT; 90 | if (m_compression.imageCompressionFlags & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT) 91 | { 92 | compression_properties->imageCompressionFlags = VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT; 93 | compression_properties->imageCompressionFixedRateFlags = m_compression.imageCompressionFixedRateFlags; 94 | } 95 | } 96 | #endif 97 | } 98 | 99 | void get_surface_capabilities_common(VkPhysicalDevice physical_device, VkSurfaceCapabilitiesKHR *surface_capabilities) 100 | { 101 | /* Image count limits */ 102 | surface_capabilities->minImageCount = 1; 103 | surface_capabilities->maxImageCount = surface_properties::MAX_SWAPCHAIN_IMAGE_COUNT; 104 | 105 | /* Surface extents */ 106 | surface_capabilities->currentExtent = { 0xffffffff, 0xffffffff }; 107 | surface_capabilities->minImageExtent = { 1, 1 }; 108 | /* Ask the device for max */ 109 | VkPhysicalDeviceProperties dev_props = {}; 110 | layer::instance_private_data::get(physical_device).disp.GetPhysicalDeviceProperties(physical_device, &dev_props); 111 | 112 | surface_capabilities->maxImageExtent = { dev_props.limits.maxImageDimension2D, 113 | dev_props.limits.maxImageDimension2D }; 114 | surface_capabilities->maxImageArrayLayers = 1; 115 | 116 | /* Surface transforms */ 117 | surface_capabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 118 | surface_capabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 119 | 120 | /* Composite alpha */ 121 | surface_capabilities->supportedCompositeAlpha = static_cast( 122 | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | 123 | VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR | VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR); 124 | 125 | /* Image usage flags */ 126 | surface_capabilities->supportedUsageFlags = 127 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | 128 | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 129 | } 130 | 131 | } /* namespace wsi */ -------------------------------------------------------------------------------- /wsi/synchronization.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file 27 | * 28 | * @brief Contains the defintions of WSI synchronization primitives. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include 34 | 35 | #include "util/file_descriptor.hpp" 36 | 37 | #include 38 | 39 | namespace layer 40 | { 41 | class device_private_data; 42 | class instance_private_data; 43 | } /* namespace layer */ 44 | 45 | namespace wsi 46 | { 47 | 48 | struct queue_submit_semaphores 49 | { 50 | const VkSemaphore *wait_semaphores; 51 | uint32_t wait_semaphores_count; 52 | const VkSemaphore *signal_semaphores; 53 | uint32_t signal_semaphores_count; 54 | }; 55 | 56 | /** 57 | * Synchronization using a Vulkan Fence object. 58 | */ 59 | class fence_sync 60 | { 61 | public: 62 | /** 63 | * Creates a new fence synchronization object. 64 | * 65 | * @param device The device private data for which to create it. 66 | * 67 | * @return Empty optional on failure or initialized fence. 68 | */ 69 | static std::optional create(layer::device_private_data &device); 70 | 71 | fence_sync() = default; 72 | fence_sync(const fence_sync &) = delete; 73 | fence_sync &operator=(const fence_sync &) = delete; 74 | 75 | fence_sync(fence_sync &&rhs); 76 | fence_sync &operator=(fence_sync &&rhs); 77 | 78 | virtual ~fence_sync(); 79 | 80 | /** 81 | * Waits for any pending payload to complete execution. 82 | * 83 | * @note This method is not threadsafe. 84 | * 85 | * @param timeout Timeout for waiting in nanoseconds. 86 | * 87 | * @return VK_SUCCESS on success or if no payload or a completed payload is set. 88 | * Other error code on failure or timeout. 89 | */ 90 | VkResult wait_payload(uint64_t timeout); 91 | 92 | /** 93 | * Sets the payload for the fence that would need to complete before operations that wait on it. 94 | * 95 | * @note This method is not threadsafe. 96 | * 97 | * @param queue The Vulkan queue that may be used to submit synchronization commands. 98 | * @param semaphores The wait and signal semaphores. 99 | * @param submission_pnext Chain of pointers to attach to the payload submission. 100 | * 101 | * @return VK_SUCCESS on success or other error code on failing to set the payload. 102 | */ 103 | VkResult set_payload(VkQueue queue, const queue_submit_semaphores &semaphores, 104 | const void *submission_pnext = nullptr); 105 | 106 | protected: 107 | /** 108 | * Non-public constructor to initialize the object with valid data. 109 | * 110 | * @param device The device private data for the fence. 111 | * @param vk_fence The created Vulkan fence. 112 | */ 113 | fence_sync(layer::device_private_data &device, VkFence vk_fence); 114 | 115 | VkFence get_fence() 116 | { 117 | return fence; 118 | } 119 | 120 | /** 121 | * Swaps current payload. This operation could be performed when exporting or importing external fences. 122 | * 123 | * @param new_payload Whether a new payload is set. 124 | * 125 | * @return If there is an existing payload that is being replaced. 126 | */ 127 | bool swap_payload(bool new_payload); 128 | 129 | layer::device_private_data &get_device() 130 | { 131 | return *dev; 132 | } 133 | 134 | private: 135 | VkFence fence{ VK_NULL_HANDLE }; 136 | bool has_payload{ false }; 137 | bool payload_finished{ false }; 138 | layer::device_private_data *dev{ nullptr }; 139 | }; 140 | 141 | /** 142 | * Synchronization using a Vulkan fence exportable to a native Sync FD object. 143 | */ 144 | class sync_fd_fence_sync : public fence_sync 145 | { 146 | public: 147 | sync_fd_fence_sync() = default; 148 | 149 | /** 150 | * Checks if a Vulkan device can support Sync FD fences. 151 | * 152 | * @param instance The instance private data for the physical device. 153 | * @param phys_dev The physical device to check support for. 154 | * 155 | * @return true if supported, false otherwise. 156 | */ 157 | static bool is_supported(layer::instance_private_data &instance, VkPhysicalDevice phys_dev); 158 | 159 | /** 160 | * Creates a new fence compatible with Sync FD. 161 | * 162 | * @param device The device private data for which to create the fence. 163 | * 164 | * @return Empty optional on failure or initialized fence. 165 | */ 166 | static std::optional create(layer::device_private_data &device); 167 | 168 | /** 169 | * Exports the fence to a native Sync FD. 170 | * 171 | * @note This method is not threadsafe. 172 | * 173 | * @return The exported Sync FD on success or empty optional on failure. 174 | */ 175 | std::optional export_sync_fd(); 176 | 177 | private: 178 | /** 179 | * Non-public constructor to initialize the object with valid data. 180 | * 181 | * @param device The device private data for the fence. 182 | * @param vk_fence The created exportable Vulkan fence. 183 | */ 184 | sync_fd_fence_sync(layer::device_private_data &device, VkFence vk_fence); 185 | }; 186 | 187 | /** 188 | * @brief Submit an empty queue operation for synchronization. 189 | * 190 | * @param device The device private data for the fence. 191 | * @param queue The Vulkan queue that may be used to submit synchronization commands. 192 | * @param fence The fence to be signalled, it could be VK_NULL_HANDLE in the absence 193 | * of a fence to be signalled. 194 | * @param semaphores The wait and signal semaphores. 195 | * @param submission_pnext Chain of pointers to attach to the payload submission. 196 | * 197 | * @return VK_SUCCESS on success, an appropiate error code otherwise. 198 | */ 199 | VkResult sync_queue_submit(const layer::device_private_data &device, VkQueue queue, VkFence fence, 200 | const queue_submit_semaphores &semaphores, const void *submission_pnext = nullptr); 201 | } /* namespace wsi */ 202 | -------------------------------------------------------------------------------- /wsi/wayland/surface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** @file 26 | * @brief Definitions for a Wayland WSI Surface 27 | */ 28 | 29 | #pragma once 30 | 31 | #ifndef __STDC_VERSION__ 32 | #define __STDC_VERSION__ 0 33 | #endif 34 | #include 35 | 36 | #include "wsi/surface.hpp" 37 | #include "surface_properties.hpp" 38 | #include "wl_object_owner.hpp" 39 | #include "util/macros.hpp" 40 | 41 | namespace wsi 42 | { 43 | namespace wayland 44 | { 45 | 46 | /** 47 | * Wayland callback for global wl_registry events to handle global objects required by @ref wsi::wayland::surface 48 | */ 49 | VWL_CAPI_CALL(void) 50 | surface_registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, 51 | uint32_t version) VWL_API_POST; 52 | 53 | class surface : public wsi::surface 54 | { 55 | public: 56 | surface() = delete; 57 | struct init_parameters; 58 | 59 | /** Constructor to allow for custom allocation, but require privately defined arguments. */ 60 | surface(const init_parameters &); 61 | 62 | /** 63 | * @brief Allocates and initializes a surface 64 | * 65 | * @param allocator An allocator to use for host allocations needed for the surface. 66 | * @param display The Wayland display used to create the VkSurface 67 | * @param surf The Wayland surface used to create the VkSurface 68 | * 69 | * @return A constructed and initalized surface or nullptr on failure 70 | */ 71 | static util::unique_ptr make_surface(const util::allocator &allocator, wl_display *display, 72 | wl_surface *surf); 73 | 74 | /** Destructor */ 75 | ~surface() override; 76 | 77 | wsi::surface_properties &get_properties() override; 78 | util::unique_ptr allocate_swapchain(layer::device_private_data &dev_data, 79 | const VkAllocationCallbacks *allocator) override; 80 | 81 | /** Returns the Wayland display */ 82 | wl_display *get_wl_display() const 83 | { 84 | return wayland_display; 85 | } 86 | 87 | /** Returns the Wayland surface */ 88 | wl_surface *get_wl_surface() const 89 | { 90 | return wayland_surface; 91 | } 92 | 93 | /** 94 | * @brief Returns a pointer to the Wayland zwp_linux_dmabuf_v1 interface. 95 | * 96 | * The raw pointer is valid throughout the lifetime of this surface. 97 | */ 98 | zwp_linux_dmabuf_v1 *get_dmabuf_interface() 99 | { 100 | return dmabuf_interface.get(); 101 | } 102 | 103 | /** 104 | * @brief Returns a pointer to the Wayland zwp_linux_surface_synchronization_v1 interface obtained for the wayland 105 | * surface. 106 | * 107 | * The raw pointer is valid for the lifetime of the surface. 108 | */ 109 | zwp_linux_surface_synchronization_v1 *get_surface_sync_interface() 110 | { 111 | return surface_sync_interface.get(); 112 | } 113 | 114 | /** 115 | * @brief Returns a reference to a list of DRM formats supported by the Wayland surface. 116 | * 117 | * The reference is valid throughout the lifetime of this surface. 118 | */ 119 | const util::vector &get_formats() const 120 | { 121 | return supported_formats; 122 | } 123 | 124 | /** 125 | * @brief Set the next frame callback. 126 | * 127 | * Make a frame request on the compositor which will be applied in the next 128 | * wl_surface::commit. It overwrites previous requested frame events. 129 | * 130 | * @return true for success, false otherwise. 131 | */ 132 | bool set_frame_callback(); 133 | 134 | /** 135 | * @brief Wait for the compositor's last requested frame event. 136 | * 137 | * @return true for success, false otherwise. 138 | */ 139 | bool wait_next_frame_event(); 140 | 141 | private: 142 | /** 143 | * @brief Initialize the WSI surface by creating Wayland queues and linking to Wayland protocols. 144 | * 145 | * @return true on success, false otherwise. 146 | */ 147 | bool init(); 148 | 149 | friend void surface_registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, 150 | const char *interface, uint32_t version) VWL_API_POST; 151 | 152 | /** The native Wayland display */ 153 | wl_display *wayland_display; 154 | 155 | /** 156 | * Container for a private queue for surface events generated by the layer. 157 | * The queue is also used for dispatching frame callback events. 158 | * It should be destroyed after the objects that attached to it. 159 | */ 160 | wayland_owner surface_queue; 161 | 162 | /** The native Wayland surface */ 163 | wl_surface *wayland_surface; 164 | /** A list of DRM formats supported by the Wayland compositor on this surface */ 165 | util::vector supported_formats; 166 | /** Surface properties specific to the Wayland surface. */ 167 | surface_properties properties; 168 | 169 | /** Container for the zwp_linux_dmabuf_v1 interface binding */ 170 | wayland_owner dmabuf_interface; 171 | 172 | /** Container for the zwp_linux_explicit_synchronization_v1 interface binding */ 173 | wayland_owner explicit_sync_interface; 174 | /** Container for the surface specific zwp_linux_surface_synchronization_v1 interface. */ 175 | wayland_owner surface_sync_interface; 176 | 177 | /** Container for the wp_presentation interface binding */ 178 | wayland_owner presentation_time_interface; 179 | 180 | /** 181 | * Container for a callback object for the latest frame done event. 182 | * 183 | * The callback object should be destroyed before the queue so any new events 184 | * on the queue will be discarded. If a proxy object is destroyed after a queue, 185 | * it is possible in the meantime for a new event to arrive and processed. 186 | * This will result in a use after free error. 187 | */ 188 | wayland_owner last_frame_callback; 189 | 190 | /** 191 | * @brief true when waiting for the server hint to present a buffer 192 | * 193 | * true if a buffer has been presented and we've not had a wl_surface::frame 194 | * callback to indicate the server is ready for the next buffer. 195 | */ 196 | bool present_pending; 197 | }; 198 | 199 | } // namespace wayland 200 | } // namespace wsi 201 | -------------------------------------------------------------------------------- /wsi/wayland/surface_properties.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019, 2021-2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include "wsi/surface_properties.hpp" 28 | #include "util/unordered_set.hpp" 29 | #include "wsi/compatible_present_modes.hpp" 30 | 31 | namespace wsi 32 | { 33 | namespace wayland 34 | { 35 | 36 | struct surface_format_properties_hasher 37 | { 38 | size_t operator()(const VkFormat &format) const 39 | { 40 | return std::hash()(static_cast(format)); 41 | } 42 | }; 43 | 44 | using surface_format_properties_map = 45 | util::unordered_map; 46 | 47 | class surface; 48 | 49 | class surface_properties : public wsi::surface_properties 50 | { 51 | public: 52 | surface_properties(surface *wsi_surface, const util::allocator &alloc); 53 | 54 | static surface_properties &get_instance(); 55 | 56 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 57 | VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override; 58 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 59 | const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 60 | VkSurfaceCapabilities2KHR *pSurfaceCapabilities) override; 61 | VkResult get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount, 62 | VkSurfaceFormatKHR *surfaceFormats, 63 | VkSurfaceFormat2KHR *extended_surface_formats) override; 64 | VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface, 65 | uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override; 66 | 67 | VkResult get_required_device_extensions(util::extension_list &extension_list) override; 68 | 69 | VkResult get_required_instance_extensions(util::extension_list &extension_list) override; 70 | 71 | PFN_vkVoidFunction get_proc_addr(const char *name) override; 72 | 73 | bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override; 74 | 75 | bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) override; 76 | 77 | #if VULKAN_WSI_LAYER_EXPERIMENTAL 78 | void get_present_timing_surface_caps(VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; 79 | #endif 80 | private: 81 | surface_properties(); 82 | 83 | /** If the properties are specific to a @ref wsi::wayland::surface this is a pointer to it. Can be nullptr for 84 | * generic Wayland surface properties. 85 | */ 86 | surface *specific_surface; 87 | /** Set of supported Vulkan formats by the @ref specific_surface. */ 88 | surface_format_properties_map supported_formats; 89 | 90 | /* List of supported presentation modes */ 91 | std::array m_supported_modes; 92 | 93 | /* Stores compatible presentation modes */ 94 | compatible_present_modes<2> m_compatible_present_modes; 95 | 96 | void populate_present_mode_compatibilities() override; 97 | 98 | void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; 99 | }; 100 | 101 | } // namespace wayland 102 | } // namespace wsi 103 | -------------------------------------------------------------------------------- /wsi/wayland/wl_helpers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019, 2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "wl_helpers.hpp" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "wl_object_owner.hpp" 34 | 35 | #include "util/log.hpp" 36 | 37 | int dispatch_queue(struct wl_display *display, struct wl_event_queue *queue, int timeout) 38 | { 39 | int err; 40 | struct pollfd pfd = {}; 41 | int retval; 42 | 43 | /* Before we sleep, dispatch any pending events. prepare_read_queue will return 0 whilst there are pending 44 | * events to dispatch on the queue. */ 45 | while (0 != wl_display_prepare_read_queue(display, queue)) 46 | { 47 | /* dispatch_queue_pending returns -1 on error, or the number of events dispatched otherwise. If we 48 | * already dispatched some events, then we might not need to sleep, as we might have just dispatched 49 | * the event we want, so return immediately. */ 50 | err = wl_display_dispatch_queue_pending(display, queue); 51 | if (err) 52 | { 53 | return (0 > err) ? -1 : 1; 54 | } 55 | } 56 | 57 | /* wl_display_read_events performs a non-blocking read. */ 58 | pfd.fd = wl_display_get_fd(display); 59 | pfd.events = POLLIN; 60 | while (true) 61 | { 62 | /* Timeout is given in milliseconds. A return value of 0, or -1 with errno set to EINTR means that we 63 | * should retry as the timeout was exceeded or we were interrupted by a signal, respectively. A 64 | * return value of 1 means that something happened, and we should inspect the pollfd structure to see 65 | * just what that was. 66 | */ 67 | err = poll(&pfd, 1, timeout); 68 | if (0 == err) 69 | { 70 | /* Timeout. */ 71 | wl_display_cancel_read(display); 72 | return 0; 73 | } 74 | else if (-1 == err) 75 | { 76 | if (EINTR == errno) 77 | { 78 | /* Interrupted by a signal; restart. This resets the timeout. */ 79 | continue; 80 | } 81 | else 82 | { 83 | /* Something else bad happened; abort. */ 84 | wl_display_cancel_read(display); 85 | return -1; 86 | } 87 | } 88 | else 89 | { 90 | if (POLLIN == pfd.revents) 91 | { 92 | /* We have data to read, and no errors; proceed to read_events. */ 93 | break; 94 | } 95 | else 96 | { 97 | /* An error occurred, e.g. file descriptor was closed from underneath us. */ 98 | wl_display_cancel_read(display); 99 | return -1; 100 | } 101 | } 102 | } 103 | 104 | /* Actually read the events from the display. A failure in read_events calls cancel_read internally for us, 105 | * so we don't need to do that here. */ 106 | err = wl_display_read_events(display); 107 | if (0 != err) 108 | { 109 | return -1; 110 | } 111 | 112 | /* Finally, if we read any events relevant to our queue, we can dispatch them. */ 113 | err = wl_display_dispatch_queue_pending(display, queue); 114 | retval = err < 0 ? -1 : 1; 115 | 116 | return retval; 117 | } 118 | -------------------------------------------------------------------------------- /wsi/wayland/wl_helpers.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019, 2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #ifndef __STDC_VERSION__ 30 | #define __STDC_VERSION__ 0 31 | #endif 32 | #include 33 | 34 | #include "util/custom_allocator.hpp" 35 | 36 | /** 37 | * @brief Dispatch events from a Wayland event queue 38 | * 39 | * Dispatch events from a given Wayland display event queue, including calling event handlers, and flush out any 40 | * requests the event handlers may have written. Specification of a timeout allows the wait to be bounded. If any 41 | * events are already pending dispatch (have been read from the display by another thread or event queue), they 42 | * will be dispatched and the function will return immediately, without waiting for new events to arrive. 43 | * 44 | * @param display Wayland display to dispatch events from 45 | * @param queue Event queue to dispatch events from; other event queues will not have their handlers called from 46 | * within this function 47 | * @param timeout Maximum time to wait for events to arrive, in milliseconds 48 | * @return 1 if one or more events were dispatched on this queue, 0 if the timeout was reached without any 49 | * events being dispatched, or -1 on error. 50 | */ 51 | int dispatch_queue(struct wl_display *display, struct wl_event_queue *queue, int timeout); 52 | -------------------------------------------------------------------------------- /wsi/wayland/wl_object_owner.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, 2024 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #ifndef __STDC_VERSION__ 28 | #define __STDC_VERSION__ 0 29 | #endif 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace wsi 38 | { 39 | namespace wayland 40 | { 41 | 42 | static inline void wayland_object_destroy(wl_registry *obj) 43 | { 44 | wl_registry_destroy(obj); 45 | } 46 | 47 | static inline void wayland_object_destroy(zwp_linux_dmabuf_v1 *obj) 48 | { 49 | zwp_linux_dmabuf_v1_destroy(obj); 50 | } 51 | 52 | static inline void wayland_object_destroy(zwp_linux_explicit_synchronization_v1 *obj) 53 | { 54 | zwp_linux_explicit_synchronization_v1_destroy(obj); 55 | } 56 | 57 | static inline void wayland_object_destroy(zwp_linux_surface_synchronization_v1 *obj) 58 | { 59 | zwp_linux_surface_synchronization_v1_destroy(obj); 60 | } 61 | 62 | static inline void wayland_object_destroy(wp_presentation *obj) 63 | { 64 | wp_presentation_destroy(obj); 65 | } 66 | 67 | static inline void wayland_object_destroy(wl_callback *obj) 68 | { 69 | wl_callback_destroy(obj); 70 | } 71 | 72 | static inline void wayland_object_destroy(wl_event_queue *obj) 73 | { 74 | wl_event_queue_destroy(obj); 75 | } 76 | 77 | template 78 | struct wayland_deleter 79 | { 80 | void operator()(T *obj) const 81 | { 82 | if (obj != nullptr) 83 | { 84 | wayland_object_destroy(obj); 85 | } 86 | } 87 | }; 88 | 89 | template 90 | using wayland_owner = std::unique_ptr>; 91 | 92 | template 93 | static std::unique_ptr> make_proxy_with_queue(T *object, wl_event_queue *queue) 94 | { 95 | auto proxy = reinterpret_cast(wl_proxy_create_wrapper(object)); 96 | if (proxy != nullptr) 97 | { 98 | wl_proxy_set_queue(reinterpret_cast(proxy), queue); 99 | } 100 | 101 | auto delete_proxy = [](T *proxy) { wl_proxy_wrapper_destroy(reinterpret_cast(proxy)); }; 102 | 103 | return std::unique_ptr>(proxy, delete_proxy); 104 | } 105 | 106 | } // namespace wayland 107 | } // namespace wsi 108 | -------------------------------------------------------------------------------- /wsi/wsi_factory.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, 2021, 2023 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file 27 | * @brief Contains the factory methods for obtaining the specific surface and swapchain implementations. 28 | */ 29 | 30 | #pragma once 31 | 32 | #include "swapchain_base.hpp" 33 | #include "surface_properties.hpp" 34 | #include "util/platform_set.hpp" 35 | 36 | #include 37 | 38 | namespace wsi 39 | { 40 | 41 | /** 42 | * @brief Obtains the surface properties for the specific surface type. 43 | * 44 | * @param instance_data The instance specific data. 45 | * @param surface The surface for which to get the properties. 46 | * 47 | * @return nullptr if surface type is unsupported. 48 | */ 49 | surface_properties *get_surface_properties(layer::instance_private_data &instance_data, VkSurfaceKHR surface); 50 | 51 | /** 52 | * @brief Allocates a surface specific swapchain. 53 | * 54 | * @param surface The surface for which a swapchain is allocated. 55 | * @param dev_data The device specific data. 56 | * @param pAllocator The allocator from which to allocate any memory. 57 | * 58 | * @return nullptr on failure. 59 | */ 60 | util::unique_ptr allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data, 61 | const VkAllocationCallbacks *pAllocator); 62 | 63 | /** 64 | * @brief Destroys a swapchain and frees memory. Used with @ref allocate_surface_swapchain. 65 | * 66 | * @param swapchain Pointer to the swapchain to destroy. 67 | * @param dev_data The device specific data. 68 | * @param pAllocator The allocator to use for freeing memory. 69 | */ 70 | void destroy_surface_swapchain(swapchain_base *swapchain, layer::device_private_data &dev_data, 71 | const VkAllocationCallbacks *pAllocator); 72 | 73 | /** 74 | * @brief Return which platforms the layer can handle for an instance constructed in the specified way. 75 | * 76 | * @details This function looks at the extensions specified in @p pCreateInfo and based on this returns a list of 77 | * platforms that the layer can support. For example, if the @c pCreateInfo.ppEnabledExtensionNames contains the string 78 | * "VK_EXT_headless_surface" then the returned platform set will contain @c VK_ICD_WSI_PLATFORM_HEADLESS. 79 | * 80 | * @param pCreateInfo Structure used when creating the instance in vkCreateInstance(). 81 | * 82 | * @return A list of WS platforms supported by the layer. 83 | */ 84 | util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *pCreateInfo); 85 | 86 | /** 87 | * @brief Add extra extensions that the layer requires to support the specified list of enabled platforms. 88 | * 89 | * @details Check whether @p phys_dev has support for the extensions required by the layer in order to support the 90 | * platforms it implements. The extensions that the layer requires to operate are added to @p extensions_to_enable. 91 | * 92 | * @param[in] phys_dev The physical device to check. 93 | * @param[in] enabled_platforms All the platforms that the layer must enable for @p phys_dev. 94 | * @param[in,out] extensions_to_enable All the extensions required by the layer are added to this list. 95 | * 96 | * @retval @c VK_SUCCESS if the operation was successful. 97 | */ 98 | VkResult add_device_extensions_required_by_layer(VkPhysicalDevice phys_dev, 99 | const util::wsi_platform_set enabled_platforms, 100 | util::extension_list &extensions_to_enable); 101 | 102 | /** 103 | * @brief Add required instance extensions by the layer. 104 | * 105 | * @param[in] enabled_platforms All the enabled platforms for the current instance. 106 | * @param[in,out] extensions_to_enable All the extensions required by the layer are added to this list. 107 | * 108 | * @retval @c VK_SUCCESS if the operation was successful. 109 | */ 110 | VkResult add_instance_extensions_required_by_layer(const util::wsi_platform_set enabled_platforms, 111 | util::extension_list &extensions_to_enable); 112 | 113 | /** 114 | * @brief Return a function pointer for surface specific functions. 115 | * 116 | * @details This function iterates through the supported platforms and queries them for the 117 | * implementation of the @p name function. 118 | * 119 | * @param name The name of the target function 120 | * @param instance_data The instance specific data. 121 | * 122 | * @return A pointer to the implementation of the @p name function or null pointer in case this 123 | * function isn't implemented for any platform. 124 | */ 125 | PFN_vkVoidFunction get_proc_addr(const char *name, const layer::instance_private_data &instance_data); 126 | 127 | } // namespace wsi 128 | -------------------------------------------------------------------------------- /wsi/x11/surface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** @file 26 | * @brief Implementation of a x11 WSI Surface 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "surface.hpp" 34 | #include "swapchain.hpp" 35 | #include "surface_properties.hpp" 36 | 37 | namespace wsi 38 | { 39 | namespace x11 40 | { 41 | 42 | struct surface::init_parameters 43 | { 44 | const util::allocator &allocator; 45 | xcb_connection_t *connection; 46 | xcb_window_t window; 47 | }; 48 | 49 | surface::surface(const init_parameters ¶ms) 50 | : wsi::surface() 51 | , m_connection(params.connection) 52 | , m_window(params.window) 53 | , properties(this, params.allocator) 54 | { 55 | } 56 | 57 | surface::~surface() 58 | { 59 | } 60 | 61 | bool surface::init() 62 | { 63 | auto dri3_cookie = xcb_dri3_query_version_unchecked(m_connection, 1, 2); 64 | auto dri3_reply = xcb_dri3_query_version_reply(m_connection, dri3_cookie, nullptr); 65 | auto has_dri3 = dri3_reply && (dri3_reply->major_version > 1 || dri3_reply->minor_version >= 2); 66 | free(dri3_reply); 67 | 68 | auto present_cookie = xcb_present_query_version_unchecked(m_connection, 1, 2); 69 | auto present_reply = xcb_present_query_version_reply(m_connection, present_cookie, nullptr); 70 | auto has_present = present_reply && (present_reply->major_version > 1 || present_reply->minor_version >= 2); 71 | free(present_reply); 72 | 73 | if (!has_dri3 || !has_present) 74 | { 75 | WSI_LOG_ERROR("DRI3 extension not present"); 76 | return false; 77 | } 78 | 79 | return true; 80 | } 81 | 82 | bool surface::get_size_and_depth(uint32_t *width, uint32_t *height, int *depth) 83 | { 84 | auto cookie = xcb_get_geometry(m_connection, m_window); 85 | if (auto *geom = xcb_get_geometry_reply(m_connection, cookie, nullptr)) 86 | { 87 | *width = static_cast(geom->width); 88 | *height = static_cast(geom->height); 89 | *depth = static_cast(geom->depth); 90 | free(geom); 91 | return true; 92 | } 93 | return false; 94 | } 95 | 96 | wsi::surface_properties &surface::get_properties() 97 | { 98 | return properties; 99 | } 100 | 101 | util::unique_ptr surface::allocate_swapchain(layer::device_private_data &dev_data, 102 | const VkAllocationCallbacks *allocator) 103 | { 104 | util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, allocator }; 105 | auto chain = util::unique_ptr(alloc.make_unique(dev_data, allocator, this)); 106 | 107 | return chain; 108 | } 109 | 110 | util::unique_ptr surface::make_surface(const util::allocator &allocator, xcb_connection_t *conn, 111 | xcb_window_t window) 112 | { 113 | init_parameters params{ allocator, conn, window }; 114 | auto wsi_surface = allocator.make_unique(params); 115 | if (wsi_surface != nullptr) 116 | { 117 | if (wsi_surface->init()) 118 | { 119 | return wsi_surface; 120 | } 121 | } 122 | return nullptr; 123 | } 124 | 125 | } /* namespace x11 */ 126 | } /* namespace wsi */ 127 | -------------------------------------------------------------------------------- /wsi/x11/surface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** @file 26 | * @brief Definitions for a x11 WSI Surface 27 | */ 28 | 29 | #pragma once 30 | #include 31 | #include 32 | #include 33 | #include "wsi/surface.hpp" 34 | #include "surface_properties.hpp" 35 | 36 | namespace wsi 37 | { 38 | namespace x11 39 | { 40 | 41 | class surface : public wsi::surface 42 | { 43 | public: 44 | /** 45 | * @brief Initialize the WSI surface. 46 | * 47 | * @return true on success, false otherwise. 48 | */ 49 | bool init(); 50 | 51 | surface() = delete; 52 | struct init_parameters; 53 | 54 | surface(const init_parameters &); 55 | ~surface(); 56 | 57 | wsi::surface_properties &get_properties() override; 58 | util::unique_ptr allocate_swapchain(layer::device_private_data &dev_data, 59 | const VkAllocationCallbacks *allocator) override; 60 | static util::unique_ptr make_surface(const util::allocator &allocator, xcb_connection_t *conn, 61 | xcb_window_t window); 62 | 63 | bool get_size_and_depth(uint32_t *width, uint32_t *height, int *depth); 64 | 65 | xcb_connection_t *get_connection() 66 | { 67 | return m_connection; 68 | } 69 | 70 | xcb_window_t get_window() 71 | { 72 | return m_window; 73 | }; 74 | 75 | private: 76 | xcb_connection_t *m_connection; 77 | xcb_window_t m_window; 78 | /** Surface properties specific to the X11 surface. */ 79 | surface_properties properties; 80 | }; 81 | 82 | } /* namespace x11 */ 83 | } /* namespace wsi */ 84 | -------------------------------------------------------------------------------- /wsi/x11/surface_properties.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019, 2021-2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | namespace wsi 31 | { 32 | namespace x11 33 | { 34 | 35 | class surface; 36 | 37 | class surface_properties : public wsi::surface_properties 38 | { 39 | public: 40 | surface_properties(surface *wsi_surface, const util::allocator &alloc); 41 | 42 | static surface_properties &get_instance(); 43 | 44 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 45 | VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override; 46 | VkResult get_surface_capabilities(VkPhysicalDevice physical_device, 47 | const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 48 | VkSurfaceCapabilities2KHR *pSurfaceCapabilities) override; 49 | VkResult get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount, 50 | VkSurfaceFormatKHR *surfaceFormats, 51 | VkSurfaceFormat2KHR *extended_surface_formats) override; 52 | VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface, 53 | uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override; 54 | 55 | VkResult get_required_device_extensions(util::extension_list &extension_list) override; 56 | 57 | VkResult get_required_instance_extensions(util::extension_list &extension_list) override; 58 | 59 | PFN_vkVoidFunction get_proc_addr(const char *name) override; 60 | 61 | bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override; 62 | 63 | bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) override; 64 | 65 | #if VULKAN_WSI_LAYER_EXPERIMENTAL 66 | void get_present_timing_surface_caps(VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; 67 | #endif 68 | private: 69 | surface_properties(); 70 | 71 | /** If the properties are specific to a @ref wsi::wayland::surface this is a pointer to it. Can be nullptr for 72 | * generic Wayland surface properties. 73 | */ 74 | surface *specific_surface; 75 | 76 | /* List of supported presentation modes */ 77 | std::array m_supported_modes; 78 | 79 | /* Stores compatible presentation modes */ 80 | compatible_present_modes<2> m_compatible_present_modes; 81 | 82 | void populate_present_mode_compatibilities() override; 83 | 84 | void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; 85 | }; 86 | 87 | } // namespace x11 88 | } // namespace wsi 89 | -------------------------------------------------------------------------------- /wsi/x11/swapchain.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019, 2021-2022 Arm Limited. 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /** 26 | * @file swapchain.hpp 27 | * 28 | * @brief Contains the class definition for a x11 swapchain. 29 | */ 30 | 31 | #pragma once 32 | 33 | #include "surface.hpp" 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | namespace wsi 46 | { 47 | namespace x11 48 | { 49 | 50 | using pfnAHardwareBuffer_release = void (*)(AHardwareBuffer *); 51 | using pfnAHardwareBuffer_sendHandleToUnixSocket = int (*)(AHardwareBuffer *, int); 52 | 53 | /** 54 | * @brief x11 swapchain class. 55 | * 56 | * This class is mostly empty, because all the swapchain stuff is handled by the swapchain class, 57 | * which we inherit. This class only provides a way to create an image and page-flip ops. 58 | */ 59 | class swapchain : public wsi::swapchain_base 60 | { 61 | public: 62 | explicit swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator, 63 | surface *wsi_surface); 64 | 65 | ~swapchain(); 66 | 67 | protected: 68 | /** 69 | * @brief Platform specific init 70 | */ 71 | VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info, 72 | bool &use_presentation_thread) override; 73 | /** 74 | * @brief Allocates and binds a new swapchain image. 75 | * 76 | * @param image_create_info Data to be used to create the image. 77 | * @param image Handle to the image. 78 | * 79 | * @return Returns VK_SUCCESS on success, otherwise an appropriate error code. 80 | */ 81 | VkResult allocate_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; 82 | 83 | /** 84 | * @brief Creates a new swapchain image. 85 | * 86 | * @param image_create_info Data to be used to create the image. 87 | * @param image Handle to the image. 88 | * 89 | * @return If image creation is successful returns VK_SUCCESS, otherwise 90 | * will return VK_ERROR_OUT_OF_DEVICE_MEMORY or VK_ERROR_INITIALIZATION_FAILED 91 | * depending on the error that occurred. 92 | */ 93 | VkResult create_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; 94 | 95 | /** 96 | * @brief Method to present and image 97 | * 98 | * It sends the next image for presentation to the presentation engine. 99 | * 100 | * @param pending_present Information on the pending present request. 101 | */ 102 | void present_image(const pending_present_request &pending_present) override; 103 | 104 | /** 105 | * @brief Method to release a swapchain image 106 | * 107 | * @param image Handle to the image about to be released. 108 | */ 109 | void destroy_image(wsi::swapchain_image &image) override; 110 | 111 | /** 112 | * @brief Sets the present payload for a swapchain image. 113 | * 114 | * @param[in] image The swapchain image for which to set a present payload. 115 | * @param queue A Vulkan queue that can be used for any Vulkan commands needed. 116 | * @param[in] sem_payload Array of Vulkan semaphores that constitute the payload. 117 | * @param[in] submission_pnext Chain of pointers to attach to the payload submission. 118 | * 119 | * @return VK_SUCCESS on success or an error code otherwise. 120 | */ 121 | VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const queue_submit_semaphores &semaphores, 122 | const void *submission_pnext) override; 123 | 124 | VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override; 125 | 126 | /** 127 | * @brief Bind image to a swapchain 128 | * 129 | * @param device is the logical device that owns the images and memory. 130 | * @param bind_image_mem_info details the image we want to bind. 131 | * @param bind_sc_info describes the swapchain memory to bind to. 132 | * 133 | * @return VK_SUCCESS on success, otherwise on failure VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY 134 | * can be returned. 135 | */ 136 | VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info, 137 | const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override; 138 | 139 | /** 140 | * @brief Method to check if there are any free images 141 | * 142 | * @return true if any images are free, otherwise false. 143 | */ 144 | bool free_image_found(); 145 | 146 | /** 147 | * @brief Hook for any actions to free up a buffer for acquire 148 | * 149 | * @param[in,out] timeout time to wait, in nanoseconds. 0 doesn't block, 150 | * UINT64_MAX waits indefinitely. The timeout should 151 | * be updated if a sleep is required - this can 152 | * be set to 0 if the semaphore is now not expected 153 | * block. 154 | */ 155 | VkResult get_free_buffer(uint64_t *timeout) override; 156 | 157 | private: 158 | xcb_connection_t *m_connection; 159 | xcb_window_t m_window; 160 | 161 | surface *m_surface; 162 | uint64_t m_send_sbc; 163 | uint64_t m_target_msc; 164 | uint64_t m_last_present_msc; 165 | 166 | xcb_special_event_t *m_special_event; 167 | VkPhysicalDeviceMemoryProperties2 m_memory_props; 168 | 169 | xcb_pixmap_t create_pixmap(swapchain_image &image); 170 | 171 | void present_event_thread(); 172 | bool m_present_event_thread_run; 173 | std::thread m_present_event_thread; 174 | std::mutex m_thread_status_lock; 175 | std::condition_variable m_thread_status_cond; 176 | util::ring_buffer m_free_buffer_pool; 177 | 178 | pfnAHardwareBuffer_release HardwareBuffer_release; 179 | pfnAHardwareBuffer_sendHandleToUnixSocket HardwareBuffer_sendHandleToUnixSocket; 180 | }; 181 | 182 | } /* namespace x11 */ 183 | } /* namespace wsi */ 184 | --------------------------------------------------------------------------------