├── .github
└── workflows
│ └── build.yml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── inc
├── client
│ ├── glimpl.h
│ ├── memory.h
│ ├── pb.h
│ ├── platform
│ │ ├── egl.h
│ │ ├── gldrv.h
│ │ ├── glx.h
│ │ ├── icd.h
│ │ ├── wgl.h
│ │ └── windrv.h
│ ├── scratch.h
│ └── spinlock.h
├── commongl.h
├── lzav.h
├── network
│ ├── LICENSE
│ ├── enet.h
│ └── packet.h
├── server
│ ├── context.h
│ ├── dynarr.h
│ ├── overlay.h
│ ├── overlay_font.h
│ └── processor.h
├── sgldebug.h
└── sharedgl.h
├── kernel
├── linux
│ ├── Makefile
│ ├── install.sh
│ ├── sharedgl.c
│ └── uninstall.sh
└── windows
│ ├── Device.c
│ ├── Device.h
│ ├── Driver.c
│ ├── Driver.h
│ ├── LICENSE
│ ├── Public.h
│ ├── Queue.c
│ ├── Queue.h
│ └── findwdk
│ ├── FindWdk.cmake
│ └── LICENSE
├── scripts
├── kcertify.bat
├── ksgldrv.inf
├── wininstall.bat
└── winuninstall.bat
└── src
├── client
├── glimpl.c
├── main.c
├── memory.c
├── pb.c
├── platform
│ ├── egl.c
│ ├── glx.c
│ ├── wgl.c
│ └── windrv.c
├── scratch.c
├── spinlock.c
└── winmain.c
└── server
├── context.c
├── dynarr.c
├── main.c
├── overlay.c
├── processor.c
└── sgldebug.c
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build SharedGL for Linux and Windows
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ${{ matrix.os }}
12 |
13 | strategy:
14 | fail-fast: false
15 |
16 | matrix:
17 | os: [ubuntu-latest, windows-latest]
18 | build_type: [Release, RelWithDebInfo]
19 | c_compiler: [clang, cl]
20 | arch: [x64, Win32]
21 | include:
22 | - os: windows-latest
23 | c_compiler: cl
24 | cpp_compiler: cl
25 | arch: x64
26 | - os: windows-latest
27 | c_compiler: cl
28 | cpp_compiler: cl
29 | arch: Win32
30 | - os: ubuntu-latest
31 | c_compiler: clang
32 | cpp_compiler: clang++
33 | exclude:
34 | - os: windows-latest
35 | c_compiler: clang
36 | - os: ubuntu-latest
37 | c_compiler: cl
38 |
39 | steps:
40 | - uses: actions/checkout@v3
41 |
42 | - name: Set reusable strings
43 | id: strings
44 | shell: bash
45 | run: |
46 | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
47 |
48 | - name: Install dependenices
49 | if: matrix.os == 'ubuntu-latest'
50 | run: |
51 | sudo apt-get update && sudo apt-get install -y libepoxy-dev libsdl2-dev libx11-dev
52 |
53 | - name: Configure CMake for Linux
54 | if: matrix.os == 'ubuntu-latest'
55 | run: >
56 | cmake -B ${{ steps.strings.outputs.build-output-dir }}
57 | -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
58 | -DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
59 | -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
60 | -S ${{ github.workspace }}
61 |
62 | - name: Configure CMake for Windows
63 | if: matrix.os == 'windows-latest'
64 | run: >
65 | cmake -B ${{ steps.strings.outputs.build-output-dir }}
66 | -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
67 | -DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
68 | -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
69 | -DCMAKE_GENERATOR_PLATFORM=${{ matrix.arch }}
70 | -S ${{ github.workspace }}
71 |
72 | - name: Build
73 | run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.15)
2 | project(sharedgl VERSION 0.9.0 LANGUAGES C)
3 |
4 | include_directories(${CMAKE_SOURCE_DIR}/inc)
5 |
6 | # set(CMAKE_C_COMPILER "clang")
7 |
8 | option(LINUX_LIB32 "Compile 32-bit libGL. Does not affect server." OFF)
9 |
10 | IF(WIN32)
11 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
12 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gz")
13 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded" CACHE STRING "Select MSVC runtime library.")
14 | set_property(GLOBAL PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
15 | ELSE()
16 | # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
17 | ENDIF(WIN32)
18 |
19 | file(GLOB GLOBBED_SERVER_SOURCES CONFIGURE_DEPENDS "src/server/*.c" "src/network/*.c" "src/client/scratch.c")
20 |
21 | # client stuff
22 | IF(UNIX)
23 | file(GLOB GLOBBED_CLIENT_SOURCES CONFIGURE_DEPENDS "src/client/*.c" "src/network/*.c")
24 | file(GLOB GLOBBED_CLIENT_P_SOURCES CONFIGURE_DEPENDS "src/client/platform/*.c")
25 | ELSEIF(WIN32)
26 | file(GLOB GLOBBED_CLIENT_SOURCES CONFIGURE_DEPENDS "src/client/winmain.c" "src/client/pb.c" "src/client/spinlock.c" "src/client/glimpl.c" "src/client/scratch.c" "src/network/*.c")
27 | file(GLOB GLOBBED_CLIENT_P_SOURCES CONFIGURE_DEPENDS "src/client/platform/windrv.c")
28 | ENDIF(UNIX)
29 |
30 | # server
31 | IF(UNIX)
32 | add_executable(sglrenderer ${GLOBBED_SERVER_SOURCES})
33 | target_link_libraries(sglrenderer SDL2 epoxy)
34 | ENDIF(UNIX)
35 |
36 | # client
37 | IF(UNIX)
38 | add_library(sharedgl-core SHARED ${GLOBBED_CLIENT_SOURCES} ${GLOBBED_CLIENT_P_SOURCES})
39 | target_link_libraries(sharedgl-core X11)
40 | set_target_properties(sharedgl-core PROPERTIES OUTPUT_NAME "GL")
41 | set_target_properties(sharedgl-core PROPERTIES VERSION 1)
42 | IF(LINUX_LIB32)
43 | target_compile_options(sharedgl-core PRIVATE "-m32")
44 | target_link_options(sharedgl-core PRIVATE "-m32")
45 | ENDIF(LINUX_LIB32)
46 | ELSEIF(WIN32)
47 | add_library(sharedgl-core SHARED ${GLOBBED_CLIENT_SOURCES} ${GLOBBED_CLIENT_P_SOURCES})
48 | IF(CMAKE_GENERATOR_PLATFORM MATCHES "Win32")
49 | set_target_properties(sharedgl-core PROPERTIES OUTPUT_NAME "sharedgl32")
50 | target_link_options(sharedgl-core PRIVATE /machine:x86)
51 | ELSE()
52 | set_target_properties(sharedgl-core PROPERTIES OUTPUT_NAME "sharedgl64")
53 | target_link_options(sharedgl-core PRIVATE /machine:x64)
54 | ENDIF()
55 | ENDIF(UNIX)
56 |
57 | # windows driver
58 | IF(WIN32 AND WINKERNEL)
59 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/kernel/windows/findwdk/")
60 | find_package(WDK REQUIRED)
61 |
62 | file(GLOB GLOBBED_KERNEL_SOURCES CONFIGURE_DEPENDS "kernel/windows/*.c")
63 | wdk_add_driver(ksgldrv KMDF 1.15 ${GLOBBED_KERNEL_SOURCES})
64 | ENDIF(WIN32 AND WINKERNEL)
65 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023-2024 dmaivel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # SharedGL 
4 |
5 | SharedGL is an OpenGL 4.6 implementation that enables 3D acceleration for Windows and Linux guests within QEMU/KVM by streaming OpenGL commands over shared memory or sockets.
6 |
7 |
8 | Click to hide: Preview
9 |
10 | 
11 |
12 |
13 |
14 |
15 | Click to reveal: Table of contents
16 |
17 | 1. [Getting started](#getting-started)
18 | 2. [Usage](#usage)
19 | - [Environment variables](#environment-variables)
20 | - [Windows in a VM](#windows-in-a-vm)
21 | - [Linux (client debugging)](#linux)
22 | - [Linux in a VM](#linux-in-a-vm)
23 | 3. [Networking](#networking)
24 | 4. [Known issues](#known-issues)
25 | 5. [Troubleshooting](#troubleshooting)
26 | 6. [Showcase](#showcase)
27 |
28 |
29 |
30 | # Getting started
31 |
32 | ## Dependencies
33 |
34 | | Name | Version |
35 | | ---- | ------- |
36 | | [CMake](https://cmake.org/) | 3.15+ |
37 | | [libepoxy](https://github.com/anholt/libepoxy) | Latest |
38 | | [SDL2](https://www.libsdl.org/) | 2.24.0+ |
39 |
40 | ## Building
41 |
42 | ```bash
43 | git clone https://github.com/dmaivel/sharedgl.git
44 | cd sharedgl
45 | mkdir build
46 | cd build
47 | cmake ..
48 | cmake --build . --target sglrenderer --config Release
49 | ```
50 |
51 | If you also wish to build the client library `libGL` for Linux, `libx11` is required. Build with `--target sharedgl-core`.
52 |
53 | For detailed build instructions for Windows, visit the [Windows section](#windows-in-a-vm). The renderer/server is only supported on Linux hosts.
54 |
55 | ### Build options
56 |
57 | These CMake options are accessible by either:
58 | 1. Using `ccmake` on `build` folder
59 | 2. Configuring with `-D...`
60 |
61 | | **Option** | **Legal values** | **Default** | **Description** |
62 | |-|-|-|-|
63 | | LINUX_LIB32 | ON/OFF | OFF | Enable if you wish to build the Linux client library (libGL) as 32-bit. This does not affect the server. |
64 |
65 | # Usage
66 | The server must be started on the host before running any clients. Note that the server can only be ran on Linux.
67 |
68 | ```bash
69 | usage: sglrenderer [-h] [-v] [-o] [-n] [-x] [-g MAJOR.MINOR] [-r WIDTHxHEIGHT] [-m SIZE] [-p PORT]
70 |
71 | options:
72 | -h display help information
73 | -v display virtual machine arguments
74 | -o enables fps overlay on clients
75 | -n enable networking instead of shared memory
76 | -x remove shared memory file
77 | -g [MAJOR.MINOR] report specific opengl version (default: 4.6)
78 | -r [WIDTHxHEIGHT] set max resolution (default: 1920x1080)
79 | -m [SIZE] max amount of megabytes program may allocate (default: 32mib)
80 | -p [PORT] if networking is enabled, specify which port to use (default: 3000)
81 | ```
82 |
83 | Your virtual machine must also be configured with a shared memory device *(unless you are using the sockets version, in which case see [networking](#networking))*. You can get the configurations from `sglrenderer` if you run it with `-v`. Sample configurations are provided below:
84 |
85 | **libvirt:**
86 | ```xml
87 | THIS IS A SAMPLE; ONLY USE THIS AS A GUIDE ON WHERE TO PLACE THE OUTPUT <-->
88 | ...
89 |
90 | ...
91 |
92 |
93 | ??
94 |
95 |
96 | ```
97 |
98 | **qemu:**
99 | ```bash
100 | # THIS IS A SAMPLE; ONLY USE THIS AS A GUIDE ON WHERE TO PLACE THE OUTPUT
101 | qemu-system-x86_64 -object memory-backend-file,size=??M,share,mem-path=/dev/shm/sharedgl_shared_memory,id=sharedgl_shared_memory
102 | ```
103 |
104 | For installation of the client driver inside the virtual machine, refer to one of these:
105 | - [Windows as the guest](#windows-in-a-vm)
106 | - [Linux as the guest](#linux-in-a-vm)
107 |
108 | ### Environment variables
109 |
110 | Variables labeled with `host` get their values from the host/server when their override isn't set.
111 |
112 | | **Option** | **Legal values** | **Default** | **Description** |
113 | |-|-|-|-|
114 | | SGL_WINED3D_DONT_VFLIP | Boolean | false | If running a DirectX application via WineD3D, ensure this variable is set to `true` in order for the application to render the framebuffer in the proper orientation. Only available for Windows clients. |
115 | | SGL_NETWORK_ENDPOINT | Ip:Port | | If networking is enabled, this environment variable must exist on the guest. Available for both Windows and Linux clients. |
116 | | SGL_RUN_WITH_LOW_PRIORITY | Boolean | false | Potentially improve performance by setting the process priority to low / `IDLE_PRIORITY_CLASS`; applications will run smoother as the kernel is given more CPU time. This benefits those with a VCPU count lower than the hosts or if using the network feature. Only available for Windows clients. |
117 | | GL_VERSION_OVERRIDE | Digit.Digit | `host` | Override the OpenGL version on the client side. Available for both Windows and Linux clients. |
118 | | GLX_VERSION_OVERRIDE | Digit.Digit | 1.4 | Override the GLX version on the client side. Only available for Linux clients. |
119 | | GLSL_VERSION_OVERRIDE | Digit.Digit | | Override the GLSL version on the client side. Available for both Windows and Linux clients. |
120 |
121 | ## Windows (in a VM)
122 |
123 | Two things must be done for the windows installation:
124 | 1. Install a compatible driver
125 | 2. Install the clients
126 |
127 | ### Kernel driver
128 |
129 | There are two possible drivers one may use:
130 | 1. VirtIO's IVSHMEM driver (no multiclient support)
131 | 1. Download and extract the upstream virtio win drivers, found [here](https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/upstream-virtio/).
132 | 2. Navigate into `...\virtio-win-upstream\Win10\amd64\`.
133 | 3. Right click on `ivshmem.inf` and press `Install`.
134 |
135 | > [!WARNING]\
136 | > If you use the included driver, test signing must be on. Enable it by running the following command in an elevated command prompt: `bcdedit.exe -set testsigning on` and restart.
137 |
138 | > [!NOTE]\
139 | > If you are looking for multiclient support but do not wish to install the patched driver, take a look into the networking feature which requires no drivers.
140 |
141 | 2. Included driver (multiclient support)
142 | 1. Use the release (>= `0.4.0`) **(Windows 10 only)**
143 | 1. Download the latest release for windows and extract the zip file.
144 | 2. Navigate into the extracted folder.
145 | 3. Right click on `ksgldrv.inf` and press `Install`.
146 | 2. Compile from source (use Visual Studio Developer Command Prompt)
147 | 1. Ensure you have installed the `WDK`, which can be found [here](https://learn.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads).
148 | 2. ```bat
149 | :: git clone https://github.com/dmaivel/sharedgl.git
150 | :: cd sharedgl
151 | mkdir build
152 | cd build
153 | cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DWINKERNEL=ON ..
154 | cmake --build . --target ksgldrv --config Release
155 | cd ..
156 | xcopy .\scripts\kcertify.bat .\build\Release\kcertify.bat
157 | xcopy .\scripts\ksgldrv.inf .\build\Release\ksgldrv.inf
158 | cd build\Release
159 | call kcertify.bat 10_X64
160 |
161 | :: requires admin privs, you may right click on the file and press install instead
162 | pnputil -i -a ksgldrv.inf
163 | ```
164 | 3. By default, this builds for Windows 10 x64 (`10_X64`). If you wish to compile for a different version or multiple versions, you must provide it through the command line like so: `kcertify.bat 10_X64,10_NI_X64`. A list of OS versions is provided on MSDN [here](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/inf2cat).
165 |
166 | ### Library / ICD
167 |
168 | There are two ways to install the library on windows:
169 | 1. Use a release (>= `0.3.1`)
170 | 1. Download the latest release for windows and extract the zip file.
171 | 2. Navigate into the extracted folder and run `wininstall.bat` and allow admin privledges.
172 | 3. The libraries should now be installed, meaning any application that uses OpenGL (32-bit and 64-bit) will use SharedGL.
173 | 2. Compile from source (use Visual Studio Developer Command Prompt)
174 | 1. ```bat
175 | :: git clone https://github.com/dmaivel/sharedgl.git
176 | :: cd sharedgl
177 | mkdir build
178 | cd build
179 | :: if you get errors regarding wdk, also use -DWINKERNEL=OFF
180 | cmake -DCMAKE_GENERATOR_PLATFORM=x64 ..
181 | cmake --build . --target sharedgl-core --config Release
182 | cmake -DCMAKE_GENERATOR_PLATFORM=Win32 ..
183 | cmake --build . --target sharedgl-core --config Release
184 | cd ..
185 | xcopy .\scripts\wininstall.bat .\build\Release\wininstall.bat
186 | cd build\Release
187 | call wininstall.bat
188 | ```
189 |
190 | ## Linux
191 |
192 | > [!CAUTION]
193 | > The following sections discuss using the *client library*, not the *renderer/server*. If your intention is to only accelerate Windows guests, you may disregard this section as all you need to do is run the renderer, no additional libraries required (other than the dependencies).
194 |
195 | For your OpenGL application to communicate with the server, the client library must be specified in your library path. Upon exporting, any program you run in the terminal where you inputted this command will run with the SGL binary.
196 |
197 | ```bash
198 | $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/sharedgl/build
199 | $ glxgears
200 | $ ...
201 | ```
202 |
203 | Some applications may require adding the library to the `LD_PRELOAD` environment variable aswell, which is done the same way as shown above.
204 |
205 | Note that the Linux library does not need to be used in a virtual machine, allowing users to debug the library entirely on the host.
206 |
207 | Some applications may require an explicit `libGLX`, so run `ln -s libGL.so.1 libGLX.so.0` in `build` to make a symlink.
208 |
209 | ## Linux in a VM
210 |
211 | For virtual Linux clients, an additional kernel module needs to be compiled in the virtual machine, resulting in a binary `sharedgl.ko` which needs to be loaded. Loading/installing can be done by running the provided script (`./kernel/linux/install.sh`), following compilation. If the module doesn't load on boot, it is recommended that you add `sharedgl` to your modprobe config.
212 |
213 | ```bash
214 | # within 'sharedgl' directory
215 | cd kernel/linux
216 | make
217 | ```
218 |
219 | > [!WARNING]\
220 | > If you move the client library to the guest from the host instead of compiling it in the guest, you may encounter the `SIGILL` exception in the virtual machine as the build compiles with the native (host) architecture. To fix, either change your cpu model to `host-model`/`host-passthrough` or comment out the `-march=native` line in the cmake script (will most likely reduce performance).
221 |
222 | # Networking
223 |
224 | No drivers are required for the network feature, meaning if you wish to have a driverless experience in your virtual machine, networking is the given alternative. If the networking feature is used exclusively, the kernel drivers do not need be compiled or installed. However, installation of the ICD for either Linux or Windows is still required.
225 | - Start the server using `-n` (and provide a port if the default is not available through `-p PORT`)
226 | - Ensure the ICD is installed
227 | - Ensure that the environment variable `SGL_NETWORK_ENDPOINT=ADDRESS:PORT` exists in the guest (`ADDRESS` being the host's IP address)
228 |
229 | The networking feature is not restricted to only virtual machines.
230 |
231 | # Known issues
232 | - **Linux clients:** New GLX FB configs may cause applications using `freeglut` or `glad` to no longer run (only tested on Linux clients).
233 |
234 | # Troubleshooting
235 |
236 | 1. If you encounter "Entry point retrieval is broken" on applications that use GLFW, use `LD_PRELOAD`.
237 | 2. If you encounter weird crashes/faults/errors such as `IOT instruction` or `No provider of glXXX found.`:
238 | - Try changing the GL version (i.e `-g 2.0`)
239 | - Allocate more memory (i.e `-m 256`)
240 | 3. Application shows a blank window in the virtual machine?
241 | - Make sure the shared memory device passes through all the memory (check the size)
242 | 4. Application doesn't run in the virtual machine? (Process exists but stalls)
243 | - Make sure the server is running
244 | - If you start the server and it still won't run, shut down the VM, run `sudo ./sglrenderer -x`, start the server, start the VM
245 | - Make sure the drivers are installed (VirtIO IVSHMEM for Windows, custom kernel must be compiled for Linux)
246 | 5. Server reports, `err: failed to open shared memory 'sharedgl_shared_memory'`
247 | - This (usually) happens when the shared memory file is created before the server runs, meaning the file was created with different privileges. You may either:
248 | - Run the server as `sudo`
249 | - Shutdown the VM, run `sudo ./sglrenderer -x`, start the server, then start the VM
250 | 6. Client outputs, `glimpl_init: failed to find memory` to the terminal
251 | - This occurs in VMs when you do not pass a shared memory device, which is required for the clients to see the shared memory
252 |
253 | # Showcase
254 |
255 |
256 | Click to reveal: Running SuperTuxKart in a Windows virtual machine
257 |
258 | https://github.com/dmaivel/sharedgl/assets/38770072/c302f546-2c05-4cb7-b415-8f01ad1dce7a
259 |
260 |
261 |
262 |
263 | Click to reveal: Running DirectX sample using WineD3D in a Windows virtual machine
264 |
265 | https://github.com/dmaivel/sharedgl/assets/38770072/f2ae2825-79d6-4c1b-813f-c826586642e2
266 |
267 |
268 |
269 |
270 | Click to reveal: Running minetest in a Windows virtual machine (old)
271 |
272 | https://github.com/dmaivel/sharedgl/assets/38770072/26c6216d-72f7-45b4-9c4f-1734de0d1c6d
273 |
274 |
275 |
276 |
277 | Click to reveal: Running glxgears in a Windows virtual machine (old)
278 |
279 | https://github.com/dmaivel/sharedgl/assets/38770072/a774db97-807e-46b9-a453-fa2ee3f4ea84
280 |
281 |
282 |
283 |
284 | Click to reveal: Running glxgears in a Linux virtual machine (old)
285 |
286 | https://github.com/dmaivel/sharedgl/assets/38770072/0d46bf46-5693-4842-a81f-2f186c396e26
287 |
288 |
289 |
290 |
291 | Click to reveal: Running a compute shader in a Linux virtual machine (old)
292 |
293 | https://github.com/dmaivel/sharedgl/assets/38770072/ded179b8-23dc-491d-ba34-4108e014f296
294 |
295 |
296 |
--------------------------------------------------------------------------------
/inc/client/glimpl.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_GLIMPL_H_
2 | #define _SGL_GLIMPL_H_
3 |
4 | #include
5 |
6 | void glimpl_init();
7 | void glimpl_submit();
8 | void glimpl_goodbye();
9 | void glimpl_report(int width, int height);
10 | void glimpl_swap_buffers(int width, int height, int vflip, int format);
11 | void *glimpl_fb_address();
12 |
13 | /*
14 | * gl... functions don't need to be public, however
15 | * for windows icd we seemingly need to get a proc
16 | * table for 1.1
17 | */
18 | #ifdef _WIN32
19 | #include
20 | PGLCLTPROCTABLE glimpl_GetProcTable();
21 | #endif
22 |
23 | #endif
--------------------------------------------------------------------------------
/inc/client/memory.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_MEMORY_H_
2 | #define _SGL_MEMORY_H_
3 |
4 | int sgl_detect_device_memory(const char *path);
5 |
6 | #endif
--------------------------------------------------------------------------------
/inc/client/pb.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_PB_H_
2 | #define _SGL_PB_H_
3 |
4 | #ifndef _WIN32
5 | #include
6 | #include
7 | #include
8 | #endif
9 |
10 | #include
11 | #include
12 |
13 | struct pb_net_hooks {
14 | int(*_pb_read)(int s);
15 | int64_t(*_pb_read64)(int s);
16 | void(*_pb_write)(int s, int c);
17 | void(*_pb_copy)(void *data, int s, size_t length);
18 | void(*_pb_memcpy)(void *src, size_t length);
19 | void*(*_pb_ptr)(size_t offs);
20 | void(*_pb_copy_to_shared)();
21 | };
22 |
23 | void pb_set_net(struct pb_net_hooks hooks, size_t internal_alloc_size);
24 |
25 | #ifndef _WIN32
26 | /*
27 | * to-do: determine if direct_access is really unneeded
28 | */
29 | void pb_set(int pb, bool direct_access);
30 | #else
31 | void pb_set(bool direct_access);
32 | void pb_unset(void);
33 | #endif
34 |
35 | void pb_reset();
36 | void pb_push(int c);
37 | void pb_pushf(float c);
38 |
39 | int pb_read(int s);
40 | int64_t pb_read64(int s);
41 | void pb_write(int s, int c);
42 |
43 | void pb_memcpy(const void *src, size_t length);
44 | void pb_memcpy_unaligned(const void *src, size_t length);
45 | void pb_realign();
46 |
47 | void *pb_ptr(size_t offs);
48 |
49 | /*
50 | * special case: return pointer within internal space
51 | * only used for networking junk
52 | * basically, todo: organize everything !!
53 | */
54 | void *pb_iptr(size_t offs);
55 |
56 | size_t pb_size();
57 |
58 | void pb_copy_to_shared();
59 |
60 | #endif
--------------------------------------------------------------------------------
/inc/client/platform/egl.h:
--------------------------------------------------------------------------------
1 | // stub
--------------------------------------------------------------------------------
/inc/client/platform/gldrv.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © Microsoft 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 | #ifdef _WIN32
24 |
25 | #ifndef _GLDRV_
26 | #define _GLDRV_
27 |
28 | #include
29 | #include
30 | #include
31 |
32 | // Number of entries expected for various versions of OpenGL
33 | #define OPENGL_VERSION_100_ENTRIES 306
34 | #define OPENGL_VERSION_110_ENTRIES 336
35 |
36 | typedef struct _GLDISPATCHTABLE {
37 | void (APIENTRY *glNewList )( GLuint list, GLenum mode );
38 | void (APIENTRY *glEndList )( void );
39 | void (APIENTRY *glCallList )( GLuint list );
40 | void (APIENTRY *glCallLists )( GLsizei n, GLenum type, const GLvoid *lists );
41 | void (APIENTRY *glDeleteLists )( GLuint list, GLsizei range );
42 | GLuint (APIENTRY *glGenLists )( GLsizei range );
43 | void (APIENTRY *glListBase )( GLuint base );
44 | void (APIENTRY *glBegin )( GLenum mode );
45 | void (APIENTRY *glBitmap )( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap );
46 | void (APIENTRY *glColor3b )( GLbyte red, GLbyte green, GLbyte blue );
47 | void (APIENTRY *glColor3bv )( const GLbyte *v );
48 | void (APIENTRY *glColor3d )( GLdouble red, GLdouble green, GLdouble blue );
49 | void (APIENTRY *glColor3dv )( const GLdouble *v );
50 | void (APIENTRY *glColor3f )( GLfloat red, GLfloat green, GLfloat blue );
51 | void (APIENTRY *glColor3fv )( const GLfloat *v );
52 | void (APIENTRY *glColor3i )( GLint red, GLint green, GLint blue );
53 | void (APIENTRY *glColor3iv )( const GLint *v );
54 | void (APIENTRY *glColor3s )( GLshort red, GLshort green, GLshort blue );
55 | void (APIENTRY *glColor3sv )( const GLshort *v );
56 | void (APIENTRY *glColor3ub )( GLubyte red, GLubyte green, GLubyte blue );
57 | void (APIENTRY *glColor3ubv )( const GLubyte *v );
58 | void (APIENTRY *glColor3ui )( GLuint red, GLuint green, GLuint blue );
59 | void (APIENTRY *glColor3uiv )( const GLuint *v );
60 | void (APIENTRY *glColor3us )( GLushort red, GLushort green, GLushort blue );
61 | void (APIENTRY *glColor3usv )( const GLushort *v );
62 | void (APIENTRY *glColor4b )( GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha );
63 | void (APIENTRY *glColor4bv )( const GLbyte *v );
64 | void (APIENTRY *glColor4d )( GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha );
65 | void (APIENTRY *glColor4dv )( const GLdouble *v );
66 | void (APIENTRY *glColor4f )( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha );
67 | void (APIENTRY *glColor4fv )( const GLfloat *v );
68 | void (APIENTRY *glColor4i )( GLint red, GLint green, GLint blue, GLint alpha );
69 | void (APIENTRY *glColor4iv )( const GLint *v );
70 | void (APIENTRY *glColor4s )( GLshort red, GLshort green, GLshort blue, GLshort alpha );
71 | void (APIENTRY *glColor4sv )( const GLshort *v );
72 | void (APIENTRY *glColor4ub )( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha );
73 | void (APIENTRY *glColor4ubv )( const GLubyte *v );
74 | void (APIENTRY *glColor4ui )( GLuint red, GLuint green, GLuint blue, GLuint alpha );
75 | void (APIENTRY *glColor4uiv )( const GLuint *v );
76 | void (APIENTRY *glColor4us )( GLushort red, GLushort green, GLushort blue, GLushort alpha );
77 | void (APIENTRY *glColor4usv )( const GLushort *v );
78 | void (APIENTRY *glEdgeFlag )( GLboolean flag );
79 | void (APIENTRY *glEdgeFlagv )( const GLboolean *flag );
80 | void (APIENTRY *glEnd )( void );
81 | void (APIENTRY *glIndexd )( GLdouble c );
82 | void (APIENTRY *glIndexdv )( const GLdouble *c );
83 | void (APIENTRY *glIndexf )( GLfloat c );
84 | void (APIENTRY *glIndexfv )( const GLfloat *c );
85 | void (APIENTRY *glIndexi )( GLint c );
86 | void (APIENTRY *glIndexiv )( const GLint *c );
87 | void (APIENTRY *glIndexs )( GLshort c );
88 | void (APIENTRY *glIndexsv )( const GLshort *c );
89 | void (APIENTRY *glNormal3b )( GLbyte nx, GLbyte ny, GLbyte nz );
90 | void (APIENTRY *glNormal3bv )( const GLbyte *v );
91 | void (APIENTRY *glNormal3d )( GLdouble nx, GLdouble ny, GLdouble nz );
92 | void (APIENTRY *glNormal3dv )( const GLdouble *v );
93 | void (APIENTRY *glNormal3f )( GLfloat nx, GLfloat ny, GLfloat nz );
94 | void (APIENTRY *glNormal3fv )( const GLfloat *v );
95 | void (APIENTRY *glNormal3i )( GLint nx, GLint ny, GLint nz );
96 | void (APIENTRY *glNormal3iv )( const GLint *v );
97 | void (APIENTRY *glNormal3s )( GLshort nx, GLshort ny, GLshort nz );
98 | void (APIENTRY *glNormal3sv )( const GLshort *v );
99 | void (APIENTRY *glRasterPos2d )( GLdouble x, GLdouble y );
100 | void (APIENTRY *glRasterPos2dv )( const GLdouble *v );
101 | void (APIENTRY *glRasterPos2f )( GLfloat x, GLfloat y );
102 | void (APIENTRY *glRasterPos2fv )( const GLfloat *v );
103 | void (APIENTRY *glRasterPos2i )( GLint x, GLint y );
104 | void (APIENTRY *glRasterPos2iv )( const GLint *v );
105 | void (APIENTRY *glRasterPos2s )( GLshort x, GLshort y );
106 | void (APIENTRY *glRasterPos2sv )( const GLshort *v );
107 | void (APIENTRY *glRasterPos3d )( GLdouble x, GLdouble y, GLdouble z );
108 | void (APIENTRY *glRasterPos3dv )( const GLdouble *v );
109 | void (APIENTRY *glRasterPos3f )( GLfloat x, GLfloat y, GLfloat z );
110 | void (APIENTRY *glRasterPos3fv )( const GLfloat *v );
111 | void (APIENTRY *glRasterPos3i )( GLint x, GLint y, GLint z );
112 | void (APIENTRY *glRasterPos3iv )( const GLint *v );
113 | void (APIENTRY *glRasterPos3s )( GLshort x, GLshort y, GLshort z );
114 | void (APIENTRY *glRasterPos3sv )( const GLshort *v );
115 | void (APIENTRY *glRasterPos4d )( GLdouble x, GLdouble y, GLdouble z, GLdouble w );
116 | void (APIENTRY *glRasterPos4dv )( const GLdouble *v );
117 | void (APIENTRY *glRasterPos4f )( GLfloat x, GLfloat y, GLfloat z, GLfloat w );
118 | void (APIENTRY *glRasterPos4fv )( const GLfloat *v );
119 | void (APIENTRY *glRasterPos4i )( GLint x, GLint y, GLint z, GLint w );
120 | void (APIENTRY *glRasterPos4iv )( const GLint *v );
121 | void (APIENTRY *glRasterPos4s )( GLshort x, GLshort y, GLshort z, GLshort w );
122 | void (APIENTRY *glRasterPos4sv )( const GLshort *v );
123 | void (APIENTRY *glRectd )( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 );
124 | void (APIENTRY *glRectdv )( const GLdouble *v1, const GLdouble *v2 );
125 | void (APIENTRY *glRectf )( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 );
126 | void (APIENTRY *glRectfv )( const GLfloat *v1, const GLfloat *v2 );
127 | void (APIENTRY *glRecti )( GLint x1, GLint y1, GLint x2, GLint y2 );
128 | void (APIENTRY *glRectiv )( const GLint *v1, const GLint *v2 );
129 | void (APIENTRY *glRects )( GLshort x1, GLshort y1, GLshort x2, GLshort y2 );
130 | void (APIENTRY *glRectsv )( const GLshort *v1, const GLshort *v2 );
131 | void (APIENTRY *glTexCoord1d )( GLdouble s );
132 | void (APIENTRY *glTexCoord1dv )( const GLdouble *v );
133 | void (APIENTRY *glTexCoord1f )( GLfloat s );
134 | void (APIENTRY *glTexCoord1fv )( const GLfloat *v );
135 | void (APIENTRY *glTexCoord1i )( GLint s );
136 | void (APIENTRY *glTexCoord1iv )( const GLint *v );
137 | void (APIENTRY *glTexCoord1s )( GLshort s );
138 | void (APIENTRY *glTexCoord1sv )( const GLshort *v );
139 | void (APIENTRY *glTexCoord2d )( GLdouble s, GLdouble t );
140 | void (APIENTRY *glTexCoord2dv )( const GLdouble *v );
141 | void (APIENTRY *glTexCoord2f )( GLfloat s, GLfloat t );
142 | void (APIENTRY *glTexCoord2fv )( const GLfloat *v );
143 | void (APIENTRY *glTexCoord2i )( GLint s, GLint t );
144 | void (APIENTRY *glTexCoord2iv )( const GLint *v );
145 | void (APIENTRY *glTexCoord2s )( GLshort s, GLshort t );
146 | void (APIENTRY *glTexCoord2sv )( const GLshort *v );
147 | void (APIENTRY *glTexCoord3d )( GLdouble s, GLdouble t, GLdouble r );
148 | void (APIENTRY *glTexCoord3dv )( const GLdouble *v );
149 | void (APIENTRY *glTexCoord3f )( GLfloat s, GLfloat t, GLfloat r );
150 | void (APIENTRY *glTexCoord3fv )( const GLfloat *v );
151 | void (APIENTRY *glTexCoord3i )( GLint s, GLint t, GLint r );
152 | void (APIENTRY *glTexCoord3iv )( const GLint *v );
153 | void (APIENTRY *glTexCoord3s )( GLshort s, GLshort t, GLshort r );
154 | void (APIENTRY *glTexCoord3sv )( const GLshort *v );
155 | void (APIENTRY *glTexCoord4d )( GLdouble s, GLdouble t, GLdouble r, GLdouble q );
156 | void (APIENTRY *glTexCoord4dv )( const GLdouble *v );
157 | void (APIENTRY *glTexCoord4f )( GLfloat s, GLfloat t, GLfloat r, GLfloat q );
158 | void (APIENTRY *glTexCoord4fv )( const GLfloat *v );
159 | void (APIENTRY *glTexCoord4i )( GLint s, GLint t, GLint r, GLint q );
160 | void (APIENTRY *glTexCoord4iv )( const GLint *v );
161 | void (APIENTRY *glTexCoord4s )( GLshort s, GLshort t, GLshort r, GLshort q );
162 | void (APIENTRY *glTexCoord4sv )( const GLshort *v );
163 | void (APIENTRY *glVertex2d )( GLdouble x, GLdouble y );
164 | void (APIENTRY *glVertex2dv )( const GLdouble *v );
165 | void (APIENTRY *glVertex2f )( GLfloat x, GLfloat y );
166 | void (APIENTRY *glVertex2fv )( const GLfloat *v );
167 | void (APIENTRY *glVertex2i )( GLint x, GLint y );
168 | void (APIENTRY *glVertex2iv )( const GLint *v );
169 | void (APIENTRY *glVertex2s )( GLshort x, GLshort y );
170 | void (APIENTRY *glVertex2sv )( const GLshort *v );
171 | void (APIENTRY *glVertex3d )( GLdouble x, GLdouble y, GLdouble z );
172 | void (APIENTRY *glVertex3dv )( const GLdouble *v );
173 | void (APIENTRY *glVertex3f )( GLfloat x, GLfloat y, GLfloat z );
174 | void (APIENTRY *glVertex3fv )( const GLfloat *v );
175 | void (APIENTRY *glVertex3i )( GLint x, GLint y, GLint z );
176 | void (APIENTRY *glVertex3iv )( const GLint *v );
177 | void (APIENTRY *glVertex3s )( GLshort x, GLshort y, GLshort z );
178 | void (APIENTRY *glVertex3sv )( const GLshort *v );
179 | void (APIENTRY *glVertex4d )( GLdouble x, GLdouble y, GLdouble z, GLdouble w );
180 | void (APIENTRY *glVertex4dv )( const GLdouble *v );
181 | void (APIENTRY *glVertex4f )( GLfloat x, GLfloat y, GLfloat z, GLfloat w );
182 | void (APIENTRY *glVertex4fv )( const GLfloat *v );
183 | void (APIENTRY *glVertex4i )( GLint x, GLint y, GLint z, GLint w );
184 | void (APIENTRY *glVertex4iv )( const GLint *v );
185 | void (APIENTRY *glVertex4s )( GLshort x, GLshort y, GLshort z, GLshort w );
186 | void (APIENTRY *glVertex4sv )( const GLshort *v );
187 | void (APIENTRY *glClipPlane )( GLenum plane, const GLdouble *equation );
188 | void (APIENTRY *glColorMaterial )( GLenum face, GLenum mode );
189 | void (APIENTRY *glCullFace )( GLenum mode );
190 | void (APIENTRY *glFogf )( GLenum pname, GLfloat param );
191 | void (APIENTRY *glFogfv )( GLenum pname, const GLfloat *params );
192 | void (APIENTRY *glFogi )( GLenum pname, GLint param );
193 | void (APIENTRY *glFogiv )( GLenum pname, const GLint *params );
194 | void (APIENTRY *glFrontFace )( GLenum mode );
195 | void (APIENTRY *glHint )( GLenum target, GLenum mode );
196 | void (APIENTRY *glLightf )( GLenum light, GLenum pname, GLfloat param );
197 | void (APIENTRY *glLightfv )( GLenum light, GLenum pname, const GLfloat *params );
198 | void (APIENTRY *glLighti )( GLenum light, GLenum pname, GLint param );
199 | void (APIENTRY *glLightiv )( GLenum light, GLenum pname, const GLint *params );
200 | void (APIENTRY *glLightModelf )( GLenum pname, GLfloat param );
201 | void (APIENTRY *glLightModelfv )( GLenum pname, const GLfloat *params );
202 | void (APIENTRY *glLightModeli )( GLenum pname, GLint param );
203 | void (APIENTRY *glLightModeliv )( GLenum pname, const GLint *params );
204 | void (APIENTRY *glLineStipple )( GLint factor, GLushort pattern );
205 | void (APIENTRY *glLineWidth )( GLfloat width );
206 | void (APIENTRY *glMaterialf )( GLenum face, GLenum pname, GLfloat param );
207 | void (APIENTRY *glMaterialfv )( GLenum face, GLenum pname, const GLfloat *params );
208 | void (APIENTRY *glMateriali )( GLenum face, GLenum pname, GLint param );
209 | void (APIENTRY *glMaterialiv )( GLenum face, GLenum pname, const GLint *params );
210 | void (APIENTRY *glPointSize )( GLfloat size );
211 | void (APIENTRY *glPolygonMode )( GLenum face, GLenum mode );
212 | void (APIENTRY *glPolygonStipple )( const GLubyte *mask );
213 | void (APIENTRY *glScissor )( GLint x, GLint y, GLsizei width, GLsizei height );
214 | void (APIENTRY *glShadeModel )( GLenum mode );
215 | void (APIENTRY *glTexParameterf )( GLenum target, GLenum pname, GLfloat param );
216 | void (APIENTRY *glTexParameterfv )( GLenum target, GLenum pname, const GLfloat *params );
217 | void (APIENTRY *glTexParameteri )( GLenum target, GLenum pname, GLint param );
218 | void (APIENTRY *glTexParameteriv )( GLenum target, GLenum pname, const GLint *params );
219 | void (APIENTRY *glTexImage1D )( GLenum target, GLint level, GLint components, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
220 | void (APIENTRY *glTexImage2D )( GLenum target, GLint level, GLint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
221 | void (APIENTRY *glTexEnvf )( GLenum target, GLenum pname, GLfloat param );
222 | void (APIENTRY *glTexEnvfv )( GLenum target, GLenum pname, const GLfloat *params );
223 | void (APIENTRY *glTexEnvi )( GLenum target, GLenum pname, GLint param );
224 | void (APIENTRY *glTexEnviv )( GLenum target, GLenum pname, const GLint *params );
225 | void (APIENTRY *glTexGend )( GLenum coord, GLenum pname, GLdouble param );
226 | void (APIENTRY *glTexGendv )( GLenum coord, GLenum pname, const GLdouble *params );
227 | void (APIENTRY *glTexGenf )( GLenum coord, GLenum pname, GLfloat param );
228 | void (APIENTRY *glTexGenfv )( GLenum coord, GLenum pname, const GLfloat *params );
229 | void (APIENTRY *glTexGeni )( GLenum coord, GLenum pname, GLint param );
230 | void (APIENTRY *glTexGeniv )( GLenum coord, GLenum pname, const GLint *params );
231 | void (APIENTRY *glFeedbackBuffer )( GLsizei size, GLenum type, GLfloat *buffer );
232 | void (APIENTRY *glSelectBuffer )( GLsizei size, GLuint *buffer );
233 | GLint (APIENTRY *glRenderMode )( GLenum mode );
234 | void (APIENTRY *glInitNames )( void );
235 | void (APIENTRY *glLoadName )( GLuint name );
236 | void (APIENTRY *glPassThrough )( GLfloat token );
237 | void (APIENTRY *glPopName )( void );
238 | void (APIENTRY *glPushName )( GLuint name );
239 | void (APIENTRY *glDrawBuffer )( GLenum mode );
240 | void (APIENTRY *glClear )( GLbitfield mask );
241 | void (APIENTRY *glClearAccum )( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha );
242 | void (APIENTRY *glClearIndex )( GLfloat c );
243 | void (APIENTRY *glClearColor )( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha );
244 | void (APIENTRY *glClearStencil )( GLint s );
245 | void (APIENTRY *glClearDepth )( GLclampd depth );
246 | void (APIENTRY *glStencilMask )( GLuint mask );
247 | void (APIENTRY *glColorMask )( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha );
248 | void (APIENTRY *glDepthMask )( GLboolean flag );
249 | void (APIENTRY *glIndexMask )( GLuint mask );
250 | void (APIENTRY *glAccum )( GLenum op, GLfloat value );
251 | void (APIENTRY *glDisable )( GLenum cap );
252 | void (APIENTRY *glEnable )( GLenum cap );
253 | void (APIENTRY *glFinish )( void );
254 | void (APIENTRY *glFlush )( void );
255 | void (APIENTRY *glPopAttrib )( void );
256 | void (APIENTRY *glPushAttrib )( GLbitfield mask );
257 | void (APIENTRY *glMap1d )( GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points );
258 | void (APIENTRY *glMap1f )( GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points );
259 | void (APIENTRY *glMap2d )( GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points );
260 | void (APIENTRY *glMap2f )( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points );
261 | void (APIENTRY *glMapGrid1d )( GLint un, GLdouble u1, GLdouble u2 );
262 | void (APIENTRY *glMapGrid1f )( GLint un, GLfloat u1, GLfloat u2 );
263 | void (APIENTRY *glMapGrid2d )( GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2 );
264 | void (APIENTRY *glMapGrid2f )( GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2 );
265 | void (APIENTRY *glEvalCoord1d )( GLdouble u );
266 | void (APIENTRY *glEvalCoord1dv )( const GLdouble *u );
267 | void (APIENTRY *glEvalCoord1f )( GLfloat u );
268 | void (APIENTRY *glEvalCoord1fv )( const GLfloat *u );
269 | void (APIENTRY *glEvalCoord2d )( GLdouble u, GLdouble v );
270 | void (APIENTRY *glEvalCoord2dv )( const GLdouble *u );
271 | void (APIENTRY *glEvalCoord2f )( GLfloat u, GLfloat v );
272 | void (APIENTRY *glEvalCoord2fv )( const GLfloat *u );
273 | void (APIENTRY *glEvalMesh1 )( GLenum mode, GLint i1, GLint i2 );
274 | void (APIENTRY *glEvalPoint1 )( GLint i );
275 | void (APIENTRY *glEvalMesh2 )( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 );
276 | void (APIENTRY *glEvalPoint2 )( GLint i, GLint j );
277 | void (APIENTRY *glAlphaFunc )( GLenum func, GLclampf ref );
278 | void (APIENTRY *glBlendFunc )( GLenum sfactor, GLenum dfactor );
279 | void (APIENTRY *glLogicOp )( GLenum opcode );
280 | void (APIENTRY *glStencilFunc )( GLenum func, GLint ref, GLuint mask );
281 | void (APIENTRY *glStencilOp )( GLenum fail, GLenum zfail, GLenum zpass );
282 | void (APIENTRY *glDepthFunc )( GLenum func );
283 | void (APIENTRY *glPixelZoom )( GLfloat xfactor, GLfloat yfactor );
284 | void (APIENTRY *glPixelTransferf )( GLenum pname, GLfloat param );
285 | void (APIENTRY *glPixelTransferi )( GLenum pname, GLint param );
286 | void (APIENTRY *glPixelStoref )( GLenum pname, GLfloat param );
287 | void (APIENTRY *glPixelStorei )( GLenum pname, GLint param );
288 | void (APIENTRY *glPixelMapfv )( GLenum map, GLint mapsize, const GLfloat *values );
289 | void (APIENTRY *glPixelMapuiv )( GLenum map, GLint mapsize, const GLuint *values );
290 | void (APIENTRY *glPixelMapusv )( GLenum map, GLint mapsize, const GLushort *values );
291 | void (APIENTRY *glReadBuffer )( GLenum mode );
292 | void (APIENTRY *glCopyPixels )( GLint x, GLint y, GLsizei width, GLsizei height, GLenum type );
293 | void (APIENTRY *glReadPixels )( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels );
294 | void (APIENTRY *glDrawPixels )( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels );
295 | void (APIENTRY *glGetBooleanv )( GLenum pname, GLboolean *params );
296 | void (APIENTRY *glGetClipPlane )( GLenum plane, GLdouble *equation );
297 | void (APIENTRY *glGetDoublev )( GLenum pname, GLdouble *params );
298 | GLenum (APIENTRY *glGetError )( void );
299 | void (APIENTRY *glGetFloatv )( GLenum pname, GLfloat *params );
300 | void (APIENTRY *glGetIntegerv )( GLenum pname, GLint *params );
301 | void (APIENTRY *glGetLightfv )( GLenum light, GLenum pname, GLfloat *params );
302 | void (APIENTRY *glGetLightiv )( GLenum light, GLenum pname, GLint *params );
303 | void (APIENTRY *glGetMapdv )( GLenum target, GLenum query, GLdouble *v );
304 | void (APIENTRY *glGetMapfv )( GLenum target, GLenum query, GLfloat *v );
305 | void (APIENTRY *glGetMapiv )( GLenum target, GLenum query, GLint *v );
306 | void (APIENTRY *glGetMaterialfv )( GLenum face, GLenum pname, GLfloat *params );
307 | void (APIENTRY *glGetMaterialiv )( GLenum face, GLenum pname, GLint *params );
308 | void (APIENTRY *glGetPixelMapfv )( GLenum map, GLfloat *values );
309 | void (APIENTRY *glGetPixelMapuiv )( GLenum map, GLuint *values );
310 | void (APIENTRY *glGetPixelMapusv )( GLenum map, GLushort *values );
311 | void (APIENTRY *glGetPolygonStipple )( GLubyte *mask );
312 | const GLubyte * (APIENTRY *glGetString )( GLenum name );
313 | void (APIENTRY *glGetTexEnvfv )( GLenum target, GLenum pname, GLfloat *params );
314 | void (APIENTRY *glGetTexEnviv )( GLenum target, GLenum pname, GLint *params );
315 | void (APIENTRY *glGetTexGendv )( GLenum coord, GLenum pname, GLdouble *params );
316 | void (APIENTRY *glGetTexGenfv )( GLenum coord, GLenum pname, GLfloat *params );
317 | void (APIENTRY *glGetTexGeniv )( GLenum coord, GLenum pname, GLint *params );
318 | void (APIENTRY *glGetTexImage )( GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels );
319 | void (APIENTRY *glGetTexParameterfv )( GLenum target, GLenum pname, GLfloat *params );
320 | void (APIENTRY *glGetTexParameteriv )( GLenum target, GLenum pname, GLint *params );
321 | void (APIENTRY *glGetTexLevelParameterfv )( GLenum target, GLint level, GLenum pname, GLfloat *params );
322 | void (APIENTRY *glGetTexLevelParameteriv )( GLenum target, GLint level, GLenum pname, GLint *params );
323 | GLboolean (APIENTRY *glIsEnabled )( GLenum cap );
324 | GLboolean (APIENTRY *glIsList )( GLuint list );
325 | void (APIENTRY *glDepthRange )( GLclampd zNear, GLclampd zFar );
326 | void (APIENTRY *glFrustum )( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar );
327 | void (APIENTRY *glLoadIdentity )( void );
328 | void (APIENTRY *glLoadMatrixf )( const GLfloat *m );
329 | void (APIENTRY *glLoadMatrixd )( const GLdouble *m );
330 | void (APIENTRY *glMatrixMode )( GLenum mode );
331 | void (APIENTRY *glMultMatrixf )( const GLfloat *m );
332 | void (APIENTRY *glMultMatrixd )( const GLdouble *m );
333 | void (APIENTRY *glOrtho )( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar );
334 | void (APIENTRY *glPopMatrix )( void );
335 | void (APIENTRY *glPushMatrix )( void );
336 | void (APIENTRY *glRotated )( GLdouble angle, GLdouble x, GLdouble y, GLdouble z );
337 | void (APIENTRY *glRotatef )( GLfloat angle, GLfloat x, GLfloat y, GLfloat z );
338 | void (APIENTRY *glScaled )( GLdouble x, GLdouble y, GLdouble z );
339 | void (APIENTRY *glScalef )( GLfloat x, GLfloat y, GLfloat z );
340 | void (APIENTRY *glTranslated )( GLdouble x, GLdouble y, GLdouble z );
341 | void (APIENTRY *glTranslatef )( GLfloat x, GLfloat y, GLfloat z );
342 | void (APIENTRY *glViewport )( GLint x, GLint y, GLsizei width, GLsizei height );
343 | // OpenGL version 1.0 entries end here
344 |
345 | // OpenGL version 1.1 entries begin here
346 | void (APIENTRY *glArrayElement )(GLint i);
347 | void (APIENTRY *glBindTexture )(GLenum target, GLuint texture);
348 | void (APIENTRY *glColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
349 | void (APIENTRY *glDisableClientState )(GLenum array);
350 | void (APIENTRY *glDrawArrays )(GLenum mode, GLint first, GLsizei count);
351 | void (APIENTRY *glDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
352 | void (APIENTRY *glEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
353 | void (APIENTRY *glEnableClientState )(GLenum array);
354 | void (APIENTRY *glIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
355 | void (APIENTRY *glIndexub )(GLubyte c);
356 | void (APIENTRY *glIndexubv )(const GLubyte *c);
357 | void (APIENTRY *glInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
358 | void (APIENTRY *glNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
359 | void (APIENTRY *glPolygonOffset )(GLfloat factor, GLfloat units);
360 | void (APIENTRY *glTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
361 | void (APIENTRY *glVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
362 | GLboolean (APIENTRY *glAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
363 | void (APIENTRY *glCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
364 | void (APIENTRY *glCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
365 | void (APIENTRY *glCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
366 | void (APIENTRY *glCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
367 | void (APIENTRY *glDeleteTextures )(GLsizei n, const GLuint *textures);
368 | void (APIENTRY *glGenTextures )(GLsizei n, GLuint *textures);
369 | void (APIENTRY *glGetPointerv )(GLenum pname, GLvoid* *params);
370 | GLboolean (APIENTRY *glIsTexture )(GLuint texture);
371 | void (APIENTRY *glPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
372 | void (APIENTRY *glTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
373 | void (APIENTRY *glTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
374 | void (APIENTRY *glPopClientAttrib )(void);
375 | void (APIENTRY *glPushClientAttrib )(GLbitfield mask);
376 | } GLDISPATCHTABLE, *PGLDISPATCHTABLE;
377 |
378 | // OpenGL Client/Driver Procedure Table.
379 |
380 | typedef struct _GLCLTPROCTABLE {
381 | _In_range_(0,OPENGL_VERSION_110_ENTRIES) int cEntries; // Number of function entries in table
382 | GLDISPATCHTABLE glDispatchTable; // OpenGL function dispatch table
383 | } GLCLTPROCTABLE, *PGLCLTPROCTABLE;
384 |
385 | // Driver GLRC handle.
386 |
387 | typedef ULONG DHGLRC;
388 |
389 | // SetProcTable function prototype for DrvSetContext.
390 |
391 | typedef VOID (APIENTRY *PFN_SETPROCTABLE)(PGLCLTPROCTABLE);
392 |
393 | // DrvSetCallbackProcs prototypes
394 | typedef VOID (APIENTRY *PFN_SETCURRENTVALUE)(VOID *pv);
395 | typedef VOID *(APIENTRY *PFN_GETCURRENTVALUE)(VOID);
396 | typedef DHGLRC (APIENTRY *PFN_GETDHGLRC)(HGLRC hrc);
397 | #if WINVER >= 0x600
398 | typedef struct _PRESENTBUFFERSCB {
399 | IN UINT nVersion;
400 | IN UINT syncType; // See PRESCB_SYNCTYPE_NONE and PRESCB_SYNCTYPE_VSYNC
401 | IN LUID luidAdapter;
402 | IN LPVOID pPrivData;
403 | IN RECT updateRect; // Update rectangle in the coordinate system of the window, whose HDC is passed to PFN_PRESENTBUFFERS
404 | } PRESENTBUFFERSCB, *LPPRESENTBUFFERSCB;
405 | typedef BOOL (APIENTRY *PFN_PRESENTBUFFERS)(HDC hdc, LPPRESENTBUFFERSCB pprsbcbData);
406 | #endif
407 | #if WINVER >= 0xA00
408 | typedef VOID (APIENTRY *PFN_GETADAPTERLUID)(HDC hdc, OUT LUID* pLuid);
409 | typedef struct _CHECKFULLSCREENSUPPORTCB {
410 | IN UINT nVersion;
411 | IN LUID luidAdapter;
412 | IN UINT hDevice;
413 | IN HMONITOR hMonitor;
414 | OUT UINT VidPnSourceId;
415 | } CHECKFULLSCREENSUPPORTCB, *LPCHECKFULLSCREENSUPPORTCB;
416 | typedef BOOL (APIENTRY *PFN_CHECKFULLSCREENSUPPORT)(HDC hdc, LPCHECKFULLSCREENSUPPORTCB pArgs);
417 | typedef struct _PRESENTTOREDIRECTIONSURFACECB {
418 | IN UINT nVersion;
419 | IN UINT hContext;
420 | IN UINT hSource;
421 | IN UINT hDestination;
422 | IN HANDLE hSharedHandle;
423 | IN UINT64 updateId;
424 | IN RECT updateRect;
425 | IN UINT broadcastContextCount;
426 | IN UINT broadcastContext[64];
427 | IN UINT broadcastSrcAllocation[64];
428 | IN UINT broadcastDstAllocation[64];
429 | IN UINT cbPrivateDriverDataSize;
430 | IN VOID *pPrivateDriverData;
431 | } PRESENTTOREDIRECTIONSURFACECB, *LPPRESENTTOREDIRECTIONSURFACECB;
432 | typedef BOOL (APIENTRY *PFN_PRESENTTOREDIRECTIONSURFACE)(HDC hdc, LPPRESENTTOREDIRECTIONSURFACECB pArgs);
433 | typedef struct _SUBMITPRESENTTOREDIRECTIONSURFACECB {
434 | IN UINT nVersion;
435 | IN HANDLE hSharedHandle;
436 | IN UINT64 updateId;
437 | IN RECT updateRect;
438 | IN UINT broadcastHwQueueCount;
439 |
440 | _Field_size_(broadcastHwQueueCount)
441 | IN UINT *broadcastHwQueue;
442 |
443 | _Field_size_(broadcastHwQueueCount)
444 | IN UINT *broadcastSrcAllocation;
445 |
446 | _Field_size_opt_(broadcastHwQueueCount)
447 | IN UINT *broadcastDstAllocation;
448 |
449 | IN UINT cbPrivateDriverDataSize;
450 | IN VOID *pPrivateDriverData;
451 | } SUBMITPRESENTTOREDIRECTIONSURFACECB, *LPSUBMITPRESENTTOREDIRECTIONSURFACECB;
452 | typedef BOOL (APIENTRY *PFN_SUBMITPRESENTTOREDIRECTIONSURFACE)(HDC hdc, LPSUBMITPRESENTTOREDIRECTIONSURFACECB pArgs);
453 | #endif
454 |
455 | // Note: Structure not referenced directly, simply present to document the expected order/count of
456 | // callbacks received through DrvSetCallbackProcs.
457 | struct WGLCALLBACKS
458 | {
459 | PFN_SETCURRENTVALUE pfnSetCurrentValue;
460 | PFN_GETCURRENTVALUE pfnGetCurrentValue;
461 | PFN_GETDHGLRC pfnGetDhglrc;
462 | PROC pfnUnused;
463 | #if WINVER >= 0x600
464 | PFN_PRESENTBUFFERS pfnPresentBuffers;
465 | #endif
466 | #if WINVER >= 0xA00
467 | PFN_GETADAPTERLUID pfnGetAdapterLuid;
468 | PFN_CHECKFULLSCREENSUPPORT pfnCheckFullscreenSupport;
469 | PFN_PRESENTTOREDIRECTIONSURFACE pfnPresentToRedirectionSurface;
470 | PFN_SUBMITPRESENTTOREDIRECTIONSURFACE pfnSubmitPresentToRedirectionSurface;
471 | #endif
472 | };
473 |
474 | // Driver context function prototypes.
475 |
476 | BOOL APIENTRY DrvCopyContext(DHGLRC, DHGLRC, UINT);
477 | DHGLRC APIENTRY DrvCreateContext(HDC);
478 | DHGLRC APIENTRY DrvCreateLayerContext(HDC, int);
479 | BOOL APIENTRY DrvDeleteContext(DHGLRC);
480 | PGLCLTPROCTABLE APIENTRY DrvSetContext(HDC,DHGLRC,PFN_SETPROCTABLE);
481 | BOOL APIENTRY DrvReleaseContext(DHGLRC);
482 | BOOL APIENTRY DrvValidateVersion(ULONG);
483 | BOOL APIENTRY DrvShareLists(DHGLRC, DHGLRC);
484 | PROC APIENTRY DrvGetProcAddress(LPCSTR);
485 | VOID APIENTRY DrvSetCallbackProcs(INT, PROC *); // See WGLCALLBACKS for expected order/count per OS.
486 | BOOL APIENTRY DrvDescribeLayerPlane(HDC, INT, INT, UINT,
487 | LPLAYERPLANEDESCRIPTOR);
488 | INT APIENTRY DrvSetLayerPaletteEntries(HDC, INT, INT, INT,
489 | CONST COLORREF *);
490 | INT APIENTRY DrvGetLayerPaletteEntries(HDC, INT, INT, INT,
491 | COLORREF *);
492 | BOOL APIENTRY DrvRealizeLayerPalette(HDC, INT, BOOL);
493 | BOOL APIENTRY DrvSwapLayerBuffers(HDC, UINT);
494 |
495 | #if WINVER >= 0x500
496 |
497 | typedef struct IDirectDrawSurface *LPDIRECTDRAWSURFACE;
498 | typedef struct _DDSURFACEDESC *LPDDSURFACEDESC;
499 |
500 | DHGLRC APIENTRY DrvCreateDirectDrawContext(HDC, LPDIRECTDRAWSURFACE,
501 | int);
502 | int APIENTRY DrvEnumTextureFormats(int, LPDDSURFACEDESC);
503 | BOOL APIENTRY DrvBindDirectDrawTexture(LPDIRECTDRAWSURFACE);
504 | DWORD APIENTRY DrvSwapMultipleBuffers(UINT cBuffers,
505 | CONST WGLSWAP *pgswap);
506 |
507 | LONG APIENTRY DrvDescribePixelFormat(HDC, INT, ULONG, PIXELFORMATDESCRIPTOR*);
508 | BOOL APIENTRY DrvSetPixelFormat(HDC, LONG);
509 | BOOL APIENTRY DrvSwapBuffers(HDC);
510 |
511 | #endif // WINVER >= 0x500
512 |
513 | #if WINVER >= 0x600
514 | typedef struct _PRESENTBUFFERS {
515 | IN HANDLE hSurface;
516 | IN LUID luidAdapter;
517 | IN ULONGLONG ullPresentToken;
518 | IN LPVOID pPrivData;
519 | } PRESENTBUFFERS, *LPPRESENTBUFFERS;
520 | typedef BOOL (APIENTRY *PFN_PRESENTBUFFERS)(HDC hdc, LPPRESENTBUFFERSCB pprsbcbData);
521 |
522 | #define PRESCB_SYNCTYPE_NONE 0
523 | #define PRESCB_SYNCTYPE_VSYNC 1
524 |
525 | BOOL APIENTRY DrvPresentBuffers(HDC hdc, LPPRESENTBUFFERS pprsbData);
526 |
527 | #endif
528 |
529 | // Input structure for OPENGL_CMD ExtEscape.
530 |
531 | typedef struct _WNDOBJ WNDOBJ;
532 | typedef struct _XLATEOBJ XLATEOBJ;
533 |
534 | typedef struct _OPENGLCMD
535 | {
536 | ULONG ulSubEsc;
537 | FLONG fl;
538 | WNDOBJ *pwo;
539 | XLATEOBJ *pxo;
540 | } OPENGLCMD, *POPENGLCMD;
541 |
542 | #if WINVER >= 0x500
543 |
544 | #define OPENGLCMD_MAXMULTI WGL_SWAPMULTIPLE_MAX
545 |
546 | typedef struct _OPENGLCMDMULTI
547 | {
548 | ULONG ulSubEsc;
549 | FLONG fl;
550 | ULONG cMulti;
551 | XLATEOBJ *pxo;
552 | } OPENGLCMDMULTI, *POPENGLCMDMULTI;
553 |
554 | #endif // WINVER >= 0x500
555 |
556 | // Flags for OPENGL_CMD ExtEscape.
557 |
558 | #define OGLCMD_NEEDWNDOBJ 0x01
559 | #define OGLCMD_NEEDXLATEOBJ 0x02
560 |
561 | #if WINVER >= 0x500
562 | #define OGLCMD_MULTIWNDOBJ 0x04
563 | #endif // WINVER >= 0x500
564 |
565 | // OPENGL_GETINFO ExtEscape sub-escape numbers. They are defined by Microsoft.
566 |
567 | #define OPENGL_GETINFO_DRVNAME 0
568 |
569 | // Input structure for OPENGL_GETINFO ExtEscape.
570 |
571 | typedef struct _OPENGLGETINFO
572 | {
573 | ULONG ulSubEsc;
574 | } OPENGLGETINFO, *POPENGLGETINFO;
575 |
576 | // Input structure for OPENGL_GETINFO_DRVNAME ExtEscape.
577 |
578 | typedef struct _GLDRVNAME
579 | {
580 | OPENGLGETINFO oglget;
581 | } GLDRVNAME, *PGLDRVNAME;
582 |
583 | // Output structure for OPENGL_GETINFO_DRVNAME ExtEscape.
584 |
585 | typedef struct _GLDRVNAMERET
586 | {
587 | ULONG ulVersion; // must be 1 for this version
588 | ULONG ulDriverVersion; // driver specific version number
589 | WCHAR awch[MAX_PATH+1];
590 | } GLDRVNAMERET, *PGLDRVNAMERET;
591 |
592 | #endif /* _GLDRV_ */
593 |
594 | #endif /* _WIN32 */
--------------------------------------------------------------------------------
/inc/client/platform/glx.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_GLX_H_
2 | #define _SGL_GLX_H_
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #define GLX_VENDOR 1
9 | #define GLX_VERSION 2
10 | #define GLX_EXTENSIONS 3
11 |
12 | #define GLX_USE_GL 1
13 | #define GLX_BUFFER_SIZE 2
14 | #define GLX_LEVEL 3
15 | #define GLX_RGBA 4
16 | #define GLX_DOUBLEBUFFER 5
17 | #define GLX_STEREO 6
18 | #define GLX_AUX_BUFFERS 7
19 | #define GLX_RED_SIZE 8
20 | #define GLX_GREEN_SIZE 9
21 | #define GLX_BLUE_SIZE 10
22 | #define GLX_ALPHA_SIZE 11
23 | #define GLX_DEPTH_SIZE 12
24 | #define GLX_STENCIL_SIZE 13
25 | #define GLX_ACCUM_RED_SIZE 14
26 | #define GLX_ACCUM_GREEN_SIZE 15
27 | #define GLX_ACCUM_BLUE_SIZE 16
28 | #define GLX_ACCUM_ALPHA_SIZE 17
29 |
30 | #define GLX_CONFIG_CAVEAT 0x20
31 | #define GLX_DONT_CARE 0xFFFFFFFF
32 | #define GLX_X_VISUAL_TYPE 0x22
33 | #define GLX_TRANSPARENT_TYPE 0x23
34 | #define GLX_TRANSPARENT_INDEX_VALUE 0x24
35 | #define GLX_TRANSPARENT_RED_VALUE 0x25
36 | #define GLX_TRANSPARENT_GREEN_VALUE 0x26
37 | #define GLX_TRANSPARENT_BLUE_VALUE 0x27
38 | #define GLX_TRANSPARENT_ALPHA_VALUE 0x28
39 | #define GLX_WINDOW_BIT 0x00000001
40 | #define GLX_PIXMAP_BIT 0x00000002
41 | #define GLX_PBUFFER_BIT 0x00000004
42 | #define GLX_AUX_BUFFERS_BIT 0x00000010
43 | #define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
44 | #define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
45 | #define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
46 | #define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
47 | #define GLX_DEPTH_BUFFER_BIT 0x00000020
48 | #define GLX_STENCIL_BUFFER_BIT 0x00000040
49 | #define GLX_ACCUM_BUFFER_BIT 0x00000080
50 | #define GLX_NONE 0x8000
51 | #define GLX_SLOW_CONFIG 0x8001
52 | #define GLX_TRUE_COLOR 0x8002
53 | #define GLX_DIRECT_COLOR 0x8003
54 | #define GLX_PSEUDO_COLOR 0x8004
55 | #define GLX_STATIC_COLOR 0x8005
56 | #define GLX_GRAY_SCALE 0x8006
57 | #define GLX_STATIC_GRAY 0x8007
58 | #define GLX_TRANSPARENT_RGB 0x8008
59 | #define GLX_TRANSPARENT_INDEX 0x8009
60 | #define GLX_VISUAL_ID 0x800B
61 | #define GLX_SCREEN 0x800C
62 | #define GLX_NON_CONFORMANT_CONFIG 0x800D
63 | #define GLX_DRAWABLE_TYPE 0x8010
64 | #define GLX_RENDER_TYPE 0x8011
65 | #define GLX_X_RENDERABLE 0x8012
66 | #define GLX_FBCONFIG_ID 0x8013
67 | #define GLX_RGBA_TYPE 0x8014
68 | #define GLX_COLOR_INDEX_TYPE 0x8015
69 | #define GLX_MAX_PBUFFER_WIDTH 0x8016
70 | #define GLX_MAX_PBUFFER_HEIGHT 0x8017
71 | #define GLX_MAX_PBUFFER_PIXELS 0x8018
72 | #define GLX_PRESERVED_CONTENTS 0x801B
73 | #define GLX_LARGEST_PBUFFER 0x801C
74 | #define GLX_WIDTH 0x801D
75 | #define GLX_HEIGHT 0x801E
76 | #define GLX_EVENT_MASK 0x801F
77 | #define GLX_DAMAGED 0x8020
78 | #define GLX_SAVED 0x8021
79 | #define GLX_WINDOW 0x8022
80 | #define GLX_PBUFFER 0x8023
81 | #define GLX_PBUFFER_HEIGHT 0x8040
82 | #define GLX_PBUFFER_WIDTH 0x8041
83 | #define GLX_RGBA_BIT 0x00000001
84 | #define GLX_COLOR_INDEX_BIT 0x00000002
85 | #define GLX_PBUFFER_CLOBBER_MASK 0x08000000
86 |
87 | #define GLX_SAMPLE_BUFFERS 0x186a0
88 | #define GLX_SAMPLES 0x186a1
89 |
90 | #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2
91 | #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
92 | #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
93 | #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
94 | #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
95 | #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
96 | #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
97 | #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
98 | #define GLX_CONTEXT_FLAGS_ARB 0x2094
99 | #define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
100 | #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
101 | #define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
102 | #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
103 | #define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
104 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
105 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
106 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
107 | #define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
108 |
109 | typedef struct __GLXcontextRec *GLXContext;
110 | typedef XID GLXPixmap;
111 | typedef XID GLXDrawable;
112 |
113 | typedef struct __GLXFBConfigRec *GLXFBConfig;
114 | typedef XID GLXFBConfigID;
115 | typedef XID GLXContextID;
116 | typedef XID GLXWindow;
117 | typedef XID GLXPbuffer;
118 |
119 | void glximpl_init();
120 |
121 | #endif
--------------------------------------------------------------------------------
/inc/client/platform/icd.h:
--------------------------------------------------------------------------------
1 | #ifndef _ICD_H_
2 | #define _ICD_H_
3 |
4 | #define ICD_SET_MAX_DIMENSIONS_DEFINITION(mw, mh, rw, rh) \
5 | void icd_set_max_dimensions(int width, int height) \
6 | { \
7 | mw = width; \
8 | mh = height; \
9 | rw = 16; \
10 | rh = 16; \
11 | }
12 |
13 | #define ICD_RESIZE_DEFINITION(rw, rh) \
14 | void icd_resize(int width, int height) \
15 | { \
16 | rw = width; \
17 | rh = height; \
18 | } \
19 |
20 | void icd_set_max_dimensions(int width, int height);
21 | void icd_resize(int width, int height);
22 |
23 | #endif
--------------------------------------------------------------------------------
/inc/client/platform/wgl.h:
--------------------------------------------------------------------------------
1 | #ifdef OVERRIDE_OPENGL32
2 | #ifndef _SGL_WGL_H_
3 | #define _SGL_WGL_H_
4 |
5 | #include
6 |
7 | void WglInit();
8 |
9 | #endif
10 | #endif
--------------------------------------------------------------------------------
/inc/client/platform/windrv.h:
--------------------------------------------------------------------------------
1 | #ifdef _WIN32
2 | #ifndef _WINDRV_H_
3 | #define _WINDRV_H_
4 |
5 | void windrv_set_module_address(HMODULE module);
6 | void windrv_set_vflip(BOOL flip);
7 |
8 | #endif
9 | #endif
--------------------------------------------------------------------------------
/inc/client/scratch.h:
--------------------------------------------------------------------------------
1 | #ifndef _SCRATCH_H_
2 | #define _SCRATCH_H_
3 |
4 | #include
5 |
6 | void *scratch_buffer_get(size_t size);
7 |
8 | #endif
--------------------------------------------------------------------------------
/inc/client/spinlock.h:
--------------------------------------------------------------------------------
1 | #ifndef _SPINLOCK_H_
2 | #define _SPINLOCK_H_
3 |
4 | void spin_lock(int *lock);
5 | void spin_unlock(int volatile *lock);
6 |
7 | #endif
--------------------------------------------------------------------------------
/inc/network/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2002-2016 Lee Salzman
4 | Copyright (c) 2017-2022 Vladyslav Hrytsenko, Dominik Madarász
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
--------------------------------------------------------------------------------
/inc/network/packet.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_PACKET_H_
2 | #define _SGL_PACKET_H_
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #ifndef _WIN32
9 | #define PACKED __attribute__((packed))
10 | #else
11 | #define PACKED
12 | #endif
13 |
14 | #ifdef _WIN32
15 | __pragma( pack(push, 1) )
16 | #endif
17 | struct PACKED sgl_packet_connect {
18 | uint32_t client_id;
19 | uint64_t framebuffer_size;
20 | uint64_t fifo_size;
21 | uint32_t gl_major;
22 | uint32_t gl_minor;
23 | uint32_t max_width;
24 | uint32_t max_height;
25 | };
26 |
27 | struct PACKED sgl_packet_retval {
28 | union {
29 | uint32_t retval_split[2];
30 | uint64_t retval;
31 | };
32 | uint32_t retval_v[256 / sizeof(uint32_t)];
33 | };
34 | #ifdef _WIN32
35 | __pragma( pack(pop))
36 | #endif
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/inc/server/context.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_CONTEXT_H_
2 | #define _SGL_CONTEXT_H_
3 |
4 | #include
5 |
6 | struct sgl_host_context {
7 | SDL_Window *window;
8 | SDL_GLContext gl_context;
9 | };
10 |
11 | void sgl_set_max_resolution(int width, int height);
12 | void sgl_get_max_resolution(int *width, int *height);
13 |
14 | struct sgl_host_context *sgl_context_create();
15 | void sgl_context_destroy(struct sgl_host_context *ctx);
16 | void sgl_set_current(struct sgl_host_context *ctx);
17 | void *sgl_read_pixels(unsigned int width, unsigned int height, void *data, int vflip, int format, size_t mem_usage);
18 |
19 | #endif
--------------------------------------------------------------------------------
/inc/server/dynarr.h:
--------------------------------------------------------------------------------
1 | #ifndef _DYNARR_H_
2 | #define _DYNARR_H_
3 |
4 | #include
5 | #include
6 |
7 | typedef bool(*dynarr_match_fn)(void *elem, void *data);
8 |
9 | void *dynarr_alloc(void **root, size_t next_offset, size_t size);
10 | void dynarr_free_element(void **root, size_t next_offset, dynarr_match_fn matcher, void *data);
11 | void dynarr_free(void **root, size_t next_offset);
12 |
13 | #endif
--------------------------------------------------------------------------------
/inc/server/overlay.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_OVERLAY_H_
2 | #define _SGL_OVERLAY_H_
3 |
4 | #include
5 |
6 | struct overlay_context {
7 | clock_t current_ticks, delta_ticks;
8 | clock_t fps;
9 | };
10 |
11 | void overlay_set_renderer_string(char *string);
12 | void overlay_enable();
13 | void overlay_stage1(struct overlay_context *ctx);
14 | void overlay_stage2(struct overlay_context *ctx, int *frame, int width, size_t mem_usage);
15 |
16 | #endif
--------------------------------------------------------------------------------
/inc/server/overlay_font.h:
--------------------------------------------------------------------------------
1 | #ifndef _OVERLAY_FONT_H_
2 | #define _OVERLAY_FONT_H_
3 |
4 | #define CHAR_WIDTH 8
5 | #define CHAR_HEIGHT 16
6 |
7 | static const unsigned char IBM[4096] =
8 | {
9 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
18 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00,
43 | 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 | 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x7e, 0x24, 0x24, 0x7e, 0x48, 0x48, 0x48, 0x00, 0x00,
45 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x3e, 0x49, 0x48, 0x38, 0x0e, 0x09, 0x49, 0x3e, 0x08, 0x00, 0x00,
46 | 0x00, 0x00, 0x00, 0x00, 0x31, 0x4a, 0x4a, 0x34, 0x08, 0x08, 0x16, 0x29, 0x29, 0x46, 0x00, 0x00,
47 | 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x14, 0x18, 0x29, 0x45, 0x42, 0x46, 0x39, 0x00, 0x00,
48 | 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 | 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00,
50 | 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00,
51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x49, 0x2a, 0x1c, 0x2a, 0x49, 0x08, 0x00, 0x00, 0x00,
52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x10,
54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
56 | 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00,
57 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x24, 0x18, 0x00, 0x00,
58 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
59 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x0c, 0x10, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00,
60 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x1c, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00,
61 | 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, 0x44, 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00,
62 | 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00,
63 | 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
64 | 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
65 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
66 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x04, 0x38, 0x00, 0x00,
67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x10, 0x00,
69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00,
70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00,
72 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x02, 0x04, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00,
73 | 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x4a, 0x56, 0x52, 0x52, 0x52, 0x4e, 0x20, 0x1e, 0x00, 0x00,
74 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
75 | 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00,
76 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x3c, 0x00, 0x00,
77 | 0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00,
78 | 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00,
79 | 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
80 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x40, 0x4e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
81 | 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
82 | 0x00, 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
83 | 0x00, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x44, 0x38, 0x00, 0x00,
84 | 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00,
85 | 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00,
86 | 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x66, 0x66, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
87 | 0x00, 0x00, 0x00, 0x00, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46, 0x46, 0x42, 0x00, 0x00,
88 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
89 | 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
90 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x5a, 0x66, 0x3c, 0x03, 0x00,
91 | 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x44, 0x42, 0x42, 0x00, 0x00,
92 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x30, 0x0c, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00,
93 | 0x00, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
94 | 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
95 | 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00,
96 | 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x5a, 0x5a, 0x66, 0x66, 0x42, 0x42, 0x00, 0x00,
97 | 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x00, 0x00,
98 | 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
99 | 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00,
100 | 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00,
101 | 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
102 | 0x00, 0x00, 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00,
103 | 0x00, 0x00, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
105 | 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
107 | 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00,
108 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
109 | 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
111 | 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
112 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3a, 0x44, 0x44, 0x44, 0x38, 0x20, 0x3c, 0x42, 0x42, 0x3c,
113 | 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
114 | 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
115 | 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x48, 0x30,
116 | 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00,
117 | 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
118 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00,
119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
120 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
121 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40,
122 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02,
123 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x30, 0x0c, 0x02, 0x42, 0x3c, 0x00, 0x00,
125 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00,
126 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
127 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00,
128 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00,
129 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x00, 0x00,
130 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x3c,
131 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00,
132 | 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x08, 0x10, 0x20, 0x10, 0x08, 0x08, 0x10, 0x10, 0x0c,
133 | 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
134 | 0x00, 0x00, 0x00, 0x30, 0x08, 0x08, 0x10, 0x10, 0x08, 0x04, 0x08, 0x10, 0x10, 0x08, 0x08, 0x30,
135 | 0x00, 0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x73, 0xca, 0x4b, 0xca, 0x73, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
137 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x71, 0xca, 0x73, 0xc2, 0x42, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
138 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x49, 0xca, 0x7a, 0xca, 0x49, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
139 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x73, 0xca, 0x73, 0xca, 0x72, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
140 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x4b, 0xea, 0x5b, 0xca, 0x4b, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
141 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x74, 0xa6, 0x25, 0xa4, 0x74, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
142 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x4b, 0xea, 0x5b, 0xca, 0x4b, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
143 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x39, 0xc2, 0x31, 0x88, 0x73, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
144 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x79, 0xc2, 0x79, 0xc0, 0x7b, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
145 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x4b, 0xc9, 0x79, 0xc9, 0x49, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
146 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x25, 0xa4, 0x3c, 0xa4, 0x24, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
147 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x45, 0xc4, 0x44, 0xa8, 0x10, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
148 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x72, 0xca, 0x72, 0xc2, 0x43, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
149 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x72, 0xca, 0x72, 0xc2, 0x43, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
150 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x0e, 0x89, 0x0e, 0x8a, 0x09, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
151 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x39, 0xc2, 0x31, 0x88, 0x73, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
152 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x39, 0xc2, 0x31, 0x88, 0x73, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
153 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x71, 0xca, 0x4a, 0xca, 0x71, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
154 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x72, 0xca, 0x72, 0xc2, 0x41, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
155 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x72, 0xca, 0x72, 0xc2, 0x41, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
156 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x3b, 0xc1, 0x31, 0x89, 0x71, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
157 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x39, 0xc2, 0x42, 0xc2, 0x39, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
158 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x22, 0xb6, 0x2a, 0xa2, 0x22, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
159 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x3b, 0xc2, 0x33, 0x8a, 0x72, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
160 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x7b, 0xc2, 0x7b, 0xc2, 0x7a, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
161 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x39, 0xc2, 0x32, 0x8a, 0x71, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
162 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x33, 0xc4, 0x25, 0x94, 0x63, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
163 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x39, 0xc2, 0x32, 0x8a, 0x71, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
164 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x39, 0xc2, 0x41, 0xc0, 0x3b, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
165 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x0e, 0x90, 0x0c, 0x82, 0x1c, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
166 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x31, 0xca, 0x49, 0xc8, 0x33, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
167 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x1c, 0x92, 0x1c, 0x90, 0x10, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
168 | 0xaa, 0x00, 0x80, 0x00, 0x80, 0x33, 0xca, 0x7b, 0xca, 0x4a, 0x80, 0x00, 0x80, 0x00, 0x80, 0x55,
169 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
171 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x49, 0x48, 0x48, 0x49, 0x3e, 0x08, 0x08, 0x00, 0x00,
172 | 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x3e, 0x61, 0x00, 0x00,
173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x42, 0x42, 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00,
174 | 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x7f, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00,
175 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
176 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x3c, 0x42, 0x42, 0x3c, 0x02, 0x42, 0x3c, 0x00, 0x00,
177 | 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa1, 0xa1, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00,
179 | 0x00, 0x00, 0x1c, 0x02, 0x1e, 0x22, 0x1e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x24, 0x24, 0x48, 0x24, 0x24, 0x12, 0x12, 0x00, 0x00,
181 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x00, 0x00,
182 | 0xaa, 0x00, 0x80, 0x3a, 0xc2, 0x33, 0x8a, 0x72, 0x80, 0x00, 0x80, 0x03, 0x80, 0x00, 0x80, 0x55,
183 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0xb9, 0xa5, 0xa5, 0xb9, 0xa9, 0xa5, 0x42, 0x3c, 0x00, 0x00,
184 | 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00,
187 | 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x18, 0x20, 0x40, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 | 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 | 0x00, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x59, 0x40, 0x80,
191 | 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7a, 0x7a, 0x7a, 0x3a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00,
192 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x30,
194 | 0x00, 0x00, 0x00, 0x10, 0x30, 0x50, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 | 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x24, 0x24, 0x12, 0x24, 0x24, 0x48, 0x48, 0x00, 0x00,
197 | 0x00, 0x00, 0x00, 0x00, 0x22, 0x62, 0x24, 0x28, 0x28, 0x12, 0x16, 0x2a, 0x4e, 0x42, 0x00, 0x00,
198 | 0x00, 0x00, 0x00, 0x00, 0x22, 0x62, 0x24, 0x28, 0x28, 0x14, 0x1a, 0x22, 0x44, 0x4e, 0x00, 0x00,
199 | 0x00, 0x00, 0x00, 0x00, 0x62, 0x12, 0x24, 0x18, 0x68, 0x12, 0x16, 0x2a, 0x4e, 0x42, 0x00, 0x00,
200 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x20, 0x40, 0x42, 0x42, 0x3c, 0x00, 0x00,
201 | 0x30, 0x0c, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
202 | 0x0c, 0x30, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
203 | 0x18, 0x24, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
204 | 0x32, 0x4c, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
205 | 0x24, 0x24, 0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
206 | 0x18, 0x24, 0x18, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
207 | 0x00, 0x00, 0x00, 0x00, 0x1f, 0x28, 0x48, 0x48, 0x7f, 0x48, 0x48, 0x48, 0x48, 0x4f, 0x00, 0x00,
208 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x3c, 0x08, 0x30,
209 | 0x30, 0x0c, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00,
210 | 0x0c, 0x30, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00,
211 | 0x18, 0x24, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00,
212 | 0x24, 0x24, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00,
213 | 0x18, 0x06, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
214 | 0x0c, 0x30, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
215 | 0x18, 0x24, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
216 | 0x24, 0x24, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
217 | 0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0xf2, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00,
218 | 0x32, 0x4c, 0x00, 0x00, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46, 0x46, 0x42, 0x00, 0x00,
219 | 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
220 | 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
221 | 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
222 | 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
223 | 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00,
225 | 0x00, 0x00, 0x00, 0x02, 0x3a, 0x44, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x22, 0x5c, 0x40, 0x00,
226 | 0x30, 0x0c, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
227 | 0x0c, 0x30, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
228 | 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
229 | 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
230 | 0x0c, 0x30, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
231 | 0x00, 0x00, 0x00, 0x40, 0x40, 0x78, 0x44, 0x42, 0x42, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00,
232 | 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x48, 0x58, 0x44, 0x42, 0x42, 0x52, 0x4c, 0x00, 0x00,
233 | 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
234 | 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
235 | 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
236 | 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
237 | 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
238 | 0x00, 0x18, 0x24, 0x18, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3e, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x49, 0x09, 0x3f, 0x48, 0x48, 0x49, 0x3e, 0x00, 0x00,
240 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x08, 0x30,
241 | 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
242 | 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
243 | 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
244 | 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
245 | 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
246 | 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
247 | 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
248 | 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00,
249 | 0x00, 0x00, 0x32, 0x0c, 0x14, 0x22, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
250 | 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
251 | 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
252 | 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
253 | 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
254 | 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
255 | 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
256 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
257 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x3c, 0x40, 0x00,
258 | 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
259 | 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
260 | 0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
261 | 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00,
262 | 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x3c,
263 | 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40,
264 | 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x3c,
265 | };
266 |
267 | #endif
--------------------------------------------------------------------------------
/inc/server/processor.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGL_PROCESSOR_H_
2 | #define _SGL_PROCESSOR_H_
3 |
4 | #include
5 | #include
6 |
7 | struct sgl_cmd_processor_args {
8 | /*
9 | * shared memory information
10 | */
11 | void *base_address;
12 | size_t memory_size;
13 |
14 | /*
15 | * use network instead of shared memory
16 | */
17 | bool network_over_shared;
18 | int port;
19 |
20 | /*
21 | * opengl version
22 | */
23 | int gl_major;
24 | int gl_minor;
25 |
26 | /*
27 | * for debugging; in the event of an exception,
28 | * this pointer will contain a pointer to the
29 | * current command in execution
30 | */
31 | int **internal_cmd_ptr;
32 | };
33 |
34 | void sgl_cmd_processor_start(struct sgl_cmd_processor_args args);
35 |
36 | #endif
--------------------------------------------------------------------------------
/inc/sgldebug.h:
--------------------------------------------------------------------------------
1 | #ifndef _SGLDEBUG_H_
2 | #define _SGLDEBUG_H_
3 |
4 | const char *sgl_cmd2str(int c);
5 |
6 | #endif
--------------------------------------------------------------------------------
/kernel/linux/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | obj-m += sharedgl.o
3 |
4 | sharedgl_mod:
5 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
6 |
7 | clean:
8 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
--------------------------------------------------------------------------------
/kernel/linux/install.sh:
--------------------------------------------------------------------------------
1 | mkdir /lib/modules/$(uname -r)/kernel/drivers/pci/sharedgl
2 | zstd sharedgl.ko
3 | mv sharedgl.ko.zst /lib/modules/$(uname -r)/kernel/drivers/pci/sharedgl/sharedgl.ko.zst
4 | depmod -a
5 | modprobe sharedgl
--------------------------------------------------------------------------------
/kernel/linux/sharedgl.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | #include
15 |
16 | struct bar_t {
17 | resource_size_t len;
18 | void __iomem *addr;
19 | resource_size_t phys;
20 | };
21 |
22 | struct pci_char {
23 | struct bar_t bar[6];
24 | dev_t major;
25 | struct cdev cdev;
26 | };
27 |
28 | static struct class *pchar_class;
29 |
30 | static int dev_open(struct inode *inode, struct file *file)
31 | {
32 | unsigned int num = iminor(file->f_path.dentry->d_inode);
33 | struct pci_char *pchar = container_of(inode->i_cdev, struct pci_char, cdev);
34 |
35 | if (num > 5)
36 | return -ENXIO;
37 | if (pchar->bar[num].len == 0)
38 | return -EIO;
39 |
40 | file->private_data = pchar;
41 | return 0;
42 | }
43 |
44 | int dev_mmap(struct file *file, struct vm_area_struct *vma)
45 | {
46 | struct pci_char *pchar = file->private_data;
47 |
48 | if (io_remap_pfn_range(vma, vma->vm_start,
49 | pchar->bar[2].phys >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
50 | vma->vm_page_prot))
51 | return -EAGAIN;
52 |
53 | return 0;
54 | }
55 |
56 | static const struct file_operations fops = {
57 | .owner = THIS_MODULE,
58 | .open = dev_open,
59 | .mmap = dev_mmap
60 | };
61 |
62 | static int my_dev_uevent(const struct device *dev, struct kobj_uevent_env *env)
63 | {
64 | add_uevent_var(env, "DEVMODE=%#o", 0666);
65 | return 0;
66 | }
67 |
68 | static int pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
69 | {
70 | int err = 0, i;
71 | int mem_bars;
72 | struct pci_char *pchar;
73 | struct device *dev;
74 | dev_t dev_num;
75 |
76 | pchar = kmalloc(sizeof(struct pci_char), GFP_KERNEL);
77 | if (!pchar) {
78 | err = -ENOMEM;
79 | goto failure_kmalloc;
80 | }
81 |
82 | err = pci_enable_device_mem(pdev);
83 | if (err)
84 | goto failure_pci_enable;
85 |
86 | mem_bars = pci_select_bars(pdev, IORESOURCE_MEM);
87 | err = pci_request_selected_regions(pdev, mem_bars, "sharedgl");
88 | if (err)
89 | goto failure_pci_regions;
90 |
91 | for (i = 0; i < 6; i++) {
92 | if (mem_bars & (1 << i)) {
93 | pchar->bar[i].addr = ioremap(pci_resource_start(pdev, i), pci_resource_len(pdev, i));
94 | if (IS_ERR(pchar->bar[i].addr)) {
95 | err = PTR_ERR(pchar->bar[i].addr);
96 | break;
97 | } else {
98 | pchar->bar[i].phys = pci_resource_start(pdev, i);
99 | pchar->bar[i].len = pci_resource_len(pdev, i);
100 | }
101 | } else {
102 | pchar->bar[i].addr = NULL;
103 | pchar->bar[i].len = 0;
104 | }
105 | }
106 |
107 | if (err) {
108 | for (i--; i >= 0; i--)
109 | if (pchar->bar[i].len)
110 | iounmap(pchar->bar[i].addr);
111 | goto failure_ioremap;
112 | }
113 |
114 | err = alloc_chrdev_region(&dev_num, 0, 6, "sharedgl");
115 | if (err)
116 | goto failure_alloc_chrdev_region;
117 |
118 | pchar->major = MAJOR(dev_num);
119 |
120 | cdev_init(&pchar->cdev, &fops);
121 | pchar->cdev.owner = THIS_MODULE;
122 |
123 | err = cdev_add(&pchar->cdev, MKDEV(pchar->major, 0), 6);
124 | if (err)
125 | goto failure_cdev_add;
126 |
127 | pchar_class->dev_uevent = my_dev_uevent;
128 | for (i = 0; i < 6; i++) {
129 | if (pchar->bar[i].len) {
130 | dev = device_create(pchar_class, &pdev->dev,
131 | MKDEV(pchar->major, i),
132 | NULL, "b%xd%xf%x_bar%d",
133 | pdev->bus->number,
134 | PCI_SLOT(pdev->devfn),
135 | PCI_FUNC(pdev->devfn), i);
136 | if (IS_ERR(dev)) {
137 | err = PTR_ERR(dev);
138 | break;
139 | }
140 | }
141 | }
142 |
143 | if (err) {
144 | for (i--; i >= 0; i--)
145 | if (pchar->bar[i].len)
146 | device_destroy(pchar_class,
147 | MKDEV(pchar->major, i));
148 | goto failure_device_create;
149 | }
150 |
151 | pci_set_drvdata(pdev, pchar);
152 | dev_info(&pdev->dev, "claimed by sharedgl\n");
153 |
154 | return 0;
155 |
156 | failure_device_create:
157 | cdev_del(&pchar->cdev);
158 |
159 | failure_cdev_add:
160 | unregister_chrdev_region(MKDEV(pchar->major, 0), 6);
161 |
162 | failure_alloc_chrdev_region:
163 | for (i = 0; i < 6; i++)
164 | if (pchar->bar[i].len)
165 | iounmap(pchar->bar[i].addr);
166 |
167 | failure_ioremap:
168 | pci_release_selected_regions(pdev,
169 | pci_select_bars(pdev, IORESOURCE_MEM));
170 |
171 | failure_pci_regions:
172 | pci_disable_device(pdev);
173 |
174 | failure_pci_enable:
175 | kfree(pchar);
176 |
177 | failure_kmalloc:
178 | return err;
179 | }
180 |
181 | static void pci_remove(struct pci_dev *pdev)
182 | {
183 | int i;
184 | struct pci_char *pchar = pci_get_drvdata(pdev);
185 |
186 | for (i = 0; i < 6; i++)
187 | if (pchar->bar[i].len)
188 | device_destroy(pchar_class,
189 | MKDEV(pchar->major, i));
190 |
191 | cdev_del(&pchar->cdev);
192 |
193 | unregister_chrdev_region(MKDEV(pchar->major, 0), 6);
194 |
195 | for (i = 0; i < 6; i++)
196 | if (pchar->bar[i].len)
197 | iounmap(pchar->bar[i].addr);
198 |
199 | pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM));
200 | pci_disable_device(pdev);
201 | kfree(pchar);
202 | }
203 |
204 | static struct pci_device_id pci_ids[] = {
205 | {
206 | .vendor = 0x1af4,
207 | .device = 0x1110,
208 | .subvendor = PCI_ANY_ID,
209 | .subdevice = PCI_ANY_ID,
210 | },
211 | { 0, }
212 | };
213 |
214 | static struct pci_driver pchar_driver = {
215 | .name = "sharedgl",
216 | .id_table = pci_ids,
217 | .probe = pci_probe,
218 | .remove = pci_remove,
219 | };
220 |
221 | static char *pci_char_devnode(const struct device *dev, umode_t *mode)
222 | {
223 | struct pci_dev *pdev = to_pci_dev(dev->parent);
224 | return kasprintf(
225 | GFP_KERNEL, "sharedgl/%02x:%02x.%02x/bar%d",
226 | pdev->bus->number,
227 | PCI_SLOT(pdev->devfn),
228 | PCI_FUNC(pdev->devfn),
229 | MINOR(dev->devt)
230 | );
231 | }
232 |
233 | static int __init pci_init(void)
234 | {
235 | int err;
236 |
237 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
238 | pchar_class = class_create("sharedgl");
239 | #else
240 | pchar_class = class_create(THIS_MODULE, "sharedgl");
241 | #endif
242 |
243 | if (IS_ERR(pchar_class)) {
244 | err = PTR_ERR(pchar_class);
245 | return err;
246 | }
247 |
248 | pchar_class->devnode = pci_char_devnode;
249 |
250 | err = pci_register_driver(&pchar_driver);
251 | if (err)
252 | goto failure_register_driver;
253 |
254 | return 0;
255 |
256 | failure_register_driver:
257 | class_destroy(pchar_class);
258 |
259 | return err;
260 | }
261 |
262 | static void __exit pci_exit(void)
263 | {
264 | pci_unregister_driver(&pchar_driver);
265 | class_destroy(pchar_class);
266 | }
267 |
268 | module_init(pci_init);
269 | module_exit(pci_exit);
270 |
271 | MODULE_LICENSE("Dual MIT/GPL");
272 | MODULE_DESCRIPTION("Driver to expose sharedgl memory");
273 | MODULE_AUTHOR("dmaivel");
--------------------------------------------------------------------------------
/kernel/linux/uninstall.sh:
--------------------------------------------------------------------------------
1 | rmmod sharedgl
2 | rm -rf /lib/modules/$(uname -r)/kernel/drivers/pci/sharedgl
3 | depmod -a
--------------------------------------------------------------------------------
/kernel/windows/Device.c:
--------------------------------------------------------------------------------
1 | #include "driver.h"
2 |
3 | #ifdef ALLOC_PRAGMA
4 | #pragma alloc_text (PAGE, IVSHMEMCreateDevice)
5 | #pragma alloc_text (PAGE, IVSHMEMEvtDevicePrepareHardware)
6 | #pragma alloc_text (PAGE, IVSHMEMEvtD0Exit)
7 | #endif
8 |
9 | NTSTATUS IVSHMEMCreateDevice(_Inout_ PWDFDEVICE_INIT DeviceInit)
10 | {
11 | WDF_OBJECT_ATTRIBUTES deviceAttributes;
12 | PDEVICE_CONTEXT deviceContext;
13 | WDFDEVICE device;
14 | NTSTATUS status;
15 |
16 | PAGED_CODE();
17 | DEBUG_INFO("%s", __FUNCTION__);
18 |
19 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
20 |
21 | WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
22 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
23 | pnpPowerCallbacks.EvtDevicePrepareHardware = IVSHMEMEvtDevicePrepareHardware;
24 | pnpPowerCallbacks.EvtDeviceReleaseHardware = IVSHMEMEvtDeviceReleaseHardware;
25 | pnpPowerCallbacks.EvtDeviceD0Entry = IVSHMEMEvtD0Entry;
26 | pnpPowerCallbacks.EvtDeviceD0Exit = IVSHMEMEvtD0Exit;
27 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
28 |
29 | WDF_FILEOBJECT_CONFIG fileConfig;
30 | WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, NULL, NULL, IVSHMEMEvtDeviceFileCleanup);
31 | WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES);
32 |
33 | status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
34 |
35 | if (!NT_SUCCESS(status))
36 | {
37 | DEBUG_ERROR("%s", "Call to WdfDeviceCreate failed");
38 | return status;
39 | }
40 |
41 | deviceContext = DeviceGetContext(device);
42 | RtlZeroMemory(deviceContext, sizeof(DEVICE_CONTEXT));
43 | KeInitializeSpinLock(&deviceContext->eventListLock);
44 | InitializeListHead(&deviceContext->eventList);
45 |
46 | status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_IVSHMEM, NULL);
47 |
48 | if (!NT_SUCCESS(status))
49 | {
50 | DEBUG_ERROR("%s", "Call to WdfDeviceCreateDeviceInterface failed");
51 | return status;
52 | }
53 |
54 | status = IVSHMEMQueueInitialize(device);
55 | if (!NT_SUCCESS(status))
56 | {
57 | DEBUG_ERROR("%s", "IVSHMEMQueueInitialize failed");
58 | return status;
59 | }
60 |
61 | return status;
62 | }
63 |
64 | PVOID IVSHMEMMmMapIoSpace(
65 | _In_ PHYSICAL_ADDRESS PhysicalAddress,
66 | _In_ SIZE_T NumberOfBytes
67 | )
68 | {
69 | typedef
70 | PVOID
71 | (*PFN_MM_MAP_IO_SPACE_EX) (
72 | _In_ PHYSICAL_ADDRESS PhysicalAddress,
73 | _In_ SIZE_T NumberOfBytes,
74 | _In_ ULONG Protect
75 | );
76 |
77 | UNICODE_STRING name;
78 | PFN_MM_MAP_IO_SPACE_EX pMmMapIoSpaceEx;
79 |
80 | RtlInitUnicodeString(&name, L"MmMapIoSpaceEx");
81 | pMmMapIoSpaceEx = (PFN_MM_MAP_IO_SPACE_EX) (ULONG_PTR)MmGetSystemRoutineAddress(&name);
82 |
83 | if (pMmMapIoSpaceEx != NULL){
84 | // Call WIN10 API if available
85 | return pMmMapIoSpaceEx(PhysicalAddress,
86 | NumberOfBytes,
87 | PAGE_READWRITE | PAGE_NOCACHE);
88 | }
89 |
90 | #pragma warning(suppress: 30029)
91 | return MmMapIoSpace(PhysicalAddress, NumberOfBytes, MmNonCached);
92 | }
93 |
94 |
95 | NTSTATUS IVSHMEMEvtDevicePrepareHardware(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesRaw, _In_ WDFCMRESLIST ResourcesTranslated)
96 | {
97 | PAGED_CODE();
98 | DEBUG_INFO("%s", __FUNCTION__);
99 | PDEVICE_CONTEXT deviceContext;
100 | deviceContext = DeviceGetContext(Device);
101 |
102 | #if (NTDDI_VERSION < NTDDI_WIN8)
103 | UNREFERENCED_PARAMETER(ResourcesRaw);
104 | #endif
105 | NTSTATUS result = STATUS_SUCCESS;
106 | int memIndex = 0;
107 |
108 | const ULONG resCount = WdfCmResourceListGetCount(ResourcesTranslated);
109 | for (ULONG i = 0; i < resCount; ++i)
110 | {
111 | PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
112 | descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
113 | if (!descriptor)
114 | {
115 | DEBUG_ERROR("%s", "Call to WdfCmResourceListGetDescriptor failed");
116 | return STATUS_DEVICE_CONFIGURATION_ERROR;
117 | }
118 |
119 | if (descriptor->Type == CmResourceTypeInterrupt && descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
120 | ++deviceContext->interruptCount;
121 | }
122 |
123 | if (deviceContext->interruptCount > 0)
124 | {
125 | deviceContext->interrupts = (WDFINTERRUPT*)ExAllocatePoolUninitialized(IVSHMEM_NONPAGED_POOL,
126 | sizeof(WDFINTERRUPT) * deviceContext->interruptCount, 'sQRI');
127 |
128 | if (!deviceContext->interrupts)
129 | {
130 | DEBUG_ERROR("Failed to allocate space for %d interrupts", deviceContext->interrupts);
131 | return STATUS_INSUFFICIENT_RESOURCES;
132 | }
133 | }
134 |
135 | for (ULONG i = 0; i < resCount; ++i)
136 | {
137 | PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
138 | descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
139 | if (!descriptor)
140 | {
141 | DEBUG_ERROR("%s", "Call to WdfCmResourceListGetDescriptor failed");
142 | return STATUS_DEVICE_CONFIGURATION_ERROR;
143 | }
144 |
145 | if (descriptor->Type == CmResourceTypeMemory)
146 | {
147 | // control registers
148 | if (memIndex == 0)
149 | {
150 | if (descriptor->u.Memory.Length != sizeof(IVSHMEMDeviceRegisters))
151 | {
152 | DEBUG_ERROR("Resource size was %u long when %u was expected",
153 | descriptor->u.Memory.Length, sizeof(IVSHMEMDeviceRegisters));
154 | result = STATUS_DEVICE_HARDWARE_ERROR;
155 | break;
156 | }
157 |
158 | deviceContext->devRegisters = (PIVSHMEMDeviceRegisters)IVSHMEMMmMapIoSpace(
159 | descriptor->u.Memory.Start,
160 | descriptor->u.Memory.Length);
161 |
162 | if (!deviceContext->devRegisters)
163 | {
164 | DEBUG_ERROR("%s", "Call to MmMapIoSpace failed");
165 | result = STATUS_DEVICE_HARDWARE_ERROR;
166 | break;
167 | }
168 | }
169 | else
170 | // shared memory resource
171 | if ((deviceContext->interruptCount == 0 && memIndex == 1) || memIndex == 2)
172 | {
173 | deviceContext->shmemAddr.PhysicalAddress = descriptor->u.Memory.Start;
174 | deviceContext->shmemAddr.NumberOfBytes = descriptor->u.Memory.Length;
175 | DEBUG_INFO("memIndex = %d pa = %llx (%llx) size = %lx (%lx)", memIndex, descriptor->u.Memory.Start.QuadPart, deviceContext->shmemAddr.PhysicalAddress.QuadPart, descriptor->u.Memory.Length, deviceContext->shmemAddr.NumberOfBytes);
176 |
177 | #if (NTDDI_VERSION >= NTDDI_WIN8)
178 | result = MmAllocateMdlForIoSpace(&deviceContext->shmemAddr, 1, &deviceContext->shmemMDL);
179 | #else
180 | deviceContext->shmemAddr.VirtualAddress = MmMapIoSpace(deviceContext->shmemAddr.PhysicalAddress, deviceContext->shmemAddr.NumberOfBytes, MmNonCached);
181 | if (deviceContext->shmemAddr.VirtualAddress) {
182 | deviceContext->shmemMDL = IoAllocateMdl(deviceContext->shmemAddr.VirtualAddress, (ULONG)deviceContext->shmemAddr.NumberOfBytes, FALSE, FALSE, NULL);
183 | if (!deviceContext->shmemMDL) {
184 | DEBUG_INFO("%s", "Call to IoAllocateMdl failed");
185 | result = STATUS_INSUFFICIENT_RESOURCES;
186 | }
187 |
188 | MmBuildMdlForNonPagedPool(deviceContext->shmemMDL);
189 | }
190 | else {
191 | DEBUG_INFO("%s", "Call to MmMapIoSpace failed");
192 | result = STATUS_INSUFFICIENT_RESOURCES;
193 | }
194 | #endif
195 | if (!NT_SUCCESS(result))
196 | {
197 | DEBUG_ERROR("%s", "Call to MmAllocateMdlForIoSpace failed");
198 | break;
199 | }
200 | }
201 | DEBUG_INFO("memIndex = %d va = %p mdl = %p", memIndex, deviceContext->shmemAddr.VirtualAddress, deviceContext->shmemMDL);
202 | ++memIndex;
203 | continue;
204 | }
205 |
206 | if (descriptor->Type == CmResourceTypeInterrupt &&
207 | (descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
208 | {
209 | WDF_INTERRUPT_CONFIG irqConfig;
210 | WDF_INTERRUPT_CONFIG_INIT(&irqConfig,
211 | IVSHMEMInterruptISR,
212 | IVSHMEMInterruptDPC);
213 | #if (NTDDI_VERSION >= NTDDI_WIN8)
214 | irqConfig.InterruptTranslated = descriptor;
215 | irqConfig.InterruptRaw = WdfCmResourceListGetDescriptor(ResourcesRaw, i);
216 | #endif
217 | NTSTATUS status = WdfInterruptCreate(Device, &irqConfig, WDF_NO_OBJECT_ATTRIBUTES,
218 | &deviceContext->interrupts[deviceContext->interruptsUsed]);
219 |
220 | if (!NT_SUCCESS(status))
221 | {
222 | DEBUG_ERROR("Call to WdfInterruptCreate failed: %08x", status);
223 | result = status;
224 | break;
225 | }
226 |
227 | if (++deviceContext->interruptsUsed == 65)
228 | DEBUG_INFO("%s", "This driver does not support > 64 interrupts, they will be ignored in the ISR.");
229 |
230 | continue;
231 | }
232 | }
233 |
234 | if (NT_SUCCESS(result))
235 | {
236 | if (!deviceContext->shmemMDL) {
237 | DEBUG_ERROR("%s", "shmemMDL == NULL");
238 | result = STATUS_DEVICE_HARDWARE_ERROR;
239 | }
240 | else
241 | {
242 | DEBUG_INFO("Shared Memory: %llx, %lx bytes", deviceContext->shmemAddr.PhysicalAddress.QuadPart, deviceContext->shmemAddr.NumberOfBytes);
243 | DEBUG_INFO("Interrupts : %d", deviceContext->interruptsUsed);
244 | }
245 | }
246 | DEBUG_INFO("%s result 0x%x", __FUNCTION__, result);
247 | return result;
248 | }
249 |
250 | NTSTATUS IVSHMEMEvtDeviceReleaseHardware(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesTranslated)
251 | {
252 | UNREFERENCED_PARAMETER(ResourcesTranslated);
253 | DEBUG_INFO("%s", __FUNCTION__);
254 |
255 | PDEVICE_CONTEXT deviceContext;
256 | deviceContext = DeviceGetContext(Device);
257 |
258 | if (deviceContext->devRegisters)
259 | {
260 | MmUnmapIoSpace(deviceContext->devRegisters, sizeof(PIVSHMEMDeviceRegisters));
261 | }
262 |
263 | if (deviceContext->shmemMap)
264 | {
265 | MmUnmapLockedPages(deviceContext->shmemMap, deviceContext->shmemMDL);
266 | deviceContext->shmemMap = NULL;
267 | }
268 |
269 | if (deviceContext->shmemMDL)
270 | {
271 | IoFreeMdl(deviceContext->shmemMDL);
272 | deviceContext->shmemMDL = NULL;
273 | }
274 |
275 | if (deviceContext->interrupts)
276 | {
277 | // WDFINTERRUPT objects are deleted by the framework
278 |
279 | ExFreePoolWithTag(deviceContext->interrupts, 'sQRI');
280 |
281 | deviceContext->interruptCount = 0;
282 | deviceContext->interruptsUsed = 0;
283 | deviceContext->interrupts = NULL;
284 | }
285 |
286 | KIRQL oldIRQL;
287 | KeAcquireSpinLock(&deviceContext->eventListLock, &oldIRQL);
288 | PLIST_ENTRY entry = deviceContext->eventList.Flink;
289 | while (entry != &deviceContext->eventList)
290 | {
291 | _Analysis_assume_(entry != NULL);
292 | PIVSHMEMEventListEntry event = CONTAINING_RECORD(entry, IVSHMEMEventListEntry, ListEntry);
293 | if (event->event)
294 | {
295 | ObDereferenceObject(event->event);
296 | }
297 | event->owner = NULL;
298 | event->event = NULL;
299 | event->vector = 0;
300 |
301 | entry = entry->Flink;
302 | }
303 | InitializeListHead(&deviceContext->eventList);
304 | deviceContext->eventBufferUsed = 0;
305 | KeReleaseSpinLock(&deviceContext->eventListLock, oldIRQL);
306 |
307 | return STATUS_SUCCESS;
308 | }
309 |
310 | NTSTATUS IVSHMEMEvtD0Entry(_In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE PreviousState)
311 | {
312 | UNREFERENCED_PARAMETER(Device);
313 | UNREFERENCED_PARAMETER(PreviousState);
314 | DEBUG_INFO("%s", __FUNCTION__);
315 | return STATUS_SUCCESS;
316 | }
317 |
318 | NTSTATUS IVSHMEMEvtD0Exit(_In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE PreviousState)
319 | {
320 | UNREFERENCED_PARAMETER(Device);
321 | UNREFERENCED_PARAMETER(PreviousState);
322 | PAGED_CODE();
323 | DEBUG_INFO("%s", __FUNCTION__);
324 | return STATUS_SUCCESS;
325 | }
326 |
327 | BOOLEAN IVSHMEMInterruptISR(_In_ WDFINTERRUPT Interrupt, _In_ ULONG MessageID)
328 | {
329 | WDFDEVICE device;
330 | PDEVICE_CONTEXT deviceContext;
331 |
332 | // out of range. if you have this many you're doing it wrong anyway
333 | if (MessageID > 64)
334 | return TRUE;
335 |
336 | device = WdfInterruptGetDevice(Interrupt);
337 | deviceContext = DeviceGetContext(device);
338 |
339 | if (!InterlockedOr64(&deviceContext->pendingISR, 1ULL << MessageID))
340 | WdfInterruptQueueDpcForIsr(Interrupt);
341 |
342 | return TRUE;
343 | }
344 |
345 | void IVSHMEMInterruptDPC(_In_ WDFINTERRUPT Interrupt, _In_ WDFOBJECT AssociatedObject)
346 | {
347 | UNREFERENCED_PARAMETER(AssociatedObject);
348 |
349 | WDFDEVICE device;
350 | PDEVICE_CONTEXT deviceContext;
351 | UINT64 pending;
352 |
353 | device = WdfInterruptGetDevice(Interrupt);
354 | deviceContext = DeviceGetContext(device);
355 |
356 | pending = InterlockedExchange64(&deviceContext->pendingISR, 0);
357 | if (!pending)
358 | return;
359 |
360 | KeAcquireSpinLockAtDpcLevel(&deviceContext->eventListLock);
361 | PLIST_ENTRY entry = deviceContext->eventList.Flink;
362 | while (entry != &deviceContext->eventList)
363 | {
364 | PIVSHMEMEventListEntry event = CONTAINING_RECORD(entry, IVSHMEMEventListEntry, ListEntry);
365 | PLIST_ENTRY next = entry->Flink;
366 | if (pending & ((LONG64)1 << event->vector))
367 | {
368 | _Analysis_assume_(event->event != NULL);
369 | KeSetEvent(event->event, 0, FALSE);
370 | if (event->singleShot)
371 | {
372 | RemoveEntryList(entry);
373 | ObDereferenceObjectDeferDelete(event->event);
374 | event->owner = NULL;
375 | event->event = NULL;
376 | event->vector = 0;
377 | --deviceContext->eventBufferUsed;
378 | }
379 | }
380 | entry = next;
381 | }
382 | KeReleaseSpinLockFromDpcLevel(&deviceContext->eventListLock);
383 | }
384 |
--------------------------------------------------------------------------------
/kernel/windows/Device.h:
--------------------------------------------------------------------------------
1 | #include "public.h"
2 |
3 | EXTERN_C_START
4 |
5 | #define MAX_EVENTS 32
6 |
7 | #pragma align(push,4)
8 | typedef struct IVSHMEMDeviceRegisters
9 | {
10 | volatile ULONG irqMask;
11 | volatile ULONG irqStatus;
12 | volatile LONG ivProvision;
13 | volatile ULONG doorbell;
14 | volatile UCHAR reserved[240];
15 | }
16 | IVSHMEMDeviceRegisters, *PIVSHMEMDeviceRegisters;
17 | #pragma align(pop)
18 |
19 | typedef struct IVSHMEMEventListEntry
20 | {
21 | WDFFILEOBJECT owner;
22 | UINT16 vector;
23 | PRKEVENT event;
24 | BOOLEAN singleShot;
25 | LIST_ENTRY ListEntry;
26 | }
27 | IVSHMEMEventListEntry, *PIVSHMEMEventListEntry;
28 |
29 | #if (NTDDI_VERSION < NTDDI_WIN8)
30 | typedef struct _MM_PHYSICAL_ADDRESS_LIST {
31 | PHYSICAL_ADDRESS PhysicalAddress;
32 | PVOID VirtualAddress;
33 | SIZE_T NumberOfBytes;
34 | } MM_PHYSICAL_ADDRESS_LIST, *PMM_PHYSICAL_ADDRESS_LIST;
35 | #endif
36 |
37 | typedef struct _DEVICE_CONTEXT
38 | {
39 | PIVSHMEMDeviceRegisters devRegisters; // the device registers (BAR0)
40 |
41 | MM_PHYSICAL_ADDRESS_LIST shmemAddr; // physical address of the shared memory (BAR2)
42 | PMDL shmemMDL; // memory discriptor list of the shared memory
43 | PVOID shmemMap; // memory mapping of the shared memory
44 | WDFFILEOBJECT owner; // the file object that currently owns the mapping
45 | UINT16 interruptCount; // the number of interrupt entries allocated
46 | UINT16 interruptsUsed; // the number of interrupt entries used
47 | WDFINTERRUPT *interrupts; // interrupts for this device
48 | LONG64 pendingISR; // flags for ISRs pending processing
49 |
50 | KSPIN_LOCK eventListLock; // spinlock for the below event list
51 | IVSHMEMEventListEntry eventBuffer[MAX_EVENTS]; // buffer of pre-allocated events
52 | UINT16 eventBufferUsed; // number of events currenty in use
53 | LIST_ENTRY eventList; // pending events to fire
54 | }
55 | DEVICE_CONTEXT, *PDEVICE_CONTEXT;
56 |
57 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, DeviceGetContext)
58 |
59 | NTSTATUS IVSHMEMCreateDevice(_Inout_ PWDFDEVICE_INIT DeviceInit);
60 |
61 | EVT_WDF_DEVICE_PREPARE_HARDWARE IVSHMEMEvtDevicePrepareHardware;
62 | EVT_WDF_DEVICE_RELEASE_HARDWARE IVSHMEMEvtDeviceReleaseHardware;
63 | EVT_WDF_DEVICE_D0_ENTRY IVSHMEMEvtD0Entry;
64 | EVT_WDF_DEVICE_D0_EXIT IVSHMEMEvtD0Exit;
65 | EVT_WDF_INTERRUPT_ISR IVSHMEMInterruptISR;
66 | EVT_WDF_INTERRUPT_DPC IVSHMEMInterruptDPC;
67 |
68 | EXTERN_C_END
69 |
--------------------------------------------------------------------------------
/kernel/windows/Driver.c:
--------------------------------------------------------------------------------
1 | #include "driver.h"
2 |
3 | #ifdef ALLOC_PRAGMA
4 | #pragma alloc_text (INIT, DriverEntry)
5 | #pragma alloc_text (PAGE, IVSHMEMEvtDeviceAdd)
6 | #pragma alloc_text (PAGE, IVSHMEMEvtDriverContextCleanup)
7 | #endif
8 |
9 | NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
10 | {
11 | WDF_DRIVER_CONFIG config;
12 | NTSTATUS status;
13 | WDF_OBJECT_ATTRIBUTES attributes;
14 |
15 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
16 | WDF_DRIVER_CONFIG_INIT(&config, IVSHMEMEvtDeviceAdd);
17 |
18 | status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, WDF_NO_HANDLE);
19 |
20 | return status;
21 | }
22 |
23 | NTSTATUS IVSHMEMEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
24 | {
25 | NTSTATUS status;
26 | UNREFERENCED_PARAMETER(Driver);
27 | PAGED_CODE();
28 |
29 | status = IVSHMEMCreateDevice(DeviceInit);
30 | return status;
31 | }
--------------------------------------------------------------------------------
/kernel/windows/Driver.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #if (NTDOI_VERSION >= NTDOI_WIN8)
6 | #define IVSHMEM_NONPAGED_POOL NonPagedPoolNx
7 | #else
8 | #define IVSHMEM_NONPAGED_POOL NonPagedPool
9 | #endif
10 |
11 | #include "device.h"
12 | #include "queue.h"
13 |
14 | // using error levels to avoid the debug print filter
15 | #define DEBUG_ERROR(fmt, ...) do { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[E:IVSHMEM] " fmt "\n", ## __VA_ARGS__)); } while (0)
16 | #define DEBUG_INFO(fmt, ...) do { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[I:IVSHMEM] " fmt "\n", ## __VA_ARGS__)); } while (0)
17 |
18 | EXTERN_C_START
19 |
20 | //
21 | // WDFDRIVER Events
22 | //
23 |
24 | DRIVER_INITIALIZE DriverEntry;
25 | EVT_WDF_DRIVER_DEVICE_ADD IVSHMEMEvtDeviceAdd;
26 | EVT_WDF_OBJECT_CONTEXT_CLEANUP IVSHMEMEvtDriverContextCleanup;
27 |
28 | EXTERN_C_END
29 |
--------------------------------------------------------------------------------
/kernel/windows/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2017-2022 Geoffrey McRae
2 | Copyright 2017-2022 Red Hat, Inc. and/or its affiliates.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright
12 | notice, this list of conditions and the following disclaimer in the
13 | documentation and/or other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/kernel/windows/Public.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | DEFINE_GUID (GUID_DEVINTERFACE_IVSHMEM,
4 | 0xdf576976,0x569d,0x4672,0x95,0xa0,0xf5,0x7e,0x4e,0xa0,0xb2,0x10);
5 | // {df576976-569d-4672-95a0-f57e4ea0b210}
6 |
7 | typedef UINT16 IVSHMEM_PEERID;
8 | typedef UINT64 IVSHMEM_SIZE;
9 |
10 | #define IVSHMEM_CACHE_NONCACHED 0
11 | #define IVSHMEM_CACHE_CACHED 1
12 | #define IVSHMEM_CACHE_WRITECOMBINED 2
13 |
14 | /*
15 | This structure is for use with the IOCTL_IVSHMEM_REQUEST_MMAP IOCTL
16 | */
17 | typedef struct IVSHMEM_MMAP_CONFIG
18 | {
19 | UINT8 cacheMode; // the caching mode of the mapping, see IVSHMEM_CACHE_* for options
20 | }
21 | IVSHMEM_MMAP_CONFIG, *PIVSHMEM_MMAP_CONFIG;
22 |
23 | /*
24 | This structure is for use with the IOCTL_IVSHMEM_REQUEST_MMAP IOCTL
25 | */
26 | typedef struct IVSHMEM_MMAP
27 | {
28 | IVSHMEM_PEERID peerID; // our peer id
29 | IVSHMEM_SIZE size; // the size of the memory region
30 | PVOID ptr; // pointer to the memory region
31 | UINT16 vectors; // the number of vectors available
32 | }
33 | IVSHMEM_MMAP, *PIVSHMEM_MMAP;
34 |
35 | /*
36 | This structure is for use with the IOCTL_IVSHMEM_RING_DOORBELL IOCTL
37 | */
38 | typedef struct IVSHMEM_RING
39 | {
40 | IVSHMEM_PEERID peerID; // the id of the peer to ring
41 | UINT16 vector; // the doorbell to ring
42 | }
43 | IVSHMEM_RING, *PIVSHMEM_RING;
44 |
45 | /*
46 | This structure is for use with the IOCTL_IVSHMEM_REGISTER_EVENT IOCTL
47 |
48 | Please Note:
49 | - The IVSHMEM driver has a hard limit of 32 events.
50 | - Events that are singleShot are released after they have been set.
51 | - At this time repeating events are only released when the driver device
52 | handle is closed, closing the event handle doesn't release it from the
53 | drivers list. While this won't cause a problem in the driver, it will
54 | cause you to run out of event slots.
55 | */
56 | typedef struct IVSHMEM_EVENT
57 | {
58 | UINT16 vector; // the vector that triggers the event
59 | HANDLE event; // the event to trigger
60 | BOOLEAN singleShot; // set to TRUE if you want the driver to only trigger this event once
61 | }
62 | IVSHMEM_EVENT, *PIVSHMEM_EVENT;
63 |
64 | #define IOCTL_IVSHMEM_REQUEST_PEERID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
65 | #define IOCTL_IVSHMEM_REQUEST_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
66 | #define IOCTL_IVSHMEM_REQUEST_MMAP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
67 | #define IOCTL_IVSHMEM_RELEASE_MMAP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
68 | #define IOCTL_IVSHMEM_RING_DOORBELL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
69 | #define IOCTL_IVSHMEM_REGISTER_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)
70 | #define IOCTL_IVSHMEM_REQUEST_KMAP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)
71 |
--------------------------------------------------------------------------------
/kernel/windows/Queue.c:
--------------------------------------------------------------------------------
1 | #include "driver.h"
2 |
3 | #ifdef ALLOC_PRAGMA
4 | #pragma alloc_text (PAGE, IVSHMEMQueueInitialize)
5 | #endif
6 |
7 | #ifdef _WIN64
8 | // 32bit struct for when a 32bit application sends IOCTL codes
9 | typedef struct IVSHMEM_MMAP32
10 | {
11 | IVSHMEM_PEERID peerID; // our peer id
12 | IVSHMEM_SIZE size; // the size of the memory region
13 | UINT32 ptr; // pointer to the memory region
14 | UINT16 vectors; // the number of vectors available
15 | }
16 | IVSHMEM_MMAP32, *PIVSHMEM_MMAP32;
17 | #endif
18 |
19 | // Forwards
20 | static NTSTATUS ioctl_request_peerid(
21 | const PDEVICE_CONTEXT DeviceContext,
22 | const size_t OutputBufferLength,
23 | const WDFREQUEST Request,
24 | size_t * BytesReturned
25 | );
26 |
27 | static NTSTATUS ioctl_request_size(
28 | const PDEVICE_CONTEXT DeviceContext,
29 | const size_t OutputBufferLength,
30 | const WDFREQUEST Request,
31 | size_t * BytesReturned
32 | );
33 |
34 | static NTSTATUS ioctl_request_mmap(
35 | const PDEVICE_CONTEXT DeviceContext,
36 | const size_t InputBufferLength,
37 | const size_t OutputBufferLength,
38 | const WDFREQUEST Request,
39 | size_t * BytesReturned,
40 | BOOLEAN ForKernel
41 | );
42 |
43 | static NTSTATUS ioctl_release_mmap(
44 | const PDEVICE_CONTEXT DeviceContext,
45 | const WDFREQUEST Request,
46 | size_t * BytesReturned
47 | );
48 |
49 | static NTSTATUS ioctl_ring_doorbell(
50 | const PDEVICE_CONTEXT DeviceContext,
51 | const size_t InputBufferLength,
52 | const WDFREQUEST Request,
53 | size_t * BytesReturned
54 | );
55 |
56 | static NTSTATUS ioctl_register_event(
57 | const PDEVICE_CONTEXT DeviceContext,
58 | const size_t InputBufferLength,
59 | const WDFREQUEST Request,
60 | size_t * BytesReturned
61 | );
62 |
63 | NTSTATUS IVSHMEMQueueInitialize(_In_ WDFDEVICE Device)
64 | {
65 | WDFQUEUE queue;
66 | NTSTATUS status;
67 | WDF_IO_QUEUE_CONFIG queueConfig;
68 |
69 | PAGED_CODE();
70 |
71 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential);
72 | queueConfig.EvtIoDeviceControl = IVSHMEMEvtIoDeviceControl;
73 | queueConfig.EvtIoStop = IVSHMEMEvtIoStop;
74 |
75 | status = WdfIoQueueCreate(Device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
76 | return status;
77 | }
78 |
79 | VOID
80 | IVSHMEMEvtIoDeviceControl(
81 | _In_ WDFQUEUE Queue,
82 | _In_ WDFREQUEST Request,
83 | _In_ size_t OutputBufferLength,
84 | _In_ size_t InputBufferLength,
85 | _In_ ULONG IoControlCode
86 | )
87 | {
88 | WDFDEVICE hDevice = WdfIoQueueGetDevice(Queue);
89 | PDEVICE_CONTEXT deviceContext = DeviceGetContext(hDevice);
90 | size_t bytesReturned = 0;
91 |
92 | // revision 0 devices have to wait until the shared memory has been provided to the vm
93 | if (deviceContext->devRegisters->ivProvision < 0)
94 | {
95 | DEBUG_INFO("Device not ready yet, ivProvision = %d", deviceContext->devRegisters->ivProvision);
96 | WdfRequestCompleteWithInformation(Request, STATUS_DEVICE_NOT_READY, 0);
97 | return;
98 | }
99 |
100 | NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
101 | switch (IoControlCode)
102 | {
103 | case IOCTL_IVSHMEM_REQUEST_PEERID:
104 | status = ioctl_request_peerid(deviceContext, OutputBufferLength, Request, &bytesReturned);
105 | break;
106 |
107 | case IOCTL_IVSHMEM_REQUEST_SIZE:
108 | status = ioctl_request_size(deviceContext, OutputBufferLength, Request, &bytesReturned);
109 | break;
110 |
111 | case IOCTL_IVSHMEM_REQUEST_MMAP:
112 | status = ioctl_request_mmap(deviceContext, InputBufferLength, OutputBufferLength, Request, &bytesReturned, FALSE);
113 | break;
114 | case IOCTL_IVSHMEM_REQUEST_KMAP:
115 | status = ioctl_request_mmap(deviceContext, InputBufferLength, OutputBufferLength, Request, &bytesReturned, TRUE);
116 | break;
117 | case IOCTL_IVSHMEM_RELEASE_MMAP:
118 | status = ioctl_release_mmap(deviceContext, Request, &bytesReturned);
119 | break;
120 |
121 | case IOCTL_IVSHMEM_RING_DOORBELL:
122 | status = ioctl_ring_doorbell(deviceContext, InputBufferLength, Request, &bytesReturned);
123 | break;
124 |
125 | case IOCTL_IVSHMEM_REGISTER_EVENT:
126 | status = ioctl_register_event(deviceContext, InputBufferLength, Request, &bytesReturned);
127 | break;
128 | }
129 |
130 | WdfRequestCompleteWithInformation(Request, status, bytesReturned);
131 | }
132 |
133 | VOID
134 | IVSHMEMEvtIoStop(
135 | _In_ WDFQUEUE Queue,
136 | _In_ WDFREQUEST Request,
137 | _In_ ULONG ActionFlags
138 | )
139 | {
140 | UNREFERENCED_PARAMETER(Queue);
141 | UNREFERENCED_PARAMETER(ActionFlags);
142 | WdfRequestStopAcknowledge(Request, TRUE);
143 | return;
144 | }
145 |
146 | VOID IVSHMEMEvtDeviceFileCleanup(_In_ WDFFILEOBJECT FileObject)
147 | {
148 | PDEVICE_CONTEXT deviceContext = DeviceGetContext(WdfFileObjectGetDevice(FileObject));
149 |
150 | // remove queued events that belonged to the session
151 | KIRQL oldIRQL;
152 | KeAcquireSpinLock(&deviceContext->eventListLock, &oldIRQL);
153 | PLIST_ENTRY entry = deviceContext->eventList.Flink;
154 | while (entry != &deviceContext->eventList)
155 | {
156 | _Analysis_assume_(entry != NULL);
157 | PIVSHMEMEventListEntry event = CONTAINING_RECORD(entry, IVSHMEMEventListEntry, ListEntry);
158 | if (event->owner != FileObject)
159 | {
160 | entry = entry->Flink;
161 | continue;
162 | }
163 |
164 | PLIST_ENTRY next = entry->Flink;
165 | RemoveEntryList(entry);
166 | ObDereferenceObject(event->event);
167 | event->owner = NULL;
168 | event->event = NULL;
169 | event->vector = 0;
170 | --deviceContext->eventBufferUsed;
171 | entry = next;
172 | }
173 | KeReleaseSpinLock(&deviceContext->eventListLock, oldIRQL);
174 |
175 | if (!deviceContext->shmemMap)
176 | return;
177 |
178 | if (deviceContext->owner != FileObject)
179 | return;
180 |
181 | MmUnmapLockedPages(deviceContext->shmemMap, deviceContext->shmemMDL);
182 | deviceContext->shmemMap = NULL;
183 | deviceContext->owner = NULL;
184 | }
185 |
186 | static NTSTATUS ioctl_request_peerid(
187 | const PDEVICE_CONTEXT DeviceContext,
188 | const size_t OutputBufferLength,
189 | const WDFREQUEST Request,
190 | size_t * BytesReturned
191 | )
192 | {
193 | if (OutputBufferLength != sizeof(IVSHMEM_PEERID))
194 | {
195 | DEBUG_ERROR("IOCTL_IVSHMEM_REQUEST_PEERID: Invalid size, expected %u but got %u", sizeof(IVSHMEM_PEERID), OutputBufferLength);
196 | return STATUS_INVALID_BUFFER_SIZE;
197 | }
198 |
199 | IVSHMEM_PEERID *out = NULL;
200 | if (!NT_SUCCESS(WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, (PVOID *)&out, NULL)))
201 | {
202 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REQUEST_PEERID: Failed to retrieve the output buffer");
203 | return STATUS_INVALID_USER_BUFFER;
204 | }
205 |
206 | *out = (IVSHMEM_PEERID)DeviceContext->devRegisters->ivProvision;
207 | *BytesReturned = sizeof(IVSHMEM_PEERID);
208 | return STATUS_SUCCESS;
209 | }
210 |
211 | static NTSTATUS ioctl_request_size(
212 | const PDEVICE_CONTEXT DeviceContext,
213 | const size_t OutputBufferLength,
214 | const WDFREQUEST Request,
215 | size_t * BytesReturned
216 | )
217 | {
218 | if (OutputBufferLength != sizeof(IVSHMEM_SIZE))
219 | {
220 | DEBUG_ERROR("IOCTL_IVSHMEM_REQUEST_SIZE: Invalid size, expected %u but got %u", sizeof(IVSHMEM_SIZE), OutputBufferLength);
221 | return STATUS_INVALID_BUFFER_SIZE;
222 | }
223 |
224 | IVSHMEM_SIZE *out = NULL;
225 | if (!NT_SUCCESS(WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, (PVOID *)&out, NULL)))
226 | {
227 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REQUEST_SIZE: Failed to retrieve the output buffer");
228 | return STATUS_INVALID_USER_BUFFER;
229 | }
230 |
231 | *out = DeviceContext->shmemAddr.NumberOfBytes;
232 | *BytesReturned = sizeof(IVSHMEM_SIZE);
233 | return STATUS_SUCCESS;
234 | }
235 |
236 | static NTSTATUS ioctl_request_mmap(
237 | const PDEVICE_CONTEXT DeviceContext,
238 | const size_t InputBufferLength,
239 | const size_t OutputBufferLength,
240 | const WDFREQUEST Request,
241 | size_t * BytesReturned,
242 | BOOLEAN ForKernel
243 | )
244 | {
245 | // only one mapping at a time is allowed
246 | // if (DeviceContext->shmemMap)
247 | // return STATUS_DEVICE_ALREADY_ATTACHED;
248 |
249 | if (InputBufferLength != sizeof(IVSHMEM_MMAP_CONFIG))
250 | {
251 | DEBUG_ERROR("IOCTL_IVSHMEM_MMAP: Invalid input size, expected %u but got %u", sizeof(IVSHMEM_MMAP_CONFIG), InputBufferLength);
252 | return STATUS_INVALID_BUFFER_SIZE;
253 | }
254 |
255 | PIVSHMEM_MMAP_CONFIG in;
256 | if (!NT_SUCCESS(WdfRequestRetrieveInputBuffer(Request, InputBufferLength, (PVOID)&in, NULL)))
257 | {
258 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_MMAP: Failed to retrieve the input buffer");
259 | return STATUS_INVALID_USER_BUFFER;
260 | }
261 |
262 | MEMORY_CACHING_TYPE cacheType;
263 | switch (in->cacheMode)
264 | {
265 | case IVSHMEM_CACHE_NONCACHED : cacheType = MmNonCached ; break;
266 | case IVSHMEM_CACHE_CACHED : cacheType = MmCached ; break;
267 | case IVSHMEM_CACHE_WRITECOMBINED: cacheType = MmWriteCombined; break;
268 | default:
269 | DEBUG_ERROR("IOCTL_IVSHMEM_MMAP: Invalid cache mode: %u", in->cacheMode);
270 | return STATUS_INVALID_PARAMETER;
271 | }
272 |
273 | #ifdef _WIN64
274 | PIRP irp = WdfRequestWdmGetIrp(Request);
275 | const BOOLEAN is32Bit = IoIs32bitProcess(irp);
276 | const size_t bufferLen = is32Bit ? sizeof(IVSHMEM_MMAP32) : sizeof(IVSHMEM_MMAP);
277 | #else
278 | const size_t bufferLen = sizeof(IVSHMEM_MMAP);
279 | #endif
280 | PVOID buffer;
281 |
282 | if (OutputBufferLength != bufferLen)
283 | {
284 | DEBUG_ERROR("IOCTL_IVSHMEM_REQUEST_MMAP: Invalid size, expected %u but got %u", bufferLen, OutputBufferLength);
285 | return STATUS_INVALID_BUFFER_SIZE;
286 | }
287 |
288 | if (!NT_SUCCESS(WdfRequestRetrieveOutputBuffer(Request, bufferLen, (PVOID *)&buffer, NULL)))
289 | {
290 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REQUEST_MMAP: Failed to retrieve the output buffer");
291 | return STATUS_INVALID_USER_BUFFER;
292 | }
293 |
294 | __try
295 | {
296 | DeviceContext->shmemMap = MmMapLockedPagesSpecifyCache(
297 | DeviceContext->shmemMDL,
298 | ForKernel ? KernelMode : UserMode,
299 | cacheType,
300 | NULL,
301 | FALSE,
302 | NormalPagePriority | MdlMappingNoExecute
303 | );
304 | }
305 | __except (EXCEPTION_EXECUTE_HANDLER)
306 | {
307 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REQUEST_MMAP: Exception trying to map pages");
308 | return STATUS_DRIVER_INTERNAL_ERROR;
309 | }
310 |
311 | if (!DeviceContext->shmemMap)
312 | {
313 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REQUEST_MMAP: shmemMap is NULL");
314 | return STATUS_DRIVER_INTERNAL_ERROR;
315 | }
316 |
317 | DeviceContext->owner = WdfRequestGetFileObject(Request);
318 | #ifdef _WIN64
319 | if (is32Bit)
320 | {
321 | PIVSHMEM_MMAP32 out = (PIVSHMEM_MMAP32)buffer;
322 | out->peerID = (UINT16)DeviceContext->devRegisters->ivProvision;
323 | out->size = (UINT64)DeviceContext->shmemAddr.NumberOfBytes;
324 | out->ptr = PtrToUint(DeviceContext->shmemMap);
325 | out->vectors = DeviceContext->interruptsUsed;
326 | }
327 | else
328 | #endif
329 | {
330 | PIVSHMEM_MMAP out = (PIVSHMEM_MMAP)buffer;
331 | out->peerID = (UINT16)DeviceContext->devRegisters->ivProvision;
332 | out->size = (UINT64)DeviceContext->shmemAddr.NumberOfBytes;
333 | out->ptr = DeviceContext->shmemMap;
334 | out->vectors = DeviceContext->interruptsUsed;
335 | }
336 |
337 | *BytesReturned = bufferLen;
338 | return STATUS_SUCCESS;
339 | }
340 |
341 | static NTSTATUS ioctl_release_mmap(
342 | const PDEVICE_CONTEXT DeviceContext,
343 | const WDFREQUEST Request,
344 | size_t * BytesReturned
345 | )
346 | {
347 | // ensure the mapping exists
348 | if (!DeviceContext->shmemMap)
349 | {
350 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_RELEASE_MMAP: not mapped");
351 | return STATUS_INVALID_DEVICE_REQUEST;
352 | }
353 |
354 | // ensure someone else other then the owner doesn't attempt to release the mapping
355 | if (DeviceContext->owner != WdfRequestGetFileObject(Request))
356 | {
357 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_RELEASE_MMAP: Invalid owner");
358 | return STATUS_INVALID_HANDLE;
359 | }
360 |
361 | MmUnmapLockedPages(DeviceContext->shmemMap, DeviceContext->shmemMDL);
362 | DeviceContext->shmemMap = NULL;
363 | DeviceContext->owner = NULL;
364 | *BytesReturned = 0;
365 | return STATUS_SUCCESS;
366 | }
367 |
368 | static NTSTATUS ioctl_ring_doorbell(
369 | const PDEVICE_CONTEXT DeviceContext,
370 | const size_t InputBufferLength,
371 | const WDFREQUEST Request,
372 | size_t * BytesReturned
373 | )
374 | {
375 | // ensure someone else other then the owner doesn't attempt to trigger IRQs
376 | if (DeviceContext->owner != WdfRequestGetFileObject(Request))
377 | {
378 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_RING_DOORBELL: Invalid owner");
379 | return STATUS_INVALID_HANDLE;
380 | }
381 |
382 | if (InputBufferLength != sizeof(IVSHMEM_RING))
383 | {
384 | DEBUG_ERROR("IOCTL_IVSHMEM_RING_DOORBELL: Invalid size, expected %u but got %u", sizeof(IVSHMEM_RING), InputBufferLength);
385 | return STATUS_INVALID_BUFFER_SIZE;
386 | }
387 |
388 | PIVSHMEM_RING in;
389 | if (!NT_SUCCESS(WdfRequestRetrieveInputBuffer(Request, InputBufferLength, (PVOID)&in, NULL)))
390 | {
391 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_RING_DOORBELL: Failed to retrieve the input buffer");
392 | return STATUS_INVALID_USER_BUFFER;
393 | }
394 |
395 | WRITE_REGISTER_ULONG(
396 | &DeviceContext->devRegisters->doorbell,
397 | (ULONG)in->vector | ((ULONG)in->peerID << 16));
398 |
399 | *BytesReturned = 0;
400 | return STATUS_SUCCESS;
401 | }
402 |
403 | static NTSTATUS ioctl_register_event(
404 | const PDEVICE_CONTEXT DeviceContext,
405 | const size_t InputBufferLength,
406 | const WDFREQUEST Request,
407 | size_t * BytesReturned
408 | )
409 | {
410 | // ensure someone else other then the owner isn't attempting to register events
411 | if (DeviceContext->owner != WdfRequestGetFileObject(Request))
412 | {
413 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REGISTER_EVENT: Invalid owner");
414 | return STATUS_INVALID_HANDLE;
415 | }
416 |
417 | if (InputBufferLength != sizeof(IVSHMEM_EVENT))
418 | {
419 | DEBUG_ERROR("IOCTL_IVSHMEM_REGISTER_EVENT: Invalid size, expected %u but got %u", sizeof(PIVSHMEM_EVENT), InputBufferLength);
420 | return STATUS_INVALID_BUFFER_SIZE;
421 | }
422 |
423 | // early non locked quick check to see if we are out of event space
424 | if (DeviceContext->eventBufferUsed == MAX_EVENTS)
425 | {
426 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REGISTER_EVENT: Event buffer full");
427 | return STATUS_INSUFFICIENT_RESOURCES;
428 | }
429 |
430 | PIVSHMEM_EVENT in;
431 | if (!NT_SUCCESS(WdfRequestRetrieveInputBuffer(Request, InputBufferLength, (PVOID)&in, NULL)))
432 | {
433 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REGISTER_EVENT: Failed to retrieve the input buffer");
434 | return STATUS_INVALID_USER_BUFFER;
435 | }
436 |
437 | PRKEVENT hObject;
438 | if (!NT_SUCCESS(ObReferenceObjectByHandle(
439 | in->event,
440 | SYNCHRONIZE | EVENT_MODIFY_STATE,
441 | *ExEventObjectType,
442 | UserMode,
443 | &hObject,
444 | NULL)))
445 | {
446 | DEBUG_ERROR("%s", "Unable to reference user-mode event object");
447 | return STATUS_INVALID_HANDLE;
448 | }
449 |
450 | // clear the event in case the caller didn't think to
451 | KeClearEvent(hObject);
452 |
453 | // lock the event list so we can push the new entry into it
454 | KIRQL oldIRQL;
455 | KeAcquireSpinLock(&DeviceContext->eventListLock, &oldIRQL);
456 | {
457 | // check again if there is space before we search as we now hold the lock
458 | if (DeviceContext->eventBufferUsed == MAX_EVENTS)
459 | {
460 | KeReleaseSpinLock(&DeviceContext->eventListLock, oldIRQL);
461 |
462 | DEBUG_ERROR("%s", "IOCTL_IVSHMEM_REGISTER_EVENT: Event buffer full");
463 | ObDereferenceObject(hObject);
464 | return STATUS_INSUFFICIENT_RESOURCES;
465 | }
466 |
467 | // look for a free slot
468 | BOOLEAN done = FALSE;
469 | for (UINT16 i = 0; i < MAX_EVENTS; ++i)
470 | {
471 | PIVSHMEMEventListEntry event = &DeviceContext->eventBuffer[i];
472 | if (event->event != NULL)
473 | continue;
474 |
475 | // found one, assign the event to it and add it to the list
476 | event->owner = WdfRequestGetFileObject(Request);
477 | event->event = hObject;
478 | event->vector = in->vector;
479 | event->singleShot = in->singleShot;
480 | ++DeviceContext->eventBufferUsed;
481 | InsertTailList(&DeviceContext->eventList, &event->ListEntry);
482 | done = TRUE;
483 | break;
484 | }
485 |
486 | // this should never occur, if it does it indicates memory corruption
487 | if (!done)
488 | {
489 | DEBUG_ERROR(
490 | "IOCTL_IVSHMEM_REGISTER_EVENT: deviceContext->eventBufferUsed (%u) < MAX_EVENTS (%u) but no slots found!",
491 | DeviceContext->eventBufferUsed, MAX_EVENTS);
492 | KeBugCheckEx(CRITICAL_STRUCTURE_CORRUPTION, 0, 0, 0, 0x1C);
493 | }
494 | }
495 | KeReleaseSpinLock(&DeviceContext->eventListLock, oldIRQL);
496 |
497 | *BytesReturned = 0;
498 | return STATUS_SUCCESS;
499 | }
500 |
--------------------------------------------------------------------------------
/kernel/windows/Queue.h:
--------------------------------------------------------------------------------
1 | EXTERN_C_START
2 |
3 | NTSTATUS IVSHMEMQueueInitialize(_In_ WDFDEVICE Device);
4 |
5 | EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL IVSHMEMEvtIoDeviceControl;
6 | EVT_WDF_IO_QUEUE_IO_STOP IVSHMEMEvtIoStop;
7 | EVT_WDF_FILE_CLEANUP IVSHMEMEvtDeviceFileCleanup;
8 |
9 | EXTERN_C_END
10 |
--------------------------------------------------------------------------------
/kernel/windows/findwdk/FindWdk.cmake:
--------------------------------------------------------------------------------
1 | # Redistribution and use is allowed under the OSI-approved 3-clause BSD license.
2 | # Copyright (c) 2018 Sergey Podobry (sergey.podobry at gmail.com). All rights reserved.
3 |
4 | #.rst:
5 | # FindWDK
6 | # ----------
7 | #
8 | # This module searches for the installed Windows Development Kit (WDK) and
9 | # exposes commands for creating kernel drivers and kernel libraries.
10 | #
11 | # Output variables:
12 | # - `WDK_FOUND` -- if false, do not try to use WDK
13 | # - `WDK_ROOT` -- where WDK is installed
14 | # - `WDK_VERSION` -- the version of the selected WDK
15 | # - `WDK_WINVER` -- the WINVER used for kernel drivers and libraries
16 | # (default value is `0x0601` and can be changed per target or globally)
17 | # - `WDK_NTDDI_VERSION` -- the NTDDI_VERSION used for kernel drivers and libraries,
18 | # if not set, the value will be automatically calculated by WINVER
19 | # (default value is left blank and can be changed per target or globally)
20 | #
21 | # Example usage:
22 | #
23 | # find_package(WDK REQUIRED)
24 | #
25 | # wdk_add_library(KmdfCppLib STATIC KMDF 1.15
26 | # KmdfCppLib.h
27 | # KmdfCppLib.cpp
28 | # )
29 | # target_include_directories(KmdfCppLib INTERFACE .)
30 | #
31 | # wdk_add_driver(KmdfCppDriver KMDF 1.15
32 | # Main.cpp
33 | # )
34 | # target_link_libraries(KmdfCppDriver KmdfCppLib)
35 | #
36 |
37 | if(DEFINED ENV{WDKContentRoot})
38 | file(GLOB WDK_NTDDK_FILES
39 | "$ENV{WDKContentRoot}/Include/*/km/ntddk.h" # WDK 10
40 | "$ENV{WDKContentRoot}/Include/km/ntddk.h" # WDK 8.0, 8.1
41 | )
42 | else()
43 | file(GLOB WDK_NTDDK_FILES
44 | "C:/Program Files*/Windows Kits/*/Include/*/km/ntddk.h" # WDK 10
45 | "C:/Program Files*/Windows Kits/*/Include/km/ntddk.h" # WDK 8.0, 8.1
46 | )
47 | endif()
48 |
49 | if(WDK_NTDDK_FILES)
50 | if (NOT CMAKE_VERSION VERSION_LESS 3.18.0)
51 | list(SORT WDK_NTDDK_FILES COMPARE NATURAL) # sort to use the latest available WDK
52 | endif()
53 | list(GET WDK_NTDDK_FILES -1 WDK_LATEST_NTDDK_FILE)
54 | endif()
55 |
56 | include(FindPackageHandleStandardArgs)
57 | find_package_handle_standard_args(WDK REQUIRED_VARS WDK_LATEST_NTDDK_FILE)
58 |
59 | if (NOT WDK_LATEST_NTDDK_FILE)
60 | return()
61 | endif()
62 |
63 | get_filename_component(WDK_ROOT ${WDK_LATEST_NTDDK_FILE} DIRECTORY)
64 | get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY)
65 | get_filename_component(WDK_VERSION ${WDK_ROOT} NAME)
66 | get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY)
67 | if (NOT WDK_ROOT MATCHES ".*/[0-9][0-9.]*$") # WDK 10 has a deeper nesting level
68 | get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY) # go up once more
69 | set(WDK_LIB_VERSION "${WDK_VERSION}")
70 | set(WDK_INC_VERSION "${WDK_VERSION}")
71 | else() # WDK 8.0, 8.1
72 | set(WDK_INC_VERSION "")
73 | foreach(VERSION winv6.3 win8 win7)
74 | if (EXISTS "${WDK_ROOT}/Lib/${VERSION}/")
75 | set(WDK_LIB_VERSION "${VERSION}")
76 | break()
77 | endif()
78 | endforeach()
79 | set(WDK_VERSION "${WDK_LIB_VERSION}")
80 | endif()
81 |
82 | message(STATUS "WDK_ROOT: " ${WDK_ROOT})
83 | message(STATUS "WDK_VERSION: " ${WDK_VERSION})
84 |
85 | set(WDK_WINVER "0x0601" CACHE STRING "Default WINVER for WDK targets")
86 | set(WDK_NTDDI_VERSION "" CACHE STRING "Specified NTDDI_VERSION for WDK targets if needed")
87 |
88 | set(WDK_ADDITIONAL_FLAGS_FILE "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/wdkflags.h")
89 | file(WRITE ${WDK_ADDITIONAL_FLAGS_FILE} "#pragma runtime_checks(\"suc\", off)")
90 |
91 | set(WDK_COMPILE_FLAGS
92 | "/Zp8" # set struct alignment
93 | "/GF" # enable string pooling
94 | "/GR-" # disable RTTI
95 | "/Gz" # __stdcall by default
96 | "/kernel" # create kernel mode binary
97 | "/FIwarning.h" # disable warnings in WDK headers
98 | "/FI${WDK_ADDITIONAL_FLAGS_FILE}" # include file to disable RTC
99 | )
100 |
101 | set(WDK_COMPILE_DEFINITIONS "WINNT=1")
102 | set(WDK_COMPILE_DEFINITIONS_DEBUG "MSC_NOOPT;DEPRECATE_DDK_FUNCTIONS=1;DBG=1")
103 |
104 | if(CMAKE_SIZEOF_VOID_P EQUAL 4)
105 | list(APPEND WDK_COMPILE_DEFINITIONS "_X86_=1;i386=1;STD_CALL")
106 | set(WDK_PLATFORM "x86")
107 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
108 | list(APPEND WDK_COMPILE_DEFINITIONS "_WIN64;_AMD64_;AMD64")
109 | set(WDK_PLATFORM "x64")
110 | else()
111 | message(FATAL_ERROR "Unsupported architecture")
112 | endif()
113 |
114 | string(CONCAT WDK_LINK_FLAGS
115 | "/MANIFEST:NO " #
116 | "/DRIVER " #
117 | "/OPT:REF " #
118 | "/INCREMENTAL:NO " #
119 | "/OPT:ICF " #
120 | "/SUBSYSTEM:NATIVE " #
121 | "/MERGE:_TEXT=.text;_PAGE=PAGE " #
122 | "/NODEFAULTLIB " # do not link default CRT
123 | "/SECTION:INIT,d " #
124 | "/VERSION:10.0 " #
125 | )
126 |
127 | # Generate imported targets for WDK lib files
128 | file(GLOB WDK_LIBRARIES "${WDK_ROOT}/Lib/${WDK_LIB_VERSION}/km/${WDK_PLATFORM}/*.lib")
129 | foreach(LIBRARY IN LISTS WDK_LIBRARIES)
130 | get_filename_component(LIBRARY_NAME ${LIBRARY} NAME_WE)
131 | string(TOUPPER ${LIBRARY_NAME} LIBRARY_NAME)
132 | add_library(WDK::${LIBRARY_NAME} INTERFACE IMPORTED)
133 | set_property(TARGET WDK::${LIBRARY_NAME} PROPERTY INTERFACE_LINK_LIBRARIES ${LIBRARY})
134 | endforeach(LIBRARY)
135 | unset(WDK_LIBRARIES)
136 |
137 | function(wdk_add_driver _target)
138 | cmake_parse_arguments(WDK "" "KMDF;WINVER;NTDDI_VERSION" "" ${ARGN})
139 |
140 | add_executable(${_target} ${WDK_UNPARSED_ARGUMENTS})
141 |
142 | set_target_properties(${_target} PROPERTIES SUFFIX ".sys")
143 | set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${WDK_COMPILE_FLAGS}")
144 | set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS
145 | "${WDK_COMPILE_DEFINITIONS};$<$:${WDK_COMPILE_DEFINITIONS_DEBUG}>;_WIN32_WINNT=${WDK_WINVER}"
146 | )
147 | set_target_properties(${_target} PROPERTIES LINK_FLAGS "${WDK_LINK_FLAGS}")
148 | if(WDK_NTDDI_VERSION)
149 | target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION})
150 | endif()
151 |
152 | target_include_directories(${_target} SYSTEM PRIVATE
153 | "${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared"
154 | "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km"
155 | "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt"
156 | )
157 |
158 | target_link_libraries(${_target} WDK::NTOSKRNL WDK::HAL WDK::BUFFEROVERFLOWK WDK::WMILIB)
159 |
160 | if(CMAKE_SIZEOF_VOID_P EQUAL 4)
161 | target_link_libraries(${_target} WDK::MEMCMP)
162 | endif()
163 |
164 | if(DEFINED WDK_KMDF)
165 | target_include_directories(${_target} SYSTEM PRIVATE "${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}")
166 | target_link_libraries(${_target}
167 | "${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfDriverEntry.lib"
168 | "${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfLdr.lib"
169 | )
170 |
171 | if(CMAKE_SIZEOF_VOID_P EQUAL 4)
172 | set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:FxDriverEntry@8")
173 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
174 | set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:FxDriverEntry")
175 | endif()
176 | else()
177 | if(CMAKE_SIZEOF_VOID_P EQUAL 4)
178 | set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:GsDriverEntry@8")
179 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
180 | set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:GsDriverEntry")
181 | endif()
182 | endif()
183 | endfunction()
184 |
185 | function(wdk_add_library _target)
186 | cmake_parse_arguments(WDK "" "KMDF;WINVER;NTDDI_VERSION" "" ${ARGN})
187 |
188 | add_library(${_target} ${WDK_UNPARSED_ARGUMENTS})
189 |
190 | set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${WDK_COMPILE_FLAGS}")
191 | set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS
192 | "${WDK_COMPILE_DEFINITIONS};$<$:${WDK_COMPILE_DEFINITIONS_DEBUG};>_WIN32_WINNT=${WDK_WINVER}"
193 | )
194 | if(WDK_NTDDI_VERSION)
195 | target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION})
196 | endif()
197 |
198 | target_include_directories(${_target} SYSTEM PRIVATE
199 | "${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared"
200 | "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km"
201 | "${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt"
202 | )
203 |
204 | if(DEFINED WDK_KMDF)
205 | target_include_directories(${_target} SYSTEM PRIVATE "${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}")
206 | endif()
207 | endfunction()
--------------------------------------------------------------------------------
/kernel/windows/findwdk/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Sergey Podobry (sergey.podobry at gmail.com). All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without modification,
4 | are permitted provided that the following conditions are met:
5 |
6 | Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | Redistributions in binary form must reproduce the above copyright notice, this
10 | list of conditions and the following disclaimer in the documentation and/or
11 | other materials provided with the distribution.
12 |
13 | Neither the name of the {organization} nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/scripts/kcertify.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | IF %1.==. GOTO defaultarg
4 | @set os_provided=%1
5 | GOTO certify
6 | :defaultarg
7 | @set os_provided="10_X64"
8 |
9 | :certify
10 | makecert -r -pe -ss PrivateCertStore -n CN=ksgldrv ksgldrv.cer
11 | Inf2cat.exe /driver:.\ /os:%os_provided%
12 | Signtool sign /v /fd sha256 /s PrivateCertStore /n ksgldrv /a /t http://timestamp.digicert.com ksgldrv.cat
13 | CertMgr.exe /add ksgldrv.cer /s /r localMachine root
14 | CertMgr.exe /add ksgldrv.cer /s /r localMachine trustedpublisher
--------------------------------------------------------------------------------
/scripts/ksgldrv.inf:
--------------------------------------------------------------------------------
1 | ;/*++
2 | ;
3 | ;Copyright (c) 2017-2021 Red Hat Inc.
4 | ;Copyright (c) 2023 dmaivel
5 | ;
6 | ;Module Name:
7 | ; KSGLDRV.inf
8 | ;
9 | ;Abstract:
10 | ;
11 | ;Installation Notes:
12 | ; Using Devcon: Type "devcon install ksgldrv.inf PCI\VEN_1AF4&DEV_1110&SUBSYS_11001AF4&REV_01" to install
13 | ;
14 | ;--*/
15 |
16 | [Version]
17 | Signature="$WINDOWS NT$"
18 | Class=System
19 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
20 | Provider=%VENDOR%
21 | CatalogFile=KSGLDRV.cat
22 | DriverVer = 09/04/2023,100.10.100.10001
23 | PnpLockDown=1
24 |
25 | [DestinationDirs]
26 | DefaultDestDir = 12
27 | KSGLDRV_Device_CoInstaller_CopyFiles = 11
28 |
29 | ; ================= Class section =====================
30 |
31 | [SourceDisksNames]
32 | 1 = %DiskName%,,,""
33 |
34 | [SourceDisksFiles]
35 | KSGLDRV.sys = 1,,
36 | ;
37 |
38 |
39 | ;*****************************************
40 | ; Install Section
41 | ;*****************************************
42 |
43 | [Manufacturer]
44 | %VENDOR%=Standard,NTamd64.10.0
45 |
46 | [Standard.NTamd64.10.0]
47 | %KSGLDRV.DeviceDesc%=KSGLDRV_Device, PCI\VEN_1AF4&DEV_1110&SUBSYS_11001AF4&REV_01, PCI\VEN_1AF4&DEV_1110
48 |
49 | [KSGLDRV_Device.NT]
50 | CopyFiles=Drivers_Dir
51 |
52 | [KSGLDRV_Device.NT.Interfaces]
53 | AddInterface={df576976-569d-4672-95a0-f57e4ea0b210}
54 |
55 | [KSGLDRV_Device.NT.HW]
56 | AddReg = KSGLDRV_AddReg
57 |
58 | [KSGLDRV_AddReg]
59 | HKR,Interrupt Management,,0x00000010
60 | HKR,Interrupt Management\MessageSignaledInterruptProperties,,0x00000010
61 | HKR,Interrupt Management\MessageSignaledInterruptProperties,MSISupported,0x00010001,1
62 |
63 | [Drivers_Dir]
64 | KSGLDRV.sys
65 |
66 | ;-------------- Service installation
67 | [KSGLDRV_Device.NT.Services]
68 | AddService = KSGLDRV,%SPSVCINST_ASSOCSERVICE%, KSGLDRV_Service_Inst
69 |
70 | ; -------------- KSGLDRV driver install sections
71 | [KSGLDRV_Service_Inst]
72 | DisplayName = %KSGLDRV.SVCDESC%
73 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER
74 | StartType = 3 ; SERVICE_DEMAND_START
75 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL
76 | ServiceBinary = %12%\ksgldrv.sys
77 |
78 | ;
79 | ;--- KSGLDRV_Device Coinstaller installation ------
80 | ;
81 |
82 | [KSGLDRV_Device.NT.CoInstallers]
83 | AddReg=KSGLDRV_Device_CoInstaller_AddReg
84 | CopyFiles=KSGLDRV_Device_CoInstaller_CopyFiles
85 |
86 | [KSGLDRV_Device_CoInstaller_AddReg]
87 | ;
88 |
89 |
90 | [KSGLDRV_Device_CoInstaller_CopyFiles]
91 | ;
92 |
93 |
94 | [KSGLDRV_Device.NT.Wdf]
95 | KmdfService = KSGLDRV, KSGLDRV_wdfsect
96 |
97 | [KSGLDRV_wdfsect]
98 | KmdfLibraryVersion = 1.15
99 |
100 | [Strings]
101 | SPSVCINST_ASSOCSERVICE= 0x00000002
102 | VENDOR = "dmaivel"
103 | DiskName = "SharedGL Installation Disk"
104 | KSGLDRV.DeviceDesc = "SharedGL Device"
105 | KSGLDRV.SVCDESC = "SharedGL Service"
106 |
--------------------------------------------------------------------------------
/scripts/wininstall.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | @cd /d "%~dp0"
3 | @set "ERRORLEVEL="
4 | @CMD /C EXIT 0
5 | @"%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" >nul 2>&1
6 | @if NOT "%ERRORLEVEL%"=="0" (
7 | @IF "%*"=="" powershell -Command Start-Process """%0""" -Verb runAs 2>nul
8 | @IF NOT "%*"=="" powershell -Command Start-Process """%0""" """%*""" -Verb runAs 2>nul
9 | @GOTO exit
10 | )
11 |
12 | @set regglkey="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"
13 | @set regglwowkey="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"
14 |
15 | @set CD=
16 | @set curloc=%CD%
17 | @IF %curloc:~0,1%%curloc:~-1%=="" set curloc=%curloc:~1,-1%
18 | @IF "%curloc:~-1%"=="\" set curloc=%curloc:~0,-1%
19 |
20 | @IF /I %PROCESSOR_ARCHITECTURE%==AMD64 IF EXIST "%curloc%\sharedgl32.dll" copy "%curloc%\sharedgl32.dll" "%windir%\SysWOW64\sharedgl.dll"
21 | @IF /I %PROCESSOR_ARCHITECTURE%==AMD64 IF EXIST "%curloc%\sharedgl64.dll" copy "%curloc%\sharedgl64.dll" "%windir%\System32\sharedgl.dll"
22 | @IF /I %PROCESSOR_ARCHITECTURE%==X86 IF EXIST "%curloc%\sharedgl32.dll" copy "%curloc%\sharedgl32.dll" "%windir%\SysWOW64\sharedgl.dll"
23 |
24 | @IF EXIST "%windir%\System32\sharedgl.dll" REG ADD %regglkey% /v DLL /t REG_SZ /d sharedgl.dll /f
25 | @IF EXIST "%windir%\System32\sharedgl.dll" REG ADD %regglkey% /v DriverVersion /t REG_DWORD /d 1 /f
26 | @IF EXIST "%windir%\System32\sharedgl.dll" REG ADD %regglkey% /v Flags /t REG_DWORD /d 1 /f
27 | @IF EXIST "%windir%\System32\sharedgl.dll" REG ADD %regglkey% /v Version /t REG_DWORD /d 2 /f
28 | @IF /I %PROCESSOR_ARCHITECTURE%==AMD64 IF EXIST "%windir%\SysWOW64\sharedgl.dll" REG ADD %regglwowkey% /v DLL /t REG_SZ /d sharedgl.dll /f
29 | @IF /I %PROCESSOR_ARCHITECTURE%==AMD64 IF EXIST "%windir%\SysWOW64\sharedgl.dll" REG ADD %regglwowkey% /v DriverVersion /t REG_DWORD /d 1 /f
30 | @IF /I %PROCESSOR_ARCHITECTURE%==AMD64 IF EXIST "%windir%\SysWOW64\sharedgl.dll" REG ADD %regglwowkey% /v Flags /t REG_DWORD /d 1 /f
31 | @IF /I %PROCESSOR_ARCHITECTURE%==AMD64 IF EXIST "%windir%\SysWOW64\sharedgl.dll" REG ADD %regglwowkey% /v Version /t REG_DWORD /d 2 /f
32 |
33 | @echo Installed SharedGL!
34 |
35 | :exit
--------------------------------------------------------------------------------
/scripts/winuninstall.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | @cd /d "%~dp0"
3 | @set "ERRORLEVEL="
4 | @CMD /C EXIT 0
5 | @"%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" >nul 2>&1
6 | @if NOT "%ERRORLEVEL%"=="0" (
7 | @IF "%*"=="" powershell -Command Start-Process """%0""" -Verb runAs 2>nul
8 | @IF NOT "%*"=="" powershell -Command Start-Process """%0""" """%*""" -Verb runAs 2>nul
9 | @GOTO exit
10 | )
11 |
12 | @IF EXIST "%windir%\System32\sharedgl.dll" del "%windir%\System32\sharedgl.dll"
13 | @IF EXIST "%windir%\SysWOW64\sharedgl.dll" del "%windir%\SysWOW64\sharedgl.dll"
14 |
15 | @set "ERRORLEVEL="
16 | @CMD /C EXIT 0
17 | @REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /d /f sharedgl.dll >nul 2>&1
18 | @if "%ERRORLEVEL%"=="0" REG DELETE "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /f
19 | @CMD /C EXIT 0
20 | @IF /I %PROCESSOR_ARCHITECTURE%==AMD64 REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /d /f sharedgl.dll >nul 2>&1
21 | @if "%ERRORLEVEL%"=="0" IF /I %PROCESSOR_ARCHITECTURE%==AMD64 REG DELETE "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /f
22 | @CMD /C EXIT 0
23 |
24 | @echo Uninstalled SharedGL!
25 |
26 | :exit
--------------------------------------------------------------------------------
/src/client/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #ifndef _WIN32
4 | #include
5 | #endif
6 |
7 | void __attribute__((constructor)) sharedgl_entry(void)
8 | {
9 | glimpl_init();
10 | #ifndef _WIN32
11 | glximpl_init();
12 | #endif
13 | }
14 |
15 | void __attribute__((destructor)) sharedgl_goodbye(void)
16 | {
17 | glimpl_goodbye();
18 | }
--------------------------------------------------------------------------------
/src/client/memory.c:
--------------------------------------------------------------------------------
1 | /*
2 | * this pertains to memory detection within Linux VMs
3 | */
4 |
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | int sgl_detect_device_memory(const char *path)
16 | {
17 | DIR *directory;
18 | struct dirent *entry = NULL;
19 |
20 | directory = opendir(path);
21 | if (directory == NULL)
22 | return -1;
23 |
24 | while ((entry = readdir(directory)) != NULL) {
25 | char full_name[256] = { 0 };
26 | snprintf(full_name, 100, "%s/%s", path, entry->d_name);
27 |
28 | if (entry->d_type == DT_DIR) {
29 | if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
30 | int fd = sgl_detect_device_memory(full_name);
31 | if (fd != -1)
32 | return fd;
33 | }
34 | } else {
35 | if (strstr(full_name, "bar2") != NULL)
36 | return open(full_name, O_RDWR, S_IRWXU);
37 | }
38 | }
39 |
40 | closedir(directory);
41 | return -1;
42 | }
--------------------------------------------------------------------------------
/src/client/pb.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 | #include
6 |
7 | #ifndef _WIN32
8 | #define __USE_GNU
9 | #define _GNU_SOURCE
10 | #include
11 | #else
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include
19 |
20 | #pragma comment (lib, "Setupapi.lib")
21 |
22 | DEFINE_GUID(GUID_DEVINTERFACE_IVSHMEM,
23 | 0xdf576976, 0x569d, 0x4672, 0x95, 0xa0, 0xf5, 0x7e, 0x4e, 0xa0, 0xb2, 0x10);
24 |
25 | #define IVSHMEM_CACHE_NONCACHED 0
26 | #define IVSHMEM_CACHE_CACHED 1
27 | #define IVSHMEM_CACHE_WRITECOMBINED 2
28 |
29 | #define IOCTL_IVSHMEM_REQUEST_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
30 | #define IOCTL_IVSHMEM_REQUEST_MMAP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
31 | #define IOCTL_IVSHMEM_RELEASE_MMAP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
32 |
33 | struct ivshmem_mmap_config {
34 | BYTE cache_mode;
35 | };
36 |
37 | struct ivshmem_mmap {
38 | WORD peer_id;
39 | DWORD64 size;
40 | PVOID pointer;
41 | WORD vectors;
42 | };
43 |
44 | static HANDLE ivshmem_handle;
45 | #endif
46 |
47 | static void *ptr;
48 | static void *base;
49 | static int *cur;
50 |
51 | static void *in_base;
52 | static int *in_cur;
53 |
54 | static bool using_direct_access = false;
55 |
56 | static struct pb_net_hooks net_hooks = { NULL };
57 |
58 | #ifndef _WIN32
59 | void pb_set(int fd, bool direct_access)
60 | {
61 | uintptr_t alloc_size;
62 |
63 | ptr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
64 | alloc_size = *(uintptr_t*)(ptr + SGL_OFFSET_REGISTER_MEMSIZE);
65 |
66 | munmap(ptr, 0x1000);
67 | ptr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
68 |
69 | base = ptr + 0x1000;
70 |
71 | if (direct_access) {
72 | using_direct_access = true;
73 | in_base = base;
74 | in_cur = base;
75 | }
76 | else {
77 | in_base = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
78 | in_cur = in_base;
79 | }
80 | }
81 | #else
82 | void pb_set(bool direct_access)
83 | {
84 | HDEVINFO device_info;
85 | PSP_DEVICE_INTERFACE_DETAIL_DATA inf_data;
86 | SP_DEVICE_INTERFACE_DATA dev_data;
87 | DWORD64 size;
88 | struct ivshmem_mmap_config config;
89 | struct ivshmem_mmap map;
90 | DWORD request_size;
91 |
92 | device_info = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
93 | ZeroMemory(&dev_data, sizeof(SP_DEVICE_INTERFACE_DATA));
94 | dev_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
95 |
96 | if (SetupDiEnumDeviceInterfaces(device_info, NULL, &GUID_DEVINTERFACE_IVSHMEM, 0, &dev_data) == FALSE)
97 | return;
98 |
99 | SetupDiGetDeviceInterfaceDetail(device_info, &dev_data, NULL, 0, &request_size, NULL);
100 | if (!request_size)
101 | return;
102 |
103 | inf_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(request_size));
104 | ZeroMemory(inf_data, request_size);
105 | inf_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
106 | if (!SetupDiGetDeviceInterfaceDetail(device_info, &dev_data, inf_data, request_size, NULL, NULL))
107 | return;
108 |
109 | ivshmem_handle = CreateFile(inf_data->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
110 | if (ivshmem_handle == INVALID_HANDLE_VALUE)
111 | return;
112 |
113 | if (inf_data)
114 | free(inf_data);
115 | SetupDiDestroyDeviceInfoList(device_info);
116 |
117 | if (!DeviceIoControl(ivshmem_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(UINT64), NULL, NULL))
118 | return;
119 |
120 | config.cache_mode = IVSHMEM_CACHE_WRITECOMBINED;
121 | ZeroMemory(&map, sizeof(struct ivshmem_mmap));
122 | if (!DeviceIoControl(ivshmem_handle, IOCTL_IVSHMEM_REQUEST_MMAP, &config, sizeof(struct ivshmem_mmap_config), &map, sizeof(struct ivshmem_mmap), NULL, NULL))
123 | return;
124 |
125 | ptr = map.pointer;
126 | base = (PVOID)((DWORD64)map.pointer + (DWORD64)0x1000);
127 |
128 | if (direct_access) {
129 | in_base = base;
130 | in_cur = in_base;
131 | }
132 | else {
133 | in_base = VirtualAlloc(NULL, map.size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
134 | in_cur = in_base;
135 | }
136 | }
137 |
138 | void pb_unset(void)
139 | {
140 | DeviceIoControl(ivshmem_handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL);
141 | CloseHandle(ivshmem_handle);
142 | }
143 | #endif
144 |
145 | void pb_set_net(struct pb_net_hooks hooks, size_t internal_alloc_size)
146 | {
147 | net_hooks = hooks;
148 |
149 | #ifndef _WIN32
150 | in_base = mmap(NULL, internal_alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
151 | in_cur = in_base;
152 | #else
153 | in_base = VirtualAlloc(NULL, internal_alloc_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
154 | in_cur = in_base;
155 | #endif
156 | }
157 |
158 | void pb_reset()
159 | {
160 | cur = base;
161 | in_cur = in_base;
162 | }
163 |
164 | void pb_push(int c)
165 | {
166 | *in_cur++ = c;
167 | }
168 |
169 | void pb_pushf(float c)
170 | {
171 | *in_cur++ = *(int*)&c;
172 | }
173 |
174 | int pb_read(int s)
175 | {
176 | if (net_hooks._pb_read)
177 | return net_hooks._pb_read(s);
178 | return *(int*)((size_t)ptr + s);
179 | }
180 |
181 | int64_t pb_read64(int s)
182 | {
183 | if (net_hooks._pb_read64)
184 | return net_hooks._pb_read64(s);
185 | return *(int64_t*)((size_t)ptr + s);
186 | }
187 |
188 | void pb_write(int s, int c)
189 | {
190 | *(int*)((size_t)ptr + s) = c;
191 | }
192 |
193 | /*
194 | * // equivalent to
195 | * int *pdata = (int*)data;
196 | * for (int i = 0; i < length / 4; i++)
197 | * pb_push(*pdata++);
198 | */
199 | void pb_memcpy(const void *src, size_t length)
200 | {
201 | // length = length - (length % 4);
202 | memcpy(in_cur, src, length);
203 | in_cur += CEIL_DIV(length, 4);
204 | }
205 |
206 | void pb_memcpy_unaligned(const void *src, size_t length)
207 | {
208 | // length = length - (length % 4);
209 | memcpy(in_cur, src, length);
210 | in_cur = (int*)((char*)in_cur + length);
211 | }
212 |
213 | static inline uintptr_t align_to_4(uintptr_t ptr)
214 | {
215 | return (ptr + 3) & ~3;
216 | }
217 |
218 | void pb_realign()
219 | {
220 | in_cur = (int*)align_to_4((uintptr_t)in_cur);
221 | }
222 |
223 | void *pb_ptr(size_t offs)
224 | {
225 | if (net_hooks._pb_ptr)
226 | return net_hooks._pb_ptr(offs);
227 | return (void*)((size_t)ptr + offs);
228 | }
229 |
230 | void *pb_iptr(size_t offs)
231 | {
232 | return (void*)((size_t)in_base + offs);
233 | }
234 |
235 | size_t pb_size()
236 | {
237 | return (size_t)in_cur - (size_t)in_base;
238 | }
239 |
240 | void pb_copy_to_shared()
241 | {
242 | if (!using_direct_access)
243 | memcpy(base, in_base, (size_t)in_cur - (size_t)in_base);
244 | }
--------------------------------------------------------------------------------
/src/client/platform/egl.c:
--------------------------------------------------------------------------------
1 | // stub
--------------------------------------------------------------------------------
/src/client/platform/glx.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 |
17 | static Window win = -1;
18 | static const char *glx_extensions = "GLX_ARB_create_context GLX_ARB_create_context_no_error GLX_ARB_create_context_profile GLX_ARB_create_context_robustness GLX_ARB_get_proc_address GLX_EXT_create_context_es2_profile GLX_EXT_create_context_es_profile GLX_EXT_visual_info";
19 |
20 | static int glx_major = 1;
21 | static int glx_minor = 4;
22 | static const char *glx_majmin_string = "1.4";
23 |
24 | static int max_width, max_height, real_width, real_height;
25 |
26 | static void *swap_sync_lock;
27 |
28 | ICD_SET_MAX_DIMENSIONS_DEFINITION(max_width, max_height, real_width, real_height);
29 | ICD_RESIZE_DEFINITION(real_width, real_height);
30 |
31 | struct glx_swap_data {
32 | XVisualInfo vinfo;
33 | XVisualInfo *visual_list;
34 | XVisualInfo visual_template;
35 | int nxvisuals;
36 | Window parent;
37 |
38 | int width, height;
39 | XImage *ximage;
40 | XEvent event;
41 |
42 | XGCValues gcv;
43 | GC gc;
44 |
45 | bool initialized;
46 | };
47 |
48 | struct glx_fb_config {
49 | int render_type,
50 | drawable_type,
51 | double_buffer,
52 | red_size,
53 | green_size,
54 | blue_size,
55 | alpha_size,
56 | stencil_size,
57 | depth_size,
58 | accum_red_size,
59 | accum_green_size,
60 | accum_blue_size,
61 | accum_alpha_size,
62 | accum_stencil_size,
63 | renderable,
64 | visual_type;
65 | // to-do: add more like stereo
66 | };
67 |
68 | static int n_valid_fb_configs;
69 |
70 | static struct glx_fb_config fb_configs[1729] = { 0 };
71 |
72 | static int fb_valid_color_sizes[] = {
73 | 0, 1, 8, 16, 24, 32
74 | };
75 |
76 | static int fb_valid_render_types[] = {
77 | GLX_RGBA_BIT, GLX_COLOR_INDEX_BIT
78 | };
79 |
80 | static int fb_valid_doublebuffer_types[] = {
81 | False, True
82 | };
83 |
84 | static int fb_valid_drawable_types[] = {
85 | GLX_WINDOW_BIT
86 | };
87 |
88 | static int fb_valid_visual_types[] = {
89 | GLX_TRUE_COLOR, GLX_DIRECT_COLOR, GLX_PSEUDO_COLOR, GLX_STATIC_COLOR, GLX_GRAY_SCALE, GLX_STATIC_GRAY
90 | };
91 |
92 | #define ARR_SIZE(x) (sizeof(x) / sizeof(*x))
93 | static void glx_generate_fb_configs()
94 | {
95 | int idx = 0;
96 | for (int a = 0; a < ARR_SIZE(fb_valid_color_sizes); a++) { // varying color size
97 | for (int b = 0; b < ARR_SIZE(fb_valid_render_types); b++) { // varying render types
98 | for (int c = 0; c < ARR_SIZE(fb_valid_doublebuffer_types); c++) { // varying double buffer
99 | for (int d = 0; d < ARR_SIZE(fb_valid_drawable_types); d++) { // varying drawable type
100 | for (int e = 0; e < ARR_SIZE(fb_valid_doublebuffer_types); e++) { // varying renderable
101 | for (int f = 0; f < ARR_SIZE(fb_valid_visual_types); f++) { // varying visual type
102 | for (int g = 0; g < ARR_SIZE(fb_valid_color_sizes); g++) { // varying depth
103 | fb_configs[idx].red_size = fb_valid_color_sizes[a];
104 | fb_configs[idx].green_size = fb_valid_color_sizes[a];
105 | fb_configs[idx].blue_size = fb_valid_color_sizes[a];
106 | fb_configs[idx].alpha_size = fb_valid_color_sizes[a];
107 | fb_configs[idx].accum_red_size = fb_valid_color_sizes[a];
108 | fb_configs[idx].accum_green_size = fb_valid_color_sizes[a];
109 | fb_configs[idx].accum_blue_size = fb_valid_color_sizes[a];
110 | fb_configs[idx].accum_alpha_size = fb_valid_color_sizes[a];
111 |
112 | fb_configs[idx].stencil_size = -1; // fb_valid_color_sizes[a];
113 | fb_configs[idx].depth_size = fb_valid_color_sizes[g];
114 |
115 | fb_configs[idx].render_type = fb_valid_render_types[b];
116 | fb_configs[idx].double_buffer = fb_valid_doublebuffer_types[c];
117 | fb_configs[idx].drawable_type = fb_valid_drawable_types[d];
118 |
119 | fb_configs[idx].renderable = fb_valid_doublebuffer_types[e];
120 | fb_configs[idx].visual_type = fb_valid_visual_types[f];
121 |
122 | idx++;
123 | }
124 | }
125 | }
126 | }
127 | }
128 | }
129 | }
130 |
131 | n_valid_fb_configs = idx;
132 | }
133 | #undef ARR_SIZE
134 |
135 | static const char *glximpl_name_to_string(int name)
136 | {
137 | switch (name) {
138 | case GLX_VENDOR: return "SharedGL";
139 | case GLX_VERSION: return glx_majmin_string;
140 | case GLX_EXTENSIONS: return glx_extensions;
141 | }
142 | return "?";
143 | }
144 |
145 | GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext share_list, Bool direct)
146 | {
147 | return (GLXContext)1;
148 | }
149 |
150 | GLXContext glXGetCurrentContext( void )
151 | {
152 | return (GLXContext)1;
153 | }
154 |
155 | void glXDestroyContext(Display *dpy, GLXContext ctx)
156 | {
157 |
158 | }
159 |
160 | Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
161 | {
162 | return True;
163 | }
164 |
165 | Bool glXQueryExtension(Display *dpy, int *errorb, int *event)
166 | {
167 | return True;
168 | }
169 |
170 | void glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
171 | {
172 |
173 | }
174 |
175 | const char *glXQueryExtensionsString(Display *dpy, int screen)
176 | {
177 | return glx_extensions;
178 | }
179 |
180 | XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attrib_list)
181 | {
182 | XVisualInfo *vinfo = malloc(sizeof(XVisualInfo));
183 | XMatchVisualInfo(dpy, XDefaultScreen(dpy), 24, TrueColor, vinfo);
184 | return vinfo;
185 | }
186 |
187 | GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
188 | {
189 | return (GLXContext)1;
190 | }
191 |
192 | Display *glXGetCurrentDisplay(void)
193 | {
194 | return XOpenDisplay(NULL);
195 | }
196 |
197 | Bool glXQueryVersion(Display *dpy, int *maj, int *min)
198 | {
199 | *maj = glx_major;
200 | *min = glx_minor;
201 | return True;
202 | }
203 |
204 | const char *glXGetClientString(Display *dpy, int name)
205 | {
206 | return glximpl_name_to_string(name);
207 | }
208 |
209 | GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attrib_list)
210 | {
211 | return win;
212 | }
213 |
214 | void glXDestroyWindow(Display *dpy, GLXWindow win)
215 | {
216 |
217 | }
218 |
219 | Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
220 | {
221 | win = drawable;
222 | return true;
223 | }
224 |
225 | int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value)
226 | {
227 | unsigned int index = (int)(size_t)config;
228 | if (index > n_valid_fb_configs) {
229 | fprintf(stderr, "glXGetFBConfigAttrib : attempted access on config %u, only %u exist\n", index, n_valid_fb_configs);
230 | return Success;
231 | }
232 |
233 | // fprintf(stderr, "glXGetFBConfigAttrib : access on config %u\n", index);
234 |
235 | struct glx_fb_config fb_config = fb_configs[index];
236 |
237 | switch (attribute) {
238 | case GLX_FBCONFIG_ID:
239 | *value = index;
240 | break;
241 | case GLX_RENDER_TYPE:
242 | *value |= fb_config.render_type; // GLX_RGBA_BIT;
243 | break;
244 | case GLX_VISUAL_ID:
245 | *value = XDefaultVisual(dpy, 0)->visualid; // fb_config.visual_type;
246 | break;
247 | case GLX_BUFFER_SIZE:
248 | *value = 1;
249 | break;
250 | case GLX_SAMPLES:
251 | *value = 32;
252 | break;
253 | case GLX_SAMPLE_BUFFERS:
254 | *value = 1;
255 | break;
256 | case GLX_DRAWABLE_TYPE:
257 | *value |= fb_config.drawable_type; // GLX_WINDOW_BIT;
258 | break;
259 | case GLX_DOUBLEBUFFER:
260 | *value = fb_config.double_buffer;
261 | break;
262 | case GLX_RED_SIZE:
263 | *value = fb_config.red_size;
264 | break;
265 | case GLX_GREEN_SIZE:
266 | *value = fb_config.green_size;
267 | break;
268 | case GLX_BLUE_SIZE:
269 | *value = fb_config.blue_size;
270 | break;
271 | case GLX_ALPHA_SIZE:
272 | *value = fb_config.alpha_size;
273 | break;
274 | case GLX_STENCIL_SIZE:
275 | *value = fb_config.stencil_size;
276 | break;
277 | case GLX_ACCUM_RED_SIZE:
278 | *value = fb_config.accum_red_size;
279 | break;
280 | case GLX_ACCUM_GREEN_SIZE:
281 | *value = fb_config.accum_green_size;
282 | break;
283 | case GLX_ACCUM_BLUE_SIZE:
284 | *value = fb_config.accum_blue_size;
285 | break;
286 | case GLX_ACCUM_ALPHA_SIZE:
287 | *value = fb_config.accum_alpha_size; // 8;
288 | break;
289 | case GLX_DEPTH_SIZE:
290 | *value = fb_config.depth_size; // 24;
291 | break;
292 | case GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB:
293 | *value = 1;
294 | break;
295 | }
296 |
297 | return Success;
298 | }
299 |
300 | GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements)
301 | {
302 | GLXFBConfig *fb_config = calloc(1, sizeof(GLXFBConfig) * n_valid_fb_configs);
303 | for (int i = 0; i < n_valid_fb_configs; i++)
304 | fb_config[i] = (GLXFBConfig)((size_t)i);
305 | *nelements = n_valid_fb_configs;
306 | return fb_config;
307 | }
308 |
309 | XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
310 | {
311 | XVisualInfo *vinfo = malloc(sizeof(XVisualInfo));
312 | XMatchVisualInfo(dpy, XDefaultScreen(dpy), 24, TrueColor, vinfo);
313 | return vinfo;
314 | }
315 |
316 | GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list)
317 | {
318 | /*
319 | * probably not needed, stuck around for testing
320 | */
321 | int *attribs = (int*)attrib_list;
322 | while (*attribs) {
323 | int attrib = *attribs++;
324 | int value = *attribs++;
325 |
326 | if (attrib == GLX_CONTEXT_PROFILE_MASK_ARB && value == GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
327 | return NULL;
328 | }
329 |
330 | return glXCreateContext(dpy, NULL, 0, 0);
331 | }
332 |
333 | int glXGetConfig(Display *dpy, XVisualInfo *visual, int attrib, int *value)
334 | {
335 | return 1;
336 | }
337 |
338 | GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attrib_list, int *nitems)
339 | {
340 | return glXGetFBConfigs(dpy, screen, nitems);
341 | }
342 |
343 | Bool glXIsDirect(Display *dpy, GLXContext ctx)
344 | {
345 | return True;
346 | }
347 |
348 | const char *glXQueryServerString( Display *dpy, int screen, int name )
349 | {
350 | return glximpl_name_to_string(name);
351 | }
352 |
353 | void glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask)
354 | {
355 |
356 | }
357 |
358 | GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *visual, Pixmap pixmap)
359 | {
360 | return (GLXPixmap)1;
361 | }
362 |
363 | void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap)
364 | {
365 |
366 | }
367 |
368 | GLXDrawable glXGetCurrentDrawable(void)
369 | {
370 | return win;
371 | }
372 |
373 | void glXUseXFont(Font font, int first, int count, int list)
374 | {
375 |
376 | }
377 |
378 | void glXWaitGL(void)
379 | {
380 |
381 | }
382 |
383 | void glXWaitX(void)
384 | {
385 |
386 | }
387 |
388 | int glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
389 | {
390 | return Success;
391 | }
392 |
393 | void glXSwapBuffers(Display* dpy, GLXDrawable drawable)
394 | {
395 | static struct glx_swap_data swap_data = { 0 };
396 |
397 | if (swap_data.initialized == false) {
398 | swap_sync_lock = pb_ptr(SGL_OFFSET_REGISTER_SWAP_BUFFERS_SYNC);
399 |
400 | XWindowAttributes attr;
401 | XGetWindowAttributes(dpy, drawable, &attr);
402 |
403 | swap_data.parent = XDefaultRootWindow(dpy);
404 | swap_data.nxvisuals = 0;
405 | swap_data.visual_template.screen = DefaultScreen(dpy);
406 | swap_data.visual_list = XGetVisualInfo(dpy, VisualScreenMask, &swap_data.visual_template, &swap_data.nxvisuals);
407 |
408 | XMatchVisualInfo(dpy, XDefaultScreen(dpy), 24, TrueColor, &swap_data.vinfo);
409 |
410 | /*
411 | * create an ximage whose pointer points to our framebuffer
412 | */
413 | swap_data.ximage = XCreateImage(dpy, swap_data.vinfo.visual, swap_data.vinfo.depth, ZPixmap, 0, glimpl_fb_address(), max_width, max_height, 8, max_width*4);
414 | swap_data.gcv.graphics_exposures = 0;
415 | swap_data.gc = XCreateGC(dpy, swap_data.parent, GCGraphicsExposures, &swap_data.gcv);
416 | swap_data.initialized = true;
417 | }
418 |
419 | /* lock */
420 | spin_lock(swap_sync_lock);
421 |
422 | /* swap */
423 | glimpl_swap_buffers(real_width, real_height, 1, GL_BGRA);
424 |
425 | /* display */
426 | XPutImage(dpy, drawable, swap_data.gc, swap_data.ximage, 0, 0, 0, 0, real_width, real_height);
427 |
428 | /* unlock */
429 | spin_unlock(swap_sync_lock);
430 |
431 | /* sync */
432 | XSync(dpy, False);
433 | }
434 |
435 | void* glXGetProcAddressARB(char* s)
436 | {
437 | // char str[64];
438 | // if (strstr(s, "EXT") || strstr(s, "ARB")) {
439 | // strcpy(str, s);
440 | // str[strlen(str) - 3] = 0;
441 | // return NULL;
442 | // }
443 |
444 | /* to-do: use stripped str? */
445 | return dlsym(NULL, s);
446 | }
447 |
448 | void *glXGetProcAddress(char *s)
449 | {
450 | return glXGetProcAddressARB(s);
451 | }
452 |
453 | void glximpl_init()
454 | {
455 | char *glx_version_override = getenv("GLX_VERSION_OVERRIDE");
456 | if (glx_version_override) {
457 | glx_majmin_string = glx_version_override;
458 | glx_major = glx_version_override[0] - '0';
459 | glx_minor = glx_version_override[2] - '0';
460 | }
461 |
462 | glx_generate_fb_configs();
463 | }
--------------------------------------------------------------------------------
/src/client/platform/wgl.c:
--------------------------------------------------------------------------------
1 | /*
2 | * DISCLAIMER:
3 | *
4 | * This portion of the repository is served as a drop-in replacement for `opengl32.dll`
5 | * Because a proper ICD implementation is provided by `drv.c`, this part of the code base
6 | * has been rendered useless as Window's opengl32 will call upon drvXXXXX functions. This
7 | * also means we don't need to use MinHook to hook onto SwapBuffers, ChoosePixelFormat,
8 | * and SetPixelFormat. Hooks shouldn't have been in place for these functions to begin with
9 | * as there are WGL equivelents, which means this code needs to be rewritten for it to
10 | * function again as MinHook will be removed from the repository. The rewriting is not currently
11 | * a priority, but this note will be updated when such a rewrite comes along. This means even
12 | * if the end-user defines `OVERRIDE_OPENGL32`, this code will not compile.
13 | */
14 |
15 | #ifdef OVERRIDE_OPENGL32
16 | #ifdef _WIN32
17 |
18 | #include
19 | #include
20 |
21 | #include
22 |
23 | #include
24 |
25 | #include
26 |
27 | HWND Window;
28 | HDC Hdc;
29 | int Width;
30 | int Height;
31 |
32 | BOOL(*SwapBuffersOriginal)(HDC unnamedParam1);
33 | int(*ChoosePixelFormatOriginal)(HDC hdc, const PIXELFORMATDESCRIPTOR *ppfd);
34 | BOOL(*SetPixelFormatOriginal)(HDC hdc, int format, const PIXELFORMATDESCRIPTOR *ppfd);
35 |
36 | GLAPI PROC wglGetProcAddress(LPCSTR unnamedParam1)
37 | {
38 | return GetProcAddress(GetModuleHandleW(NULL), unnamedParam1);
39 | }
40 |
41 | BOOL wglMakeCurrent(HDC unnamedParam1, HGLRC unnamedParam2)
42 | {
43 | Hdc = unnamedParam1;
44 | Window = WindowFromDC(Hdc);
45 |
46 | RECT Rect;
47 | if (GetClientRect(Window, &Rect)) {
48 | Width = Rect.right - Rect.left;
49 | Height = Rect.bottom - Rect.top;
50 | }
51 |
52 | return TRUE;
53 | }
54 |
55 | BOOL wglDeleteContext(HGLRC unnamedParam1)
56 | {
57 | return TRUE; // STUB
58 | }
59 |
60 | HGLRC wglCreateContext(HDC unnamedParam1)
61 | {
62 | return (HGLRC)1; // STUB
63 | }
64 |
65 | HDC wglGetCurrentDC()
66 | {
67 | return Hdc;
68 | }
69 |
70 | GLAPI BOOL SwapBuffersHook(HDC unnamedParam1)
71 | {
72 | static BITMAPINFO bmi = {
73 | .bmiHeader.biSize = sizeof(BITMAPINFO),
74 | .bmiHeader.biPlanes = 1,
75 | .bmiHeader.biBitCount = 32,
76 | .bmiHeader.biCompression = BI_RGB,
77 | .bmiHeader.biSizeImage = 0,
78 | .bmiHeader.biClrUsed = 0,
79 | .bmiHeader.biClrImportant = 0,
80 | .bmiHeader.biXPelsPerMeter = 0,
81 | .bmiHeader.biYPelsPerMeter = 0
82 | };
83 |
84 | static int Init = 0;
85 | static void *Frame = NULL;
86 |
87 | if (!Init) {
88 | bmi.bmiHeader.biWidth = Width;
89 | bmi.bmiHeader.biHeight = -Height;
90 |
91 | glimpl_report(Width, Height);
92 |
93 | Frame = glimpl_fb_address();
94 | Init = 1;
95 | }
96 |
97 | glimpl_swap_buffers(Width, Height, 1, GL_BGRA); /* to-do: fix overlay so vflip and -Height won't be needed */
98 | SetDIBitsToDevice(Hdc, 0, 0, Width, Height, 0, 0, 0, Height, Frame, &bmi, DIB_RGB_COLORS);
99 | // StretchDIBits(Hdc, 0, 0, Width, Height, 0, 0, Width, Height, Frame, &bmi, DIB_RGB_COLORS, SRCCOPY);
100 |
101 | return TRUE;
102 | }
103 |
104 | int ChoosePixelFormatHook(HDC hdc, const PIXELFORMATDESCRIPTOR *ppfd)
105 | {
106 | return TRUE; // STUB
107 | }
108 |
109 | BOOL SetPixelFormatHook(HDC hdc, int format, const PIXELFORMATDESCRIPTOR *ppfd)
110 | {
111 | return TRUE; // STUB
112 | }
113 |
114 | void WglInit()
115 | {
116 | MH_Initialize();
117 |
118 | MH_CreateHook(SwapBuffers, SwapBuffersHook, (PVOID*)(&SwapBuffersOriginal));
119 | MH_EnableHook(SwapBuffers);
120 |
121 | MH_CreateHook(ChoosePixelFormat, ChoosePixelFormatHook, (PVOID*)(&ChoosePixelFormatOriginal));
122 | MH_EnableHook(ChoosePixelFormat);
123 |
124 | MH_CreateHook(SetPixelFormat, SetPixelFormatHook, (PVOID*)(&SetPixelFormatOriginal));
125 | MH_EnableHook(SetPixelFormat);
126 | }
127 |
128 | #endif
129 | #endif
--------------------------------------------------------------------------------
/src/client/platform/windrv.c:
--------------------------------------------------------------------------------
1 | #ifdef _WIN32
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 |
17 | static PIXELFORMATDESCRIPTOR pfd_table[64] = { 0 };
18 | static int pfd_count = 0;
19 |
20 | static struct WGLCALLBACKS callbacks;
21 |
22 | static int max_width, max_height, real_width, real_height;
23 |
24 | static void *swap_sync_lock;
25 |
26 | ICD_SET_MAX_DIMENSIONS_DEFINITION(max_width, max_height, real_width, real_height);
27 | ICD_RESIZE_DEFINITION(real_width, real_height);
28 |
29 | typedef HGLRC(WINAPI * wglCreateContext_t )(HDC);
30 | typedef BOOL(WINAPI * wglDeleteContext_t )(HGLRC);
31 |
32 | static wglCreateContext_t g_pfnwglCreateContext = NULL;
33 | static wglDeleteContext_t g_pfnwglDeleteContext = NULL;
34 |
35 | struct pfd_color_info {
36 | int rbits, gbits, bbits, abits;
37 | int rshift, gshift, bshift, ashift;
38 | };
39 |
40 | struct pfd_depth_info {
41 | int depthbits, stencilbits;
42 | };
43 |
44 | static struct pfd_color_info pfd_colors[4] = {
45 | { 8, 8, 8, 0, 16, 8, 0, 0 },
46 | { 8, 8, 8, 0, 8, 16, 24, 0 },
47 | { 8, 8, 8, 8, 16, 8, 0, 24 },
48 | { 8, 8, 8, 8, 8, 16, 24, 0 }
49 | };
50 |
51 | static struct pfd_depth_info pfd_depths[4] = {
52 | { 32, 0 },
53 | { 24, 0 },
54 | { 16, 0 },
55 | { 24, 8 }
56 | };
57 |
58 | struct wgl_extension_entry {
59 | const char *name;
60 | PROC proc;
61 | };
62 |
63 | static HMODULE module_handle = 0;
64 | static BOOL do_vflip = TRUE;
65 |
66 | void windrv_set_module_address(HMODULE module)
67 | {
68 | module_handle = module;
69 | }
70 |
71 | void windrv_set_vflip(BOOL flip)
72 | {
73 | do_vflip = flip;
74 | }
75 |
76 | // removed WGL_ARB_pixel_format
77 | static const char *wgl_extensions = "WGL_ARB_create_context WGL_ARB_create_context_profile WGL_ARB_extensions_string WGL_ARB_framebuffer_sRGB";
78 |
79 | static HGLRC wgl_create_context(HDC hdc)
80 | {
81 | if (g_pfnwglCreateContext == NULL)
82 | g_pfnwglCreateContext = (wglCreateContext_t)GetProcAddress(GetModuleHandleA("opengl32.dll"), "wglCreateContext");
83 |
84 | return g_pfnwglCreateContext(hdc);
85 | }
86 |
87 | static BOOL wgl_delete_context(HGLRC hglrc)
88 | {
89 | if (g_pfnwglDeleteContext == NULL)
90 | g_pfnwglDeleteContext = (wglDeleteContext_t)GetProcAddress(GetModuleHandleA("opengl32.dll"), "wglDeleteContext");
91 |
92 | return g_pfnwglDeleteContext(hglrc);
93 | }
94 |
95 | const char* wglGetExtensionsStringARB(HDC hdc)
96 | {
97 | return wgl_extensions;
98 | }
99 |
100 | HGLRC wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList)
101 | {
102 | return wgl_create_context(hDC);
103 | }
104 |
105 | BOOL wglGetPixelFormatAttribivARB(HDC hdc,
106 | int iPixelFormat,
107 | int iLayerPlane,
108 | UINT nAttributes,
109 | const int *piAttributes,
110 | int *piValues)
111 | {
112 | return TRUE;
113 | }
114 |
115 | BOOL wglGetPixelFormatAttribfvARB(HDC hdc,
116 | int iPixelFormat,
117 | int iLayerPlane,
118 | UINT nAttributes,
119 | const int *piAttributes,
120 | FLOAT *pfValues)
121 | {
122 | return TRUE;
123 | }
124 |
125 | BOOL wglChoosePixelFormatARB(HDC hdc,
126 | const int *piAttribIList,
127 | const FLOAT *pfAttribFList,
128 | UINT nMaxFormats,
129 | int *piFormats,
130 | UINT *nNumFormats)
131 | {
132 | *piFormats = 1;
133 | *nNumFormats = 1;
134 | return TRUE;
135 | }
136 |
137 | #define WGL_EXTENSION_ENTRY(P) { #P, (PROC) P }
138 |
139 | static const struct wgl_extension_entry wgl_extension_entries[] = {
140 |
141 | /* WGL_ARB_extensions_string */
142 | WGL_EXTENSION_ENTRY( wglGetExtensionsStringARB ),
143 |
144 | /* WGL_ARB_pixel_format */
145 | // WGL_EXTENSION_ENTRY( wglChoosePixelFormatARB ),
146 | // WGL_EXTENSION_ENTRY( wglGetPixelFormatAttribfvARB ),
147 | // WGL_EXTENSION_ENTRY( wglGetPixelFormatAttribivARB ),
148 |
149 | /* WGL_ARB_create_context */
150 | WGL_EXTENSION_ENTRY( wglCreateContextAttribsARB ),
151 |
152 | { NULL, NULL }
153 | };
154 |
155 | static void pfd_add(
156 | bool doublebuffer, bool gdi, unsigned int accum,
157 | int rbits, int gbits, int bbits, int abits,
158 | int rshift, int gshift, int bshift, int ashift,
159 | int depthbits, int stencilbits)
160 | {
161 | pfd_table[pfd_count].nSize = sizeof(pfd_table[pfd_count]);
162 | pfd_table[pfd_count].nVersion = 1;
163 | pfd_table[pfd_count].dwFlags = PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION | PFD_DRAW_TO_WINDOW;
164 |
165 | if (doublebuffer)
166 | pfd_table[pfd_count].dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
167 |
168 | if (gdi)
169 | pfd_table[pfd_count].dwFlags |= PFD_SUPPORT_GDI;
170 |
171 | pfd_table[pfd_count].iPixelType = PFD_TYPE_RGBA;
172 | pfd_table[pfd_count].iLayerType = PFD_MAIN_PLANE;
173 |
174 | pfd_table[pfd_count].cColorBits = rbits + gbits + bbits + abits;
175 | pfd_table[pfd_count].cRedBits = rbits;
176 | pfd_table[pfd_count].cRedShift = rshift;
177 | pfd_table[pfd_count].cGreenBits = gbits;
178 | pfd_table[pfd_count].cGreenShift = gshift;
179 | pfd_table[pfd_count].cBlueBits = bbits;
180 | pfd_table[pfd_count].cBlueShift = bshift;
181 | pfd_table[pfd_count].cAlphaBits = abits;
182 | pfd_table[pfd_count].cAlphaShift = ashift;
183 | pfd_table[pfd_count].cAccumBits = 4*accum;
184 | pfd_table[pfd_count].cAccumRedBits = accum;
185 | pfd_table[pfd_count].cAccumGreenBits = accum;
186 | pfd_table[pfd_count].cAccumBlueBits = accum;
187 | pfd_table[pfd_count].cAccumAlphaBits = accum;
188 | pfd_table[pfd_count].cDepthBits = depthbits;
189 | pfd_table[pfd_count].cStencilBits = stencilbits;
190 | pfd_table[pfd_count].cAuxBuffers = 0;
191 | pfd_table[pfd_count].iLayerType = 0;
192 | pfd_table[pfd_count].bReserved = 0;
193 | pfd_table[pfd_count].dwLayerMask = 0;
194 | pfd_table[pfd_count].dwVisibleMask = 0;
195 | pfd_table[pfd_count].dwDamageMask = 0;
196 |
197 | pfd_count++;
198 | }
199 |
200 | /*
201 | * accounts for accum
202 | */
203 | static void pfd_add2(
204 | bool doublebuffer, bool gdi, unsigned int accum,
205 | int rbits, int gbits, int bbits, int abits,
206 | int rshift, int gshift, int bshift, int ashift,
207 | int depthbits, int stencilbits)
208 | {
209 | for (int i = 0; i < 2; i++)
210 | pfd_add(doublebuffer, gdi, i * accum, rbits, gbits, bbits, abits, rshift, gshift, bshift, ashift, depthbits, stencilbits);
211 | }
212 |
213 | static void pfd_init()
214 | {
215 | /*
216 | * optional doublebuffer
217 | * no gdi
218 | */
219 | for (int i = 0; i < 2; i++) {
220 | for (int color = 0; color < 4; color++)
221 | for (int depth = 0; depth < 4; depth++)
222 | pfd_add2(i, false, 16,
223 | pfd_colors[color].rbits, pfd_colors[color].gbits, pfd_colors[color].bbits, pfd_colors[color].abits,
224 | pfd_colors[color].rshift, pfd_colors[color].gshift, pfd_colors[color].bshift, pfd_colors[color].ashift,
225 | pfd_depths[depth].depthbits, pfd_depths[depth].stencilbits);
226 | }
227 | }
228 |
229 | DHGLRC APIENTRY DrvCreateContext(HDC hdc)
230 | {
231 | return (DHGLRC)1;
232 | }
233 |
234 | DHGLRC APIENTRY DrvCreateLayerContext(HDC hdc, INT iLayerPlane)
235 | {
236 | return (DHGLRC)1;
237 | }
238 |
239 | BOOL APIENTRY DrvDeleteContext(DHGLRC dhglrc)
240 | {
241 | return wgl_delete_context(dhglrc);
242 | }
243 |
244 | BOOL APIENTRY DrvCopyContext(DHGLRC dhrcSource, DHGLRC dhrcDest, UINT fuMask)
245 | {
246 | return TRUE;
247 | }
248 |
249 | PGLCLTPROCTABLE APIENTRY DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE pfnSetProcTable)
250 | {
251 | return glimpl_GetProcTable();
252 | }
253 |
254 | BOOL APIENTRY DrvReleaseContext(DHGLRC dhglrc)
255 | {
256 | return TRUE;
257 | }
258 |
259 | BOOL APIENTRY DrvValidateVersion(ULONG ulVersion)
260 | {
261 | return TRUE;
262 | }
263 |
264 | BOOL APIENTRY DrvShareLists(DHGLRC dhglrc1, DHGLRC dhglrc2)
265 | {
266 | return TRUE;
267 | }
268 |
269 | PROC APIENTRY DrvGetProcAddress(LPCSTR lpszProc)
270 | {
271 | if (lpszProc[0] == 'g' && lpszProc[1] == 'l')
272 | return GetProcAddress(module_handle, lpszProc);
273 |
274 | if (lpszProc[0] == 'w' && lpszProc[1] == 'g' && lpszProc[2] == 'l')
275 | for (struct wgl_extension_entry *entry = wgl_extension_entries; entry->name; entry++)
276 | if (strcmp(lpszProc, entry->name) == 0)
277 | return entry->proc;
278 |
279 | return NULL;
280 | }
281 |
282 | void APIENTRY DrvSetCallbackProcs(INT nProcs, PROC *pProcs)
283 | {
284 | size_t size = MIN(nProcs * sizeof(*pProcs), sizeof(callbacks));
285 | memcpy(&callbacks, pProcs, size);
286 |
287 | return;
288 | }
289 |
290 | BOOL APIENTRY DrvDescribeLayerPlane(HDC hdc, INT iPixelFormat, INT iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
291 | {
292 | return FALSE;
293 | }
294 |
295 | int APIENTRY DrvGetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart, INT cEntries, COLORREF *pcr)
296 | {
297 | return 0;
298 | }
299 |
300 | int APIENTRY DrvSetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart, INT cEntries, CONST COLORREF *pcr)
301 | {
302 | return 0;
303 | }
304 |
305 | BOOL APIENTRY DrvRealizeLayerPalette(HDC hdc, INT iLayerPlane, BOOL bRealize)
306 | {
307 | return FALSE;
308 | }
309 |
310 | BOOL APIENTRY DrvSwapBuffers(HDC hdc)
311 | {
312 | static BITMAPINFO bmi = {
313 | .bmiHeader.biSize = sizeof(BITMAPINFO),
314 | .bmiHeader.biPlanes = 1,
315 | .bmiHeader.biBitCount = 32,
316 | .bmiHeader.biCompression = BI_RGB,
317 | .bmiHeader.biSizeImage = 0,
318 | .bmiHeader.biClrUsed = 0,
319 | .bmiHeader.biClrImportant = 0,
320 | .bmiHeader.biXPelsPerMeter = 0,
321 | .bmiHeader.biYPelsPerMeter = 0
322 | };
323 |
324 | static int init = 0;
325 | static void *framebuffer = NULL;
326 |
327 | if (!init) {
328 | bmi.bmiHeader.biWidth = max_width;
329 | bmi.bmiHeader.biHeight = -max_height;
330 |
331 | swap_sync_lock = pb_ptr(SGL_OFFSET_REGISTER_SWAP_BUFFERS_SYNC);
332 | framebuffer = glimpl_fb_address();
333 | init = 1;
334 | }
335 |
336 | spin_lock(swap_sync_lock);
337 |
338 | glimpl_swap_buffers(real_width, real_height, do_vflip, GL_BGRA); /* to-do: fix overlay so vflip and -Height won't be needed */
339 | SetDIBitsToDevice(hdc, 0, 0, real_width, real_height, 0, 0, 0, real_height, framebuffer, &bmi, DIB_RGB_COLORS);
340 | // StretchDIBits(hdc, 0, 0, real_width, real_height, 0, 0, real_width, real_height, framebuffer, &bmi, DIB_RGB_COLORS, SRCCOPY);
341 |
342 | spin_unlock(swap_sync_lock);
343 |
344 | return TRUE;
345 | }
346 |
347 | BOOL APIENTRY DrvPresentBuffers(HDC hdc, LPPRESENTBUFFERS data)
348 | {
349 | return TRUE;
350 | }
351 |
352 | BOOL APIENTRY DrvSwapLayerBuffers(HDC hdc, UINT fuPlanes)
353 | {
354 | if (fuPlanes & WGL_SWAP_MAIN_PLANE)
355 | return DrvSwapBuffers(hdc);
356 |
357 | return FALSE;
358 | }
359 |
360 | LONG APIENTRY DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd, PIXELFORMATDESCRIPTOR *ppfd)
361 | {
362 | if (!pfd_count)
363 | pfd_init();
364 |
365 | --iPixelFormat;
366 |
367 | if (iPixelFormat >= pfd_count || iPixelFormat < 0 || cjpfd != sizeof(PIXELFORMATDESCRIPTOR))
368 | return pfd_count;
369 |
370 | if (ppfd != NULL)
371 | memcpy(ppfd, &pfd_table[iPixelFormat], sizeof(PIXELFORMATDESCRIPTOR));
372 |
373 | return pfd_count;
374 | }
375 |
376 | BOOL APIENTRY DrvSetPixelFormat(HDC hdc, LONG iPixelFormat)
377 | {
378 | if (GetPixelFormat(hdc) == 0)
379 | SetPixelFormat(hdc, iPixelFormat, NULL);
380 |
381 | return TRUE;
382 | }
383 |
384 | // BOOL APIENTRY DrvMakeCurrent(HDC hDC, HGLRC hRC)
385 | // {
386 | // return TRUE;
387 | // }
388 |
389 | #endif
--------------------------------------------------------------------------------
/src/client/scratch.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #ifdef _WIN32
5 | #include
6 | #else
7 | #define __USE_GNU
8 | #define _GNU_SOURCE
9 | #include
10 | #include
11 | #include
12 | #endif
13 |
14 | static void *address = NULL;
15 | static size_t current_size = 0;
16 |
17 | static inline uintptr_t align_to_4kb(uintptr_t ptr)
18 | {
19 | return (ptr + 4095) & ~4095;
20 | }
21 |
22 | #ifdef _WIN32
23 | static void *windows_mremap(void *old_address, size_t old_size, size_t new_size)
24 | {
25 | MEMORY_BASIC_INFORMATION mbi;
26 | void *new_address;
27 |
28 | /*
29 | * check to see if we can extend the current allocation
30 | */
31 | if (VirtualQuery((char*)old_address + old_size, &mbi, sizeof(mbi)) == sizeof(mbi))
32 | if (mbi.State == MEM_FREE && mbi.RegionSize >= (new_size - old_size))
33 | if (VirtualAlloc((char*)old_address + old_size, new_size - old_size, MEM_COMMIT, PAGE_READWRITE))
34 | return old_address;
35 |
36 | /*
37 | * otherwise, allocate a new region, copy, free
38 | * this can be expensive, but will rarely be performed
39 | */
40 | new_address = VirtualAlloc(NULL, new_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
41 | if (new_address) {
42 | memcpy(new_address, old_address, old_size);
43 | VirtualFree(old_address, 0, MEM_RELEASE);
44 | return new_address;
45 | }
46 |
47 | return NULL;
48 | }
49 | #endif
50 |
51 | void *scratch_buffer_get(size_t size)
52 | {
53 | if (!current_size) {
54 | current_size = align_to_4kb(size);
55 | #ifdef _WIN32
56 | address = VirtualAlloc(NULL, current_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
57 | #else
58 | address = mmap(NULL, current_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
59 | #endif
60 | return address;
61 | }
62 | else {
63 | size_t aligned_size = align_to_4kb(size);
64 | if (current_size < aligned_size) {
65 | #ifdef _WIN32
66 | address = windows_mremap(address, current_size, aligned_size);
67 | #else
68 | address = mremap(address, current_size, aligned_size, MREMAP_MAYMOVE);
69 | #endif
70 | current_size = aligned_size;
71 | return address;
72 | }
73 |
74 | return address;
75 | }
76 | }
--------------------------------------------------------------------------------
/src/client/spinlock.c:
--------------------------------------------------------------------------------
1 | #include
2 | #if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
3 | #include
4 | #else
5 | // #warning Non-x86 platform detected, assuming ARM.
6 | #define _mm_pause() asm volatile("yield");
7 | #endif
8 |
9 | #ifdef _WIN32
10 | #include
11 | #endif
12 |
13 | void spin_lock(int *lock)
14 | {
15 | #ifndef _WIN32
16 | while (!__sync_bool_compare_and_swap(lock, 0, 1))
17 | _mm_pause();
18 | #else
19 | while (InterlockedCompareExchange(lock, 1, 0))
20 | _mm_pause();
21 | #endif
22 | }
23 |
24 | void spin_unlock(int volatile *lock)
25 | {
26 | #ifndef _WIN32
27 | asm volatile ("":::"memory");
28 | #endif
29 | *lock = 0;
30 | }
--------------------------------------------------------------------------------
/src/client/winmain.c:
--------------------------------------------------------------------------------
1 | #ifdef _WIN32 /* globbed */
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | static char env_value[16];
9 |
10 | BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved)
11 | {
12 | if (reason == DLL_PROCESS_ATTACH) {
13 | DWORD result;
14 |
15 | /*
16 | * some weird hack that can speed up processes, reducing apparent lag;
17 | * by setting the priority of the program to "low", we give the kernel
18 | * more CPU time, which is crucial because the kernel driver is how data
19 | * between the VM and host move.
20 | */
21 | result = GetEnvironmentVariableA("SGL_RUN_WITH_LOW_PRIORITY", env_value, 16);
22 | if (strcmp(env_value, "true") == 0)
23 | SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
24 |
25 | /*
26 | * if running a directx application via WineD3D, we don't need to perform a
27 | * vertical flip as the library appears to perform this action for us
28 | */
29 | result = GetEnvironmentVariableA("SGL_WINED3D_DONT_VFLIP", env_value, 16);
30 | if (strcmp(env_value, "true") == 0)
31 | windrv_set_vflip(FALSE);
32 |
33 | windrv_set_module_address(module);
34 | glimpl_init();
35 | }
36 | if (reason == DLL_PROCESS_DETACH)
37 | glimpl_goodbye();
38 |
39 | return TRUE;
40 | }
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/src/server/context.c:
--------------------------------------------------------------------------------
1 | #define SHAREDGL_HOST
2 | #include
3 | #include
4 | #include
5 |
6 | static bool is_vid_init = false;
7 | static int mw = 1920;
8 | static int mh = 1080;
9 | static bool is_overlay_string_init = false;
10 |
11 | void sgl_set_max_resolution(int width, int height)
12 | {
13 | mw = width;
14 | mh = height;
15 | }
16 |
17 | void sgl_get_max_resolution(int *width, int *height)
18 | {
19 | *width = mw;
20 | *height = mh;
21 | }
22 |
23 | struct sgl_host_context *sgl_context_create()
24 | {
25 | struct sgl_host_context *context = (struct sgl_host_context *)malloc(sizeof(struct sgl_host_context));
26 |
27 | if (!is_vid_init) {
28 | SDL_Init(SDL_INIT_VIDEO);
29 | is_vid_init = true;
30 | }
31 |
32 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
33 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
34 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
35 | SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
36 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
37 | SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
38 |
39 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
40 | SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
41 | // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
42 | // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
43 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
44 |
45 | context->window = SDL_CreateWindow(
46 | "SDL Offscreen Window",
47 | SDL_WINDOWPOS_CENTERED,
48 | SDL_WINDOWPOS_CENTERED,
49 | mw, mh,
50 | SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
51 | if (context->window == NULL) {
52 | fprintf(stderr, "%s: Failed to create window\n", __func__);
53 | SDL_Quit();
54 | exit(1);
55 | }
56 |
57 | context->gl_context = SDL_GL_CreateContext(context->window);
58 | if (context->gl_context == NULL) {
59 | fprintf(stderr, "%s: Failed to create GL context\n", __func__);
60 | SDL_DestroyWindow(context->window);
61 | SDL_Quit();
62 | exit(1);
63 | }
64 |
65 | sgl_set_current(context);
66 |
67 | if (!is_overlay_string_init) {
68 | overlay_set_renderer_string((char*)glGetString(GL_RENDERER));
69 | is_overlay_string_init = true;
70 | }
71 |
72 | return context;
73 | }
74 |
75 | void sgl_context_destroy(struct sgl_host_context *ctx)
76 | {
77 | sgl_set_current(NULL);
78 | SDL_DestroyWindow(ctx->window);
79 | SDL_GL_DeleteContext(ctx->gl_context);
80 | free(ctx);
81 | }
82 |
83 | #ifdef SGL_DEBUG_EMIT_FRAMES
84 | SDL_Window *window;
85 | #endif
86 |
87 | void sgl_set_current(struct sgl_host_context *ctx)
88 | {
89 | if (ctx == NULL)
90 | SDL_GL_MakeCurrent(NULL, NULL);
91 | else
92 | SDL_GL_MakeCurrent(ctx->window, ctx->gl_context);
93 |
94 | #ifdef SGL_DEBUG_EMIT_FRAMES
95 | if (ctx)
96 | window = ctx->window;
97 | #endif
98 | }
99 |
100 | void *sgl_read_pixels(unsigned int width, unsigned int height, void *data, int vflip, int format, size_t mem_usage)
101 | {
102 | static struct overlay_context overlay_ctx = { 0 };
103 |
104 | overlay_stage1(&overlay_ctx);
105 |
106 | glReadPixels(0, 0, mw, height, format, GL_UNSIGNED_BYTE, data); // GL_BGRA
107 | int *pdata = data;
108 |
109 | if (vflip) {
110 | for (int y = 0; y < height / 2; y++) {
111 | for (int x = 0; x < mw; x++) {
112 | int *ptop = &pdata[y * mw + x];
113 | int *pbottom = &pdata[(height - y - 1) * mw + x];
114 |
115 | int vtop = *ptop;
116 | int vbottom = *pbottom;
117 |
118 | *ptop = vbottom;
119 | *pbottom = vtop;
120 | }
121 | }
122 | }
123 |
124 | overlay_stage2(&overlay_ctx, data, mw, mem_usage);
125 |
126 | #ifdef SGL_DEBUG_EMIT_FRAMES
127 | SDL_GL_SwapWindow(window);
128 | #endif
129 |
130 | return data;
131 | }
--------------------------------------------------------------------------------
/src/server/dynarr.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | void *dynarr_alloc(void **root, size_t next_offset, size_t size)
5 | {
6 | /*
7 | * if list hasn't started, then start the dam list
8 | */
9 | if (*root == NULL) {
10 | *root = calloc(1, size);
11 | return *root;
12 | }
13 |
14 | /*
15 | * otherwise, iterate through the list until we find the next spot to allocate to
16 | */
17 | void *next;
18 |
19 | /*
20 | * iterate through root until next = NULL
21 | */
22 | for (next = *root; *(void**)(next + next_offset); next = *(void**)(next + next_offset));
23 |
24 | /*
25 | * allocation
26 | */
27 | *(void**)(next + next_offset) = calloc(1, size);
28 |
29 | return *(void**)(next + next_offset);
30 | }
31 |
32 | void dynarr_free_element(void **root, size_t next_offset, dynarr_match_fn matcher, void *data)
33 | {
34 | void *prev = NULL;
35 |
36 | for (void *elem = *root; elem;) {
37 | void *next = *(void**)(elem + next_offset);
38 |
39 | if (matcher(elem, data)) {
40 | /*
41 | * check if element is first, otherwise doesn't matter
42 | */
43 | if (prev == NULL)
44 | *root = next;
45 | else
46 | *(void**)(prev + next_offset) = next;
47 |
48 | free(elem);
49 | }
50 | else
51 | prev = elem;
52 |
53 | elem = next;
54 | }
55 | }
56 |
57 | void dynarr_free(void **root, size_t next_offset)
58 | {
59 | /*
60 | * recursively call up until the last element
61 | * (elements need to be freed in reverse order)
62 | */
63 | if (*(void**)(root)) {
64 | dynarr_free(*(void**)(root + next_offset), next_offset);
65 | free(*root);
66 | }
67 | }
--------------------------------------------------------------------------------
/src/server/main.c:
--------------------------------------------------------------------------------
1 | #define SHAREDGL_HOST
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 |
18 | #include
19 | #include
20 |
21 | static void *shm_ptr;
22 | static size_t shm_size;
23 |
24 | static int *internal_cmd_ptr;
25 |
26 | static const char *usage =
27 | "usage: sglrenderer [-h] [-v] [-o] [-n] [-x] [-g MAJOR.MINOR] [-r WIDTHxHEIGHT] [-m SIZE] [-p PORT]\n"
28 | "\n"
29 | "options:\n"
30 | " -h display help information\n"
31 | " -v display virtual machine arguments\n"
32 | " -o enables fps overlay on clients\n"
33 | " -n enable network server instead of using shared memory\n"
34 | " -x remove shared memory file\n"
35 | " -g [MAJOR.MINOR] report specific opengl version (default: %d.%d)\n"
36 | " -r [WIDTHxHEIGHT] set max resolution (default: 1920x1080)\n"
37 | " -m [SIZE] max amount of megabytes program may allocate (default: 32mib)\n"
38 | " -p [PORT] if networking is enabled, specify which port to use (default: 3000)\n";
39 |
40 | static void generate_virtual_machine_arguments(size_t m)
41 | {
42 | static const char *libvirt_string =
43 | "\n"
44 | " \n"
45 | " %ld\n"
46 | "\n";
47 |
48 | static const char *qemu_string =
49 | "-object memory-backend-file,size=%ldM,share,mem-path=/dev/shm/" SGL_SHARED_MEMORY_NAME ",id=" SGL_SHARED_MEMORY_NAME "\n";
50 |
51 | fprintf(stderr, "\nlibvirt:\n");
52 | fprintf(stderr, libvirt_string, m);
53 | fprintf(stderr, "\nqemu:\n");
54 | fprintf(stderr, qemu_string, m);
55 | fprintf(stderr, "\n");
56 | }
57 |
58 | static void term_handler(int sig)
59 | {
60 | munmap(shm_ptr, shm_size);
61 | int icmd = *internal_cmd_ptr;
62 |
63 | switch (sig) {
64 | case SIGINT:
65 | break;
66 | case SIGSEGV:
67 | PRINT_LOG("server stopped! segmentation fault on %s (%d)\n", sgl_cmd2str(icmd), icmd);
68 | break;
69 | // shouldn't ever reach here
70 | case SIGPIPE:
71 | PRINT_LOG("server stopped! socket unexpectedly closed\n");
72 | break;
73 | }
74 |
75 | exit(1);
76 | }
77 |
78 | static void arg_parser_protector(int sig)
79 | {
80 | PRINT_LOG("expected second argument\n");
81 | exit(1);
82 | }
83 |
84 | int main(int argc, char **argv)
85 | {
86 | bool print_virtual_machine_arguments = false;
87 |
88 | bool network_over_shared = false;
89 | int port = 3000;
90 |
91 | int major = SGL_DEFAULT_MAJOR;
92 | int minor = SGL_DEFAULT_MINOR;
93 |
94 | shm_size = 32;
95 |
96 | signal(SIGSEGV, arg_parser_protector);
97 |
98 | for (int i = 1; i < argc; i++) {
99 | switch (argv[i][1]) {
100 | case 'h':
101 | fprintf(stderr, usage, SGL_DEFAULT_MAJOR, SGL_DEFAULT_MINOR);
102 | return 0;
103 | case 'v':
104 | print_virtual_machine_arguments = true;
105 | break;
106 | case 'n':
107 | network_over_shared = true;
108 | break;
109 | case 'o':
110 | overlay_enable();
111 | break;
112 | case 'x':
113 | shm_unlink(SGL_SHARED_MEMORY_NAME);
114 | PRINT_LOG("unlinked shared memory '%s'\n", SGL_SHARED_MEMORY_NAME);
115 | return 0;
116 | case 'g':
117 | major = argv[i + 1][0] - '0';
118 | minor = argv[i + 1][2] - '0';
119 | i++;
120 | break;
121 | case 'r': {
122 | int width, height, j;
123 | for (j = 0; j < strlen(argv[i + 1]); j++)
124 | if (argv[i + 1][j] == 'x')
125 | break;
126 | sgl_set_max_resolution(
127 | atoi(argv[i + 1]),
128 | atoi(&argv[i + 1][j + 1])
129 | );
130 | i++;
131 | break;
132 | }
133 | case 'm':
134 | shm_size = atoi(argv[i + 1]);
135 | i++;
136 | break;
137 | case 'p':
138 | port = atoi(argv[i + 1]);
139 | i++;
140 | break;
141 | default:
142 | PRINT_LOG("unrecognized command-line option '%s'\n", argv[i]);
143 | }
144 | }
145 |
146 | signal(SIGINT, term_handler);
147 | signal(SIGSEGV, term_handler);
148 | signal(SIGPIPE, SIG_IGN);
149 |
150 | PRINT_LOG("press CTRL+C to terminate server\n");
151 |
152 | if (print_virtual_machine_arguments) {
153 | if (!network_over_shared)
154 | generate_virtual_machine_arguments(shm_size);
155 | else
156 | PRINT_LOG("command line argument '-v' ignored as networking is enabled\n");
157 | }
158 |
159 | /*
160 | * allocate memory, only create a shared memory file if using shared memory
161 | */
162 | shm_size *= 1024 * 1024;
163 | if (!network_over_shared) {
164 | int shm_fd = shm_open(SGL_SHARED_MEMORY_NAME, O_CREAT | O_RDWR, S_IRWXU);
165 | if (shm_fd == -1) {
166 | PRINT_LOG("failed to open shared memory '%s'\n", SGL_SHARED_MEMORY_NAME);
167 | return -1;
168 | }
169 |
170 | if (ftruncate(shm_fd, shm_size) == -1) {
171 | PRINT_LOG("failed to truncate shared memory\n");
172 | return -2;
173 | }
174 |
175 | shm_ptr = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
176 | }
177 | else {
178 | shm_ptr = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
179 | }
180 |
181 | PRINT_LOG("reserved %ld MiB of memory\n", shm_size / 1024 / 1024);
182 |
183 | struct sgl_cmd_processor_args args = {
184 | .base_address = shm_ptr,
185 | .memory_size = shm_size,
186 |
187 | .network_over_shared = network_over_shared,
188 | .port = port,
189 |
190 | .gl_major = major,
191 | .gl_minor = minor,
192 |
193 | .internal_cmd_ptr = &internal_cmd_ptr,
194 | };
195 |
196 | int mw, mh;
197 | sgl_get_max_resolution(&mw, &mh);
198 | PRINT_LOG("maximum resolution set to %dx%d\n", mw, mh);
199 | PRINT_LOG("reporting gl version %d.%d\n", major, minor);
200 |
201 | sgl_cmd_processor_start(args);
202 | }
--------------------------------------------------------------------------------
/src/server/overlay.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | static void overlay_draw_char(int *display, int width, char c, int x, int y, unsigned int fg)
9 | {
10 | int mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
11 | const unsigned char *gylph = IBM + (int)c * CHAR_HEIGHT;
12 |
13 | unsigned char *color;
14 |
15 | for (int cy = 0; cy < CHAR_HEIGHT; cy++)
16 | for (int cx = 0; cx < CHAR_WIDTH; cx++) {
17 | /*
18 | * darken pixels
19 | */
20 | color = (unsigned char*)&display[(y + cy) * width + (x + ((CHAR_WIDTH - 1) - cx))];
21 | color[0] = color[0] * 120 / 255;
22 | color[1] = color[1] * 120 / 255;
23 | color[2] = color[2] * 120 / 255;
24 | color[3] = color[3] * 120 / 255;
25 |
26 | if (gylph[cy] & mask[cx])
27 | display[(y + cy) * width + (x + ((CHAR_WIDTH - 1) - cx))] = fg;
28 | }
29 | }
30 |
31 | static void overlay_draw_text(int *display, int width, char *text, int x, int y, unsigned int fg)
32 | {
33 | char* c = text;
34 | for (int i = x; *c; i += CHAR_WIDTH)
35 | overlay_draw_char(
36 | display,
37 | width,
38 | *c++,
39 | i,
40 | y,
41 | fg
42 | );
43 | }
44 |
45 | static bool overlay_enabled = false;
46 | static char overlay_string[256] = "SharedGL using ";
47 |
48 | void overlay_set_renderer_string(char *string)
49 | {
50 | strcpy(overlay_string + 15, string);
51 | }
52 |
53 | void overlay_enable()
54 | {
55 | overlay_enabled = true;
56 | }
57 |
58 | void overlay_stage1(struct overlay_context *ctx)
59 | {
60 | if (!overlay_enabled)
61 | return;
62 |
63 | ctx->delta_ticks = clock() - ctx->current_ticks;
64 | if (ctx->current_ticks && ctx->delta_ticks != 0)
65 | ctx->fps = CLOCKS_PER_SEC / ctx->delta_ticks;
66 | }
67 |
68 | void overlay_stage2(struct overlay_context *ctx, int *frame, int width, size_t mem_usage)
69 | {
70 | if (!overlay_enabled)
71 | return;
72 |
73 | double usage = mem_usage;
74 | bool is_mb = false;
75 |
76 | if (mem_usage > 0x100000) {
77 | usage /= 0x100000;
78 | is_mb = true;
79 | }
80 | else {
81 | usage /= 0x1000;
82 | }
83 |
84 | if (ctx->current_ticks) {
85 | char str[12];
86 | char mem[24];
87 | sprintf(str, "FPS: %ld", ctx->fps);
88 | sprintf(mem, "MEM: %.2f %s", usage, is_mb ? "MB" : "KB");
89 |
90 | overlay_draw_text(frame, width, overlay_string, 0, CHAR_HEIGHT * 0, 0xffffff);
91 | overlay_draw_text(frame, width, mem, 0, CHAR_HEIGHT * 1, 0xffffff);
92 | overlay_draw_text(frame, width, str, 0, CHAR_HEIGHT * 2, 0xffffff);
93 | }
94 |
95 | ctx->current_ticks = clock();
96 | }
--------------------------------------------------------------------------------