├── .dir-locals.el ├── .editorconfig ├── .github ├── scripts │ ├── epoxy-ci-linux.sh │ └── epoxy-ci-osx.sh └── workflows │ ├── linux.yml │ ├── macos.yml │ ├── msvc-env.yml │ └── msys2.yml ├── .gitignore ├── COPYING ├── README.md ├── cross └── fedora-mingw64.txt ├── doc ├── Doxyfile.in └── meson.build ├── include └── epoxy │ ├── common.h │ ├── egl.h │ ├── gl.h │ ├── glx.h │ ├── meson.build │ └── wgl.h ├── meson.build ├── meson_options.txt ├── registry ├── README.md ├── egl.xml ├── gl.xml ├── glx.xml └── wgl.xml ├── src ├── dispatch_common.c ├── dispatch_common.h ├── dispatch_egl.c ├── dispatch_glx.c ├── dispatch_wgl.c ├── gen_dispatch.py └── meson.build └── test ├── cgl_core.c ├── cgl_epoxy_api.c ├── dlwrap.c ├── dlwrap.h ├── egl_common.c ├── egl_common.h ├── egl_epoxy_api.c ├── egl_gl.c ├── egl_has_extension_nocontext.c ├── egl_without_glx.c ├── gl_version.c ├── glx_alias_prefer_same_name.c ├── glx_beginend.c ├── glx_common.c ├── glx_common.h ├── glx_gles2.c ├── glx_glxgetprocaddress_nocontext.c ├── glx_has_extension_nocontext.c ├── glx_public_api.c ├── glx_public_api_core.c ├── glx_static.c ├── headerguards.c ├── khronos_typedefs.c ├── khronos_typedefs.h ├── khronos_typedefs_nonepoxy.c ├── meson.build ├── miscdefines.c ├── wgl_common.c ├── wgl_common.h ├── wgl_core_and_exts.c ├── wgl_per_context_funcptrs.c └── wgl_usefontbitmaps.c /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((nil 2 | (indent-tabs-mode . nil) 3 | (tab-width . 8) 4 | (c-basic-offset . 4) 5 | ) 6 | ) 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | 6 | [*.{c,h}] 7 | indent_style = space 8 | indent_size = 4 9 | end_of_line = lf 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [.travis.yml] 14 | indent_style = space 15 | indent_size = 2 16 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | 20 | [meson.build] 21 | indent_style = space 22 | indent_size = 8 23 | -------------------------------------------------------------------------------- /.github/scripts/epoxy-ci-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dump_log_and_quit() { 4 | local exitcode=$1 5 | 6 | cat meson-logs/testlog.txt 7 | 8 | exit $exitcode 9 | } 10 | 11 | # Start Xvfb 12 | XVFB_WHD=${XVFB_WHD:-1280x720x16} 13 | 14 | Xvfb :99 -ac -screen 0 $XVFB_WHD -nolisten tcp & 15 | xvfb=$! 16 | 17 | export DISPLAY=:99 18 | 19 | srcdir=$( pwd ) 20 | builddir=$( mktemp -d build_XXXXXX ) 21 | 22 | meson --prefix /usr "$@" $builddir $srcdir || exit $? 23 | 24 | cd $builddir 25 | 26 | ninja || exit $? 27 | meson test || dump_log_and_quit $? 28 | 29 | cd .. 30 | 31 | # Stop Xvfb 32 | kill -9 ${xvfb} 33 | -------------------------------------------------------------------------------- /.github/scripts/epoxy-ci-osx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | dump_log_and_quit() { 4 | local exitcode=$1 5 | 6 | cat meson-logs/testlog.txt 7 | 8 | exit $exitcode 9 | } 10 | 11 | export SDKROOT=$( xcodebuild -version -sdk macosx Path ) 12 | export CPPFLAGS=-I/usr/local/include 13 | export LDFLAGS=-L/usr/local/lib 14 | export OBJC=$CC 15 | export PATH=$HOME/tools:$PATH 16 | 17 | srcdir=$( pwd ) 18 | builddir=$( mktemp -d build_XXXXXX ) 19 | 20 | meson ${BUILDOPTS} $builddir $srcdir || exit $? 21 | 22 | cd $builddir 23 | 24 | ninja || exit $? 25 | meson test || dump_log_and_quit $? 26 | 27 | cd .. 28 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu 2 | on: 3 | push: 4 | branches-ignore: 5 | - debian 6 | - khronos-registry 7 | jobs: 8 | build: 9 | strategy: 10 | matrix: 11 | os: 12 | - ubuntu-18.04 13 | compiler: 14 | - gcc 15 | - clang 16 | build-opts: 17 | - '' 18 | - '-Dglx=no' 19 | - '-Degl=no' 20 | - '-Dx11=false' 21 | runs-on: ${{ matrix.os }} 22 | steps: 23 | - uses: actions/checkout@v2 24 | - run: > 25 | sudo apt-get update && 26 | sudo apt-get install --no-install-recommends 27 | libgl1-mesa-dev 28 | libegl1-mesa-dev 29 | libgles2-mesa-dev 30 | libgl1-mesa-dri 31 | ninja-build 32 | - uses: actions/setup-python@v2 33 | with: 34 | python-version: 3.x 35 | - run: | 36 | python -m pip install --upgrade pip 37 | pip3 install meson 38 | /bin/sh -c "CC=${{ matrix.compiler }} .github/scripts/epoxy-ci-linux.sh ${{ matrix.build-opts }}" 39 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | on: 3 | push: 4 | branches-ignore: 5 | - debian 6 | - khronos-registry 7 | jobs: 8 | build: 9 | strategy: 10 | matrix: 11 | build-opts: 12 | - '' 13 | - '-Dglx=no' 14 | - '-Degl=no' 15 | - '-Dx11=false' 16 | runs-on: macos-10.15 17 | steps: 18 | - uses: actions/checkout@v2 19 | - uses: actions/setup-python@v2 20 | with: 21 | python-version: 3.x 22 | - run: | 23 | brew install ninja 24 | python -m pip install --upgrade pip 25 | pip3 install meson 26 | /bin/sh -c "CC=clang .github/scripts/epoxy-ci-osx.sh ${{ matrix.build-opts }}" 27 | -------------------------------------------------------------------------------- /.github/workflows/msvc-env.yml: -------------------------------------------------------------------------------- 1 | name: MSVC Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: windows-latest 12 | env: 13 | PYTHONIOENCODING: "utf-8" 14 | steps: 15 | - uses: actions/checkout@master 16 | - uses: actions/setup-python@v1 17 | - uses: seanmiddleditch/gha-setup-vsdevenv@master 18 | - uses: BSFishy/meson-build@v1.0.1 19 | with: 20 | action: test 21 | directory: _build 22 | options: --verbose --fatal-meson-warnings 23 | meson-version: 0.54.3 24 | -------------------------------------------------------------------------------- /.github/workflows/msys2.yml: -------------------------------------------------------------------------------- 1 | name: MSYS2 Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: windows-latest 12 | defaults: 13 | run: 14 | shell: msys2 {0} 15 | env: 16 | PYTHONIOENCODING: "utf-8" 17 | steps: 18 | - uses: actions/checkout@master 19 | - uses: msys2/setup-msys2@v2 20 | with: 21 | msystem: MINGW64 22 | update: true 23 | install: base-devel git mingw-w64-x86_64-meson mingw-w64-x86_64-ninja mingw-w64-x86_64-pkg-config mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-pip mingw-w64-x86_64-toolchain 24 | - name: Build 25 | run: | 26 | meson setup _build 27 | meson compile -C _build 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # X.Org module default exclusion patterns 3 | # The next section if for module specific patterns 4 | # 5 | # Do not edit the following section 6 | # GNU Build System (Autotools) 7 | aclocal.m4 8 | autom4te.cache/ 9 | autoscan.log 10 | ChangeLog 11 | compile 12 | config.guess 13 | config.h 14 | config.h.in 15 | config.log 16 | config-ml.in 17 | config.py 18 | config.status 19 | config.status.lineno 20 | config.sub 21 | configure 22 | configure.scan 23 | depcomp 24 | .deps/ 25 | INSTALL 26 | install-sh 27 | .libs/ 28 | libtool 29 | libtool.m4 30 | ltmain.sh 31 | lt~obsolete.m4 32 | ltoptions.m4 33 | ltsugar.m4 34 | ltversion.m4 35 | Makefile 36 | Makefile.in 37 | mdate-sh 38 | missing 39 | mkinstalldirs 40 | *.pc 41 | py-compile 42 | stamp-h? 43 | symlink-tree 44 | texinfo.tex 45 | ylwrap 46 | src/sna/git_version.h 47 | src/sna/brw/brw_test 48 | 49 | # Do not edit the following section 50 | # Edit Compile Debug Document Distribute 51 | *~ 52 | *.[0-9] 53 | *.[0-9]x 54 | *.bak 55 | *.bin 56 | core 57 | *.dll 58 | *.exe 59 | *-ISO*.bdf 60 | *-JIS*.bdf 61 | *-KOI8*.bdf 62 | *.kld 63 | *.ko 64 | *.ko.cmd 65 | *.lai 66 | *.l[oa] 67 | *.[oa] 68 | *.obj 69 | *.so 70 | *.pcf.gz 71 | *.pdb 72 | *.tar.bz2 73 | *.tar.gz 74 | # 75 | # Add & Override patterns for gldispatch 76 | # 77 | # Edit the following section as needed 78 | # For example, !report.pc overrides *.pc. See 'man gitignore' 79 | # 80 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | The libepoxy project code is covered by the MIT license: 2 | 3 | /* 4 | * Copyright © 2013-2014 Intel Corporation 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice (including the next 14 | * paragraph) shall be included in all copies or substantial portions of the 15 | * 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 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | The generated code is derived from Khronos's xml files, which appear 27 | under the following license: 28 | 29 | /* 30 | * Copyright (c) 2013 The Khronos Group Inc. 31 | * 32 | * Permission is hereby granted, free of charge, to any person obtaining a 33 | * copy of this software and/or associated documentation files (the 34 | * "Materials"), to deal in the Materials without restriction, including 35 | * without limitation the rights to use, copy, modify, merge, publish, 36 | * distribute, sublicense, and/or sell copies of the Materials, and to 37 | * permit persons to whom the Materials are furnished to do so, subject to 38 | * the following conditions: 39 | * 40 | * The above copyright notice and this permission notice shall be included 41 | * in all copies or substantial portions of the Materials. 42 | * 43 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 44 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 45 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 46 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 47 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 48 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 49 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 50 | */ 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Ubuntu](https://github.com/anholt/libepoxy/workflows/Ubuntu/badge.svg) 2 | ![macOS](https://github.com/anholt/libepoxy/workflows/macOS/badge.svg) 3 | ![MSVC Build](https://github.com/anholt/libepoxy/workflows/MSVC%20Build/badge.svg) 4 | ![MSYS2 Build](https://github.com/anholt/libepoxy/workflows/MSYS2%20Build/badge.svg) 5 | [![License: MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) 6 | 7 | Epoxy is a library for handling OpenGL function pointer management for 8 | you. 9 | 10 | It hides the complexity of `dlopen()`, `dlsym()`, `glXGetProcAddress()`, 11 | `eglGetProcAddress()`, etc. from the app developer, with very little 12 | knowledge needed on their part. They get to read GL specs and write 13 | code using undecorated function names like `glCompileShader()`. 14 | 15 | Don't forget to check for your extensions or versions being present 16 | before you use them, just like before! We'll tell you what you forgot 17 | to check for instead of just segfaulting, though. 18 | 19 | Features 20 | -------- 21 | 22 | * Automatically initializes as new GL functions are used. 23 | * GL 4.6 core and compatibility context support. 24 | * GLES 1/2/3 context support. 25 | * Knows about function aliases so (e.g.) `glBufferData()` can be 26 | used with `GL_ARB_vertex_buffer_object` implementations, along 27 | with GL 1.5+ implementations. 28 | * EGL, GLX, and WGL support. 29 | * Can be mixed with non-epoxy GL usage. 30 | 31 | Building 32 | -------- 33 | 34 | ```sh 35 | mkdir _build && cd _build 36 | meson 37 | ninja 38 | sudo ninja install 39 | ``` 40 | 41 | Dependencies for Debian: 42 | 43 | * meson 44 | * libegl1-mesa-dev 45 | 46 | Dependencies for macOS (using MacPorts): 47 | 48 | * pkgconfig 49 | * meson 50 | 51 | The test suite has additional dependencies depending on the platform. 52 | (X11, EGL, a running X Server). 53 | 54 | Switching your code to using epoxy 55 | ---------------------------------- 56 | 57 | It should be as easy as replacing: 58 | 59 | ```cpp 60 | #include 61 | #include 62 | #include 63 | ``` 64 | 65 | with: 66 | 67 | ```cpp 68 | #include 69 | #include 70 | ``` 71 | 72 | As long as epoxy's headers appear first, you should be ready to go. 73 | Additionally, some new helpers become available, so you don't have to 74 | write them: 75 | 76 | `int epoxy_gl_version()` returns the GL version: 77 | 78 | * 12 for GL 1.2 79 | * 20 for GL 2.0 80 | * 44 for GL 4.4 81 | 82 | `bool epoxy_has_gl_extension()` returns whether a GL extension is 83 | available (`GL_ARB_texture_buffer_object`, for example). 84 | 85 | Note that this is not terribly fast, so keep it out of your hot paths, 86 | ok? 87 | 88 | Why not use libGLEW? 89 | -------------------- 90 | 91 | GLEW has several issues: 92 | 93 | * Doesn't know about aliases of functions (There are 5 providers of 94 | `glPointParameterfv()`, for example, and you don't want to have to 95 | choose which one to call when they're all the same). 96 | * Doesn't support OpenGL ES. 97 | * Has a hard-to-maintain parser of extension specification text 98 | instead of using the old .spec file or the new .xml. 99 | * Has significant startup time overhead when `glewInit()` 100 | autodetects the world. 101 | * User-visible multithreading support choice for win32. 102 | 103 | The motivation for this project came out of previous use of libGLEW in 104 | [piglit](http://piglit.freedesktop.org/). Other GL dispatch code 105 | generation projects had similar failures. Ideally, piglit wants to be 106 | able to build a single binary for a test that can run on whatever 107 | context or window system it chooses, not based on link time choices. 108 | 109 | We had to solve some of GLEW's problems for piglit and solving them 110 | meant replacing every single piece of GLEW, so we built 111 | piglit-dispatch from scratch. And since we wanted to reuse it in 112 | other GL-related projects, this is the result. 113 | 114 | Known issues when running on Windows 115 | ------------------------------------ 116 | 117 | The automatic per-context symbol resolution for win32 requires that 118 | epoxy knows when `wglMakeCurrent()` is called, because `wglGetProcAddress()` 119 | returns values depend on the context's device and pixel format. If 120 | `wglMakeCurrent()` is called from outside of epoxy (in a way that might 121 | change the device or pixel format), then epoxy needs to be notified of 122 | the change using the `epoxy_handle_external_wglMakeCurrent()` function. 123 | 124 | The win32 `wglMakeCurrent()` variants are slower than they should be, 125 | because they should be caching the resolved dispatch tables instead of 126 | resetting an entire thread-local dispatch table every time. 127 | -------------------------------------------------------------------------------- /cross/fedora-mingw64.txt: -------------------------------------------------------------------------------- 1 | [binaries] 2 | c = '/usr/bin/x86_64-w64-mingw32-gcc' 3 | cpp = '/usr/bin/x86_64-w64-mingw32-cpp' 4 | ar = '/usr/bin/x86_64-w64-mingw32-ar' 5 | strip = '/usr/bin/x86_64-w64-mingw32-strip' 6 | pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config' 7 | exe_wrapper = 'wine' 8 | 9 | [properties] 10 | root = '/usr/x86_64-w64-mingw32/sys-root/mingw' 11 | c_args = [ '-pipe', '-Wp,-D_FORTIFY_SOURCE=2', '-fexceptions', '--param=ssp-buffer-size=4', '-I/usr/x86_64-w64-mingw32/sys-root/mingw/include' ] 12 | c_link_args = [ '-L/usr/x86_64-w64-mingw32/sys-root/mingw/lib' ] 13 | 14 | [host_machine] 15 | system = 'windows' 16 | cpu_family = 'x86_64' 17 | cpu = 'x86_64' 18 | endian = 'little' 19 | -------------------------------------------------------------------------------- /doc/Doxyfile.in: -------------------------------------------------------------------------------- 1 | DOXYFILE_ENCODING = UTF-8 2 | PROJECT_NAME = @PACKAGE_NAME@ 3 | PROJECT_NUMBER = @PACKAGE_VERSION@ 4 | PROJECT_BRIEF = 5 | PROJECT_LOGO = 6 | OUTPUT_DIRECTORY = doc 7 | CREATE_SUBDIRS = NO 8 | ALLOW_UNICODE_NAMES = YES 9 | OUTPUT_LANGUAGE = English 10 | BRIEF_MEMBER_DESC = YES 11 | REPEAT_BRIEF = YES 12 | ABBREVIATE_BRIEF = 13 | ALWAYS_DETAILED_SEC = NO 14 | INLINE_INHERITED_MEMB = NO 15 | FULL_PATH_NAMES = YES 16 | STRIP_FROM_PATH = "@top_srcdir@/include" "@top_builddir@/include" 17 | 18 | SHORT_NAMES = NO 19 | JAVADOC_AUTOBRIEF = YES 20 | QT_AUTOBRIEF = NO 21 | MULTILINE_CPP_IS_BRIEF = NO 22 | INHERIT_DOCS = YES 23 | SEPARATE_MEMBER_PAGES = NO 24 | TAB_SIZE = 8 25 | ALIASES = "newin{2}=\xrefitem since_\1_\2 \"Since @PACKAGE_NAME@ \1.\2\" \"New API in @PACKAGE_NAME@ \1.\2\"" 26 | TCL_SUBST = 27 | OPTIMIZE_OUTPUT_FOR_C = YES 28 | OPTIMIZE_OUTPUT_JAVA = NO 29 | OPTIMIZE_FOR_FORTRAN = NO 30 | OPTIMIZE_OUTPUT_VHDL = NO 31 | EXTENSION_MAPPING = 32 | MARKDOWN_SUPPORT = YES 33 | AUTOLINK_SUPPORT = YES 34 | BUILTIN_STL_SUPPORT = NO 35 | CPP_CLI_SUPPORT = NO 36 | SIP_SUPPORT = NO 37 | IDL_PROPERTY_SUPPORT = NO 38 | DISTRIBUTE_GROUP_DOC = NO 39 | GROUP_NESTED_COMPOUNDS = NO 40 | SUBGROUPING = YES 41 | INLINE_GROUPED_CLASSES = NO 42 | INLINE_SIMPLE_STRUCTS = NO 43 | TYPEDEF_HIDES_STRUCT = NO 44 | LOOKUP_CACHE_SIZE = 0 45 | 46 | EXTRACT_ALL = YES 47 | EXTRACT_PRIVATE = NO 48 | EXTRACT_PACKAGE = NO 49 | EXTRACT_STATIC = NO 50 | EXTRACT_LOCAL_CLASSES = NO 51 | EXTRACT_LOCAL_METHODS = NO 52 | EXTRACT_ANON_NSPACES = NO 53 | HIDE_UNDOC_MEMBERS = YES 54 | HIDE_UNDOC_CLASSES = YES 55 | HIDE_FRIEND_COMPOUNDS = YES 56 | HIDE_IN_BODY_DOCS = YES 57 | INTERNAL_DOCS = NO 58 | CASE_SENSE_NAMES = YES 59 | HIDE_SCOPE_NAMES = NO 60 | HIDE_COMPOUND_REFERENCE= NO 61 | SHOW_INCLUDE_FILES = YES 62 | SHOW_GROUPED_MEMB_INC = NO 63 | FORCE_LOCAL_INCLUDES = NO 64 | INLINE_INFO = YES 65 | SORT_MEMBER_DOCS = YES 66 | SORT_BRIEF_DOCS = NO 67 | SORT_MEMBERS_CTORS_1ST = YES 68 | SORT_GROUP_NAMES = YES 69 | SORT_BY_SCOPE_NAME = YES 70 | STRICT_PROTO_MATCHING = NO 71 | GENERATE_TODOLIST = YES 72 | GENERATE_TESTLIST = NO 73 | GENERATE_BUGLIST = YES 74 | GENERATE_DEPRECATEDLIST= YES 75 | ENABLED_SECTIONS = 76 | MAX_INITIALIZER_LINES = 2 77 | SHOW_USED_FILES = YES 78 | SHOW_FILES = YES 79 | SHOW_NAMESPACES = NO 80 | FILE_VERSION_FILTER = 81 | LAYOUT_FILE = 82 | CITE_BIB_FILES = 83 | 84 | QUIET = YES 85 | WARNINGS = YES 86 | WARN_IF_UNDOCUMENTED = YES 87 | WARN_IF_DOC_ERROR = YES 88 | WARN_NO_PARAMDOC = YES 89 | WARN_AS_ERROR = NO 90 | WARN_FORMAT = "$file:$line: $text" 91 | WARN_LOGFILE = doc/doxygen.log 92 | 93 | INPUT = "@top_srcdir@/include/epoxy" "@top_srcdir@/src" 94 | INPUT_ENCODING = UTF-8 95 | FILE_PATTERNS = "*.h" "*.c" 96 | RECURSIVE = NO 97 | EXCLUDE = "@top_srcdir@/src/gen_dispatch.py" 98 | EXCLUDE_SYMLINKS = YES 99 | EXCLUDE_PATTERNS = 100 | EXCLUDE_SYMBOLS = _* GLAPI* KHRONOS_* APIENTRY* GLX* wgl* EPOXY_CALLSPEC EPOXY_BEGIN_DECLS EPOXY_END_DECLS 101 | EXAMPLE_PATH = 102 | EXAMPLE_PATTERNS = 103 | EXAMPLE_RECURSIVE = NO 104 | IMAGE_PATH = 105 | INPUT_FILTER = 106 | FILTER_PATTERNS = 107 | FILTER_SOURCE_FILES = NO 108 | FILTER_SOURCE_PATTERNS = 109 | USE_MDFILE_AS_MAINPAGE = 110 | 111 | SOURCE_BROWSER = NO 112 | INLINE_SOURCES = NO 113 | STRIP_CODE_COMMENTS = YES 114 | REFERENCED_BY_RELATION = NO 115 | REFERENCES_RELATION = NO 116 | REFERENCES_LINK_SOURCE = YES 117 | SOURCE_TOOLTIPS = YES 118 | USE_HTAGS = NO 119 | VERBATIM_HEADERS = NO 120 | 121 | ALPHABETICAL_INDEX = YES 122 | COLS_IN_ALPHA_INDEX = 3 123 | IGNORE_PREFIX = "epoxy" 124 | 125 | GENERATE_HTML = YES 126 | HTML_OUTPUT = html 127 | HTML_FILE_EXTENSION = .html 128 | HTML_HEADER = 129 | HTML_FOOTER = 130 | HTML_STYLESHEET = 131 | HTML_EXTRA_STYLESHEET = 132 | HTML_EXTRA_FILES = 133 | HTML_COLORSTYLE_HUE = 220 134 | HTML_COLORSTYLE_SAT = 100 135 | HTML_COLORSTYLE_GAMMA = 80 136 | HTML_TIMESTAMP = YES 137 | HTML_DYNAMIC_SECTIONS = NO 138 | HTML_INDEX_NUM_ENTRIES = 100 139 | GENERATE_DOCSET = NO 140 | DOCSET_FEEDNAME = "Doxygen generated docs" 141 | DOCSET_BUNDLE_ID = org.doxygen.Project 142 | DOCSET_PUBLISHER_ID = org.doxygen.Publisher 143 | DOCSET_PUBLISHER_NAME = Publisher 144 | GENERATE_HTMLHELP = NO 145 | CHM_FILE = 146 | HHC_LOCATION = 147 | GENERATE_CHI = NO 148 | CHM_INDEX_ENCODING = 149 | BINARY_TOC = NO 150 | TOC_EXPAND = NO 151 | GENERATE_QHP = NO 152 | QCH_FILE = 153 | QHP_NAMESPACE = 154 | QHP_VIRTUAL_FOLDER = doc 155 | QHP_CUST_FILTER_NAME = 156 | QHP_CUST_FILTER_ATTRS = 157 | QHP_SECT_FILTER_ATTRS = 158 | QHG_LOCATION = 159 | GENERATE_ECLIPSEHELP = NO 160 | ECLIPSE_DOC_ID = org.doxygen.Project 161 | DISABLE_INDEX = NO 162 | GENERATE_TREEVIEW = NO 163 | ENUM_VALUES_PER_LINE = 1 164 | TREEVIEW_WIDTH = 250 165 | EXT_LINKS_IN_WINDOW = NO 166 | FORMULA_FONTSIZE = 10 167 | FORMULA_TRANSPARENT = YES 168 | USE_MATHJAX = NO 169 | MATHJAX_FORMAT = HTML-CSS 170 | MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest 171 | MATHJAX_EXTENSIONS = 172 | MATHJAX_CODEFILE = 173 | SEARCHENGINE = NO 174 | SERVER_BASED_SEARCH = NO 175 | EXTERNAL_SEARCH = NO 176 | SEARCHENGINE_URL = 177 | SEARCHDATA_FILE = 178 | EXTERNAL_SEARCH_ID = 179 | EXTRA_SEARCH_MAPPINGS = 180 | 181 | GENERATE_LATEX = NO 182 | GENERATE_RTF = NO 183 | GENERATE_MAN = NO 184 | GENERATE_XML = NO 185 | GENERATE_DOCBOOK = NO 186 | GENERATE_AUTOGEN_DEF = NO 187 | GENERATE_PERLMOD = NO 188 | 189 | ENABLE_PREPROCESSING = YES 190 | MACRO_EXPANSION = YES 191 | EXPAND_ONLY_PREDEF = YES 192 | SEARCH_INCLUDES = YES 193 | INCLUDE_PATH = "@top_srcdir@/include" \ 194 | "@top_builddir@/include" 195 | INCLUDE_FILE_PATTERNS = *.h 196 | PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \ 197 | "EPOXY_BEGIN_DECLS=" \ 198 | "EPOXY_END_DECLS=" \ 199 | "EPOXY_PUBLIC=" 200 | EXPAND_AS_DEFINED = 201 | SKIP_FUNCTION_MACROS = YES 202 | 203 | ALLEXTERNALS = NO 204 | EXTERNAL_GROUPS = NO 205 | EXTERNAL_PAGES = NO 206 | 207 | HAVE_DOT = @HAVE_DOT@ 208 | CLASS_DIAGRAMS = NO 209 | MSCGEN_PATH = 210 | DIA_PATH = 211 | HIDE_UNDOC_RELATIONS = NO 212 | DOT_NUM_THREADS = 0 213 | DOT_FONTNAME = Sans 214 | DOT_FONTSIZE = 10 215 | DOT_FONTPATH = 216 | CLASS_GRAPH = NO 217 | COLLABORATION_GRAPH = YES 218 | GROUP_GRAPHS = YES 219 | UML_LOOK = NO 220 | UML_LIMIT_NUM_FIELDS = 10 221 | TEMPLATE_RELATIONS = NO 222 | INCLUDE_GRAPH = NO 223 | INCLUDED_BY_GRAPH = NO 224 | CALL_GRAPH = NO 225 | CALLER_GRAPH = NO 226 | GRAPHICAL_HIERARCHY = YES 227 | DIRECTORY_GRAPH = YES 228 | DOT_IMAGE_FORMAT = png 229 | INTERACTIVE_SVG = NO 230 | DOT_PATH = 231 | DOTFILE_DIRS = 232 | MSCFILE_DIRS = 233 | DIAFILE_DIRS = 234 | PLANTUML_JAR_PATH = 235 | PLANTUML_INCLUDE_PATH = 236 | DOT_GRAPH_MAX_NODES = 50 237 | MAX_DOT_GRAPH_DEPTH = 0 238 | DOT_TRANSPARENT = NO 239 | DOT_MULTI_TARGETS = YES 240 | GENERATE_LEGEND = YES 241 | DOT_CLEANUP = YES 242 | -------------------------------------------------------------------------------- /doc/meson.build: -------------------------------------------------------------------------------- 1 | doxyfile_conf = configuration_data() 2 | doxyfile_conf.set('PACKAGE_NAME', meson.project_name()) 3 | doxyfile_conf.set('PACKAGE_VERSION', meson.project_version()) 4 | doxyfile_conf.set('top_srcdir', meson.source_root()) 5 | doxyfile_conf.set('top_builddir', meson.build_root()) 6 | 7 | if find_program('dot', required: false).found() 8 | doxyfile_conf.set('HAVE_DOT', 'YES') 9 | else 10 | doxyfile_conf.set('HAVE_DOT', 'NO') 11 | endif 12 | 13 | doxyfile = configure_file(input: 'Doxyfile.in', 14 | output: 'Doxyfile', 15 | configuration: doxyfile_conf, 16 | install: false) 17 | 18 | docdir = join_paths(epoxy_datadir, 'doc') 19 | 20 | html_target = custom_target('epoxy-docs', 21 | input: [ doxyfile ], 22 | output: [ 'html' ], 23 | command: [ doxygen, doxyfile ], 24 | install: true, 25 | install_dir: join_paths(docdir, 'epoxy')) 26 | -------------------------------------------------------------------------------- /include/epoxy/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Emmanuele Bassi 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** @file common.h 25 | * 26 | * A common header file, used to define macros and shared symbols. 27 | */ 28 | 29 | #ifndef EPOXY_COMMON_H 30 | #define EPOXY_COMMON_H 31 | 32 | #ifdef __cplusplus 33 | # define EPOXY_BEGIN_DECLS extern "C" { 34 | # define EPOXY_END_DECLS } 35 | #else 36 | # define EPOXY_BEGIN_DECLS 37 | # define EPOXY_END_DECLS 38 | #endif 39 | 40 | #ifndef EPOXY_PUBLIC 41 | # if defined(_MSC_VER) 42 | # define EPOXY_PUBLIC __declspec(dllimport) extern 43 | # else 44 | # define EPOXY_PUBLIC extern 45 | # endif 46 | #endif 47 | 48 | #if defined(_MSC_VER) && !defined(__bool_true_false_are_defined) && (_MSC_VER < 1800) 49 | typedef unsigned char bool; 50 | # define false 0 51 | # define true 1 52 | #else 53 | # include 54 | #endif 55 | 56 | EPOXY_BEGIN_DECLS 57 | 58 | EPOXY_PUBLIC bool epoxy_extension_in_string(const char *extension_list, 59 | const char *ext); 60 | 61 | EPOXY_END_DECLS 62 | 63 | #endif /* EPOXY_COMMON_H */ 64 | -------------------------------------------------------------------------------- /include/epoxy/egl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** @file egl.h 25 | * 26 | * Provides an implementation of an EGL dispatch layer using global 27 | * function pointers 28 | * 29 | * You should include `` instead of ``. 30 | */ 31 | 32 | #ifndef EPOXY_EGL_H 33 | #define EPOXY_EGL_H 34 | 35 | #include "epoxy/common.h" 36 | 37 | #if defined(__egl_h_) || defined(__eglext_h_) 38 | #error epoxy/egl.h must be included before (or in place of) GL/egl.h 39 | #else 40 | #define __egl_h_ 41 | #define __eglext_h_ 42 | #endif 43 | 44 | EPOXY_BEGIN_DECLS 45 | 46 | #include "epoxy/egl_generated.h" 47 | 48 | EPOXY_PUBLIC bool epoxy_has_egl_extension(EGLDisplay dpy, const char *extension); 49 | EPOXY_PUBLIC int epoxy_egl_version(EGLDisplay dpy); 50 | EPOXY_PUBLIC bool epoxy_has_egl(void); 51 | 52 | EPOXY_END_DECLS 53 | 54 | #endif /* EPOXY_EGL_H */ 55 | -------------------------------------------------------------------------------- /include/epoxy/gl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** @file gl.h 25 | * 26 | * Provides an implementation of a GL dispatch layer using either 27 | * global function pointers or a hidden vtable. 28 | * 29 | * You should include `` instead of `` and ``. 30 | */ 31 | 32 | #ifndef EPOXY_GL_H 33 | #define EPOXY_GL_H 34 | 35 | #include "epoxy/common.h" 36 | 37 | #if defined(__gl_h_) || defined(__glext_h_) 38 | #error epoxy/gl.h must be included before (or in place of) GL/gl.h 39 | #else 40 | #define __gl_h_ 41 | #define __glext_h_ 42 | #endif 43 | 44 | #define KHRONOS_SUPPORT_INT64 1 45 | #define KHRONOS_SUPPORT_FLOAT 1 46 | #define KHRONOS_APIATTRIBUTES 47 | 48 | #ifndef _WIN32 49 | /* APIENTRY and GLAPIENTRY are not used on Linux or Mac. */ 50 | #define APIENTRY 51 | #define GLAPIENTRY 52 | #define EPOXY_CALLSPEC 53 | #define GLAPI 54 | #define KHRONOS_APIENTRY 55 | #define KHRONOS_APICALL 56 | 57 | #else 58 | #ifndef APIENTRY 59 | #ifndef WINAPI 60 | #define WINAPI __stdcall 61 | #endif 62 | #define APIENTRY WINAPI 63 | #endif 64 | 65 | #ifndef GLAPIENTRY 66 | #define GLAPIENTRY APIENTRY 67 | #endif 68 | 69 | #ifndef EPOXY_CALLSPEC 70 | #define EPOXY_CALLSPEC __stdcall 71 | #endif 72 | 73 | #ifndef GLAPI 74 | #define GLAPI extern 75 | #endif 76 | 77 | #define KHRONOS_APIENTRY __stdcall 78 | #define KHRONOS_APICALL __declspec(dllimport) __stdcall 79 | 80 | #endif /* _WIN32 */ 81 | 82 | #ifndef APIENTRYP 83 | #define APIENTRYP APIENTRY * 84 | #endif 85 | 86 | #ifndef GLAPIENTRYP 87 | #define GLAPIENTRYP GLAPIENTRY * 88 | #endif 89 | 90 | EPOXY_BEGIN_DECLS 91 | 92 | #include "epoxy/gl_generated.h" 93 | 94 | EPOXY_PUBLIC bool epoxy_has_gl_extension(const char *extension); 95 | EPOXY_PUBLIC bool epoxy_is_desktop_gl(void); 96 | EPOXY_PUBLIC int epoxy_gl_version(void); 97 | EPOXY_PUBLIC int epoxy_glsl_version(void); 98 | 99 | /* 100 | * the type of the stub function that the failure handler must return; 101 | * this function will be called on subsequent calls to the same bogus 102 | * function name 103 | */ 104 | typedef void (*epoxy_resolver_stub_t)(void); 105 | 106 | /* the type of the failure handler itself */ 107 | typedef epoxy_resolver_stub_t 108 | (*epoxy_resolver_failure_handler_t)(const char *name); 109 | 110 | EPOXY_PUBLIC epoxy_resolver_failure_handler_t 111 | epoxy_set_resolver_failure_handler(epoxy_resolver_failure_handler_t handler); 112 | 113 | EPOXY_END_DECLS 114 | 115 | #endif /* EPOXY_GL_H */ 116 | -------------------------------------------------------------------------------- /include/epoxy/glx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** @file glx.h 25 | * 26 | * Provides an implementation of a GLX dispatch layer using global 27 | * function pointers. 28 | * 29 | * You should include `` instead of ``. 30 | */ 31 | 32 | #ifndef EPOXY_GLX_H 33 | #define EPOXY_GLX_H 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #if defined(GLX_H) || defined(__glxext_h_) 40 | #error epoxy/glx.h must be included before (or in place of) GL/glx.h 41 | #else 42 | #define GLX_H 43 | #define __glx_h__ 44 | #define __glxext_h_ 45 | #endif 46 | 47 | EPOXY_BEGIN_DECLS 48 | 49 | #include "epoxy/glx_generated.h" 50 | 51 | EPOXY_PUBLIC bool epoxy_has_glx_extension(Display *dpy, int screen, const char *extension); 52 | EPOXY_PUBLIC int epoxy_glx_version(Display *dpy, int screen); 53 | EPOXY_PUBLIC bool epoxy_has_glx(Display *dpy); 54 | 55 | EPOXY_END_DECLS 56 | 57 | #endif /* EPOXY_GLX_H */ 58 | -------------------------------------------------------------------------------- /include/epoxy/meson.build: -------------------------------------------------------------------------------- 1 | headers = [ 'common.h' ] 2 | 3 | # GL is always generated 4 | generated_headers = [ [ 'gl.h', 'gl_generated.h', gl_registry ] ] 5 | 6 | if build_egl 7 | generated_headers += [ [ 'egl.h', 'egl_generated.h', egl_registry ] ] 8 | endif 9 | 10 | if build_glx 11 | generated_headers += [ [ 'glx.h', 'glx_generated.h', glx_registry ] ] 12 | endif 13 | 14 | if build_wgl 15 | generated_headers += [ [ 'wgl.h', 'wgl_generated.h', wgl_registry ] ] 16 | endif 17 | 18 | gen_headers = [] 19 | 20 | foreach g: generated_headers 21 | header = g[0] 22 | gen_header = g[1] 23 | registry = g[2] 24 | generated = custom_target(gen_header, 25 | input: registry, 26 | output: [ gen_header ], 27 | command: [ 28 | gen_dispatch_py, 29 | '--header', 30 | '--no-source', 31 | '--outputdir=@OUTDIR@', 32 | '@INPUT@', 33 | ], 34 | install: true, 35 | install_dir: join_paths(epoxy_includedir, 'epoxy')) 36 | 37 | gen_headers += [ generated ] 38 | headers += [ header ] 39 | endforeach 40 | 41 | epoxy_headers = files(headers) + gen_headers 42 | 43 | install_headers(headers, subdir: 'epoxy') 44 | -------------------------------------------------------------------------------- /include/epoxy/wgl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** @file wgl.h 25 | * 26 | * Provides an implementation of a WGL dispatch layer using a hidden 27 | * vtable. 28 | */ 29 | 30 | #ifndef EPOXY_WGL_H 31 | #define EPOXY_WGL_H 32 | 33 | #include 34 | 35 | #include "epoxy/common.h" 36 | 37 | #undef wglUseFontBitmaps 38 | #undef wglUseFontOutlines 39 | 40 | #if defined(__wglxext_h_) 41 | #error epoxy/wgl.h must be included before (or in place of) wgl.h 42 | #else 43 | #define __wglxext_h_ 44 | #endif 45 | 46 | #ifdef UNICODE 47 | #define wglUseFontBitmaps wglUseFontBitmapsW 48 | #else 49 | #define wglUseFontBitmaps wglUseFontBitmapsA 50 | #endif 51 | 52 | EPOXY_BEGIN_DECLS 53 | 54 | #include "epoxy/wgl_generated.h" 55 | 56 | EPOXY_PUBLIC bool epoxy_has_wgl_extension(HDC hdc, const char *extension); 57 | EPOXY_PUBLIC void epoxy_handle_external_wglMakeCurrent(void); 58 | 59 | EPOXY_END_DECLS 60 | 61 | #endif /* EPOXY_WGL_H */ 62 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('libepoxy', 'c', version: '1.5.11', 2 | default_options: [ 3 | 'buildtype=debugoptimized', 4 | 'c_std=gnu99', 5 | 'warning_level=1', 6 | ], 7 | license: 'MIT', 8 | meson_version: '>= 0.54.0') 9 | 10 | epoxy_version = meson.project_version().split('.') 11 | epoxy_major_version = epoxy_version[0].to_int() 12 | epoxy_minor_version = epoxy_version[1].to_int() 13 | epoxy_micro_version = epoxy_version[2].to_int() 14 | 15 | epoxy_prefix = get_option('prefix') 16 | epoxy_libdir = join_paths(epoxy_prefix, get_option('libdir')) 17 | epoxy_datadir = join_paths(epoxy_prefix, get_option('datadir')) 18 | epoxy_includedir = join_paths(epoxy_prefix, get_option('includedir')) 19 | 20 | cc = meson.get_compiler('c') 21 | host_system = host_machine.system() 22 | 23 | conf = configuration_data() 24 | conf.set_quoted('PACKAGE_NAME', meson.project_name()) 25 | conf.set_quoted('PACKAGE_VERSION', meson.project_version()) 26 | conf.set_quoted('PACKAGE_STRING', '@0@-@1@'.format(meson.project_name(), meson.project_version())) 27 | conf.set_quoted('PACKAGE_DATADIR', join_paths(get_option('prefix'), get_option('datadir'))) 28 | conf.set_quoted('PACKAGE_LIBDIR', join_paths(get_option('prefix'), get_option('libdir'))) 29 | conf.set_quoted('PACKAGE_LOCALEDIR', join_paths(get_option('prefix'), get_option('datadir'), 'locale')) 30 | conf.set_quoted('PACKAGE_LIBEXECDIR', join_paths(get_option('prefix'), get_option('libexecdir'))) 31 | conf.set('HAVE_KHRPLATFORM_H', cc.has_header('KHR/khrplatform.h')) 32 | 33 | # GLX can be used on different platforms, so we expose a 34 | # configure time switch to enable or disable it; in case 35 | # the "auto" default value is set, we only enable GLX 36 | # support on Linux and Unix 37 | enable_glx = get_option('glx') 38 | if enable_glx == 'auto' 39 | build_glx = not ['windows', 'darwin', 'android', 'haiku'].contains(host_system) 40 | else 41 | build_glx = enable_glx == 'yes' 42 | endif 43 | 44 | enable_egl = get_option('egl') 45 | if enable_egl == 'auto' 46 | build_egl = not ['windows', 'darwin'].contains(host_system) 47 | else 48 | build_egl = enable_egl == 'yes' 49 | endif 50 | 51 | enable_x11 = get_option('x11') 52 | if not enable_x11 53 | if enable_glx == 'yes' 54 | error('GLX support is explicitly enabled, but X11 was disabled') 55 | endif 56 | build_glx = false 57 | endif 58 | 59 | # The remaining platform specific API for GL/GLES are enabled 60 | # depending on the platform we're building for 61 | if host_system == 'windows' 62 | build_wgl = true 63 | has_znow = true 64 | elif host_system == 'darwin' 65 | build_wgl = false 66 | has_znow = false 67 | else 68 | build_wgl = false 69 | has_znow = true 70 | endif 71 | 72 | conf.set10('ENABLE_GLX', build_glx) 73 | conf.set10('ENABLE_EGL', build_egl) 74 | conf.set10('ENABLE_X11', enable_x11) 75 | 76 | # Compiler flags, taken from the Xorg macros 77 | if cc.get_id() == 'msvc' 78 | # Compiler options taken from msvc_recommended_pragmas.h 79 | # in GLib, based on _Win32_Programming_ by Rector and Newcomer 80 | test_cflags = [ 81 | '-we4002', # too many actual parameters for macro 82 | '-we4003', # not enough actual parameters for macro 83 | '-w14010', # single-line comment contains line-continuation character 84 | '-we4013', # 'function' undefined; assuming extern returning int 85 | '-w14016', # no function return type; using int as default 86 | '-we4020', # too many actual parameters 87 | '-we4021', # too few actual parameters 88 | '-we4027', # function declared without formal parameter list 89 | '-we4029', # declared formal parameter list different from definition 90 | '-we4033', # 'function' must return a value 91 | '-we4035', # 'function' : no return value 92 | '-we4045', # array bounds overflow 93 | '-we4047', # different levels of indirection 94 | '-we4049', # terminating line number emission 95 | '-we4053', # an expression of type void was used as an operand 96 | '-we4071', # no function prototype given 97 | '-we4819', # the file contains a character that cannot be represented in the current code page 98 | '/utf-8', # Set the input and exec encoding to utf-8, like is the default with GCC 99 | ] 100 | elif cc.get_id() == 'gcc' or cc.get_id() == 'clang' 101 | test_cflags = [ 102 | '-Wpointer-arith', 103 | '-Wmissing-declarations', 104 | '-Wformat=2', 105 | '-Wstrict-prototypes', 106 | '-Wmissing-prototypes', 107 | '-Wnested-externs', 108 | '-Wbad-function-cast', 109 | '-Wold-style-definition', 110 | '-Wdeclaration-after-statement', 111 | '-Wunused', 112 | '-Wuninitialized', 113 | '-Wshadow', 114 | '-Wmissing-noreturn', 115 | '-Wmissing-format-attribute', 116 | '-Wredundant-decls', 117 | '-Wlogical-op', 118 | '-Werror=implicit', 119 | '-Werror=nonnull', 120 | '-Werror=init-self', 121 | '-Werror=main', 122 | '-Werror=missing-braces', 123 | '-Werror=sequence-point', 124 | '-Werror=return-type', 125 | '-Werror=trigraphs', 126 | '-Werror=array-bounds', 127 | '-Werror=write-strings', 128 | '-Werror=address', 129 | '-Werror=int-to-pointer-cast', 130 | '-Werror=pointer-to-int-cast', 131 | '-fno-strict-aliasing', 132 | '-Wno-int-conversion', 133 | ] 134 | else 135 | test_cflags = [] 136 | endif 137 | 138 | common_cflags = cc.get_supported_arguments(test_cflags) 139 | 140 | libtype = get_option('default_library') 141 | 142 | # Visibility compiler flags; we only use this for shared libraries 143 | visibility_cflags = [] 144 | if libtype == 'shared' 145 | if host_system == 'windows' 146 | conf.set('DLL_EXPORT', true) 147 | conf.set('EPOXY_PUBLIC', '__declspec(dllexport) extern') 148 | if cc.get_id() != 'msvc' 149 | visibility_cflags += [ '-fvisibility=hidden' ] 150 | endif 151 | else 152 | conf.set('EPOXY_PUBLIC', '__attribute__((visibility("default"))) extern') 153 | visibility_cflags += [ '-fvisibility=hidden' ] 154 | endif 155 | endif 156 | 157 | # The inline keyword is available only for C++ in MSVC. 158 | # So we need to use Microsoft specific __inline. 159 | if host_system == 'windows' 160 | if cc.get_id() == 'msvc' 161 | conf.set('inline', '__inline') 162 | endif 163 | endif 164 | 165 | # Dependencies 166 | dl_dep = cc.find_library('dl', required: false) 167 | gl_dep = dependency('gl', required: false) 168 | if not gl_dep.found() and not build_glx 169 | gl_dep = dependency('opengl', required: false) 170 | endif 171 | egl_dep = dependency('egl', required: false) 172 | elg_headers_dep = egl_dep.partial_dependency(compile_args: true, includes: true) 173 | 174 | # Optional dependencies for tests 175 | x11_dep = dependency('x11', required: false) 176 | x11_headers_dep = x11_dep.partial_dependency(compile_args: true, includes: true) 177 | 178 | # GLES v2 and v1 may have pkg-config files, courtesy of downstream 179 | # packagers; let's check those first, and fall back to find_library() 180 | # if we fail 181 | gles2_dep = dependency('glesv2', required: false) 182 | if not gles2_dep.found() 183 | gles2_dep = cc.find_library('libGLESv2', required: false) 184 | endif 185 | 186 | gles1_dep = dependency('glesv1_cm', required: false) 187 | if not gles1_dep.found() 188 | gles1_dep = cc.find_library('libGLESv1_CM', required: false) 189 | endif 190 | 191 | # On windows, the DLL has to have all of its functions 192 | # resolved at link time, so we have to link directly against 193 | # opengl32. But that's the only GL provider, anyway. 194 | if host_system == 'windows' 195 | opengl32_dep = cc.find_library('opengl32', required: true) 196 | 197 | # When building against static libraries, we need to control 198 | # the order of the dependencies, and gdi32 provides symbols 199 | # needed when using opengl32, like SetPixelFormat and 200 | # ChoosePixelFormat. This is mostly a workaround for older 201 | # versions of Meson. 202 | gdi32_dep = cc.find_library('gdi32', required: true) 203 | endif 204 | 205 | # Generates the dispatch tables 206 | gen_dispatch_py = find_program('src/gen_dispatch.py') 207 | 208 | gl_registry = files('registry/gl.xml') 209 | egl_registry = files('registry/egl.xml') 210 | glx_registry = files('registry/glx.xml') 211 | wgl_registry = files('registry/wgl.xml') 212 | 213 | libepoxy_inc = [ 214 | include_directories('include'), 215 | include_directories('src'), 216 | ] 217 | 218 | subdir('include/epoxy') 219 | subdir('src') 220 | 221 | if get_option('tests') 222 | subdir('test') 223 | endif 224 | 225 | if get_option('docs') 226 | doxygen = find_program('doxygen', required: false) 227 | if doxygen.found() 228 | subdir('doc') 229 | else 230 | message('Documentation disabled without doxygen') 231 | endif 232 | endif 233 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('docs', 2 | type: 'boolean', value: false, 3 | description: 'Enable generating the Epoxy API reference (depends on Doxygen)') 4 | option('glx', 5 | type: 'combo', 6 | choices: [ 'auto', 'yes', 'no' ], 7 | value: 'auto', 8 | description: 'Enable GLX support') 9 | option('egl', 10 | type: 'combo', 11 | choices: [ 'auto', 'yes', 'no' ], 12 | value: 'auto', 13 | description: 'Enable EGL support') 14 | option('x11', 15 | type: 'boolean', 16 | value: true, 17 | description: 'Enable X11 support (GLX or EGL-X11)') 18 | option('tests', 19 | type: 'boolean', 20 | value: true, 21 | description: 'Build the test suite') 22 | -------------------------------------------------------------------------------- /registry/README.md: -------------------------------------------------------------------------------- 1 | ## Updating the registry XML 2 | 3 | In order to update the registry XML files and retain the history you cannot 4 | simply download the files the [Khronos website](https://khronos.org/registry/OpenGL/index_gl.php) 5 | and copy them into this directory. You should follow these steps, instead: 6 | 7 | 1. check out the `khronos-registry` branch 8 | 2. download the XML files from the Khronos repository 9 | 3. copy them under the `registry` directory 10 | 4. check the result for consistency and commit it 11 | 5. check out the `master` branch and merge the `khronos-registry` branch 12 | into it with the appropriate commit message 13 | 14 | -------------------------------------------------------------------------------- /src/dispatch_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013-2014 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * \mainpage Epoxy 26 | * 27 | * \section intro_sec Introduction 28 | * 29 | * Epoxy is a library for handling OpenGL function pointer management for 30 | * you. 31 | * 32 | * It hides the complexity of `dlopen()`, `dlsym()`, `glXGetProcAddress()`, 33 | * `eglGetProcAddress()`, etc. from the app developer, with very little 34 | * knowledge needed on their part. They get to read GL specs and write 35 | * code using undecorated function names like `glCompileShader()`. 36 | * 37 | * Don't forget to check for your extensions or versions being present 38 | * before you use them, just like before! We'll tell you what you forgot 39 | * to check for instead of just segfaulting, though. 40 | * 41 | * \section features_sec Features 42 | * 43 | * - Automatically initializes as new GL functions are used. 44 | * - GL 4.6 core and compatibility context support. 45 | * - GLES 1/2/3 context support. 46 | * - Knows about function aliases so (e.g.) `glBufferData()` can be 47 | * used with `GL_ARB_vertex_buffer_object` implementations, along 48 | * with GL 1.5+ implementations. 49 | * - EGL, GLX, and WGL support. 50 | * - Can be mixed with non-epoxy GL usage. 51 | * 52 | * \section using_sec Using Epoxy 53 | * 54 | * Using Epoxy should be as easy as replacing: 55 | * 56 | * ```cpp 57 | * #include 58 | * #include 59 | * #include 60 | * ``` 61 | * 62 | * with: 63 | * 64 | * ```cpp 65 | * #include 66 | * #include 67 | * ``` 68 | * 69 | * \subsection using_include_sec Headers 70 | * 71 | * Epoxy comes with the following public headers: 72 | * 73 | * - `epoxy/gl.h` - For GL API 74 | * - `epoxy/egl.h` - For EGL API 75 | * - `epoxy/glx.h` - For GLX API 76 | * - `epoxy/wgl.h` - For WGL API 77 | * 78 | * \section links_sec Additional links 79 | * 80 | * The latest version of the Epoxy code is available on [GitHub](https://github.com/anholt/libepoxy). 81 | * 82 | * For bug reports and enhancements, please use the [Issues](https://github.com/anholt/libepoxy/issues) 83 | * link. 84 | * 85 | * The scope of this API reference does not include the documentation for 86 | * OpenGL and OpenGL ES. For more information on those programming interfaces 87 | * please visit: 88 | * 89 | * - [Khronos](https://www.khronos.org/) 90 | * - [OpenGL page on Khronos.org](https://www.khronos.org/opengl/) 91 | * - [OpenGL ES page on Khronos.org](https://www.khronos.org/opengles/) 92 | * - [docs.GL](http://docs.gl/) 93 | */ 94 | 95 | /** 96 | * @file dispatch_common.c 97 | * 98 | * @brief Implements common code shared by the generated GL/EGL/GLX dispatch code. 99 | * 100 | * A collection of some important specs on getting GL function pointers. 101 | * 102 | * From the linux GL ABI (http://www.opengl.org/registry/ABI/): 103 | * 104 | * "3.4. The libraries must export all OpenGL 1.2, GLU 1.3, GLX 1.3, and 105 | * ARB_multitexture entry points statically. 106 | * 107 | * 3.5. Because non-ARB extensions vary so widely and are constantly 108 | * increasing in number, it's infeasible to require that they all be 109 | * supported, and extensions can always be added to hardware drivers 110 | * after the base link libraries are released. These drivers are 111 | * dynamically loaded by libGL, so extensions not in the base 112 | * library must also be obtained dynamically. 113 | * 114 | * 3.6. To perform the dynamic query, libGL also must export an entry 115 | * point called 116 | * 117 | * void (*glXGetProcAddressARB(const GLubyte *))(); 118 | * 119 | * The full specification of this function is available separately. It 120 | * takes the string name of a GL or GLX entry point and returns a pointer 121 | * to a function implementing that entry point. It is functionally 122 | * identical to the wglGetProcAddress query defined by the Windows OpenGL 123 | * library, except that the function pointers returned are context 124 | * independent, unlike the WGL query." 125 | * 126 | * From the EGL 1.4 spec: 127 | * 128 | * "Client API function pointers returned by eglGetProcAddress are 129 | * independent of the display and the currently bound client API context, 130 | * and may be used by any client API context which supports the extension. 131 | * 132 | * eglGetProcAddress may be queried for all of the following functions: 133 | * 134 | * • All EGL and client API extension functions supported by the 135 | * implementation (whether those extensions are supported by the current 136 | * client API context or not). This includes any mandatory OpenGL ES 137 | * extensions. 138 | * 139 | * eglGetProcAddress may not be queried for core (non-extension) functions 140 | * in EGL or client APIs 20 . 141 | * 142 | * For functions that are queryable with eglGetProcAddress, 143 | * implementations may choose to also export those functions statically 144 | * from the object libraries im- plementing those functions. However, 145 | * portable clients cannot rely on this behavior. 146 | * 147 | * From the GLX 1.4 spec: 148 | * 149 | * "glXGetProcAddress may be queried for all of the following functions: 150 | * 151 | * • All GL and GLX extension functions supported by the implementation 152 | * (whether those extensions are supported by the current context or 153 | * not). 154 | * 155 | * • All core (non-extension) functions in GL and GLX from version 1.0 up 156 | * to and including the versions of those specifications supported by 157 | * the implementation, as determined by glGetString(GL VERSION) and 158 | * glXQueryVersion queries." 159 | */ 160 | 161 | #include 162 | #include 163 | #ifdef _WIN32 164 | #include 165 | #else 166 | #include 167 | #include 168 | #include 169 | #endif 170 | #include 171 | #include 172 | #include 173 | 174 | #include "dispatch_common.h" 175 | 176 | #if defined(__APPLE__) 177 | #define GLX_LIB "/opt/X11/lib/libGL.1.dylib" 178 | #define OPENGL_LIB "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL" 179 | #define GLES1_LIB "libGLESv1_CM.so" 180 | #define GLES2_LIB "libGLESv2.so" 181 | #elif defined(__ANDROID__) 182 | #define GLX_LIB "libGLESv2.so" 183 | #define EGL_LIB "libEGL.so" 184 | #define GLES1_LIB "libGLESv1_CM.so" 185 | #define GLES2_LIB "libGLESv2.so" 186 | #elif defined(_WIN32) 187 | #define EGL_LIB "libEGL.dll" 188 | #define GLES1_LIB "libGLES_CM.dll" 189 | #define GLES2_LIB "libGLESv2.dll" 190 | #define OPENGL_LIB "OPENGL32" 191 | #else 192 | #define GLVND_GLX_LIB "libGLX.so.1" 193 | #define GLX_LIB "libGL.so.1" 194 | #define EGL_LIB "libEGL.so.1" 195 | #define GLES1_LIB "libGLESv1_CM.so.1" 196 | #define GLES2_LIB "libGLESv2.so.2" 197 | #define OPENGL_LIB "libOpenGL.so.0" 198 | #endif 199 | 200 | #ifdef __GNUC__ 201 | #define CONSTRUCT(_func) static void _func (void) __attribute__((constructor)); 202 | #define DESTRUCT(_func) static void _func (void) __attribute__((destructor)); 203 | #elif defined (_MSC_VER) && (_MSC_VER >= 1500) 204 | #define CONSTRUCT(_func) \ 205 | static void _func(void); \ 206 | static int _func ## _wrapper(void) { _func(); return 0; } \ 207 | __pragma(section(".CRT$XCU",read)) \ 208 | __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _wrapper; 209 | 210 | #define DESTRUCT(_func) \ 211 | static void _func(void); \ 212 | static int _func ## _constructor(void) { atexit (_func); return 0; } \ 213 | __pragma(section(".CRT$XCU",read)) \ 214 | __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor; 215 | 216 | #else 217 | #error "You will need constructor support for your compiler" 218 | #endif 219 | 220 | struct api { 221 | #ifndef _WIN32 222 | /* 223 | * Locking for making sure we don't double-dlopen(). 224 | */ 225 | pthread_mutex_t mutex; 226 | #endif 227 | 228 | /* 229 | * dlopen() return value for the GLX API. This is libGLX.so.1 if the 230 | * runtime is glvnd-enabled, else libGL.so.1 231 | */ 232 | void *glx_handle; 233 | 234 | /* 235 | * dlopen() return value for the desktop GL library. 236 | * 237 | * On Windows this is OPENGL32. On OSX this is classic libGL. On Linux 238 | * this is either libOpenGL (if the runtime is glvnd-enabled) or 239 | * classic libGL.so.1 240 | */ 241 | void *gl_handle; 242 | 243 | /* dlopen() return value for libEGL.so.1 */ 244 | void *egl_handle; 245 | 246 | /* dlopen() return value for libGLESv1_CM.so.1 */ 247 | void *gles1_handle; 248 | 249 | /* dlopen() return value for libGLESv2.so.2 */ 250 | void *gles2_handle; 251 | 252 | /* 253 | * This value gets incremented when any thread is in 254 | * glBegin()/glEnd() called through epoxy. 255 | * 256 | * We're not guaranteed to be called through our wrapper, so the 257 | * conservative paths also try to handle the failure cases they'll 258 | * see if begin_count didn't reflect reality. It's also a bit of 259 | * a bug that the conservative paths might return success because 260 | * some other thread was in epoxy glBegin/glEnd while our thread 261 | * is trying to resolve, but given that it's basically just for 262 | * informative error messages, we shouldn't need to care. 263 | */ 264 | long begin_count; 265 | }; 266 | 267 | static struct api api = { 268 | #ifndef _WIN32 269 | .mutex = PTHREAD_MUTEX_INITIALIZER, 270 | #else 271 | 0, 272 | #endif 273 | }; 274 | 275 | static bool library_initialized; 276 | 277 | static bool epoxy_current_context_is_glx(void); 278 | 279 | #if PLATFORM_HAS_EGL 280 | static EGLenum 281 | epoxy_egl_get_current_gl_context_api(void); 282 | #endif 283 | 284 | CONSTRUCT (library_init) 285 | 286 | static void 287 | library_init(void) 288 | { 289 | library_initialized = true; 290 | } 291 | 292 | static bool 293 | get_dlopen_handle(void **handle, const char *lib_name, bool exit_on_fail, bool load) 294 | { 295 | if (*handle) 296 | return true; 297 | 298 | if (!library_initialized) { 299 | fputs("Attempting to dlopen() while in the dynamic linker.\n", stderr); 300 | abort(); 301 | } 302 | 303 | #ifdef _WIN32 304 | *handle = LoadLibraryA(lib_name); 305 | #else 306 | pthread_mutex_lock(&api.mutex); 307 | if (!*handle) { 308 | int flags = RTLD_LAZY | RTLD_LOCAL; 309 | if (!load) 310 | flags |= RTLD_NOLOAD; 311 | 312 | *handle = dlopen(lib_name, flags); 313 | if (!*handle) { 314 | if (exit_on_fail) { 315 | fprintf(stderr, "Couldn't open %s: %s\n", lib_name, dlerror()); 316 | abort(); 317 | } else { 318 | (void)dlerror(); 319 | } 320 | } 321 | } 322 | pthread_mutex_unlock(&api.mutex); 323 | #endif 324 | 325 | return *handle != NULL; 326 | } 327 | 328 | static void * 329 | do_dlsym(void **handle, const char *name, bool exit_on_fail) 330 | { 331 | void *result; 332 | const char *error = ""; 333 | 334 | #ifdef _WIN32 335 | result = GetProcAddress(*handle, name); 336 | #else 337 | result = dlsym(*handle, name); 338 | if (!result) 339 | error = dlerror(); 340 | #endif 341 | if (!result && exit_on_fail) { 342 | fprintf(stderr, "%s() not found: %s\n", name, error); 343 | abort(); 344 | } 345 | 346 | return result; 347 | } 348 | 349 | /** 350 | * @brief Checks whether we're using OpenGL or OpenGL ES 351 | * 352 | * @return `true` if we're using OpenGL 353 | */ 354 | bool 355 | epoxy_is_desktop_gl(void) 356 | { 357 | const char *es_prefix = "OpenGL ES"; 358 | const char *version; 359 | 360 | #if PLATFORM_HAS_EGL 361 | /* PowerVR's OpenGL ES implementation (and perhaps other) don't 362 | * comply with the standard, which states that 363 | * "glGetString(GL_VERSION)" should return a string starting with 364 | * "OpenGL ES". Therefore, to distinguish desktop OpenGL from 365 | * OpenGL ES, we must also check the context type through EGL (we 366 | * can do that as PowerVR is only usable through EGL). 367 | */ 368 | if (!epoxy_current_context_is_glx()) { 369 | switch (epoxy_egl_get_current_gl_context_api()) { 370 | case EGL_OPENGL_API: return true; 371 | case EGL_OPENGL_ES_API: return false; 372 | case EGL_NONE: 373 | default: break; 374 | } 375 | } 376 | #endif 377 | 378 | if (api.begin_count) 379 | return true; 380 | 381 | version = (const char *)glGetString(GL_VERSION); 382 | 383 | /* If we didn't get a version back, there are only two things that 384 | * could have happened: either malloc failure (which basically 385 | * doesn't exist), or we were called within a glBegin()/glEnd(). 386 | * Assume the second, which only exists for desktop GL. 387 | */ 388 | if (!version) 389 | return true; 390 | 391 | return strncmp(es_prefix, version, strlen(es_prefix)); 392 | } 393 | 394 | static int 395 | epoxy_internal_gl_version(GLenum version_string, int error_version, int factor) 396 | { 397 | const char *version = (const char *)glGetString(version_string); 398 | GLint major, minor; 399 | int scanf_count; 400 | 401 | if (!version) 402 | return error_version; 403 | 404 | /* skip to version number */ 405 | while (!isdigit(*version) && *version != '\0') 406 | version++; 407 | 408 | /* Interpret version number */ 409 | scanf_count = sscanf(version, "%i.%i", &major, &minor); 410 | if (scanf_count != 2) { 411 | fprintf(stderr, "Unable to interpret GL_VERSION string: %s\n", 412 | version); 413 | abort(); 414 | } 415 | 416 | return factor * major + minor; 417 | } 418 | 419 | /** 420 | * @brief Returns the version of OpenGL we are using 421 | * 422 | * The version is encoded as: 423 | * 424 | * ``` 425 | * 426 | * version = major * 10 + minor 427 | * 428 | * ``` 429 | * 430 | * So it can be easily used for version comparisons. 431 | * 432 | * @return The encoded version of OpenGL we are using 433 | */ 434 | int 435 | epoxy_gl_version(void) 436 | { 437 | return epoxy_internal_gl_version(GL_VERSION, 0, 10); 438 | } 439 | 440 | int 441 | epoxy_conservative_gl_version(void) 442 | { 443 | if (api.begin_count) 444 | return 100; 445 | 446 | return epoxy_internal_gl_version(GL_VERSION, 100, 10); 447 | } 448 | 449 | /** 450 | * @brief Returns the version of the GL Shading Language we are using 451 | * 452 | * The version is encoded as: 453 | * 454 | * ``` 455 | * 456 | * version = major * 100 + minor 457 | * 458 | * ``` 459 | * 460 | * So it can be easily used for version comparisons. 461 | * 462 | * @return The encoded version of the GL Shading Language we are using 463 | */ 464 | int 465 | epoxy_glsl_version(void) 466 | { 467 | if (epoxy_gl_version() >= 20 || 468 | epoxy_has_gl_extension ("GL_ARB_shading_language_100")) 469 | return epoxy_internal_gl_version(GL_SHADING_LANGUAGE_VERSION, 0, 100); 470 | 471 | return 0; 472 | } 473 | 474 | /** 475 | * @brief Checks for the presence of an extension in an OpenGL extension string 476 | * 477 | * @param extension_list The string containing the list of extensions to check 478 | * @param ext The name of the GL extension 479 | * @return `true` if the extension is available' 480 | * 481 | * @note If you are looking to check whether a normal GL, EGL or GLX extension 482 | * is supported by the client, this probably isn't the function you want. 483 | * 484 | * Some parts of the spec for OpenGL and friends will return an OpenGL formatted 485 | * extension string that is separate from the usual extension strings for the 486 | * spec. This function provides easy parsing of those strings. 487 | * 488 | * @see epoxy_has_gl_extension() 489 | * @see epoxy_has_egl_extension() 490 | * @see epoxy_has_glx_extension() 491 | */ 492 | bool 493 | epoxy_extension_in_string(const char *extension_list, const char *ext) 494 | { 495 | const char *ptr = extension_list; 496 | int len; 497 | 498 | if (!ext) 499 | return false; 500 | 501 | len = strlen(ext); 502 | 503 | if (extension_list == NULL || *extension_list == '\0') 504 | return false; 505 | 506 | /* Make sure that don't just find an extension with our name as a prefix. */ 507 | while (true) { 508 | ptr = strstr(ptr, ext); 509 | if (!ptr) 510 | return false; 511 | 512 | if (ptr[len] == ' ' || ptr[len] == 0) 513 | return true; 514 | ptr += len; 515 | } 516 | } 517 | 518 | static bool 519 | epoxy_internal_has_gl_extension(const char *ext, bool invalid_op_mode) 520 | { 521 | if (epoxy_gl_version() < 30) { 522 | const char *exts = (const char *)glGetString(GL_EXTENSIONS); 523 | if (!exts) 524 | return invalid_op_mode; 525 | return epoxy_extension_in_string(exts, ext); 526 | } else { 527 | int num_extensions; 528 | int i; 529 | 530 | glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); 531 | if (num_extensions == 0) 532 | return invalid_op_mode; 533 | 534 | for (i = 0; i < num_extensions; i++) { 535 | const char *gl_ext = (const char *)glGetStringi(GL_EXTENSIONS, i); 536 | if (!gl_ext) 537 | return false; 538 | if (strcmp(ext, gl_ext) == 0) 539 | return true; 540 | } 541 | 542 | return false; 543 | } 544 | } 545 | 546 | bool 547 | epoxy_load_glx(bool exit_if_fails, bool load) 548 | { 549 | #if PLATFORM_HAS_GLX 550 | # ifdef GLVND_GLX_LIB 551 | /* prefer the glvnd library if it exists */ 552 | if (!api.glx_handle) 553 | get_dlopen_handle(&api.glx_handle, GLVND_GLX_LIB, false, load); 554 | # endif 555 | if (!api.glx_handle) 556 | get_dlopen_handle(&api.glx_handle, GLX_LIB, exit_if_fails, load); 557 | #endif 558 | return api.glx_handle != NULL; 559 | } 560 | 561 | void * 562 | epoxy_conservative_glx_dlsym(const char *name, bool exit_if_fails) 563 | { 564 | #if PLATFORM_HAS_GLX 565 | if (epoxy_load_glx(exit_if_fails, exit_if_fails)) 566 | return do_dlsym(&api.glx_handle, name, exit_if_fails); 567 | #endif 568 | return NULL; 569 | } 570 | 571 | /** 572 | * Tests whether the currently bound context is EGL or GLX, trying to 573 | * avoid loading libraries unless necessary. 574 | */ 575 | static bool 576 | epoxy_current_context_is_glx(void) 577 | { 578 | #if !PLATFORM_HAS_GLX 579 | return false; 580 | #else 581 | void *sym; 582 | 583 | sym = epoxy_conservative_glx_dlsym("glXGetCurrentContext", false); 584 | if (sym) { 585 | if (glXGetCurrentContext()) 586 | return true; 587 | } else { 588 | (void)dlerror(); 589 | } 590 | 591 | #if PLATFORM_HAS_EGL 592 | sym = epoxy_conservative_egl_dlsym("eglGetCurrentContext", false); 593 | if (sym) { 594 | if (epoxy_egl_get_current_gl_context_api() != EGL_NONE) 595 | return false; 596 | } else { 597 | (void)dlerror(); 598 | } 599 | #endif /* PLATFORM_HAS_EGL */ 600 | 601 | return false; 602 | #endif /* PLATFORM_HAS_GLX */ 603 | } 604 | 605 | /** 606 | * @brief Returns true if the given GL extension is supported in the current context. 607 | * 608 | * @param ext The name of the GL extension 609 | * @return `true` if the extension is available 610 | * 611 | * @note that this function can't be called from within `glBegin()` and `glEnd()`. 612 | * 613 | * @see epoxy_has_egl_extension() 614 | * @see epoxy_has_glx_extension() 615 | */ 616 | bool 617 | epoxy_has_gl_extension(const char *ext) 618 | { 619 | return epoxy_internal_has_gl_extension(ext, false); 620 | } 621 | 622 | bool 623 | epoxy_conservative_has_gl_extension(const char *ext) 624 | { 625 | if (api.begin_count) 626 | return true; 627 | 628 | return epoxy_internal_has_gl_extension(ext, true); 629 | } 630 | 631 | bool 632 | epoxy_load_egl(bool exit_if_fails, bool load) 633 | { 634 | #if PLATFORM_HAS_EGL 635 | return get_dlopen_handle(&api.egl_handle, EGL_LIB, exit_if_fails, load); 636 | #else 637 | return false; 638 | #endif 639 | } 640 | 641 | void * 642 | epoxy_conservative_egl_dlsym(const char *name, bool exit_if_fails) 643 | { 644 | #if PLATFORM_HAS_EGL 645 | if (epoxy_load_egl(exit_if_fails, exit_if_fails)) 646 | return do_dlsym(&api.egl_handle, name, exit_if_fails); 647 | #endif 648 | return NULL; 649 | } 650 | 651 | void * 652 | epoxy_egl_dlsym(const char *name) 653 | { 654 | return epoxy_conservative_egl_dlsym(name, true); 655 | } 656 | 657 | void * 658 | epoxy_glx_dlsym(const char *name) 659 | { 660 | return epoxy_conservative_glx_dlsym(name, true); 661 | } 662 | 663 | static void 664 | epoxy_load_gl(void) 665 | { 666 | if (api.gl_handle) 667 | return; 668 | 669 | #if defined(_WIN32) || defined(__APPLE__) 670 | get_dlopen_handle(&api.gl_handle, OPENGL_LIB, true, true); 671 | #else 672 | 673 | // Prefer GLX_LIB over OPENGL_LIB to maintain existing behavior. 674 | // Using the inverse ordering OPENGL_LIB -> GLX_LIB, causes issues such as: 675 | // https://github.com/anholt/libepoxy/issues/240 (apitrace missing calls) 676 | // https://github.com/anholt/libepoxy/issues/252 (Xorg boot crash) 677 | get_dlopen_handle(&api.glx_handle, GLX_LIB, false, true); 678 | api.gl_handle = api.glx_handle; 679 | 680 | #if defined(OPENGL_LIB) 681 | if (!api.gl_handle) 682 | get_dlopen_handle(&api.gl_handle, OPENGL_LIB, false, true); 683 | #endif 684 | 685 | if (!api.gl_handle) { 686 | #if defined(OPENGL_LIB) 687 | fprintf(stderr, "Couldn't open %s or %s\n", GLX_LIB, OPENGL_LIB); 688 | #else 689 | fprintf(stderr, "Couldn't open %s\n", GLX_LIB); 690 | #endif 691 | abort(); 692 | } 693 | 694 | #endif 695 | } 696 | 697 | void * 698 | epoxy_gl_dlsym(const char *name) 699 | { 700 | epoxy_load_gl(); 701 | 702 | return do_dlsym(&api.gl_handle, name, true); 703 | } 704 | 705 | void * 706 | epoxy_gles1_dlsym(const char *name) 707 | { 708 | if (epoxy_current_context_is_glx()) { 709 | return epoxy_get_proc_address(name); 710 | } else { 711 | get_dlopen_handle(&api.gles1_handle, GLES1_LIB, true, true); 712 | return do_dlsym(&api.gles1_handle, name, true); 713 | } 714 | } 715 | 716 | void * 717 | epoxy_gles2_dlsym(const char *name) 718 | { 719 | if (epoxy_current_context_is_glx()) { 720 | return epoxy_get_proc_address(name); 721 | } else { 722 | get_dlopen_handle(&api.gles2_handle, GLES2_LIB, true, true); 723 | return do_dlsym(&api.gles2_handle, name, true); 724 | } 725 | } 726 | 727 | /** 728 | * Does the appropriate dlsym() or eglGetProcAddress() for GLES3 729 | * functions. 730 | * 731 | * Mesa interpreted GLES as intending that the GLES3 functions were 732 | * available only through eglGetProcAddress() and not dlsym(), while 733 | * ARM's Mali drivers interpreted GLES as intending that GLES3 734 | * functions were available only through dlsym() and not 735 | * eglGetProcAddress(). Thanks, Khronos. 736 | */ 737 | void * 738 | epoxy_gles3_dlsym(const char *name) 739 | { 740 | if (epoxy_current_context_is_glx()) { 741 | return epoxy_get_proc_address(name); 742 | } else { 743 | if (get_dlopen_handle(&api.gles2_handle, GLES2_LIB, false, true)) { 744 | void *func = do_dlsym(&api.gles2_handle, name, false); 745 | 746 | if (func) 747 | return func; 748 | } 749 | 750 | return epoxy_get_proc_address(name); 751 | } 752 | } 753 | 754 | /** 755 | * Performs either the dlsym or glXGetProcAddress()-equivalent for 756 | * core functions in desktop GL. 757 | */ 758 | void * 759 | epoxy_get_core_proc_address(const char *name, int core_version) 760 | { 761 | #ifdef _WIN32 762 | int core_symbol_support = 11; 763 | #elif defined(__ANDROID__) 764 | /** 765 | * All symbols must be resolved through eglGetProcAddress 766 | * on Android 767 | */ 768 | int core_symbol_support = 0; 769 | #else 770 | int core_symbol_support = 12; 771 | #endif 772 | 773 | if (core_version <= core_symbol_support) { 774 | return epoxy_gl_dlsym(name); 775 | } else { 776 | return epoxy_get_proc_address(name); 777 | } 778 | } 779 | 780 | #if PLATFORM_HAS_EGL 781 | static EGLenum 782 | epoxy_egl_get_current_gl_context_api(void) 783 | { 784 | EGLint curapi; 785 | 786 | if (!api.egl_handle) 787 | return EGL_NONE; 788 | 789 | if (eglQueryContext(eglGetCurrentDisplay(), eglGetCurrentContext(), 790 | EGL_CONTEXT_CLIENT_TYPE, &curapi) == EGL_FALSE) { 791 | (void)eglGetError(); 792 | return EGL_NONE; 793 | } 794 | 795 | return (EGLenum) curapi; 796 | } 797 | #endif /* PLATFORM_HAS_EGL */ 798 | 799 | /** 800 | * Performs the dlsym() for the core GL 1.0 functions that we use for 801 | * determining version and extension support for deciding on dlsym 802 | * versus glXGetProcAddress() for all other functions. 803 | * 804 | * This needs to succeed on implementations without GLX (since 805 | * glGetString() and glGetIntegerv() are both in GLES1/2 as well, and 806 | * at call time we don't know for sure what API they're trying to use 807 | * without inspecting contexts ourselves). 808 | */ 809 | void * 810 | epoxy_get_bootstrap_proc_address(const char *name) 811 | { 812 | /* If we already have a library that links to libglapi loaded, 813 | * use that. 814 | */ 815 | #if PLATFORM_HAS_GLX 816 | if (api.glx_handle && glXGetCurrentContext()) 817 | return epoxy_gl_dlsym(name); 818 | #endif 819 | 820 | /* If epoxy hasn't loaded any API-specific library yet, try to 821 | * figure out what API the context is using and use that library, 822 | * since future calls will also use that API (this prevents a 823 | * non-X11 ES2 context from loading a bunch of X11 junk). 824 | */ 825 | #if PLATFORM_HAS_EGL 826 | get_dlopen_handle(&api.egl_handle, EGL_LIB, false, true); 827 | if (api.egl_handle) { 828 | int version = 0; 829 | switch (epoxy_egl_get_current_gl_context_api()) { 830 | case EGL_OPENGL_API: 831 | return epoxy_gl_dlsym(name); 832 | case EGL_OPENGL_ES_API: 833 | if (eglQueryContext(eglGetCurrentDisplay(), 834 | eglGetCurrentContext(), 835 | EGL_CONTEXT_CLIENT_VERSION, 836 | &version)) { 837 | if (version >= 2) 838 | return epoxy_gles2_dlsym(name); 839 | else 840 | return epoxy_gles1_dlsym(name); 841 | } 842 | } 843 | } 844 | #endif /* PLATFORM_HAS_EGL */ 845 | 846 | /* Fall back to GLX */ 847 | return epoxy_gl_dlsym(name); 848 | } 849 | 850 | void * 851 | epoxy_get_proc_address(const char *name) 852 | { 853 | #if PLATFORM_HAS_EGL 854 | GLenum egl_api = EGL_NONE; 855 | 856 | if (!epoxy_current_context_is_glx()) 857 | egl_api = epoxy_egl_get_current_gl_context_api(); 858 | 859 | switch (egl_api) { 860 | case EGL_OPENGL_API: 861 | case EGL_OPENGL_ES_API: 862 | return eglGetProcAddress(name); 863 | case EGL_NONE: 864 | break; 865 | } 866 | #endif 867 | 868 | #if defined(_WIN32) 869 | return wglGetProcAddress(name); 870 | #elif defined(__APPLE__) 871 | return epoxy_gl_dlsym(name); 872 | #elif PLATFORM_HAS_GLX 873 | if (epoxy_current_context_is_glx()) 874 | return glXGetProcAddressARB((const GLubyte *)name); 875 | assert(0 && "Couldn't find current GLX or EGL context.\n"); 876 | #endif 877 | 878 | return NULL; 879 | } 880 | 881 | WRAPPER_VISIBILITY (void) 882 | WRAPPER(epoxy_glBegin)(GLenum primtype) 883 | { 884 | #ifdef _WIN32 885 | InterlockedIncrement(&api.begin_count); 886 | #else 887 | pthread_mutex_lock(&api.mutex); 888 | api.begin_count++; 889 | pthread_mutex_unlock(&api.mutex); 890 | #endif 891 | 892 | epoxy_glBegin_unwrapped(primtype); 893 | } 894 | 895 | WRAPPER_VISIBILITY (void) 896 | WRAPPER(epoxy_glEnd)(void) 897 | { 898 | epoxy_glEnd_unwrapped(); 899 | 900 | #ifdef _WIN32 901 | InterlockedDecrement(&api.begin_count); 902 | #else 903 | pthread_mutex_lock(&api.mutex); 904 | api.begin_count--; 905 | pthread_mutex_unlock(&api.mutex); 906 | #endif 907 | } 908 | 909 | PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped; 910 | PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped; 911 | 912 | epoxy_resolver_failure_handler_t epoxy_resolver_failure_handler; 913 | 914 | /** 915 | * Sets the function that will be called every time Epoxy fails to 916 | * resolve a symbol. 917 | * 918 | * @param handler The new handler function 919 | * @return The previous handler function 920 | */ 921 | epoxy_resolver_failure_handler_t 922 | epoxy_set_resolver_failure_handler(epoxy_resolver_failure_handler_t handler) 923 | { 924 | #ifdef _WIN32 925 | return InterlockedExchangePointer((void**)&epoxy_resolver_failure_handler, 926 | handler); 927 | #else 928 | epoxy_resolver_failure_handler_t old; 929 | pthread_mutex_lock(&api.mutex); 930 | old = epoxy_resolver_failure_handler; 931 | epoxy_resolver_failure_handler = handler; 932 | pthread_mutex_unlock(&api.mutex); 933 | return old; 934 | #endif 935 | } 936 | -------------------------------------------------------------------------------- /src/dispatch_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #ifdef _WIN32 27 | #define PLATFORM_HAS_EGL ENABLE_EGL 28 | #define PLATFORM_HAS_GLX ENABLE_GLX 29 | #define PLATFORM_HAS_WGL 1 30 | #elif defined(__APPLE__) 31 | #define PLATFORM_HAS_EGL 0 32 | #define PLATFORM_HAS_GLX ENABLE_GLX 33 | #define PLATFORM_HAS_WGL 0 34 | #elif defined(ANDROID) 35 | #define PLATFORM_HAS_EGL ENABLE_EGL 36 | #define PLATFORM_HAS_GLX 0 37 | #define PLATFORM_HAS_WGL 0 38 | #else 39 | #define PLATFORM_HAS_EGL ENABLE_EGL 40 | #define PLATFORM_HAS_GLX ENABLE_GLX 41 | #define PLATFORM_HAS_WGL 0 42 | #endif 43 | 44 | #include "epoxy/gl.h" 45 | #if PLATFORM_HAS_GLX 46 | #include "epoxy/glx.h" 47 | #endif 48 | #if PLATFORM_HAS_EGL 49 | # if !ENABLE_X11 50 | /* Disable including X11 headers if the X11 support was disabled at 51 | * configuration time 52 | */ 53 | # define EGL_NO_X11 1 54 | /* Older versions of Mesa use this symbol to achieve the same result 55 | * as EGL_NO_X11 56 | */ 57 | # define MESA_EGL_NO_X11_HEADERS 1 58 | # endif 59 | #include "epoxy/egl.h" 60 | #endif 61 | #if PLATFORM_HAS_WGL 62 | #include "epoxy/wgl.h" 63 | #endif 64 | 65 | #if defined(__GNUC__) 66 | #define PACKED __attribute__((__packed__)) 67 | #define ENDPACKED 68 | #elif defined (_MSC_VER) 69 | #define PACKED __pragma(pack(push,1)) 70 | #define ENDPACKED __pragma(pack(pop)) 71 | #else 72 | #define PACKED 73 | #define ENDPACKED 74 | #endif 75 | 76 | /* On win32, we're going to need to keep a per-thread dispatch table, 77 | * since the function pointers depend on the device and pixel format 78 | * of the current context. 79 | */ 80 | #if defined(_WIN32) 81 | #define USING_DISPATCH_TABLE 1 82 | #else 83 | #define USING_DISPATCH_TABLE 0 84 | #endif 85 | 86 | #define UNWRAPPED_PROTO(x) (GLAPIENTRY *x) 87 | #define WRAPPER_VISIBILITY(type) static type GLAPIENTRY 88 | #define WRAPPER(x) x ## _wrapped 89 | 90 | #define GEN_GLOBAL_REWRITE_PTR(name, args, passthrough) \ 91 | static void EPOXY_CALLSPEC \ 92 | name##_global_rewrite_ptr args \ 93 | { \ 94 | if (name == (void *)name##_global_rewrite_ptr) \ 95 | name = (void *)name##_resolver(); \ 96 | name passthrough; \ 97 | } 98 | 99 | #define GEN_GLOBAL_REWRITE_PTR_RET(ret, name, args, passthrough) \ 100 | static ret EPOXY_CALLSPEC \ 101 | name##_global_rewrite_ptr args \ 102 | { \ 103 | if (name == (void *)name##_global_rewrite_ptr) \ 104 | name = (void *)name##_resolver(); \ 105 | return name passthrough; \ 106 | } 107 | 108 | #if USING_DISPATCH_TABLE 109 | #define GEN_DISPATCH_TABLE_REWRITE_PTR(name, args, passthrough) \ 110 | static void EPOXY_CALLSPEC \ 111 | name##_dispatch_table_rewrite_ptr args \ 112 | { \ 113 | struct dispatch_table *dispatch_table = get_dispatch_table(); \ 114 | \ 115 | dispatch_table->name = (void *)name##_resolver(); \ 116 | dispatch_table->name passthrough; \ 117 | } 118 | 119 | #define GEN_DISPATCH_TABLE_REWRITE_PTR_RET(ret, name, args, passthrough) \ 120 | static ret EPOXY_CALLSPEC \ 121 | name##_dispatch_table_rewrite_ptr args \ 122 | { \ 123 | struct dispatch_table *dispatch_table = get_dispatch_table(); \ 124 | \ 125 | dispatch_table->name = (void *)name##_resolver(); \ 126 | return dispatch_table->name passthrough; \ 127 | } 128 | 129 | #define GEN_DISPATCH_TABLE_THUNK(name, args, passthrough) \ 130 | static void EPOXY_CALLSPEC \ 131 | name##_dispatch_table_thunk args \ 132 | { \ 133 | get_dispatch_table()->name passthrough; \ 134 | } 135 | 136 | #define GEN_DISPATCH_TABLE_THUNK_RET(ret, name, args, passthrough) \ 137 | static ret EPOXY_CALLSPEC \ 138 | name##_dispatch_table_thunk args \ 139 | { \ 140 | return get_dispatch_table()->name passthrough; \ 141 | } 142 | 143 | #else 144 | #define GEN_DISPATCH_TABLE_REWRITE_PTR(name, args, passthrough) 145 | #define GEN_DISPATCH_TABLE_REWRITE_PTR_RET(ret, name, args, passthrough) 146 | #define GEN_DISPATCH_TABLE_THUNK(name, args, passthrough) 147 | #define GEN_DISPATCH_TABLE_THUNK_RET(ret, name, args, passthrough) 148 | #endif 149 | 150 | #define GEN_THUNKS(name, args, passthrough) \ 151 | GEN_GLOBAL_REWRITE_PTR(name, args, passthrough) \ 152 | GEN_DISPATCH_TABLE_REWRITE_PTR(name, args, passthrough) \ 153 | GEN_DISPATCH_TABLE_THUNK(name, args, passthrough) 154 | 155 | #define GEN_THUNKS_RET(ret, name, args, passthrough) \ 156 | GEN_GLOBAL_REWRITE_PTR_RET(ret, name, args, passthrough) \ 157 | GEN_DISPATCH_TABLE_REWRITE_PTR_RET(ret, name, args, passthrough) \ 158 | GEN_DISPATCH_TABLE_THUNK_RET(ret, name, args, passthrough) 159 | 160 | void *epoxy_egl_dlsym(const char *name); 161 | void *epoxy_glx_dlsym(const char *name); 162 | void *epoxy_gl_dlsym(const char *name); 163 | void *epoxy_gles1_dlsym(const char *name); 164 | void *epoxy_gles2_dlsym(const char *name); 165 | void *epoxy_gles3_dlsym(const char *name); 166 | void *epoxy_get_proc_address(const char *name); 167 | void *epoxy_get_core_proc_address(const char *name, int core_version); 168 | void *epoxy_get_bootstrap_proc_address(const char *name); 169 | 170 | int epoxy_conservative_gl_version(void); 171 | bool epoxy_conservative_has_gl_extension(const char *name); 172 | int epoxy_conservative_glx_version(void); 173 | bool epoxy_conservative_has_glx_extension(const char *name); 174 | int epoxy_conservative_egl_version(void); 175 | bool epoxy_conservative_has_egl_extension(const char *name); 176 | bool epoxy_conservative_has_wgl_extension(const char *name); 177 | void *epoxy_conservative_egl_dlsym(const char *name, bool exit_if_fails); 178 | void *epoxy_conservative_glx_dlsym(const char *name, bool exit_if_fails); 179 | 180 | bool epoxy_load_glx(bool exit_if_fails, bool load); 181 | bool epoxy_load_egl(bool exit_if_fails, bool load); 182 | 183 | #define glBegin_unwrapped epoxy_glBegin_unwrapped 184 | #define glEnd_unwrapped epoxy_glEnd_unwrapped 185 | extern void UNWRAPPED_PROTO(glBegin_unwrapped)(GLenum primtype); 186 | extern void UNWRAPPED_PROTO(glEnd_unwrapped)(void); 187 | 188 | extern epoxy_resolver_failure_handler_t epoxy_resolver_failure_handler; 189 | 190 | #if USING_DISPATCH_TABLE 191 | void gl_init_dispatch_table(void); 192 | void gl_switch_to_dispatch_table(void); 193 | void wgl_init_dispatch_table(void); 194 | void wgl_switch_to_dispatch_table(void); 195 | extern uint32_t gl_tls_index, gl_tls_size; 196 | extern uint32_t wgl_tls_index, wgl_tls_size; 197 | 198 | #define wglMakeCurrent_unwrapped epoxy_wglMakeCurrent_unwrapped 199 | #define wglMakeContextCurrentARB_unwrapped epoxy_wglMakeContextCurrentARB_unwrapped 200 | #define wglMakeContextCurrentEXT_unwrapped epoxy_wglMakeContextCurrentEXT_unwrapped 201 | #define wglMakeAssociatedContextCurrentAMD_unwrapped epoxy_wglMakeAssociatedContextCurrentAMD_unwrapped 202 | extern BOOL UNWRAPPED_PROTO(wglMakeCurrent_unwrapped)(HDC hdc, HGLRC hglrc); 203 | extern BOOL UNWRAPPED_PROTO(wglMakeContextCurrentARB_unwrapped)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 204 | extern BOOL UNWRAPPED_PROTO(wglMakeContextCurrentEXT_unwrapped)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 205 | extern BOOL UNWRAPPED_PROTO(wglMakeAssociatedContextCurrentAMD_unwrapped)(HGLRC hglrc); 206 | #endif /* _WIN32_ */ 207 | -------------------------------------------------------------------------------- /src/dispatch_egl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "dispatch_common.h" 29 | 30 | int 31 | epoxy_conservative_egl_version(void) 32 | { 33 | EGLDisplay dpy = eglGetCurrentDisplay(); 34 | 35 | if (!dpy) 36 | return 14; 37 | 38 | return epoxy_egl_version(dpy); 39 | } 40 | 41 | /** 42 | * @brief Returns the version of OpenGL we are using 43 | * 44 | * The version is encoded as: 45 | * 46 | * ``` 47 | * 48 | * version = major * 10 + minor 49 | * 50 | * ``` 51 | * 52 | * So it can be easily used for version comparisons. 53 | * 54 | * @param The EGL display 55 | * 56 | * @return The encoded version of EGL we are using 57 | * 58 | * @see epoxy_gl_version() 59 | */ 60 | int 61 | epoxy_egl_version(EGLDisplay dpy) 62 | { 63 | int major, minor; 64 | const char *version_string; 65 | int ret; 66 | 67 | version_string = eglQueryString(dpy, EGL_VERSION); 68 | if (!version_string) 69 | return 0; 70 | 71 | ret = sscanf(version_string, "%d.%d", &major, &minor); 72 | assert(ret == 2); 73 | return major * 10 + minor; 74 | } 75 | 76 | bool 77 | epoxy_conservative_has_egl_extension(const char *ext) 78 | { 79 | return epoxy_has_egl_extension(eglGetCurrentDisplay(), ext); 80 | } 81 | 82 | /** 83 | * @brief Returns true if the given EGL extension is supported in the current context. 84 | * 85 | * @param dpy The EGL display 86 | * @param extension The name of the EGL extension 87 | * 88 | * @return `true` if the extension is available 89 | * 90 | * @see epoxy_has_gl_extension() 91 | * @see epoxy_has_glx_extension() 92 | */ 93 | bool 94 | epoxy_has_egl_extension(EGLDisplay dpy, const char *ext) 95 | { 96 | return epoxy_extension_in_string(eglQueryString(dpy, EGL_EXTENSIONS), ext) || epoxy_extension_in_string(eglQueryString(NULL, EGL_EXTENSIONS), ext); 97 | } 98 | 99 | /** 100 | * @brief Checks whether EGL is available. 101 | * 102 | * @return `true` if EGL is available 103 | * 104 | * @newin{1,4} 105 | */ 106 | bool 107 | epoxy_has_egl(void) 108 | { 109 | #if !PLATFORM_HAS_EGL 110 | return false; 111 | #else 112 | if (epoxy_load_egl(false, true)) { 113 | EGLDisplay* (* pf_eglGetCurrentDisplay) (void); 114 | 115 | pf_eglGetCurrentDisplay = epoxy_conservative_egl_dlsym("eglGetCurrentDisplay", false); 116 | if (pf_eglGetCurrentDisplay) 117 | return true; 118 | } 119 | 120 | return false; 121 | #endif /* PLATFORM_HAS_EGL */ 122 | } 123 | -------------------------------------------------------------------------------- /src/dispatch_glx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "dispatch_common.h" 29 | 30 | /** 31 | * If we can determine the GLX version from the current context, then 32 | * return that, otherwise return a version that will just send us on 33 | * to dlsym() or get_proc_address(). 34 | */ 35 | int 36 | epoxy_conservative_glx_version(void) 37 | { 38 | Display *dpy = glXGetCurrentDisplay(); 39 | GLXContext ctx = glXGetCurrentContext(); 40 | int screen; 41 | 42 | if (!dpy || !ctx) 43 | return 14; 44 | 45 | glXQueryContext(dpy, ctx, GLX_SCREEN, &screen); 46 | 47 | return epoxy_glx_version(dpy, screen); 48 | } 49 | 50 | 51 | /** 52 | * @brief Returns the version of GLX we are using 53 | * 54 | * The version is encoded as: 55 | * 56 | * ``` 57 | * 58 | * version = major * 10 + minor 59 | * 60 | * ``` 61 | * 62 | * So it can be easily used for version comparisons. 63 | * 64 | * @param dpy The X11 display 65 | * @param screen The X11 screen 66 | * 67 | * @return The encoded version of GLX we are using 68 | * 69 | * @see epoxy_gl_version() 70 | */ 71 | int 72 | epoxy_glx_version(Display *dpy, int screen) 73 | { 74 | int server_major, server_minor; 75 | int client_major, client_minor; 76 | int server, client; 77 | const char *version_string; 78 | int ret; 79 | 80 | version_string = glXQueryServerString(dpy, screen, GLX_VERSION); 81 | if (!version_string) 82 | return 0; 83 | 84 | ret = sscanf(version_string, "%d.%d", &server_major, &server_minor); 85 | assert(ret == 2); 86 | server = server_major * 10 + server_minor; 87 | 88 | version_string = glXGetClientString(dpy, GLX_VERSION); 89 | if (!version_string) 90 | return 0; 91 | 92 | ret = sscanf(version_string, "%d.%d", &client_major, &client_minor); 93 | assert(ret == 2); 94 | client = client_major * 10 + client_minor; 95 | 96 | if (client < server) 97 | return client; 98 | else 99 | return server; 100 | } 101 | 102 | /** 103 | * If we can determine the GLX extension support from the current 104 | * context, then return that, otherwise give the answer that will just 105 | * send us on to get_proc_address(). 106 | */ 107 | bool 108 | epoxy_conservative_has_glx_extension(const char *ext) 109 | { 110 | Display *dpy = glXGetCurrentDisplay(); 111 | GLXContext ctx = glXGetCurrentContext(); 112 | int screen; 113 | 114 | if (!dpy || !ctx) 115 | return true; 116 | 117 | glXQueryContext(dpy, ctx, GLX_SCREEN, &screen); 118 | 119 | return epoxy_has_glx_extension(dpy, screen, ext); 120 | } 121 | 122 | /** 123 | * @brief Returns true if the given GLX extension is supported in the current context. 124 | * 125 | * @param dpy The X11 display 126 | * @param screen The X11 screen 127 | * @param extension The name of the GLX extension 128 | * 129 | * @return `true` if the extension is available 130 | * 131 | * @see epoxy_has_gl_extension() 132 | * @see epoxy_has_egl_extension() 133 | */ 134 | bool 135 | epoxy_has_glx_extension(Display *dpy, int screen, const char *ext) 136 | { 137 | /* No, you can't just use glXGetClientString or 138 | * glXGetServerString() here. Those each tell you about one half 139 | * of what's needed for an extension to be supported, and 140 | * glXQueryExtensionsString() is what gives you the intersection 141 | * of the two. 142 | */ 143 | return epoxy_extension_in_string(glXQueryExtensionsString(dpy, screen), ext); 144 | } 145 | 146 | /** 147 | * @brief Checks whether GLX is available. 148 | * 149 | * @param dpy The X11 display 150 | * 151 | * @return `true` if GLX is available 152 | * 153 | * @newin{1,4} 154 | */ 155 | bool 156 | epoxy_has_glx(Display *dpy) 157 | { 158 | #if !PLATFORM_HAS_GLX 159 | return false; 160 | #else 161 | if (epoxy_load_glx(false, true)) { 162 | Bool (* pf_glXQueryExtension) (Display *, int *, int *); 163 | int error_base, event_base; 164 | 165 | pf_glXQueryExtension = epoxy_conservative_glx_dlsym("glXQueryExtension", false); 166 | if (pf_glXQueryExtension && pf_glXQueryExtension(dpy, &error_base, &event_base)) 167 | return true; 168 | } 169 | 170 | return false; 171 | #endif /* !PLATFORM_HAS_GLX */ 172 | } 173 | -------------------------------------------------------------------------------- /src/dispatch_wgl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "dispatch_common.h" 29 | 30 | static bool first_context_current = false; 31 | static bool already_switched_to_dispatch_table = false; 32 | 33 | /** 34 | * If we can determine the WGL extension support from the current 35 | * context, then return that, otherwise give the answer that will just 36 | * send us on to get_proc_address(). 37 | */ 38 | bool 39 | epoxy_conservative_has_wgl_extension(const char *ext) 40 | { 41 | HDC hdc = wglGetCurrentDC(); 42 | 43 | if (!hdc) 44 | return true; 45 | 46 | return epoxy_has_wgl_extension(hdc, ext); 47 | } 48 | 49 | bool 50 | epoxy_has_wgl_extension(HDC hdc, const char *ext) 51 | { 52 | PFNWGLGETEXTENSIONSSTRINGARBPROC getext; 53 | 54 | getext = (void *)wglGetProcAddress("wglGetExtensionsStringARB"); 55 | if (!getext) { 56 | fputs("Implementation unexpectedly missing " 57 | "WGL_ARB_extensions_string. Probably a libepoxy bug.\n", 58 | stderr); 59 | return false; 60 | } 61 | 62 | return epoxy_extension_in_string(getext(hdc), ext); 63 | } 64 | 65 | /** 66 | * Does the work necessary to update the win32 per-thread dispatch 67 | * tables when wglMakeCurrent() is called. 68 | * 69 | * Right now, we use global function pointers until the second 70 | * MakeCurrent occurs, at which point we switch to dispatch tables. 71 | * This could be improved in the future to track a resolved dispatch 72 | * table per context and reuse it when the context is made current 73 | * again. 74 | */ 75 | void 76 | epoxy_handle_external_wglMakeCurrent(void) 77 | { 78 | if (!first_context_current) { 79 | first_context_current = true; 80 | } else { 81 | if (!already_switched_to_dispatch_table) { 82 | already_switched_to_dispatch_table = true; 83 | gl_switch_to_dispatch_table(); 84 | wgl_switch_to_dispatch_table(); 85 | } 86 | 87 | gl_init_dispatch_table(); 88 | wgl_init_dispatch_table(); 89 | } 90 | } 91 | 92 | /** 93 | * This global symbol is apparently looked up by Windows when loading 94 | * a DLL, but it doesn't declare the prototype. 95 | */ 96 | BOOL WINAPI 97 | DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved); 98 | 99 | BOOL WINAPI 100 | DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) 101 | { 102 | void *data; 103 | 104 | switch (reason) { 105 | case DLL_PROCESS_ATTACH: 106 | gl_tls_index = TlsAlloc(); 107 | if (gl_tls_index == TLS_OUT_OF_INDEXES) 108 | return FALSE; 109 | wgl_tls_index = TlsAlloc(); 110 | if (wgl_tls_index == TLS_OUT_OF_INDEXES) 111 | return FALSE; 112 | 113 | first_context_current = false; 114 | 115 | /* FALLTHROUGH */ 116 | 117 | case DLL_THREAD_ATTACH: 118 | data = LocalAlloc(LPTR, gl_tls_size); 119 | TlsSetValue(gl_tls_index, data); 120 | 121 | data = LocalAlloc(LPTR, wgl_tls_size); 122 | TlsSetValue(wgl_tls_index, data); 123 | 124 | break; 125 | 126 | case DLL_THREAD_DETACH: 127 | case DLL_PROCESS_DETACH: 128 | data = TlsGetValue(gl_tls_index); 129 | LocalFree(data); 130 | 131 | data = TlsGetValue(wgl_tls_index); 132 | LocalFree(data); 133 | 134 | if (reason == DLL_PROCESS_DETACH) { 135 | TlsFree(gl_tls_index); 136 | TlsFree(wgl_tls_index); 137 | } 138 | break; 139 | } 140 | 141 | return TRUE; 142 | } 143 | 144 | WRAPPER_VISIBILITY (BOOL) 145 | WRAPPER(epoxy_wglMakeCurrent)(HDC hdc, HGLRC hglrc) 146 | { 147 | BOOL ret = epoxy_wglMakeCurrent_unwrapped(hdc, hglrc); 148 | 149 | epoxy_handle_external_wglMakeCurrent(); 150 | 151 | return ret; 152 | } 153 | 154 | 155 | WRAPPER_VISIBILITY (BOOL) 156 | WRAPPER(epoxy_wglMakeContextCurrentARB)(HDC hDrawDC, 157 | HDC hReadDC, 158 | HGLRC hglrc) 159 | { 160 | BOOL ret = epoxy_wglMakeContextCurrentARB_unwrapped(hDrawDC, hReadDC, 161 | hglrc); 162 | 163 | epoxy_handle_external_wglMakeCurrent(); 164 | 165 | return ret; 166 | } 167 | 168 | 169 | WRAPPER_VISIBILITY (BOOL) 170 | WRAPPER(epoxy_wglMakeContextCurrentEXT)(HDC hDrawDC, 171 | HDC hReadDC, 172 | HGLRC hglrc) 173 | { 174 | BOOL ret = epoxy_wglMakeContextCurrentEXT_unwrapped(hDrawDC, hReadDC, 175 | hglrc); 176 | 177 | epoxy_handle_external_wglMakeCurrent(); 178 | 179 | return ret; 180 | } 181 | 182 | 183 | WRAPPER_VISIBILITY (BOOL) 184 | WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)(HGLRC hglrc) 185 | { 186 | BOOL ret = epoxy_wglMakeAssociatedContextCurrentAMD_unwrapped(hglrc); 187 | 188 | epoxy_handle_external_wglMakeCurrent(); 189 | 190 | return ret; 191 | } 192 | 193 | PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped; 194 | PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped; 195 | PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped; 196 | PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped; 197 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | # Configuration file 2 | configure_file(output: 'config.h', configuration: conf) 3 | 4 | # List of generated sources: 5 | # - name of the generated file 6 | # - registry source file 7 | # - additional sources 8 | generated_sources = [ 9 | [ 'gl_generated_dispatch.c', gl_registry, [ 'dispatch_common.c', 'dispatch_common.h' ] ] 10 | ] 11 | 12 | if build_egl 13 | generated_sources += [ [ 'egl_generated_dispatch.c', egl_registry, 'dispatch_egl.c' ] ] 14 | endif 15 | 16 | if build_glx 17 | generated_sources += [ [ 'glx_generated_dispatch.c', glx_registry, 'dispatch_glx.c' ] ] 18 | endif 19 | 20 | if build_wgl 21 | generated_sources += [ [ 'wgl_generated_dispatch.c', wgl_registry, 'dispatch_wgl.c' ] ] 22 | endif 23 | 24 | gen_sources = [ ] 25 | sources = [ ] 26 | 27 | foreach g: generated_sources 28 | gen_source = g[0] 29 | registry = g[1] 30 | source = g[2] 31 | 32 | generated = custom_target(gen_source, 33 | input: registry, 34 | output: [ gen_source ], 35 | command: [ 36 | gen_dispatch_py, 37 | '--source', 38 | '--no-header', 39 | '--outputdir=@OUTDIR@', 40 | '@INPUT@', 41 | ]) 42 | 43 | gen_sources += [ generated ] 44 | sources += [ source ] 45 | endforeach 46 | 47 | epoxy_sources = sources + gen_sources 48 | 49 | common_ldflags = [] 50 | 51 | if host_system == 'linux' and cc.get_id() == 'gcc' 52 | common_ldflags += cc.get_supported_link_arguments([ '-Wl,-Bsymbolic-functions', '-Wl,-z,relro' ]) 53 | endif 54 | 55 | # Maintain compatibility with autotools; see: https://github.com/anholt/libepoxy/issues/108 56 | darwin_versions = [1, '1.0'] 57 | 58 | epoxy_deps = [ dl_dep, ] 59 | if host_system == 'windows' 60 | epoxy_deps += [ opengl32_dep, gdi32_dep ] 61 | endif 62 | if enable_x11 63 | epoxy_deps += [ x11_headers_dep, ] 64 | endif 65 | if build_egl 66 | epoxy_deps += [ elg_headers_dep, ] 67 | endif 68 | 69 | libepoxy = library( 70 | 'epoxy', 71 | sources: epoxy_sources + epoxy_headers, 72 | version: '0.0.0', 73 | darwin_versions: darwin_versions, 74 | install: true, 75 | dependencies: epoxy_deps, 76 | include_directories: libepoxy_inc, 77 | c_args: common_cflags + visibility_cflags, 78 | link_args: common_ldflags, 79 | ) 80 | 81 | epoxy_has_glx = build_glx ? '1' : '0' 82 | epoxy_has_egl = build_egl ? '1' : '0' 83 | epoxy_has_wgl = build_wgl ? '1' : '0' 84 | 85 | libepoxy_dep = declare_dependency( 86 | link_with: libepoxy, 87 | include_directories: libepoxy_inc, 88 | dependencies: epoxy_deps, 89 | sources: epoxy_headers, 90 | variables: { 91 | 'epoxy_has_glx': epoxy_has_glx, 92 | 'epoxy_has_egl': epoxy_has_egl, 93 | 'epoxy_has_wgl': epoxy_has_wgl, 94 | }, 95 | ) 96 | meson.override_dependency('epoxy', libepoxy_dep) 97 | 98 | # We don't want to add these dependencies to the library, as they are 99 | # not needed when building Epoxy; we do want to add them to the generated 100 | # pkg-config file, for consumers of Epoxy 101 | gl_reqs = [] 102 | if gl_dep.found() and gl_dep.type_name() == 'pkgconfig' 103 | gl_reqs += gl_dep.name() 104 | endif 105 | if build_egl and egl_dep.found() and egl_dep.type_name() == 'pkgconfig' 106 | gl_reqs += 'egl' 107 | endif 108 | 109 | pkg = import('pkgconfig') 110 | pkg.generate( 111 | libraries: libepoxy, 112 | name: 'epoxy', 113 | description: 'GL dispatch library', 114 | version: meson.project_version(), 115 | variables: [ 116 | 'epoxy_has_glx=@0@'.format(epoxy_has_glx), 117 | 'epoxy_has_egl=@0@'.format(epoxy_has_egl), 118 | 'epoxy_has_wgl=@0@'.format(epoxy_has_wgl), 119 | ], 120 | filebase: 'epoxy', 121 | requires_private: ' '.join(gl_reqs), 122 | ) 123 | -------------------------------------------------------------------------------- /test/cgl_core.c: -------------------------------------------------------------------------------- 1 | /* This is a copy of the test used by HomeBrew's libepoxy recipe, 2 | * originally written by Mikko Lehtonen. 3 | * 4 | * The Homebrew recipe is released under the BSD 2-Clause license. 5 | * 6 | * Copyright (c) 2009-present, Homebrew contributors 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, this 13 | * list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | int 38 | main (void) 39 | { 40 | CGLPixelFormatAttribute attribs[] = {0}; 41 | CGLPixelFormatObj pix; 42 | CGLContextObj ctx; 43 | int npix; 44 | 45 | CGLChoosePixelFormat(attribs, &pix, &npix); 46 | CGLCreateContext(pix, (void *) 0, &ctx); 47 | 48 | glClear(GL_COLOR_BUFFER_BIT); 49 | 50 | CGLReleaseContext(ctx); 51 | CGLReleasePixelFormat(pix); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /test/cgl_epoxy_api.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Emmanuele Bassi 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file cgl_epoxy_api.c 26 | * 27 | * Tests the Epoxy API using the CoreGraphics OpenGL framework. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | int 38 | main (void) 39 | { 40 | CGLPixelFormatAttribute attribs[] = {0}; 41 | CGLPixelFormatObj pix; 42 | CGLContextObj ctx; 43 | const char *string; 44 | bool pass = true; 45 | int npix; 46 | GLint shader; 47 | 48 | CGLChoosePixelFormat(attribs, &pix, &npix); 49 | CGLCreateContext(pix, (void *) 0, &ctx); 50 | CGLSetCurrentContext(ctx); 51 | 52 | if (!epoxy_is_desktop_gl()) { 53 | fputs("Claimed not to be desktop\n", stderr); 54 | pass = false; 55 | } 56 | 57 | if (epoxy_gl_version() < 20) { 58 | fprintf(stderr, "Claimed to be GL version %d\n", 59 | epoxy_gl_version()); 60 | pass = false; 61 | } 62 | 63 | if (epoxy_glsl_version() < 100) { 64 | fprintf(stderr, "Claimed to have GLSL version %d\n", 65 | epoxy_glsl_version()); 66 | pass = false; 67 | } 68 | 69 | string = (const char *)glGetString(GL_VERSION); 70 | printf("GL version: %s - Epoxy: %d\n", string, epoxy_gl_version()); 71 | 72 | string = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); 73 | printf("GLSL version: %s - Epoxy: %d\n", string, epoxy_glsl_version()); 74 | 75 | shader = glCreateShader(GL_FRAGMENT_SHADER); 76 | pass = glIsShader(shader); 77 | 78 | CGLSetCurrentContext(NULL); 79 | CGLReleaseContext(ctx); 80 | CGLReleasePixelFormat(pix); 81 | 82 | return pass != true; 83 | } 84 | -------------------------------------------------------------------------------- /test/dlwrap.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Intel Corporation 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | /** @file dlwrap.c 23 | * 24 | * Implements a wrapper for dlopen() and dlsym() so that epoxy will 25 | * end up finding symbols from the testcases named 26 | * "override_EGL_eglWhatever()" or "override_GLES2_glWhatever()" or 27 | * "override_GL_glWhatever()" when it tries to dlopen() and dlsym() 28 | * the real GL or EGL functions in question. 29 | * 30 | * This lets us simulate some target systems in the test suite, or 31 | * just stub out GL functions so we can be sure of what's being 32 | * called. 33 | */ 34 | 35 | /* dladdr is a glibc extension */ 36 | #define _GNU_SOURCE 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "dlwrap.h" 46 | 47 | #define STRNCMP_LITERAL(var, literal) \ 48 | strncmp ((var), (literal), sizeof (literal) - 1) 49 | 50 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) 51 | 52 | void *libfips_handle; 53 | 54 | typedef void *(*fips_dlopen_t)(const char *filename, int flag); 55 | typedef void *(*fips_dlsym_t)(void *handle, const char *symbol); 56 | 57 | void *override_EGL_eglGetProcAddress(const char *name); 58 | void *override_GL_glXGetProcAddress(const char *name); 59 | void *override_GL_glXGetProcAddressARB(const char *name); 60 | void __dlclose(void *handle); 61 | 62 | static struct libwrap { 63 | const char *filename; 64 | const char *symbol_prefix; 65 | void *handle; 66 | } wrapped_libs[] = { 67 | { "libGL.so", "GL", NULL }, 68 | { "libEGL.so", "EGL", NULL }, 69 | { "libGLESv2.so", "GLES2", NULL }, 70 | { "libOpenGL.so", "GL", NULL}, 71 | }; 72 | 73 | /* Match 'filename' against an internal list of libraries for which 74 | * libfips has wrappers. 75 | * 76 | * Returns true and sets *index_ret if a match is found. 77 | * Returns false if no match is found. */ 78 | static struct libwrap * 79 | find_wrapped_library(const char *filename) 80 | { 81 | unsigned i; 82 | 83 | if (!filename) 84 | return NULL; 85 | 86 | for (i = 0; i < ARRAY_SIZE(wrapped_libs); i++) { 87 | if (strncmp(wrapped_libs[i].filename, filename, 88 | strlen(wrapped_libs[i].filename)) == 0) { 89 | return &wrapped_libs[i]; 90 | } 91 | } 92 | 93 | return NULL; 94 | } 95 | 96 | /* Many (most?) OpenGL programs dlopen libGL.so.1 rather than linking 97 | * against it directly, which means they would not be seeing our 98 | * wrapped GL symbols via LD_PRELOAD. So we catch the dlopen in a 99 | * wrapper here and redirect it to our library. 100 | */ 101 | void * 102 | dlopen(const char *filename, int flag) 103 | { 104 | void *ret; 105 | struct libwrap *wrap; 106 | 107 | /* Before deciding whether to redirect this dlopen to our own 108 | * library, we call the real dlopen. This assures that any 109 | * expected side-effects from loading the intended library are 110 | * resolved. Below, we may still return a handle pointing to 111 | * our own library, and not what is opened here. */ 112 | ret = dlwrap_real_dlopen(filename, flag); 113 | 114 | /* If filename is not a wrapped library, just return real dlopen */ 115 | wrap = find_wrapped_library(filename); 116 | if (!wrap) 117 | return ret; 118 | 119 | wrap->handle = ret; 120 | 121 | /* We use wrapped_libs as our handles to libraries. */ 122 | return wrap; 123 | } 124 | 125 | /** 126 | * Wraps dlclose to hide our faked handles from it. 127 | */ 128 | void 129 | __dlclose(void *handle) 130 | { 131 | struct libwrap *wrap = handle; 132 | 133 | if (wrap < wrapped_libs || 134 | wrap >= wrapped_libs + ARRAY_SIZE(wrapped_libs)) { 135 | void (*real_dlclose)(void *handle) = dlwrap_real_dlsym(RTLD_NEXT, "__dlclose"); 136 | real_dlclose(handle); 137 | } 138 | } 139 | 140 | void * 141 | dlwrap_real_dlopen(const char *filename, int flag) 142 | { 143 | static fips_dlopen_t real_dlopen = NULL; 144 | 145 | if (!real_dlopen) { 146 | real_dlopen = (fips_dlopen_t) dlwrap_real_dlsym(RTLD_NEXT, "dlopen"); 147 | if (!real_dlopen) { 148 | fputs("Error: Failed to find symbol for dlopen.\n", stderr); 149 | exit(1); 150 | } 151 | } 152 | 153 | return real_dlopen(filename, flag); 154 | } 155 | 156 | /** 157 | * Return the dlsym() on the application's namespace for 158 | * "override__" 159 | */ 160 | static void * 161 | wrapped_dlsym(const char *prefix, const char *name) 162 | { 163 | char *wrap_name; 164 | void *symbol; 165 | 166 | if (asprintf(&wrap_name, "override_%s_%s", prefix, name) < 0) { 167 | fputs("Error: Failed to allocate memory.\n", stderr); 168 | abort(); 169 | } 170 | 171 | symbol = dlwrap_real_dlsym(RTLD_DEFAULT, wrap_name); 172 | free(wrap_name); 173 | return symbol; 174 | } 175 | 176 | /* Since we redirect dlopens of libGL.so and libEGL.so to libfips we 177 | * need to ensure that dlysm succeeds for all functions that might be 178 | * defined in the real, underlying libGL library. But we're far too 179 | * lazy to implement wrappers for function that would simply 180 | * pass-through, so instead we also wrap dlysm and arrange for it to 181 | * pass things through with RTLD_next if libfips does not have the 182 | * function desired. */ 183 | void * 184 | dlsym(void *handle, const char *name) 185 | { 186 | struct libwrap *wrap = handle; 187 | 188 | /* Make sure that handle is actually one of our wrapped libs. */ 189 | if (wrap < wrapped_libs || 190 | wrap >= wrapped_libs + ARRAY_SIZE(wrapped_libs)) { 191 | wrap = NULL; 192 | } 193 | 194 | /* Failing that, anything specifically requested from the 195 | * libfips library should be redirected to a real GL 196 | * library. */ 197 | 198 | if (wrap) { 199 | void *symbol = wrapped_dlsym(wrap->symbol_prefix, name); 200 | if (symbol) 201 | return symbol; 202 | else 203 | return dlwrap_real_dlsym(wrap->handle, name); 204 | } 205 | 206 | /* And anything else is some unrelated dlsym. Just pass it 207 | * through. (This also covers the cases of lookups with 208 | * special handles such as RTLD_DEFAULT or RTLD_NEXT.) 209 | */ 210 | return dlwrap_real_dlsym(handle, name); 211 | } 212 | 213 | void * 214 | dlwrap_real_dlsym(void *handle, const char *name) 215 | { 216 | static fips_dlsym_t real_dlsym = NULL; 217 | 218 | if (!real_dlsym) { 219 | /* FIXME: This brute-force, hard-coded searching for a versioned 220 | * symbol is really ugly. The only reason I'm doing this is because 221 | * I need some way to lookup the "dlsym" function in libdl, but 222 | * I can't use 'dlsym' to do it. So dlvsym works, but forces me 223 | * to guess what the right version is. 224 | * 225 | * Potential fixes here: 226 | * 227 | * 1. Use libelf to actually inspect libdl.so and 228 | * find the right version, (finding the right 229 | * libdl.so can be made easier with 230 | * dl_iterate_phdr). 231 | * 232 | * 2. Use libelf to find the offset of the 'dlsym' 233 | * symbol within libdl.so, (and then add this to 234 | * the base address at which libdl.so is loaded 235 | * as reported by dl_iterate_phdr). 236 | * 237 | * In the meantime, I'll just keep augmenting this 238 | * hard-coded version list as people report bugs. */ 239 | const char *version[] = { 240 | "GLIBC_2.17", 241 | "GLIBC_2.4", 242 | "GLIBC_2.3", 243 | "GLIBC_2.2.5", 244 | "GLIBC_2.2", 245 | "GLIBC_2.0", 246 | "FBSD_1.0" 247 | }; 248 | int num_versions = sizeof(version) / sizeof(version[0]); 249 | int i; 250 | for (i = 0; i < num_versions; i++) { 251 | real_dlsym = (fips_dlsym_t) dlvsym(RTLD_NEXT, "dlsym", version[i]); 252 | if (real_dlsym) 253 | break; 254 | } 255 | if (i == num_versions) { 256 | fputs("Internal error: Failed to find real dlsym\n", stderr); 257 | fputs("This may be a simple matter of fips not knowing about the version of GLIBC that\n" 258 | "your program is using. Current known versions are:\n\n\t", 259 | stderr); 260 | for (i = 0; i < num_versions; i++) 261 | fprintf(stderr, "%s ", version[i]); 262 | fputs("\n\nYou can inspect your version by first finding libdl.so.2:\n" 263 | "\n" 264 | "\tldd | grep libdl.so\n" 265 | "\n" 266 | "And then inspecting the version attached to the dlsym symbol:\n" 267 | "\n" 268 | "\treadelf -s /path/to/libdl.so.2 | grep dlsym\n" 269 | "\n" 270 | "And finally, adding the version to dlwrap.c:dlwrap_real_dlsym.\n", 271 | stderr); 272 | 273 | exit(1); 274 | } 275 | } 276 | 277 | return real_dlsym(handle, name); 278 | } 279 | 280 | void * 281 | override_GL_glXGetProcAddress(const char *name) 282 | { 283 | void *symbol; 284 | 285 | symbol = wrapped_dlsym("GL", name); 286 | if (symbol) 287 | return symbol; 288 | 289 | return DEFER_TO_GL("libGL.so.1", override_GL_glXGetProcAddress, 290 | "glXGetProcAddress", (name)); 291 | } 292 | 293 | void * 294 | override_GL_glXGetProcAddressARB(const char *name) 295 | { 296 | void *symbol; 297 | 298 | symbol = wrapped_dlsym("GL", name); 299 | if (symbol) 300 | return symbol; 301 | 302 | return DEFER_TO_GL("libGL.so.1", override_GL_glXGetProcAddressARB, 303 | "glXGetProcAddressARB", (name)); 304 | } 305 | 306 | void * 307 | override_EGL_eglGetProcAddress(const char *name) 308 | { 309 | void *symbol; 310 | 311 | if (!STRNCMP_LITERAL(name, "gl")) { 312 | symbol = wrapped_dlsym("GLES2", name); 313 | if (symbol) 314 | return symbol; 315 | } 316 | 317 | if (!STRNCMP_LITERAL(name, "egl")) { 318 | symbol = wrapped_dlsym("EGL", name); 319 | if (symbol) 320 | return symbol; 321 | } 322 | 323 | return DEFER_TO_GL("libEGL.so.1", override_EGL_eglGetProcAddress, 324 | "eglGetProcAddress", (name)); 325 | } 326 | -------------------------------------------------------------------------------- /test/dlwrap.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Intel Corporation 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef DLWRAP_H 23 | #define DLWRAP_H 24 | 25 | #define _GNU_SOURCE 26 | #include 27 | 28 | /* Call the *real* dlopen. We have our own wrapper for dlopen that, of 29 | * necessity must use claim the symbol 'dlopen'. So whenever anything 30 | * internal needs to call the real, underlying dlopen function, the 31 | * thing to call is dlwrap_real_dlopen. 32 | */ 33 | void * 34 | dlwrap_real_dlopen(const char *filename, int flag); 35 | 36 | /* Perform a dlopen on the libfips library itself. 37 | * 38 | * Many places in fips need to lookup symbols within the libfips 39 | * library itself, (and not in any other library). This function 40 | * provides a reliable way to get a handle for performing such 41 | * lookups. 42 | * 43 | * The returned handle can be passed to dlwrap_real_dlsym for the 44 | * lookups. */ 45 | void * 46 | dlwrap_dlopen_libfips(void); 47 | 48 | /* Call the *real* dlsym. We have our own wrapper for dlsym that, of 49 | * necessity must use claim the symbol 'dlsym'. So whenever anything 50 | * internal needs to call the real, underlying dlysm function, the 51 | * thing to call is dlwrap_real_dlsym. 52 | */ 53 | void * 54 | dlwrap_real_dlsym(void *handle, const char *symbol); 55 | 56 | #define DEFER_TO_GL(library, func, name, args) \ 57 | ({ \ 58 | void *lib = dlwrap_real_dlopen(library, RTLD_LAZY | RTLD_LOCAL); \ 59 | typeof(&func) real_func = dlwrap_real_dlsym(lib, name); \ 60 | /* gcc extension -- func's return value is the return value of \ 61 | * the statement. \ 62 | */ \ 63 | real_func args; \ 64 | }) 65 | 66 | #endif 67 | 68 | -------------------------------------------------------------------------------- /test/egl_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include "egl_common.h" 28 | 29 | /** 30 | * Do whatever it takes to get us an EGL display for the system. 31 | * 32 | * This needs to be ported to other window systems. 33 | */ 34 | EGLDisplay * 35 | get_egl_display_or_skip(void) 36 | { 37 | Display *dpy = XOpenDisplay(NULL); 38 | EGLint major, minor; 39 | EGLDisplay *edpy; 40 | bool ok; 41 | 42 | if (!dpy) 43 | errx(77, "couldn't open display\n"); 44 | 45 | edpy = eglGetDisplay(dpy); 46 | if (!edpy) 47 | errx(1, "Couldn't get EGL display for X11 Display.\n"); 48 | 49 | ok = eglInitialize(edpy, &major, &minor); 50 | if (!ok) 51 | errx(1, "eglInitialize() failed\n"); 52 | 53 | return edpy; 54 | } 55 | -------------------------------------------------------------------------------- /test/egl_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | EGLDisplay * 25 | get_egl_display_or_skip(void); 26 | -------------------------------------------------------------------------------- /test/egl_epoxy_api.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Emmanuele Bassi 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file epoxy_api.c 26 | * 27 | * Tests the Epoxy API using EGL. 28 | */ 29 | 30 | #ifdef __sun 31 | #define __EXTENSIONS__ 32 | #else 33 | #define _GNU_SOURCE 34 | #endif 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "epoxy/gl.h" 41 | #include "epoxy/egl.h" 42 | 43 | #include "egl_common.h" 44 | 45 | static bool 46 | make_egl_current_and_test(EGLDisplay *dpy, EGLContext ctx) 47 | { 48 | const char *string; 49 | GLuint shader; 50 | bool pass = true; 51 | 52 | eglMakeCurrent(dpy, NULL, NULL, ctx); 53 | 54 | if (!epoxy_is_desktop_gl()) { 55 | fputs("Claimed to be desktop\n", stderr); 56 | pass = false; 57 | } 58 | 59 | if (epoxy_gl_version() < 20) { 60 | fprintf(stderr, "Claimed to be GL version %d\n", 61 | epoxy_gl_version()); 62 | pass = false; 63 | } 64 | 65 | if (epoxy_glsl_version() < 100) { 66 | fprintf(stderr, "Claimed to have GLSL version %d\n", 67 | epoxy_glsl_version()); 68 | pass = false; 69 | } 70 | 71 | string = (const char *)glGetString(GL_VERSION); 72 | printf("GL version: %s - Epoxy: %d\n", string, epoxy_gl_version()); 73 | 74 | string = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); 75 | printf("GLSL version: %s - Epoxy: %d\n", string, epoxy_glsl_version()); 76 | 77 | shader = glCreateShader(GL_FRAGMENT_SHADER); 78 | pass = glIsShader(shader); 79 | 80 | return pass; 81 | } 82 | 83 | static void 84 | init_egl(EGLDisplay *dpy, EGLContext *out_ctx) 85 | { 86 | static const EGLint config_attribs[] = { 87 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 88 | EGL_RED_SIZE, 1, 89 | EGL_GREEN_SIZE, 1, 90 | EGL_BLUE_SIZE, 1, 91 | EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, 92 | EGL_NONE 93 | }; 94 | static const EGLint context_attribs[] = { 95 | EGL_CONTEXT_CLIENT_VERSION, 2, 96 | EGL_NONE 97 | }; 98 | EGLContext ctx; 99 | EGLConfig cfg; 100 | EGLint count; 101 | 102 | if (!epoxy_has_egl_extension(dpy, "EGL_KHR_surfaceless_context")) 103 | errx(77, "Test requires EGL_KHR_surfaceless_context"); 104 | 105 | if (!eglBindAPI(EGL_OPENGL_API)) 106 | errx(77, "Couldn't initialize EGL with desktop GL\n"); 107 | 108 | if (!eglChooseConfig(dpy, config_attribs, &cfg, 1, &count)) 109 | errx(77, "Couldn't get an EGLConfig\n"); 110 | 111 | ctx = eglCreateContext(dpy, cfg, NULL, context_attribs); 112 | if (!ctx) 113 | errx(77, "Couldn't create a GL context\n"); 114 | 115 | *out_ctx = ctx; 116 | } 117 | 118 | int 119 | main(int argc, char **argv) 120 | { 121 | bool pass = true; 122 | 123 | EGLContext egl_ctx; 124 | EGLDisplay *dpy = get_egl_display_or_skip(); 125 | const char *extensions = eglQueryString(dpy, EGL_EXTENSIONS); 126 | char *first_space; 127 | char *an_extension; 128 | 129 | /* We don't have any extensions guaranteed by the ABI, so for the 130 | * touch test we just check if the first one is reported to be there. 131 | */ 132 | first_space = strstr(extensions, " "); 133 | if (first_space) { 134 | an_extension = strndup(extensions, first_space - extensions); 135 | } else { 136 | an_extension = strdup(extensions); 137 | } 138 | 139 | if (!epoxy_extension_in_string(extensions, an_extension)) 140 | errx(1, "Implementation reported absence of %s", an_extension); 141 | 142 | free(an_extension); 143 | 144 | init_egl(dpy, &egl_ctx); 145 | pass = make_egl_current_and_test(dpy, egl_ctx); 146 | 147 | return pass != true; 148 | } 149 | -------------------------------------------------------------------------------- /test/egl_gl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file egl_gl.c 26 | * 27 | * Tests that epoxy works with EGL using desktop OpenGL. 28 | */ 29 | 30 | #define _GNU_SOURCE 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "epoxy/gl.h" 39 | #include "epoxy/egl.h" 40 | #include "epoxy/glx.h" 41 | 42 | #include "egl_common.h" 43 | #include "glx_common.h" 44 | #include "dlwrap.h" 45 | 46 | static bool 47 | make_egl_current_and_test(EGLDisplay *dpy, EGLContext ctx) 48 | { 49 | const char *string; 50 | GLuint shader; 51 | bool pass = true; 52 | 53 | eglMakeCurrent(dpy, NULL, NULL, ctx); 54 | 55 | if (!epoxy_is_desktop_gl()) { 56 | fputs("Claimed to be desktop\n", stderr); 57 | pass = false; 58 | } 59 | 60 | if (epoxy_gl_version() < 20) { 61 | fprintf(stderr, "Claimed to be GL version %d\n", 62 | epoxy_gl_version()); 63 | pass = false; 64 | } 65 | 66 | string = (const char *)glGetString(GL_VERSION); 67 | printf("GL version: %s\n", string); 68 | 69 | shader = glCreateShader(GL_FRAGMENT_SHADER); 70 | pass = glIsShader(shader); 71 | 72 | return pass; 73 | } 74 | 75 | static void 76 | init_egl(EGLDisplay **out_dpy, EGLContext *out_ctx) 77 | { 78 | EGLDisplay *dpy = get_egl_display_or_skip(); 79 | static const EGLint config_attribs[] = { 80 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 81 | EGL_RED_SIZE, 1, 82 | EGL_GREEN_SIZE, 1, 83 | EGL_BLUE_SIZE, 1, 84 | EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, 85 | EGL_NONE 86 | }; 87 | static const EGLint context_attribs[] = { 88 | EGL_CONTEXT_CLIENT_VERSION, 2, 89 | EGL_NONE 90 | }; 91 | EGLContext ctx; 92 | EGLConfig cfg; 93 | EGLint count; 94 | 95 | if (!epoxy_has_egl_extension(dpy, "EGL_KHR_surfaceless_context")) 96 | errx(77, "Test requires EGL_KHR_surfaceless_context"); 97 | 98 | if (!eglBindAPI(EGL_OPENGL_API)) 99 | errx(77, "Couldn't initialize EGL with desktop GL\n"); 100 | 101 | if (!eglChooseConfig(dpy, config_attribs, &cfg, 1, &count)) 102 | errx(77, "Couldn't get an EGLConfig\n"); 103 | 104 | ctx = eglCreateContext(dpy, cfg, NULL, context_attribs); 105 | if (!ctx) 106 | errx(77, "Couldn't create a GL context\n"); 107 | 108 | *out_dpy = dpy; 109 | *out_ctx = ctx; 110 | } 111 | 112 | int 113 | main(int argc, char **argv) 114 | { 115 | bool pass = true; 116 | EGLDisplay *egl_dpy; 117 | EGLContext egl_ctx; 118 | 119 | /* Force epoxy to have loaded both EGL and GLX libs already -- we 120 | * can't assume anything about symbol resolution based on having 121 | * EGL or GLX loaded. 122 | */ 123 | (void)glXGetCurrentContext(); 124 | (void)eglGetCurrentContext(); 125 | 126 | init_egl(&egl_dpy, &egl_ctx); 127 | pass = make_egl_current_and_test(egl_dpy, egl_ctx) && pass; 128 | 129 | return pass != true; 130 | } 131 | -------------------------------------------------------------------------------- /test/egl_has_extension_nocontext.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file egl_has_extension_nocontext.c 26 | * 27 | * Catches a bug in early development where eglGetProcAddress() with 28 | * no context bound would fail out in dispatch. 29 | */ 30 | 31 | #ifdef __sun 32 | #define __EXTENSIONS__ 33 | #else 34 | #define _GNU_SOURCE 35 | #endif 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "epoxy/gl.h" 42 | #include "epoxy/egl.h" 43 | 44 | #include "egl_common.h" 45 | 46 | int 47 | main(int argc, char **argv) 48 | { 49 | bool pass = true; 50 | 51 | EGLDisplay *dpy = get_egl_display_or_skip(); 52 | const char *extensions = eglQueryString(dpy, EGL_EXTENSIONS); 53 | char *first_space; 54 | char *an_extension; 55 | 56 | /* We don't have any extensions guaranteed by the ABI, so for the 57 | * touch test we just check if the first one is reported to be there. 58 | */ 59 | first_space = strstr(extensions, " "); 60 | if (first_space) { 61 | an_extension = strndup(extensions, first_space - extensions); 62 | } else { 63 | an_extension = strdup(extensions); 64 | } 65 | 66 | if (!epoxy_has_egl_extension(dpy, an_extension)) 67 | errx(1, "Implementation reported absence of %s", an_extension); 68 | 69 | free(an_extension); 70 | 71 | if (epoxy_has_egl_extension(dpy, "GLX_ARB_ham_sandwich")) 72 | errx(1, "Implementation reported presence of GLX_ARB_ham_sandwich"); 73 | 74 | return pass != true; 75 | } 76 | -------------------------------------------------------------------------------- /test/egl_without_glx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file egl_without_glx.c 26 | * 27 | * Tries to test operation of the library on a GL stack with EGL and 28 | * GLES but no GLX or desktop GL (such as Arm's Mali GLES3 drivers). 29 | * This test is varied by the GLES_VERSION defined at compile time to 30 | * test either a GLES1-only or a GLES2-only system. 31 | */ 32 | 33 | #define _GNU_SOURCE 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "epoxy/gl.h" 42 | #include "epoxy/egl.h" 43 | 44 | #include "egl_common.h" 45 | 46 | /** 47 | * Wraps the system dlopen(), which libepoxy will end up calling when 48 | * it tries to dlopen() the API libraries, and errors out the 49 | * libraries we're trying to simulate not being installed on the 50 | * system. 51 | */ 52 | void * 53 | dlopen(const char *filename, int flag) 54 | { 55 | void * (*dlopen_unwrapped)(const char *filename, int flag); 56 | 57 | if (filename) { 58 | if (!strcmp(filename, "libGL.so.1")) 59 | return NULL; 60 | #if GLES_VERSION == 2 61 | if (!strcmp(filename, "libGLESv1_CM.so.1")) 62 | return NULL; 63 | #else 64 | if (!strcmp(filename, "libGLESv2.so.2")) 65 | return NULL; 66 | #endif 67 | } 68 | 69 | dlopen_unwrapped = dlsym(RTLD_NEXT, "dlopen"); 70 | assert(dlopen_unwrapped); 71 | 72 | return dlopen_unwrapped(filename, flag); 73 | } 74 | 75 | 76 | static EGLenum last_api; 77 | static EGLenum extra_error = EGL_SUCCESS; 78 | 79 | /** 80 | * Override of the real libEGL's eglBindAPI to simulate the target 81 | * system's eglBindAPI. 82 | */ 83 | static EGLBoolean 84 | override_eglBindAPI(EGLenum api) 85 | { 86 | void *egl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); 87 | EGLBoolean (*real_eglBindAPI)(EGLenum api) = dlsym(egl, "eglBindAPI"); 88 | 89 | last_api = api; 90 | 91 | if (api == EGL_OPENGL_API) { 92 | extra_error = EGL_BAD_PARAMETER; 93 | return EGL_FALSE; 94 | } 95 | 96 | assert(real_eglBindAPI); 97 | return real_eglBindAPI(api); 98 | } 99 | 100 | /** 101 | * Override of the real libEGL's eglGetError() to feed back the error 102 | * that might have been generated by override_eglBindAPI(). 103 | */ 104 | static EGLint 105 | override_eglGetError(void) 106 | { 107 | void *egl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); 108 | EGLint (*real_eglGetError)(void) = dlsym(egl, "eglGetError"); 109 | 110 | if (extra_error != EGL_SUCCESS) { 111 | EGLenum error = extra_error; 112 | extra_error = EGL_SUCCESS; 113 | return error; 114 | } 115 | 116 | assert(real_eglGetError); 117 | return real_eglGetError(); 118 | } 119 | 120 | int 121 | main(int argc, char **argv) 122 | { 123 | bool pass = true; 124 | EGLDisplay *dpy = get_egl_display_or_skip(); 125 | EGLint context_attribs[] = { 126 | EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, 127 | EGL_NONE 128 | }; 129 | EGLConfig cfg; 130 | EGLint config_attribs[] = { 131 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 132 | EGL_RED_SIZE, 1, 133 | EGL_GREEN_SIZE, 1, 134 | EGL_BLUE_SIZE, 1, 135 | EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, 136 | EGL_NONE 137 | }; 138 | EGLint count; 139 | EGLContext ctx; 140 | const unsigned char *string; 141 | 142 | epoxy_eglBindAPI = override_eglBindAPI; 143 | epoxy_eglGetError = override_eglGetError; 144 | 145 | if (!epoxy_has_egl_extension(dpy, "EGL_KHR_surfaceless_context")) 146 | errx(77, "Test requires EGL_KHR_surfaceless_context"); 147 | 148 | eglBindAPI(EGL_OPENGL_ES_API); 149 | 150 | if (!eglChooseConfig(dpy, config_attribs, &cfg, 1, &count)) 151 | errx(77, "Couldn't get an EGLConfig\n"); 152 | 153 | ctx = eglCreateContext(dpy, cfg, NULL, context_attribs); 154 | if (!ctx) 155 | errx(77, "Couldn't create a GLES%d context\n", GLES_VERSION); 156 | 157 | eglMakeCurrent(dpy, NULL, NULL, ctx); 158 | 159 | string = glGetString(GL_VERSION); 160 | printf("GL_VERSION: %s\n", string); 161 | 162 | assert(eglGetError() == EGL_SUCCESS); 163 | 164 | return pass != true; 165 | } 166 | -------------------------------------------------------------------------------- /test/gl_version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Broadcom 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include "epoxy/gl.h" 27 | 28 | GLenum mock_enum; 29 | const char *mock_gl_version; 30 | const char *mock_glsl_version; 31 | 32 | static const GLubyte * EPOXY_CALLSPEC override_glGetString(GLenum name) 33 | { 34 | switch (name) { 35 | case GL_VERSION: 36 | return (GLubyte *)mock_gl_version; 37 | case GL_SHADING_LANGUAGE_VERSION: 38 | return (GLubyte *)mock_glsl_version; 39 | default: 40 | assert(!"unexpected glGetString() enum"); 41 | return 0; 42 | } 43 | } 44 | 45 | static bool 46 | test_version(const char *gl_string, int gl_version, 47 | const char *glsl_string, int glsl_version) 48 | { 49 | int epoxy_version; 50 | 51 | mock_gl_version = gl_string; 52 | mock_glsl_version = glsl_string; 53 | 54 | epoxy_version = epoxy_gl_version(); 55 | if (epoxy_version != gl_version) { 56 | fprintf(stderr, 57 | "glGetString(GL_VERSION) = \"%s\" returned epoxy_gl_version() " 58 | "%d instead of %d\n", gl_string, epoxy_version, gl_version); 59 | return false; 60 | } 61 | 62 | 63 | epoxy_version = epoxy_glsl_version(); 64 | if (epoxy_version != glsl_version) { 65 | fprintf(stderr, 66 | "glGetString() = \"%s\" returned epoxy_glsl_version() " 67 | "%d instead of %d\n", glsl_string, epoxy_version, glsl_version); 68 | return false; 69 | } 70 | 71 | return true; 72 | } 73 | 74 | int 75 | main(int argc, char **argv) 76 | { 77 | bool pass = true; 78 | 79 | epoxy_glGetString = override_glGetString; 80 | 81 | pass = pass && test_version("3.0 Mesa 13.0.6", 30, 82 | "1.30", 130); 83 | pass = pass && test_version("OpenGL ES 2.0 Mesa 20.1.0-devel (git-4bb19a330e)", 20, 84 | "OpenGL ES GLSL ES 1.0.16", 100); 85 | pass = pass && test_version("OpenGL ES 3.2 Mesa 18.3.0-devel", 32, 86 | "OpenGL ES GLSL ES 3.20", 320); 87 | pass = pass && test_version("4.5.0 NVIDIA 384.130", 45, 88 | "4.50", 450); 89 | 90 | return pass != true; 91 | } 92 | -------------------------------------------------------------------------------- /test/glx_alias_prefer_same_name.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file glx_gles2.c 26 | * 27 | * Catches a bug where a GLES2 context using 28 | * GLX_EXT_create_context_es2_profile would try to find the symbols in 29 | * libGLESv2.so.2 instead of libGL.so.1. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include "epoxy/gl.h" 36 | #include "epoxy/glx.h" 37 | #include 38 | 39 | #include "glx_common.h" 40 | 41 | static Display *dpy; 42 | 43 | static int last_call; 44 | 45 | #define CORE_FUNC_VAL 100 46 | #define EXT_FUNC_VAL 101 47 | 48 | void 49 | override_GL_glBindTexture(GLenum target); 50 | void 51 | override_GL_glBindTextureEXT(GLenum target); 52 | 53 | void 54 | override_GL_glBindTexture(GLenum target) 55 | { 56 | last_call = CORE_FUNC_VAL; 57 | } 58 | 59 | void 60 | override_GL_glBindTextureEXT(GLenum target) 61 | { 62 | last_call = EXT_FUNC_VAL; 63 | } 64 | 65 | int 66 | main(int argc, char **argv) 67 | { 68 | bool pass = true; 69 | 70 | dpy = get_display_or_skip(); 71 | make_glx_context_current_or_skip(dpy); 72 | 73 | if (!epoxy_has_gl_extension("GL_EXT_texture_object")) 74 | errx(77, "Test requires GL_EXT_texture_object"); 75 | 76 | glBindTexture(GL_TEXTURE_2D, 1); 77 | pass = pass && last_call == CORE_FUNC_VAL; 78 | glBindTextureEXT(GL_TEXTURE_2D, 1); 79 | pass = pass && last_call == EXT_FUNC_VAL; 80 | 81 | return pass != true; 82 | } 83 | -------------------------------------------------------------------------------- /test/glx_beginend.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include "epoxy/gl.h" 27 | #include "epoxy/glx.h" 28 | #include 29 | 30 | #include "glx_common.h" 31 | 32 | static Display *dpy; 33 | static bool has_argb2101010; 34 | 35 | static bool 36 | test_with_epoxy(void) 37 | { 38 | glBegin(GL_TRIANGLES); 39 | { 40 | /* Hit a base entrypoint that won't call gl_version() */ 41 | glVertex2f(0, 0); 42 | 43 | /* Hit an entrypoint that will call probably call gl_version() */ 44 | glMultiTexCoord4f(GL_TEXTURE0, 0.0, 0.0, 0.0, 0.0); 45 | 46 | /* Hit an entrypoint that will probably call 47 | * epoxy_conservative_has_extension(); 48 | */ 49 | if (has_argb2101010) { 50 | glTexCoordP4ui(GL_UNSIGNED_INT_2_10_10_10_REV, 0); 51 | } 52 | } 53 | glEnd(); 54 | 55 | /* No error should have been generated in the process. */ 56 | return glGetError() == 0; 57 | } 58 | 59 | 60 | 61 | #undef glBegin 62 | #undef glEnd 63 | extern void glBegin(GLenum primtype); 64 | extern void glEnd(void); 65 | 66 | static bool 67 | test_without_epoxy(void) 68 | { 69 | glBegin(GL_TRIANGLES); 70 | { 71 | /* Hit a base entrypoint that won't call gl_version() */ 72 | glVertex4f(0, 0, 0, 0); 73 | 74 | /* Hit an entrypoint that will call probably call gl_version() */ 75 | glMultiTexCoord3f(GL_TEXTURE0, 0.0, 0.0, 0.0); 76 | 77 | /* Hit an entrypoint that will probably call 78 | * epoxy_conservative_has_extension(); 79 | */ 80 | if (has_argb2101010) { 81 | glTexCoordP3ui(GL_UNSIGNED_INT_2_10_10_10_REV, 0); 82 | } 83 | } 84 | glEnd(); 85 | 86 | /* We can't make any assertions about error presence this time 87 | * around. This test is just trying to catch segfaults. 88 | */ 89 | return true; 90 | } 91 | 92 | int 93 | main(int argc, char **argv) 94 | { 95 | bool pass = true; 96 | 97 | dpy = get_display_or_skip(); 98 | make_glx_context_current_or_skip(dpy); 99 | 100 | has_argb2101010 = 101 | epoxy_has_gl_extension("GL_ARB_vertex_type_2_10_10_10_rev"); 102 | 103 | pass = pass && test_with_epoxy(); 104 | pass = pass && test_without_epoxy(); 105 | 106 | return pass != true; 107 | } 108 | -------------------------------------------------------------------------------- /test/glx_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009, 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include "glx_common.h" 28 | 29 | Display * 30 | get_display_or_skip(void) 31 | { 32 | Display *dpy = XOpenDisplay(NULL); 33 | 34 | if (!dpy) { 35 | fputs("couldn't open display\n", stderr); 36 | exit(77); 37 | } 38 | 39 | return dpy; 40 | } 41 | 42 | XVisualInfo * 43 | get_glx_visual(Display *dpy) 44 | { 45 | XVisualInfo *visinfo; 46 | int attrib[] = { 47 | GLX_RGBA, 48 | GLX_RED_SIZE, 1, 49 | GLX_GREEN_SIZE, 1, 50 | GLX_BLUE_SIZE, 1, 51 | GLX_DOUBLEBUFFER, 52 | None 53 | }; 54 | int screen = DefaultScreen(dpy); 55 | 56 | visinfo = glXChooseVisual(dpy, screen, attrib); 57 | if (visinfo == NULL) { 58 | fputs("Couldn't get an RGBA, double-buffered visual\n", stderr); 59 | exit(1); 60 | } 61 | 62 | return visinfo; 63 | } 64 | 65 | Window 66 | get_glx_window(Display *dpy, XVisualInfo *visinfo, bool map) 67 | { 68 | XSetWindowAttributes window_attr; 69 | unsigned long mask; 70 | int screen = DefaultScreen(dpy); 71 | Window root_win = RootWindow(dpy, screen); 72 | Window win; 73 | 74 | window_attr.background_pixel = 0; 75 | window_attr.border_pixel = 0; 76 | window_attr.colormap = XCreateColormap(dpy, root_win, 77 | visinfo->visual, AllocNone); 78 | window_attr.event_mask = StructureNotifyMask | ExposureMask | 79 | KeyPressMask; 80 | mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 81 | win = XCreateWindow(dpy, root_win, 0, 0, 82 | 10, 10, /* width, height */ 83 | 0, visinfo->depth, InputOutput, 84 | visinfo->visual, mask, &window_attr); 85 | 86 | return win; 87 | } 88 | 89 | void 90 | make_glx_context_current_or_skip(Display *dpy) 91 | { 92 | GLXContext ctx; 93 | XVisualInfo *visinfo = get_glx_visual(dpy); 94 | Window win = get_glx_window(dpy, visinfo, false); 95 | 96 | ctx = glXCreateContext(dpy, visinfo, False, True); 97 | if (ctx == None) { 98 | fputs("glXCreateContext failed\n", stderr); 99 | exit(1); 100 | } 101 | 102 | glXMakeCurrent(dpy, win, ctx); 103 | } 104 | 105 | GLXFBConfig 106 | get_fbconfig_for_visinfo(Display *dpy, XVisualInfo *visinfo) 107 | { 108 | int i, nconfigs; 109 | GLXFBConfig ret = None, *configs; 110 | 111 | configs = glXGetFBConfigs(dpy, visinfo->screen, &nconfigs); 112 | if (!configs) 113 | return None; 114 | 115 | for (i = 0; i < nconfigs; i++) { 116 | int v; 117 | 118 | if (glXGetFBConfigAttrib(dpy, configs[i], GLX_VISUAL_ID, &v)) 119 | continue; 120 | 121 | if (v == visinfo->visualid) { 122 | ret = configs[i]; 123 | break; 124 | } 125 | } 126 | 127 | XFree(configs); 128 | return ret; 129 | } 130 | -------------------------------------------------------------------------------- /test/glx_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include "epoxy/glx.h" 25 | 26 | Display * 27 | get_display_or_skip(void); 28 | 29 | void 30 | make_glx_context_current_or_skip(Display *dpy); 31 | 32 | GLXFBConfig 33 | get_fbconfig_for_visinfo(Display *dpy, XVisualInfo *visinfo); 34 | 35 | XVisualInfo * 36 | get_glx_visual(Display *dpy); 37 | 38 | Window 39 | get_glx_window(Display *dpy, XVisualInfo *visinfo, bool map); 40 | -------------------------------------------------------------------------------- /test/glx_gles2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file glx_gles2.c 26 | * 27 | * Catches a bug where a GLES2 context using 28 | * GLX_EXT_create_context_es2_profile would try to find the symbols in 29 | * libGLESv2.so.2 instead of libGL.so.1. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include "epoxy/gl.h" 36 | #include "epoxy/glx.h" 37 | #include 38 | 39 | #include "glx_common.h" 40 | 41 | static Display *dpy; 42 | 43 | GLuint 44 | override_GLES2_glCreateShader(GLenum target); 45 | 46 | GLuint 47 | override_GLES2_glCreateShader(GLenum target) 48 | { 49 | return 0; 50 | } 51 | 52 | void 53 | override_GLES2_glGenQueries(GLsizei n, GLuint *ids); 54 | 55 | void 56 | override_GLES2_glGenQueries(GLsizei n, GLuint *ids) 57 | { 58 | int i; 59 | for (i = 0; i < n; i++) 60 | ids[i] = 0; 61 | } 62 | 63 | int 64 | main(int argc, char **argv) 65 | { 66 | bool pass = true; 67 | XVisualInfo *vis; 68 | Window win; 69 | GLXContext ctx; 70 | GLXFBConfig config; 71 | int context_attribs[] = { 72 | GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, 73 | GLX_CONTEXT_MAJOR_VERSION_ARB, 2, 74 | GLX_CONTEXT_MINOR_VERSION_ARB, 0, 75 | 0 76 | }; 77 | GLuint shader; 78 | 79 | dpy = get_display_or_skip(); 80 | 81 | if (!epoxy_has_glx_extension(dpy, 0, "GLX_EXT_create_context_es2_profile")) 82 | errx(77, "Test requires GLX_EXT_create_context_es2_profile"); 83 | 84 | vis = get_glx_visual(dpy); 85 | config = get_fbconfig_for_visinfo(dpy, vis); 86 | win = get_glx_window(dpy, vis, false); 87 | 88 | ctx = glXCreateContextAttribsARB(dpy, config, NULL, true, 89 | context_attribs); 90 | 91 | glXMakeCurrent(dpy, win, ctx); 92 | 93 | if (epoxy_is_desktop_gl()) { 94 | errx(1, "GLES2 context creation made a desktop context\n"); 95 | } 96 | 97 | if (epoxy_gl_version() < 20) { 98 | errx(1, "GLES2 context creation made a version %f context\n", 99 | epoxy_gl_version() / 10.0f); 100 | } 101 | 102 | /* Test using an entrypoint that's in GLES2, but not the desktop GL ABI. */ 103 | shader = glCreateShader(GL_FRAGMENT_SHADER); 104 | if (shader == 0) 105 | errx(1, "glCreateShader() failed\n"); 106 | glDeleteShader(shader); 107 | 108 | if (epoxy_gl_version() >= 30) { 109 | GLuint q = 0; 110 | 111 | glGenQueries(1, &q); 112 | if (!q) 113 | errx(1, "glGenQueries() failed\n"); 114 | glDeleteQueries(1, &q); 115 | } 116 | 117 | return pass != true; 118 | } 119 | -------------------------------------------------------------------------------- /test/glx_glxgetprocaddress_nocontext.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file glx_glxgetprocaddress_nocontext.c 26 | * 27 | * Catches a bug in early development where glXGetProcAddress() with 28 | * no context bound would fail out in dispatch. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include "epoxy/gl.h" 35 | #include "epoxy/glx.h" 36 | #include 37 | 38 | #include "glx_common.h" 39 | 40 | static Display *dpy; 41 | 42 | int 43 | main(int argc, char **argv) 44 | { 45 | bool pass = true; 46 | void *func; 47 | 48 | dpy = get_display_or_skip(); 49 | if (epoxy_glx_version(dpy, 0) < 14) 50 | errx(77, "GLX version 1.4 required for glXGetProcAddress().\n"); 51 | 52 | func = glXGetProcAddress((const GLubyte *)"glGetString"); 53 | if (!func) 54 | errx(1, "glXGetProcAddress() returned NULL\n"); 55 | 56 | return pass != true; 57 | } 58 | -------------------------------------------------------------------------------- /test/glx_has_extension_nocontext.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file glx_has_extension_nocontext.c 26 | * 27 | * Catches a bug in early development where glXGetProcAddress() with 28 | * no context bound would fail out in dispatch. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include "epoxy/gl.h" 35 | #include "epoxy/glx.h" 36 | #include 37 | 38 | #include "glx_common.h" 39 | 40 | static Display *dpy; 41 | 42 | int 43 | main(int argc, char **argv) 44 | { 45 | bool pass = true; 46 | 47 | dpy = get_display_or_skip(); 48 | 49 | if (!epoxy_has_glx_extension(dpy, 0, "GLX_ARB_get_proc_address")) 50 | errx(1, "Implementation reported absence of GLX_ARB_get_proc_address"); 51 | 52 | if (epoxy_has_glx_extension(dpy, 0, "GLX_ARB_ham_sandwich")) 53 | errx(1, "Implementation reported presence of GLX_ARB_ham_sandwich"); 54 | 55 | return pass != true; 56 | } 57 | -------------------------------------------------------------------------------- /test/glx_public_api.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include "epoxy/gl.h" 27 | #include "epoxy/glx.h" 28 | #include 29 | 30 | #include "glx_common.h" 31 | 32 | static Display *dpy; 33 | 34 | static bool 35 | test_gl_version(void) 36 | { 37 | int version = epoxy_gl_version(); 38 | if (version < 12) { 39 | fprintf(stderr, 40 | "Reported GL version %d, should be at least 12\n", 41 | version); 42 | return false; 43 | } 44 | 45 | return true; 46 | } 47 | 48 | static bool 49 | test_glx_version(void) 50 | { 51 | int version = epoxy_glx_version(dpy, 0); 52 | const char *version_string; 53 | int ret; 54 | int server_major, server_minor; 55 | int client_major, client_minor; 56 | int server, client, expected; 57 | 58 | if (version < 13) { 59 | fprintf(stderr, 60 | "Reported GLX version %d, should be at least 13 " 61 | "according to Linux GL ABI\n", 62 | version); 63 | return false; 64 | } 65 | 66 | version_string = glXQueryServerString(dpy, 0, GLX_VERSION); 67 | ret = sscanf(version_string, "%d.%d", &server_major, &server_minor); 68 | assert(ret == 2); 69 | server = server_major * 10 + server_minor; 70 | 71 | version_string = glXGetClientString(dpy, GLX_VERSION); 72 | ret = sscanf(version_string, "%d.%d", &client_major, &client_minor); 73 | assert(ret == 2); 74 | client = client_major * 10 + client_minor; 75 | 76 | if (client < server) 77 | expected = client; 78 | else 79 | expected = server; 80 | 81 | if (version != expected) { 82 | fprintf(stderr, 83 | "Reported GLX version %d, should be %d (%s)\n", 84 | version, expected, version_string); 85 | return false; 86 | } 87 | 88 | return true; 89 | } 90 | 91 | static bool 92 | test_glx_extension_supported(void) 93 | { 94 | if (!epoxy_has_glx_extension(dpy, 0, "GLX_ARB_get_proc_address")) { 95 | fputs("Incorrectly reported no support for GLX_ARB_get_proc_address " 96 | "(should always be present in Linux ABI)\n", 97 | stderr); 98 | return false; 99 | } 100 | 101 | if (epoxy_has_glx_extension(dpy, 0, "GLX_EXT_ham_sandwich")) { 102 | fputs("Incorrectly reported support for GLX_EXT_ham_sandwich\n", 103 | stderr); 104 | return false; 105 | } 106 | 107 | return true; 108 | } 109 | 110 | int 111 | main(int argc, char **argv) 112 | { 113 | bool pass = true; 114 | 115 | dpy = get_display_or_skip(); 116 | make_glx_context_current_or_skip(dpy); 117 | 118 | pass = test_gl_version() && pass; 119 | pass = test_glx_version() && pass; 120 | pass = test_glx_extension_supported() && pass; 121 | 122 | return pass != true; 123 | } 124 | -------------------------------------------------------------------------------- /test/glx_public_api_core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "epoxy/gl.h" 29 | #include "epoxy/glx.h" 30 | #include 31 | 32 | #include "glx_common.h" 33 | 34 | static Display *dpy; 35 | 36 | static bool 37 | test_has_extensions(void) 38 | { 39 | int num_extensions; 40 | 41 | glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); 42 | 43 | for (int i = 0; i < num_extensions; i++) { 44 | char *ext = (char *)glGetStringi(GL_EXTENSIONS, i); 45 | 46 | if (!epoxy_has_gl_extension(ext)) { 47 | fprintf(stderr, "GL implementation reported support for %s, " 48 | "but epoxy didn't\n", ext); 49 | return false; 50 | } 51 | } 52 | 53 | if (epoxy_has_gl_extension("GL_ARB_ham_sandwich")) { 54 | fputs("epoxy implementation reported support for " 55 | "GL_ARB_ham_sandwich, but it shouldn't\n", 56 | stderr); 57 | return false; 58 | } 59 | 60 | return true; 61 | } 62 | 63 | static bool 64 | test_gl_version(void) 65 | { 66 | int gl_version, epoxy_version; 67 | int major, minor; 68 | 69 | glGetIntegerv(GL_MAJOR_VERSION, &major); 70 | glGetIntegerv(GL_MINOR_VERSION, &minor); 71 | gl_version = major * 10 + minor; 72 | 73 | if (gl_version < 32) { 74 | fprintf(stderr, 75 | "Implementation reported GL version %d, should be at least 32\n", 76 | gl_version); 77 | return false; 78 | } 79 | 80 | epoxy_version = epoxy_gl_version(); 81 | if (epoxy_version != gl_version) { 82 | fprintf(stderr, 83 | "Epoxy reported GL version %d, should be %d\n", 84 | epoxy_version, gl_version); 85 | return false; 86 | } 87 | 88 | return true; 89 | } 90 | 91 | static bool 92 | test_glx_version(void) 93 | { 94 | int version = epoxy_glx_version(dpy, 0); 95 | const char *version_string; 96 | int ret; 97 | int server_major, server_minor; 98 | int client_major, client_minor; 99 | int server, client, expected; 100 | 101 | if (version < 13) { 102 | fprintf(stderr, 103 | "Reported GLX version %d, should be at least 13 " 104 | "according to Linux GL ABI\n", 105 | version); 106 | return false; 107 | } 108 | 109 | version_string = glXQueryServerString(dpy, 0, GLX_VERSION); 110 | ret = sscanf(version_string, "%d.%d", &server_major, &server_minor); 111 | assert(ret == 2); 112 | server = server_major * 10 + server_minor; 113 | 114 | version_string = glXGetClientString(dpy, GLX_VERSION); 115 | ret = sscanf(version_string, "%d.%d", &client_major, &client_minor); 116 | assert(ret == 2); 117 | client = client_major * 10 + client_minor; 118 | 119 | if (client < server) 120 | expected = client; 121 | else 122 | expected = server; 123 | 124 | if (version != expected) { 125 | fprintf(stderr, 126 | "Reported GLX version %d, should be %d (%s)\n", 127 | version, expected, version_string); 128 | return false; 129 | } 130 | 131 | return true; 132 | } 133 | 134 | static int 135 | error_handler(Display *d, XErrorEvent *ev) 136 | { 137 | return 0; 138 | } 139 | 140 | int 141 | main(int argc, char **argv) 142 | { 143 | bool pass = true; 144 | XVisualInfo *visinfo; 145 | Window win; 146 | GLXFBConfig config; 147 | static const int attribs[] = { 148 | GLX_CONTEXT_PROFILE_MASK_ARB, 149 | GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 150 | GLX_CONTEXT_MAJOR_VERSION_ARB, 151 | 3, 152 | GLX_CONTEXT_MINOR_VERSION_ARB, 153 | 2, 154 | None 155 | }; 156 | GLXContext ctx; 157 | int (*old_handler)(Display *, XErrorEvent *); 158 | 159 | dpy = get_display_or_skip(); 160 | 161 | if (!epoxy_has_glx_extension(dpy, 0, "GLX_ARB_create_context_profile")) 162 | errx(77, "Test requires GLX_ARB_create_context_profile"); 163 | 164 | visinfo = get_glx_visual(dpy); 165 | win = get_glx_window(dpy, visinfo, false); 166 | config = get_fbconfig_for_visinfo(dpy, visinfo); 167 | 168 | old_handler = XSetErrorHandler(error_handler); 169 | ctx = glXCreateContextAttribsARB(dpy, config, NULL, True, attribs); 170 | if (ctx == None) 171 | errx(77, "glXCreateContext failed"); 172 | XSetErrorHandler(old_handler); 173 | 174 | glXMakeCurrent(dpy, win, ctx); 175 | 176 | pass = test_gl_version() && pass; 177 | pass = test_glx_version() && pass; 178 | pass = test_has_extensions() && pass; 179 | 180 | return pass != true; 181 | } 182 | -------------------------------------------------------------------------------- /test/glx_static.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file glx_static.c 26 | * 27 | * Simple touch-test of using epoxy when linked statically. On Linux, 28 | * the ifunc support we'd like to use has some significant behavior 29 | * changes depending on whether it's a static build or shared library 30 | * build. 31 | * 32 | * Note that if configured without --enable-static, this test will end 33 | * up dynamically linked anyway, defeating the test. 34 | */ 35 | 36 | #include 37 | #include 38 | #include "epoxy/gl.h" 39 | #include "epoxy/glx.h" 40 | #include 41 | #include 42 | 43 | #include "glx_common.h" 44 | 45 | int 46 | main(int argc, char **argv) 47 | { 48 | bool pass = true; 49 | int val; 50 | 51 | #if NEEDS_TO_BE_STATIC 52 | if (dlsym(NULL, "epoxy_glCompileShader")) { 53 | fputs("glx_static requires epoxy built with --enable-static\n", stderr); 54 | return 77; 55 | } 56 | #endif 57 | 58 | Display *dpy = get_display_or_skip(); 59 | make_glx_context_current_or_skip(dpy); 60 | 61 | glEnable(GL_LIGHTING); 62 | val = 0; 63 | glGetIntegerv(GL_LIGHTING, &val); 64 | if (!val) { 65 | fputs("Enabling GL_LIGHTING didn't stick.\n", stderr); 66 | pass = false; 67 | } 68 | 69 | return pass != true; 70 | } 71 | -------------------------------------------------------------------------------- /test/headerguards.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #ifdef BUILD_EGL 29 | #include 30 | #include 31 | #endif 32 | 33 | #ifdef BUILD_GLX 34 | #include 35 | #include 36 | #endif 37 | 38 | #ifdef BUILD_EGL 39 | #include 40 | #include 41 | #include 42 | #include 43 | #endif 44 | 45 | #ifdef BUILD_GLX 46 | #ifdef __APPLE__ 47 | #include 48 | #include 49 | #else 50 | #include 51 | #include 52 | #endif 53 | #include 54 | #include 55 | #endif 56 | 57 | int main(int argc, char **argv) 58 | { 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /test/khronos_typedefs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include "khronos_typedefs.h" 26 | #include "epoxy/gl.h" 27 | 28 | #define COMPARE_SIZE(type) \ 29 | do { \ 30 | if (sizeof(type) != system_sizes[type ## _slot]) { \ 31 | fprintf(stderr, "system %s is size %d, epoxy is %d\n", \ 32 | #type, \ 33 | (int)system_sizes[type ## _slot], \ 34 | (int)sizeof(type)); \ 35 | error = true; \ 36 | } \ 37 | } while (0) 38 | 39 | int 40 | main(int argc, char **argv) 41 | { 42 | uint32_t system_sizes[khronos_typedef_count]; 43 | bool error = false; 44 | 45 | get_system_typedef_sizes(system_sizes); 46 | 47 | COMPARE_SIZE(khronos_int8_t); 48 | COMPARE_SIZE(khronos_uint8_t); 49 | COMPARE_SIZE(khronos_int16_t); 50 | COMPARE_SIZE(khronos_uint16_t); 51 | COMPARE_SIZE(khronos_int32_t); 52 | COMPARE_SIZE(khronos_uint32_t); 53 | COMPARE_SIZE(khronos_int64_t); 54 | COMPARE_SIZE(khronos_uint64_t); 55 | COMPARE_SIZE(khronos_intptr_t); 56 | COMPARE_SIZE(khronos_uintptr_t); 57 | COMPARE_SIZE(khronos_ssize_t); 58 | COMPARE_SIZE(khronos_usize_t); 59 | COMPARE_SIZE(khronos_float_t); 60 | COMPARE_SIZE(khronos_utime_nanoseconds_t); 61 | COMPARE_SIZE(khronos_stime_nanoseconds_t); 62 | COMPARE_SIZE(khronos_boolean_enum_t); 63 | 64 | return error; 65 | } 66 | -------------------------------------------------------------------------------- /test/khronos_typedefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | enum typedef_slot { 27 | khronos_int8_t_slot, 28 | khronos_uint8_t_slot, 29 | khronos_int16_t_slot, 30 | khronos_uint16_t_slot, 31 | khronos_int32_t_slot, 32 | khronos_uint32_t_slot, 33 | khronos_int64_t_slot, 34 | khronos_uint64_t_slot, 35 | khronos_intptr_t_slot, 36 | khronos_uintptr_t_slot, 37 | khronos_ssize_t_slot, 38 | khronos_usize_t_slot, 39 | khronos_float_t_slot, 40 | /* khrplatform.h claims it defines khronos_time_ns_t, but it doesn't. */ 41 | khronos_utime_nanoseconds_t_slot, 42 | khronos_stime_nanoseconds_t_slot, 43 | khronos_boolean_enum_t_slot, 44 | khronos_typedef_count 45 | }; 46 | 47 | void get_system_typedef_sizes(uint32_t *sizes); 48 | -------------------------------------------------------------------------------- /test/khronos_typedefs_nonepoxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include "config.h" 28 | #include "khronos_typedefs.h" 29 | 30 | #ifdef HAVE_KHRPLATFORM_H 31 | 32 | #include 33 | 34 | #define GET_SIZE(type) sizes[type ## _slot] = sizeof(type) 35 | 36 | void 37 | get_system_typedef_sizes(uint32_t *sizes) 38 | { 39 | GET_SIZE(khronos_int8_t); 40 | GET_SIZE(khronos_uint8_t); 41 | GET_SIZE(khronos_int16_t); 42 | GET_SIZE(khronos_uint16_t); 43 | GET_SIZE(khronos_int32_t); 44 | GET_SIZE(khronos_uint32_t); 45 | GET_SIZE(khronos_int64_t); 46 | GET_SIZE(khronos_uint64_t); 47 | GET_SIZE(khronos_intptr_t); 48 | GET_SIZE(khronos_uintptr_t); 49 | GET_SIZE(khronos_ssize_t); 50 | GET_SIZE(khronos_usize_t); 51 | GET_SIZE(khronos_float_t); 52 | GET_SIZE(khronos_utime_nanoseconds_t); 53 | GET_SIZE(khronos_stime_nanoseconds_t); 54 | GET_SIZE(khronos_boolean_enum_t); 55 | } 56 | 57 | #else /* !HAVE_KHRPLATFORM_H */ 58 | 59 | /* Don't care -- this is a conditional case in test code. */ 60 | #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn" 61 | 62 | void 63 | get_system_typedef_sizes(uint32_t *sizes) 64 | { 65 | fputs("./configure failed to find khrplatform.h\n", stderr); 66 | exit(77); 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /test/meson.build: -------------------------------------------------------------------------------- 1 | dl_dep = cc.find_library('dl', required: false) 2 | has_dlvsym = cc.has_function('dlvsym', dependencies: dl_dep) 3 | 4 | has_gles1 = gles1_dep.found() 5 | has_gles2 = gles2_dep.found() 6 | build_x11_tests = enable_x11 and x11_dep.found() 7 | 8 | test_cflags = common_cflags 9 | if not has_dlvsym 10 | test_cflags += [ 11 | '-D_XOPEN_SOURCE', 12 | '-D_POSIX_C_SOURCE=200809L', 13 | ] 14 | endif 15 | 16 | # Unconditionally built tests 17 | test('header_guards', 18 | executable('header guards', 'headerguards.c', 19 | c_args: common_cflags, 20 | dependencies: libepoxy_dep, 21 | include_directories: libepoxy_inc)) 22 | test('misc_defines', 23 | executable('misc defines', 'miscdefines.c', 24 | c_args: common_cflags, 25 | dependencies: libepoxy_dep, 26 | include_directories: libepoxy_inc)) 27 | test('khronos_typedefs', 28 | executable('khronos typedefs', [ 29 | 'khronos_typedefs.c', 30 | 'khronos_typedefs.h', 31 | 'khronos_typedefs_nonepoxy.c', 32 | ], 33 | c_args: common_cflags, 34 | dependencies: libepoxy_dep, 35 | include_directories: libepoxy_inc)) 36 | test('gl_version', 37 | executable('gl_version', 38 | 'gl_version.c', 39 | c_args: common_cflags, 40 | dependencies: libepoxy_dep, 41 | include_directories: libepoxy_inc)) 42 | 43 | if build_egl and build_x11_tests 44 | egl_common_sources = [ 'egl_common.h', 'egl_common.c', ] 45 | egl_common_lib = static_library('egl_common', 46 | sources: egl_common_sources, 47 | dependencies: libepoxy_dep, 48 | include_directories: libepoxy_inc, 49 | c_args: common_cflags, 50 | install: false) 51 | 52 | egl_tests = [ 53 | [ 'egl_has_extension_nocontext', [], [ 'egl_has_extension_nocontext.c' ], true, ], 54 | [ 'egl_epoxy_api', [], [ 'egl_epoxy_api.c' ], true ], 55 | [ 'egl_gles1_without_glx', [ '-DGLES_VERSION=1', ], [ 'egl_without_glx.c' ], has_gles1, ], 56 | [ 'egl_gles2_without_glx', [ '-DGLES_VERSION=2', ], [ 'egl_without_glx.c' ], has_gles2, ], 57 | ] 58 | 59 | if build_glx 60 | egl_tests += [ 61 | [ 'egl_gl', [], [ 'egl_gl.c' ], true, ], 62 | ] 63 | endif 64 | 65 | foreach test: egl_tests 66 | test_name = test[0] 67 | test_source = test[2] 68 | test_args = test[1] 69 | test_run = test[3] 70 | 71 | if test_run 72 | test_bin = executable(test_name, test_source, 73 | c_args: test_cflags + test_args, 74 | include_directories: libepoxy_inc, 75 | dependencies: [ libepoxy_dep, x11_dep, egl_dep, dl_dep ], 76 | link_with: egl_common_lib, 77 | link_args: '-rdynamic') 78 | test(test_name, test_bin) 79 | endif 80 | endforeach 81 | endif 82 | 83 | if build_glx and build_x11_tests 84 | glx_common_sources = [ 'glx_common.h', 'glx_common.c', ] 85 | glx_common_lib = static_library('glx_common', 86 | sources: glx_common_sources, 87 | dependencies: libepoxy_dep, 88 | include_directories: libepoxy_inc, 89 | c_args: common_cflags, 90 | install: false) 91 | 92 | # glx_beginend links directly with the GL library, so we need to check it 93 | # separately 94 | test('glx_beginend', executable('glx_beginend', 'glx_beginend.c', 95 | c_args: test_cflags, 96 | include_directories: libepoxy_inc, 97 | dependencies: [ libepoxy_dep, x11_dep, gl_dep, dl_dep ], 98 | link_with: glx_common_lib)) 99 | 100 | glx_tests = [ 101 | [ 'glx_public_api', [ 'glx_public_api.c' ], [], [], true ], 102 | [ 'glx_public_api_core', [ 'glx_public_api_core.c' ], [], [], true ], 103 | [ 'glx_glxgetprocaddress_nocontext', [ 'glx_glxgetprocaddress_nocontext.c' ], [], [], true ], 104 | [ 'glx_has_extension_nocontext', [ 'glx_has_extension_nocontext.c' ], [], [], true ], 105 | [ 'glx_static', [ 'glx_static.c' ], [ '-DNEEDS_TO_BE_STATIC'], [ '-static' ], libtype == 'static' ], 106 | [ 'glx_shared_znow', [ 'glx_static.c', ], [], [ '-Wl,-z,now' ], has_znow ], 107 | [ 'glx_alias_prefer_same_name', [ 'glx_alias_prefer_same_name.c', 'dlwrap.c', 'dlwrap.h' ], [], [ '-rdynamic' ], has_dlvsym ], 108 | [ 'glx_gles2', [ 'glx_gles2.c', 'dlwrap.c', 'dlwrap.h' ], [], [ '-rdynamic' ], has_dlvsym ], 109 | ] 110 | 111 | foreach test: glx_tests 112 | test_name = test[0] 113 | test_source = test[1] 114 | test_c_args = test[2] 115 | test_link_args = test[3] 116 | test_run = test[4] 117 | 118 | if test_run 119 | test_bin = executable(test_name, test_source, 120 | c_args: test_cflags + test_c_args, 121 | include_directories: libepoxy_inc, 122 | dependencies: [ libepoxy_dep, x11_dep, dl_dep ], 123 | link_with: glx_common_lib, 124 | link_args: test_link_args) 125 | test(test_name, test_bin) 126 | endif 127 | endforeach 128 | endif 129 | 130 | # WGL 131 | if build_wgl 132 | wgl_common_sources = [ 'wgl_common.h', 'wgl_common.c', ] 133 | wgl_common_lib = static_library('wgl_common', 134 | sources: wgl_common_sources, 135 | dependencies: libepoxy_dep, 136 | include_directories: libepoxy_inc, 137 | c_args: common_cflags, 138 | install: false) 139 | 140 | wgl_tests = [ 141 | [ 'wgl_core_and_exts', [ 'wgl_core_and_exts.c' ], [], ], 142 | [ 'wgl_per_context_funcptrs', [ 'wgl_per_context_funcptrs.c' ], [], ], 143 | [ 'wgl_usefontbitmaps', [ 'wgl_usefontbitmaps.c'], [], ], 144 | [ 'wgl_usefontbitmaps_unicode', [ 'wgl_usefontbitmaps.c' ], [ '-DUNICODE' ], ], 145 | ] 146 | 147 | foreach test: wgl_tests 148 | test_name = test[0] 149 | test_source = test[1] 150 | test_c_args = test[2] 151 | 152 | test_bin = executable(test_name, test_source, 153 | c_args: test_cflags + test_c_args, 154 | include_directories: libepoxy_inc, 155 | dependencies: [ libepoxy_dep ], 156 | link_with: wgl_common_lib) 157 | 158 | test(test_name, test_bin) 159 | endforeach 160 | endif 161 | 162 | # Apple 163 | if host_machine.system().contains('darwin') 164 | opengl_dep = dependency('appleframeworks', modules: ['OpenGL', 'Carbon'], required: true) 165 | 166 | cgl_tests = [ 167 | [ 'cgl_core', [ 'cgl_core.c' ] ], 168 | [ 'cgl_epoxy_api', [ 'cgl_epoxy_api.c' ] ], 169 | ] 170 | 171 | foreach t: cgl_tests 172 | test_name = t[0] 173 | test_sources = t[1] 174 | 175 | test(test_name, 176 | executable( 177 | test_name, test_sources, 178 | c_args: test_cflags, 179 | include_directories: libepoxy_inc, 180 | dependencies: [ libepoxy_dep, opengl_dep ], 181 | ), 182 | ) 183 | endforeach 184 | endif 185 | -------------------------------------------------------------------------------- /test/miscdefines.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | #ifdef BUILD_EGL 27 | #include 28 | #endif 29 | 30 | #ifdef BUILD_GLX 31 | #include 32 | #endif 33 | 34 | #if GL_VERSION_3_2 != 1 35 | #error bad GL_VERSION_3_2 36 | #endif 37 | 38 | #if GL_ARB_ES2_compatibility != 1 39 | #error bad GL_ARB_ES2_compatibility 40 | #endif 41 | 42 | #ifndef GLAPI 43 | #error missing GLAPI 44 | #endif 45 | 46 | #ifndef GLAPIENTRY 47 | #error missing GLAPIENTRY 48 | #endif 49 | 50 | #ifndef GLAPIENTRYP 51 | #error missing GLAPIENTRYP 52 | #endif 53 | 54 | #ifndef APIENTRY 55 | #error missing APIENTRY 56 | #endif 57 | 58 | #ifndef APIENTRYP 59 | #error missing APIENTRYP 60 | #endif 61 | 62 | /* Do we want to export GL_GLEXT_VERSION? */ 63 | 64 | int main(int argc, char **argv) 65 | { 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /test/wgl_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include "wgl_common.h" 27 | 28 | static int (*test_callback)(HDC hdc); 29 | 30 | static void 31 | setup_pixel_format(HDC hdc) 32 | { 33 | PIXELFORMATDESCRIPTOR pfd = { 34 | sizeof(PIXELFORMATDESCRIPTOR), 35 | 1, 36 | PFD_SUPPORT_OPENGL | 37 | PFD_DRAW_TO_WINDOW | 38 | PFD_DOUBLEBUFFER, 39 | PFD_TYPE_RGBA, 40 | 32, 41 | 0, 0, 0, 0, 0, 0, 42 | 0, 43 | 0, 44 | 0, 45 | 0, 0, 0, 0, 46 | 16, 47 | 0, 48 | 0, 49 | PFD_MAIN_PLANE, 50 | 0, 51 | 0, 0, 0, 52 | }; 53 | int pixel_format; 54 | 55 | pixel_format = ChoosePixelFormat(hdc, &pfd); 56 | if (!pixel_format) { 57 | fputs("ChoosePixelFormat failed.\n", stderr); 58 | exit(1); 59 | } 60 | 61 | if (SetPixelFormat(hdc, pixel_format, &pfd) != TRUE) { 62 | fputs("SetPixelFormat() failed.\n", stderr); 63 | exit(1); 64 | } 65 | } 66 | 67 | static LRESULT CALLBACK 68 | window_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) 69 | { 70 | HDC hdc = GetDC(hwnd); 71 | int ret; 72 | 73 | switch (message) { 74 | case WM_CREATE: 75 | setup_pixel_format(hdc); 76 | ret = test_callback(hdc); 77 | ReleaseDC(hwnd, hdc); 78 | exit(ret); 79 | return 0; 80 | default: 81 | return DefWindowProc(hwnd, message, wparam, lparam); 82 | } 83 | } 84 | 85 | void 86 | make_window_and_test(int (*callback)(HDC hdc)) 87 | { 88 | const char *class_name = "epoxy"; 89 | const char *window_name = "epoxy"; 90 | int width = 150; 91 | int height = 150; 92 | HWND hwnd; 93 | HINSTANCE hcurrentinst = NULL; 94 | WNDCLASS window_class; 95 | MSG msg; 96 | 97 | test_callback = callback; 98 | 99 | memset(&window_class, 0, sizeof(window_class)); 100 | window_class.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 101 | window_class.lpfnWndProc = window_proc; 102 | window_class.cbClsExtra = 0; 103 | window_class.cbWndExtra = 0; 104 | window_class.hInstance = hcurrentinst; 105 | window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); 106 | window_class.hCursor = LoadCursor(NULL, IDC_ARROW); 107 | window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 108 | window_class.lpszMenuName = NULL; 109 | window_class.lpszClassName = class_name; 110 | if (!RegisterClass(&window_class)) { 111 | fputs("Failed to register window class\n", stderr); 112 | exit(1); 113 | } 114 | 115 | /* create window */ 116 | hwnd = CreateWindow(class_name, window_name, 117 | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 118 | 0, 0, width, height, 119 | NULL, NULL, hcurrentinst, NULL); 120 | 121 | ShowWindow(hwnd, SW_SHOWDEFAULT); 122 | UpdateWindow(hwnd); 123 | 124 | while (GetMessage(&msg, NULL, 0, 0)) { 125 | TranslateMessage(&msg); 126 | DispatchMessage(&msg); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /test/wgl_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | void 27 | make_window_and_test(int (*callback)(HDC hdc)); 28 | -------------------------------------------------------------------------------- /test/wgl_core_and_exts.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | #include "wgl_common.h" 27 | #include 28 | 29 | static int 30 | test_function(HDC hdc) 31 | { 32 | bool pass = true; 33 | int val; 34 | HGLRC ctx; 35 | 36 | ctx = wglCreateContext(hdc); 37 | if (!ctx) { 38 | fputs("Failed to create wgl context\n", stderr); 39 | return 1; 40 | } 41 | if (!wglMakeCurrent(hdc, ctx)) { 42 | fputs("Failed to make context current\n", stderr); 43 | return 1; 44 | } 45 | 46 | /* GL 1.0 APIs are available as symbols in opengl32.dll. */ 47 | glEnable(GL_LIGHTING); 48 | val = 0; 49 | glGetIntegerv(GL_LIGHTING, &val); 50 | if (!val) { 51 | fputs("Enabling GL_LIGHTING didn't stick.\n", stderr); 52 | pass = false; 53 | } 54 | 55 | if (epoxy_gl_version() >= 15 || 56 | epoxy_has_gl_extension("GL_ARB_vertex_buffer_object")) { 57 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 1234); 58 | 59 | val = 0; 60 | glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &val); 61 | if (val != 1234) { 62 | printf("GL_ELEMENT_ARRAY_BUFFER_BINDING didn't stick: %d\n", val); 63 | pass = false; 64 | } 65 | } 66 | 67 | wglMakeCurrent(NULL, NULL); 68 | wglDeleteContext(ctx); 69 | 70 | return !pass; 71 | } 72 | 73 | int 74 | main(int argc, char **argv) 75 | { 76 | make_window_and_test(test_function); 77 | 78 | /* UNREACHED */ 79 | return 1; 80 | } 81 | -------------------------------------------------------------------------------- /test/wgl_per_context_funcptrs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /** 25 | * @file wgl_per_context_funcptrs.c 26 | * 27 | * Tests that epoxy works correctly when wglGetProcAddress() returns 28 | * different function pointers for different contexts. 29 | * 30 | * wgl allows that to be the case when the device or pixel format are 31 | * different. We don't know if the underlying implementation actually 32 | * *will* return different function pointers, so force the issue by 33 | * overriding wglGetProcAddress() to return our function pointers with 34 | * magic behavior. This way we can test epoxy's implementation 35 | * regardless. 36 | */ 37 | 38 | #include 39 | #include 40 | 41 | #include "wgl_common.h" 42 | #include 43 | 44 | #define CREATESHADER_CTX1_VAL 1001 45 | #define CREATESHADER_CTX2_VAL 1002 46 | 47 | static HGLRC ctx1, ctx2, current_context; 48 | static bool pass = true; 49 | 50 | #define OVERRIDE_API(type) __declspec(dllexport) type __stdcall 51 | 52 | OVERRIDE_API (GLuint) override_glCreateShader_ctx1(GLenum target); 53 | OVERRIDE_API (GLuint) override_glCreateShader_ctx2(GLenum target); 54 | OVERRIDE_API (PROC) override_wglGetProcAddress(LPCSTR name); 55 | 56 | OVERRIDE_API (GLuint) 57 | override_glCreateShader_ctx1(GLenum target) 58 | { 59 | if (current_context != ctx1) { 60 | fputs("ctx1 called while other context current\n", stderr); 61 | pass = false; 62 | } 63 | return CREATESHADER_CTX1_VAL; 64 | } 65 | 66 | OVERRIDE_API (GLuint) 67 | override_glCreateShader_ctx2(GLenum target) 68 | { 69 | if (current_context != ctx2) { 70 | fputs("ctx2 called while other context current\n", stderr); 71 | pass = false; 72 | } 73 | return CREATESHADER_CTX2_VAL; 74 | } 75 | 76 | OVERRIDE_API (PROC) 77 | override_wglGetProcAddress(LPCSTR name) 78 | { 79 | assert(strcmp(name, "glCreateShader") == 0); 80 | 81 | if (current_context == ctx1) { 82 | return (PROC)override_glCreateShader_ctx1; 83 | } else { 84 | assert(current_context == ctx2); 85 | return (PROC)override_glCreateShader_ctx2; 86 | } 87 | } 88 | 89 | static void 90 | test_createshader(HDC hdc, HGLRC ctx) 91 | { 92 | GLuint shader, expected; 93 | int ctxnum; 94 | 95 | wglMakeCurrent(hdc, ctx); 96 | current_context = ctx; 97 | 98 | /* Install our GPA override so we can force per-context function 99 | * pointers. 100 | */ 101 | wglGetProcAddress = override_wglGetProcAddress; 102 | 103 | if (ctx == ctx1) { 104 | expected = CREATESHADER_CTX1_VAL; 105 | ctxnum = 1; 106 | } else { 107 | assert(ctx == ctx2); 108 | expected = CREATESHADER_CTX2_VAL; 109 | ctxnum = 2; 110 | } 111 | 112 | shader = glCreateShader(GL_FRAGMENT_SHADER); 113 | printf("ctx%d: Returned %d\n", ctxnum, shader); 114 | if (shader != expected) { 115 | fprintf(stderr, " expected %d\n", expected); 116 | pass = false; 117 | } 118 | } 119 | 120 | static int 121 | test_function(HDC hdc) 122 | { 123 | ctx1 = wglCreateContext(hdc); 124 | ctx2 = wglCreateContext(hdc); 125 | if (!ctx1 || !ctx2) { 126 | fputs("Failed to create wgl contexts\n", stderr); 127 | return 1; 128 | } 129 | 130 | if (!wglMakeCurrent(hdc, ctx1)) { 131 | fputs("Failed to make context current\n", stderr); 132 | return 1; 133 | } 134 | 135 | if (epoxy_gl_version() < 20) { 136 | /* We could possibly do a 1.3 entrypoint or something instead. */ 137 | fputs("Test relies on overriding a GL 2.0 entrypoint\n", stderr); 138 | return 77; 139 | } 140 | 141 | /* Force resolving epoxy_wglGetProcAddress. */ 142 | wglGetProcAddress("glCreateShader"); 143 | 144 | test_createshader(hdc, ctx1); 145 | test_createshader(hdc, ctx1); 146 | test_createshader(hdc, ctx2); 147 | test_createshader(hdc, ctx2); 148 | test_createshader(hdc, ctx1); 149 | test_createshader(hdc, ctx2); 150 | 151 | wglMakeCurrent(NULL, NULL); 152 | wglDeleteContext(ctx1); 153 | wglDeleteContext(ctx2); 154 | 155 | return !pass; 156 | } 157 | 158 | int 159 | main(int argc, char **argv) 160 | { 161 | make_window_and_test(test_function); 162 | 163 | /* UNREACHED */ 164 | return 1; 165 | } 166 | -------------------------------------------------------------------------------- /test/wgl_usefontbitmaps.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * 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 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | #include "wgl_common.h" 27 | #include 28 | 29 | static int 30 | test_function(HDC hdc) 31 | { 32 | bool pass = true; 33 | HGLRC ctx; 34 | GLuint dlist[2] = {100, 101}; 35 | const char *string = "some string"; 36 | 37 | ctx = wglCreateContext(hdc); 38 | if (!ctx) { 39 | fputs("Failed to create wgl context\n", stderr); 40 | return 1; 41 | } 42 | if (!wglMakeCurrent(hdc, ctx)) { 43 | fputs("Failed to make context current\n", stderr); 44 | return 1; 45 | } 46 | 47 | /* First, use the #ifdeffed variant of the function */ 48 | wglUseFontBitmaps(hdc, 0, 255, dlist[0]); 49 | glListBase(dlist[1]); 50 | glCallLists(strlen(string), GL_UNSIGNED_BYTE, string); 51 | 52 | /* Now, use the specific version, manually. */ 53 | #ifdef UNICODE 54 | wglUseFontBitmapsW(hdc, 0, 255, dlist[0]); 55 | #else 56 | wglUseFontBitmapsA(hdc, 0, 255, dlist[0]); 57 | #endif 58 | glListBase(dlist[1]); 59 | glCallLists(strlen(string), GL_UNSIGNED_BYTE, string); 60 | 61 | wglMakeCurrent(NULL, NULL); 62 | wglDeleteContext(ctx); 63 | 64 | return !pass; 65 | } 66 | 67 | int 68 | main(int argc, char **argv) 69 | { 70 | make_window_and_test(test_function); 71 | 72 | /* UNREACHED */ 73 | return 1; 74 | } 75 | --------------------------------------------------------------------------------