├── lwjgl3-swt-common ├── .gitignore ├── src │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── lwjgl │ │ │ ├── vulkan │ │ │ └── swt │ │ │ │ ├── VKData.java │ │ │ │ ├── PlatformVKCanvas.java │ │ │ │ └── VKCanvas.java │ │ │ └── opengl │ │ │ └── swt │ │ │ ├── PlatformGLCanvas.java │ │ │ ├── AbstractPlatformGLCanvas.java │ │ │ ├── GLCanvas.java │ │ │ └── GLData.java │ └── test │ │ └── java │ │ └── org │ │ └── lwjgl │ │ └── vulkan │ │ └── swt │ │ ├── VKUtil.java │ │ └── SimpleDemo.java └── pom.xml ├── lwjgl3-swt-linux ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── lwjgl │ └── opengl │ └── swt │ └── PlatformLinuxGLCanvas.java ├── lwjgl3-swt-macos ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── lwjgl │ └── opengl │ └── swt │ └── PlatformMacOSXGLCanvas.java ├── lwjgl3-swt-windows ├── .gitignore ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── lwjgl │ │ │ └── opengl │ │ │ └── swt │ │ │ ├── SwtHelperWin32.java │ │ │ ├── NvGLESDemo.java │ │ │ ├── Swt33CoreMsDemo.java │ │ │ └── SharedContextsDemo.java │ └── main │ │ └── java │ │ └── org │ │ └── lwjgl │ │ ├── vulkan │ │ └── swt │ │ │ └── PlatformWin32VKCanvas.java │ │ └── opengl │ │ └── swt │ │ └── PlatformWin32GLCanvas.java └── pom.xml ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .github └── workflows │ └── build-and-publish.yaml ├── LICENSE ├── README.md ├── gradlew.bat ├── gradlew ├── mvnw.cmd ├── mvnw └── pom.xml /lwjgl3-swt-common/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.classpath 3 | /.project 4 | /.settings/ 5 | -------------------------------------------------------------------------------- /lwjgl3-swt-linux/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.classpath 3 | /.project 4 | /.settings/ 5 | -------------------------------------------------------------------------------- /lwjgl3-swt-macos/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.classpath 3 | /.project 4 | /.settings/ 5 | -------------------------------------------------------------------------------- /lwjgl3-swt-windows/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.classpath 3 | /.project 4 | /.settings/ 5 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LWJGLX/lwjgl3-swt/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LWJGLX/lwjgl3-swt/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle/ 2 | /.settings/ 3 | /build/ 4 | /dist/ 5 | /nbproject/ 6 | /target/ 7 | /bin/ 8 | /.idea/ 9 | /out/ 10 | /.classpath 11 | /.project 12 | *.iml 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar 3 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/main/java/org/lwjgl/vulkan/swt/VKData.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.vulkan.swt; 2 | 3 | import org.lwjgl.vulkan.VkInstance; 4 | 5 | /** 6 | * Contains information to create a {@link VKCanvas}. 7 | * 8 | * @author Kai Burjack 9 | */ 10 | public class VKData { 11 | 12 | /** 13 | * The {@link VkInstance} on behalf of which to create a window surface. 14 | */ 15 | public VkInstance instance; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/main/java/org/lwjgl/vulkan/swt/PlatformVKCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.vulkan.swt; 2 | 3 | import org.eclipse.swt.widgets.Composite; 4 | import org.lwjgl.vulkan.VkPhysicalDevice; 5 | 6 | public interface PlatformVKCanvas { 7 | 8 | int checkStyle(Composite parent, int style); 9 | 10 | void resetStyle(Composite parent); 11 | 12 | long create(Composite composite, VKData data); 13 | 14 | boolean getPhysicalDevicePresentationSupport(VkPhysicalDevice physicalDevice, int queueFamily); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /lwjgl3-swt-windows/src/test/java/org/lwjgl/opengl/swt/SwtHelperWin32.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import org.eclipse.swt.internal.win32.OS; 4 | import org.eclipse.swt.widgets.Shell; 5 | 6 | public class SwtHelperWin32 { 7 | 8 | public static void properFullscreen(Shell shell) { 9 | if (!shell.getFullScreen()) { 10 | int lStyle = OS.GetWindowLong(shell.handle, OS.GWL_STYLE); 11 | lStyle &= ~OS.WS_THICKFRAME; 12 | OS.SetWindowLong(shell.handle, OS.GWL_STYLE, lStyle); 13 | } else { 14 | int lStyle = OS.GetWindowLong(shell.handle, OS.GWL_STYLE); 15 | lStyle ^= OS.WS_THICKFRAME; 16 | OS.SetWindowLong(shell.handle, OS.GWL_STYLE, lStyle); 17 | } 18 | shell.setFullScreen(!shell.getFullScreen()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/main/java/org/lwjgl/opengl/swt/PlatformGLCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import org.eclipse.swt.widgets.Composite; 4 | 5 | /** 6 | * Interface of platform-specific GLCanvas delegate classes. 7 | * 8 | * @author Kai Burjack 9 | */ 10 | interface PlatformGLCanvas { 11 | 12 | long create(GLCanvas canvas, GLData attribs, GLData effective); 13 | 14 | boolean isCurrent(long context); 15 | 16 | boolean makeCurrent(GLCanvas canvas, long context); 17 | 18 | boolean deleteContext(GLCanvas canvas, long context); 19 | 20 | boolean swapBuffers(GLCanvas canvas); 21 | 22 | boolean delayBeforeSwapNV(GLCanvas canvas, float seconds); 23 | 24 | int checkStyle(Composite parent, int style); 25 | 26 | void resetStyle(Composite parent); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/build-and-publish.yaml: -------------------------------------------------------------------------------- 1 | name: build-and-publish 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | if: ${{ github.repository_owner == 'LWJGLX' }} 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Set up JDK 1.8 13 | uses: actions/setup-java@v1 14 | with: 15 | java-version: 1.8 16 | - name: Cache local Maven repository 17 | uses: actions/cache@v2 18 | with: 19 | path: ~/.m2/repository 20 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} 21 | restore-keys: | 22 | ${{ runner.os }}-maven- 23 | - name: Build with Maven 24 | run: ./mvnw -B package 25 | - name: Release Maven package 26 | uses: samuelmeuli/action-maven-publish@v1 27 | with: 28 | gpg_private_key: ${{ secrets.gpg_private_key }} 29 | gpg_passphrase: ${{ secrets.gpg_passphrase }} 30 | nexus_username: ${{ secrets.nexus_username }} 31 | nexus_password: ${{ secrets.nexus_password }} 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kai Burjack 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. 22 | 23 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | org.lwjglx 8 | lwjgl3-swt 9 | 1.0.0 10 | 11 | 12 | lwjgl3-swt-common 13 | 14 | 15 | 16 | windows 17 | 18 | 19 | Windows 20 | 21 | 22 | 23 | 24 | org.eclipse.platform 25 | org.eclipse.swt.win32.win32.x86_64 26 | 27 | 28 | 29 | 30 | linux 31 | 32 | 33 | Linux 34 | 35 | 36 | 37 | 38 | org.eclipse.platform 39 | org.eclipse.swt.gtk.linux.x86_64 40 | 41 | 42 | 43 | 44 | mac 45 | 46 | 47 | Mac 48 | 49 | 50 | 51 | macos 52 | 53 | 54 | 55 | org.eclipse.platform 56 | org.eclipse.swt.cocoa.macosx.x86_64 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /lwjgl3-swt-linux/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | org.lwjglx 8 | lwjgl3-swt 9 | 1.0.0 10 | 11 | 12 | lwjgl3-swt-linux 13 | 14 | 15 | 16 | ${project.groupId} 17 | lwjgl3-swt-common 18 | ${project.version} 19 | 20 | 21 | org.eclipse.platform 22 | org.eclipse.swt.win32.win32.x86_64 23 | 24 | 25 | org.eclipse.platform 26 | org.eclipse.swt.gtk.linux.x86_64 27 | 28 | 29 | org.eclipse.platform 30 | org.eclipse.swt.cocoa.macosx.x86_64 31 | 32 | 33 | 34 | 35 | org.eclipse.platform 36 | org.eclipse.swt.gtk.linux.x86_64 37 | 38 | 39 | org.lwjgl 40 | lwjgl 41 | natives-linux 42 | 43 | 44 | org.lwjgl 45 | lwjgl-opengl 46 | natives-linux 47 | 48 | 49 | org.lwjgl 50 | lwjgl-opengles 51 | natives-linux 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /lwjgl3-swt-macos/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | org.lwjglx 8 | lwjgl3-swt 9 | 1.0.0 10 | 11 | 12 | lwjgl3-swt-macos 13 | 14 | 15 | 16 | ${project.groupId} 17 | lwjgl3-swt-common 18 | ${project.version} 19 | 20 | 21 | org.eclipse.platform 22 | org.eclipse.swt.win32.win32.x86_64 23 | 24 | 25 | org.eclipse.platform 26 | org.eclipse.swt.gtk.linux.x86_64 27 | 28 | 29 | org.eclipse.platform 30 | org.eclipse.swt.cocoa.macosx.x86_64 31 | 32 | 33 | 34 | 35 | org.eclipse.platform 36 | org.eclipse.swt.cocoa.macosx.x86_64 37 | 38 | 39 | org.lwjgl 40 | lwjgl 41 | natives-macos 42 | 43 | 44 | org.lwjgl 45 | lwjgl-opengl 46 | natives-macos 47 | 48 | 49 | org.lwjgl 50 | lwjgl-opengles 51 | natives-macos 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /lwjgl3-swt-windows/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | org.lwjglx 8 | lwjgl3-swt 9 | 1.0.0 10 | 11 | 12 | lwjgl3-swt-windows 13 | 14 | 15 | 16 | ${project.groupId} 17 | lwjgl3-swt-common 18 | ${project.version} 19 | 20 | 21 | org.eclipse.platform 22 | org.eclipse.swt.win32.win32.x86_64 23 | 24 | 25 | org.eclipse.platform 26 | org.eclipse.swt.gtk.linux.x86_64 27 | 28 | 29 | org.eclipse.platform 30 | org.eclipse.swt.cocoa.macosx.x86_64 31 | 32 | 33 | 34 | 35 | org.eclipse.platform 36 | org.eclipse.swt.win32.win32.x86_64 37 | 38 | 39 | org.lwjgl 40 | lwjgl 41 | natives-windows 42 | 43 | 44 | org.lwjgl 45 | lwjgl-opengl 46 | natives-windows 47 | 48 | 49 | org.lwjgl 50 | lwjgl-opengles 51 | natives-windows 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /lwjgl3-swt-windows/src/main/java/org/lwjgl/vulkan/swt/PlatformWin32VKCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.vulkan.swt; 2 | 3 | import static org.lwjgl.system.MemoryStack.*; 4 | import static org.lwjgl.vulkan.KHRWin32Surface.*; 5 | import static org.lwjgl.vulkan.VK10.*; 6 | 7 | import java.nio.LongBuffer; 8 | 9 | import org.eclipse.swt.SWTException; 10 | import org.eclipse.swt.internal.win32.OS; 11 | import org.eclipse.swt.widgets.Composite; 12 | import org.lwjgl.vulkan.VkPhysicalDevice; 13 | import org.lwjgl.vulkan.VkWin32SurfaceCreateInfoKHR; 14 | 15 | public class PlatformWin32VKCanvas implements PlatformVKCanvas { 16 | private static final String USE_OWNDC_KEY = "org.eclipse.swt.internal.win32.useOwnDC"; 17 | 18 | public int checkStyle(Composite parent, int style) { 19 | // Somehow we need to temporarily set 'org.eclipse.swt.internal.win32.useOwnDC' to true or else context creation on Windows fails... 20 | if (parent != null) { 21 | // Removed windows version check - SWT dropped support for windows before Vista 22 | // https://github.com/eclipse/eclipse.platform.swt/commit/84c9e305cb087110cb300a5e58f86583cf80914d#diff-bb4584995e162b851fafacf3b046cc35 23 | parent.getDisplay().setData(USE_OWNDC_KEY, Boolean.TRUE); 24 | } 25 | return style; 26 | } 27 | 28 | public void resetStyle(Composite parent) { 29 | parent.getDisplay().setData(USE_OWNDC_KEY, Boolean.FALSE); 30 | } 31 | 32 | @Override 33 | public long create(Composite composite, VKData data) { 34 | VkWin32SurfaceCreateInfoKHR sci = VkWin32SurfaceCreateInfoKHR.callocStack() 35 | .sType(VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) 36 | .hinstance(OS.GetModuleHandle(null)) 37 | .hwnd(composite.handle); 38 | LongBuffer pSurface = stackMallocLong(1); 39 | int err = vkCreateWin32SurfaceKHR(data.instance, sci, null, pSurface); 40 | long surface = pSurface.get(0); 41 | if (err != VK_SUCCESS) { 42 | throw new SWTException("Calling vkCreateWin32SurfaceKHR failed with error: " + err); 43 | } 44 | return surface; 45 | } 46 | 47 | public boolean getPhysicalDevicePresentationSupport(VkPhysicalDevice physicalDevice, int queueFamily) { 48 | return vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamily); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What is it? 2 | 3 | Revised drop-in implementation of SWT's GLCanvas. 4 | 5 | ## What does it get me? 6 | 7 | Support for: 8 | - creating OpenGL 3.0 and 3.2 core/compatibility contexts (including debug/forward compatible) 9 | - OpenGL ES contexts 10 | - no error contexts 11 | - floating-point and sRGB pixel formats 12 | - multisampled framebuffers (also with different number of color samples - Nvidia only) 13 | - v-sync/swap control 14 | - context flush control 15 | - robust buffer access (with application/share-group isolation) 16 | - sync'ing buffer swaps over multiple windows and cards - Nvidia only 17 | - delay before swap - Nvidia only 18 | 19 | ## Why does it exist? 20 | 21 | The above features have been lacking for some years in the SWT-provided GLCanvas implementation. 22 | The purpose of the new implementation on top of LWJGL 3 is to have full support for those features in an OpenGL SWT application. 23 | 24 | ## How to use it? 25 | 26 | In your existing SWT application just replace all imports of `org.eclipse.swt.opengl.*` with `org.lwjgl.opengl.swt.*`. 27 | The new implementation is a drop-in replacement, which means that your current SWT code should work like before. 28 | To use the new features you can use the new fields in the `GLData` class, such as using real multisampled framebuffers or creating a OpenGL 3.2 core context. 29 | 30 | If your current OpenGL SWT setup looks like this: 31 | ```Java 32 | Display display = new Display(); 33 | Shell shell = new Shell(display); 34 | shell.setLayout(new FillLayout()); 35 | GLData data = new GLData(); 36 | GLCanvas canvas = new GLCanvas(shell, 0, data); 37 | ``` 38 | then adding multisampling and using a OpenGL 3.2 core context is as easy as doing: 39 | ```Java 40 | Display display = new Display(); 41 | Shell shell = new Shell(display); 42 | shell.setLayout(new FillLayout()); 43 | GLData data = new GLData(); 44 | data.profile = GLData.Profile.CORE; 45 | data.majorVersion = 3; 46 | data.minorVersion = 2; 47 | data.samples = 4; // 4x multisampling 48 | data.swapInterval = 1; // for enabling v-sync (swapbuffers sync'ed to monitor refresh) 49 | GLCanvas canvas = new GLCanvas(shell, 0, data); 50 | ``` 51 | 52 | ## Vulkan support 53 | 54 | Much like with the GLCanvas/GLData for OpenGL there is now also first exprimental Win32 support for Vulkan: 55 | ```Java 56 | Display display = new Display(); 57 | Shell shell = new Shell(display); 58 | shell.setLayout(new FillLayout()); 59 | VKData data = new VKData(); 60 | data.instance = instance; // <- the VkInstance created outside via LWJGL 3 61 | VKCanvas canvas = new VKCanvas(shell, 0, data); 62 | long surface = canvas.surface; 63 | ``` 64 | 65 | ## What is planned for the future? 66 | 67 | Support for: 68 | - Vulkan 69 | - associating rendering contexts with specific GPUs on Nvidia and AMD 70 | - pbuffers (there are interesting extensions that are only supported for pbuffers, such as EXT_packed_float and NV_video_output) 71 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/main/java/org/lwjgl/vulkan/swt/VKCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.vulkan.swt; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.widgets.Canvas; 5 | import org.eclipse.swt.widgets.Composite; 6 | import org.lwjgl.system.Platform; 7 | import org.lwjgl.vulkan.VkPhysicalDevice; 8 | 9 | /** 10 | * A SWT {@link Canvas} that supports to be drawn on using Vulkan. 11 | * 12 | * @author Kai Burjack 13 | */ 14 | public class VKCanvas extends Canvas { 15 | private static PlatformVKCanvas platformCanvas; 16 | static { 17 | String platformClassName; 18 | switch (Platform.get()) { 19 | case WINDOWS: 20 | platformClassName = "org.lwjgl.vulkan.swt.PlatformWin32VKCanvas"; 21 | break; 22 | default: 23 | throw new AssertionError("NYI"); 24 | } 25 | try { 26 | @SuppressWarnings("unchecked") 27 | Class clazz = (Class) VKCanvas.class.getClassLoader().loadClass(platformClassName); 28 | platformCanvas = clazz.newInstance(); 29 | } catch (ClassNotFoundException e) { 30 | throw new AssertionError("Platform-specific VKCanvas class not found: " + platformClassName); 31 | } catch (InstantiationException e) { 32 | throw new AssertionError("Could not instantiate platform-specific VKCanvas class: " + platformClassName); 33 | } catch (IllegalAccessException e) { 34 | throw new AssertionError("Could not instantiate platform-specific VKCanvas class: " + platformClassName); 35 | } 36 | } 37 | 38 | /** 39 | * The Vulkan surface handle for this {@link VKCanvas}. 40 | */ 41 | public long surface; 42 | 43 | /** 44 | * Create a {@link VKCanvas} widget using the attributes described in the supplied {@link VKData} object. 45 | * 46 | * @param parent 47 | * a parent composite widget 48 | * @param style 49 | * the bitwise OR'ing of widget styles 50 | * @param data 51 | * the necessary data to create a VKCanvas 52 | */ 53 | public VKCanvas(Composite parent, int style, VKData data) { 54 | super(parent, platformCanvas.checkStyle(parent, style)); 55 | if (Platform.get() == Platform.WINDOWS) { 56 | platformCanvas.resetStyle(parent); 57 | } 58 | if (data == null) 59 | SWT.error(SWT.ERROR_NULL_ARGUMENT); 60 | surface = platformCanvas.create(this, data); 61 | } 62 | 63 | /** 64 | * Determine whether there is presentation support for the given {@link VkPhysicalDevice} in a command queue of the specified 65 | * queueFamiliy. 66 | * 67 | * @param physicalDevice 68 | * the Vulkan {@link VkPhysicalDevice} 69 | * @param queueFamily 70 | * the command queue family 71 | * @return true of false 72 | */ 73 | public boolean getPhysicalDevicePresentationSupport(VkPhysicalDevice physicalDevice, int queueFamily) { 74 | return platformCanvas.getPhysicalDevicePresentationSupport(physicalDevice, queueFamily); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem http://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/test/java/org/lwjgl/vulkan/swt/VKUtil.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.vulkan.swt; 2 | 3 | import static org.lwjgl.vulkan.EXTDebugReport.*; 4 | import static org.lwjgl.vulkan.KHRDisplaySwapchain.*; 5 | import static org.lwjgl.vulkan.KHRSurface.*; 6 | import static org.lwjgl.vulkan.KHRSwapchain.*; 7 | import static org.lwjgl.vulkan.VK10.*; 8 | 9 | public class VKUtil { 10 | 11 | /** 12 | * Translates a Vulkan {@code VkResult} value to a String describing the result. 13 | * 14 | * @param result 15 | * the {@code VkResult} value 16 | * 17 | * @return the result description 18 | */ 19 | public static String translateVulkanResult(int result) { 20 | switch (result) { 21 | // Success codes 22 | case VK_SUCCESS: 23 | return "Command successfully completed."; 24 | case VK_NOT_READY: 25 | return "A fence or query has not yet completed."; 26 | case VK_TIMEOUT: 27 | return "A wait operation has not completed in the specified time."; 28 | case VK_EVENT_SET: 29 | return "An event is signaled."; 30 | case VK_EVENT_RESET: 31 | return "An event is unsignaled."; 32 | case VK_INCOMPLETE: 33 | return "A return array was too small for the result."; 34 | case VK_SUBOPTIMAL_KHR: 35 | return "A swapchain no longer matches the surface properties exactly, but can still be used to present to the surface successfully."; 36 | 37 | // Error codes 38 | case VK_ERROR_OUT_OF_HOST_MEMORY: 39 | return "A host memory allocation has failed."; 40 | case VK_ERROR_OUT_OF_DEVICE_MEMORY: 41 | return "A device memory allocation has failed."; 42 | case VK_ERROR_INITIALIZATION_FAILED: 43 | return "Initialization of an object could not be completed for implementation-specific reasons."; 44 | case VK_ERROR_DEVICE_LOST: 45 | return "The logical or physical device has been lost."; 46 | case VK_ERROR_MEMORY_MAP_FAILED: 47 | return "Mapping of a memory object has failed."; 48 | case VK_ERROR_LAYER_NOT_PRESENT: 49 | return "A requested layer is not present or could not be loaded."; 50 | case VK_ERROR_EXTENSION_NOT_PRESENT: 51 | return "A requested extension is not supported."; 52 | case VK_ERROR_FEATURE_NOT_PRESENT: 53 | return "A requested feature is not supported."; 54 | case VK_ERROR_INCOMPATIBLE_DRIVER: 55 | return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons."; 56 | case VK_ERROR_TOO_MANY_OBJECTS: 57 | return "Too many objects of the type have already been created."; 58 | case VK_ERROR_FORMAT_NOT_SUPPORTED: 59 | return "A requested format is not supported on this device."; 60 | case VK_ERROR_SURFACE_LOST_KHR: 61 | return "A surface is no longer available."; 62 | case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: 63 | return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API."; 64 | case VK_ERROR_OUT_OF_DATE_KHR: 65 | return "A surface has changed in such a way that it is no longer compatible with the swapchain, and further presentation requests using the " 66 | + "swapchain will fail. Applications must query the new surface properties and recreate their swapchain if they wish to continue" + "presenting to the surface."; 67 | case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: 68 | return "The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an" + " image."; 69 | case VK_ERROR_VALIDATION_FAILED_EXT: 70 | return "A validation layer found an error."; 71 | default: 72 | return String.format("%s [%d]", "Unknown", Integer.valueOf(result)); 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/test/java/org/lwjgl/vulkan/swt/SimpleDemo.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.vulkan.swt; 2 | 3 | import static org.lwjgl.system.MemoryUtil.*; 4 | import static org.lwjgl.vulkan.KHRSurface.*; 5 | import static org.lwjgl.vulkan.KHRWin32Surface.*; 6 | import static org.lwjgl.vulkan.KHRXlibSurface.*; 7 | import static org.lwjgl.vulkan.VK10.*; 8 | import static org.lwjgl.vulkan.swt.VKUtil.*; 9 | 10 | import java.nio.ByteBuffer; 11 | 12 | import org.eclipse.swt.SWT; 13 | import org.eclipse.swt.layout.FillLayout; 14 | import org.eclipse.swt.widgets.Display; 15 | import org.eclipse.swt.widgets.Event; 16 | import org.eclipse.swt.widgets.Listener; 17 | import org.eclipse.swt.widgets.Shell; 18 | import org.lwjgl.PointerBuffer; 19 | import org.lwjgl.system.MemoryUtil; 20 | import org.lwjgl.system.Platform; 21 | import org.lwjgl.vulkan.VkApplicationInfo; 22 | import org.lwjgl.vulkan.VkInstance; 23 | import org.lwjgl.vulkan.VkInstanceCreateInfo; 24 | 25 | /** 26 | * Shows how to create a simple Vulkan instance and a {@link VKCanvas}. 27 | * 28 | * @author Kai Burjack 29 | */ 30 | public class SimpleDemo { 31 | 32 | /** 33 | * Create a Vulkan instance using LWJGL 3. 34 | * 35 | * @return the VkInstance handle 36 | */ 37 | private static VkInstance createInstance() { 38 | VkApplicationInfo appInfo = VkApplicationInfo.calloc() 39 | .sType(VK_STRUCTURE_TYPE_APPLICATION_INFO) 40 | .pApplicationName(memUTF8("SWT Vulkan Demo")) 41 | .pEngineName(memUTF8("")) 42 | .apiVersion(VK_MAKE_VERSION(1, 0, 2)); 43 | ByteBuffer VK_KHR_SURFACE_EXTENSION = memUTF8(VK_KHR_SURFACE_EXTENSION_NAME); 44 | ByteBuffer VK_KHR_OS_SURFACE_EXTENSION; 45 | if (Platform.get() == Platform.WINDOWS) 46 | VK_KHR_OS_SURFACE_EXTENSION = memUTF8(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); 47 | else 48 | VK_KHR_OS_SURFACE_EXTENSION = memUTF8(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); 49 | PointerBuffer ppEnabledExtensionNames = memAllocPointer(2); 50 | ppEnabledExtensionNames.put(VK_KHR_SURFACE_EXTENSION); 51 | ppEnabledExtensionNames.put(VK_KHR_OS_SURFACE_EXTENSION); 52 | ppEnabledExtensionNames.flip(); 53 | VkInstanceCreateInfo pCreateInfo = VkInstanceCreateInfo.calloc() 54 | .sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO) 55 | .pNext(0L) 56 | .pApplicationInfo(appInfo); 57 | if (ppEnabledExtensionNames.remaining() > 0) { 58 | pCreateInfo.ppEnabledExtensionNames(ppEnabledExtensionNames); 59 | } 60 | PointerBuffer pInstance = MemoryUtil.memAllocPointer(1); 61 | int err = vkCreateInstance(pCreateInfo, null, pInstance); 62 | if (err != VK_SUCCESS) { 63 | throw new RuntimeException("Failed to create VkInstance: " + translateVulkanResult(err)); 64 | } 65 | long instance = pInstance.get(0); 66 | memFree(pInstance); 67 | VkInstance ret = new VkInstance(instance, pCreateInfo); 68 | memFree(ppEnabledExtensionNames); 69 | memFree(VK_KHR_OS_SURFACE_EXTENSION); 70 | memFree(VK_KHR_SURFACE_EXTENSION); 71 | appInfo.free(); 72 | return ret; 73 | } 74 | 75 | public static void main(String[] args) { 76 | // Create the Vulkan instance 77 | VkInstance instance = createInstance(); 78 | 79 | // Create SWT Display, Shell and VKCanvas 80 | final Display display = new Display(); 81 | final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE); 82 | shell.setLayout(new FillLayout()); 83 | shell.addListener(SWT.Traverse, new Listener() { 84 | public void handleEvent(Event event) { 85 | switch (event.detail) { 86 | case SWT.TRAVERSE_ESCAPE: 87 | shell.close(); 88 | event.detail = SWT.TRAVERSE_NONE; 89 | event.doit = false; 90 | break; 91 | } 92 | } 93 | }); 94 | VKData data = new VKData(); 95 | data.instance = instance; // <- set Vulkan instance 96 | final VKCanvas canvas = new VKCanvas(shell, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE, data); 97 | shell.setSize(800, 600); 98 | shell.open(); 99 | while (!shell.isDisposed()) { 100 | if (!display.readAndDispatch()) 101 | display.sleep(); 102 | } 103 | canvas.dispose(); 104 | display.dispose(); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/main/java/org/lwjgl/opengl/swt/AbstractPlatformGLCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import org.eclipse.swt.widgets.Composite; 4 | import org.lwjgl.opengl.swt.GLData.API; 5 | 6 | abstract class AbstractPlatformGLCanvas implements PlatformGLCanvas { 7 | 8 | protected static boolean atLeast32(int major, int minor) { 9 | return major == 3 && minor >= 2 || major > 3; 10 | } 11 | 12 | protected static boolean atLeast30(int major, int minor) { 13 | return major == 3 && minor >= 0 || major > 3; 14 | } 15 | 16 | protected static boolean validVersionGL(int major, int minor) { 17 | return (major == 0 && minor == 0) || // unspecified gets highest supported version on Nvidia 18 | (major >= 1 && minor >= 0) && 19 | (major != 1 || minor <= 5) && 20 | (major != 2 || minor <= 1) && 21 | (major != 3 || minor <= 3) && 22 | (major != 4 || minor <= 5); 23 | } 24 | 25 | protected static boolean validVersionGLES(int major, int minor) { 26 | return (major == 0 && minor == 0) || // unspecified gets 1.1 on Nvidia 27 | (major >= 1 && minor >= 0) && 28 | (major != 1 || minor <= 1) && 29 | (major != 2 || minor <= 0); 30 | } 31 | 32 | /** 33 | * Validate the given {@link GLData} and throw an exception on validation error. 34 | * 35 | * @param attribs 36 | * the {@link GLData} to validate 37 | */ 38 | public static void validateAttributes(GLData attribs) { 39 | if (attribs.alphaSize < 0) { 40 | throw new IllegalArgumentException("Alpha bits cannot be less than 0"); 41 | } 42 | if (attribs.redSize < 0) { 43 | throw new IllegalArgumentException("Red bits cannot be less than 0"); 44 | } 45 | if (attribs.greenSize < 0) { 46 | throw new IllegalArgumentException("Green bits cannot be less than 0"); 47 | } 48 | if (attribs.blueSize < 0) { 49 | throw new IllegalArgumentException("Blue bits cannot be less than 0"); 50 | } 51 | if (attribs.stencilSize < 0) { 52 | throw new IllegalArgumentException("Stencil bits cannot be less than 0"); 53 | } 54 | if (attribs.depthSize < 0) { 55 | throw new IllegalArgumentException("Depth bits cannot be less than 0"); 56 | } 57 | if (attribs.forwardCompatible && !atLeast30(attribs.majorVersion, attribs.minorVersion)) { 58 | throw new IllegalArgumentException("Forward-compatibility is only defined for OpenGL version 3.0 and above"); 59 | } 60 | if (attribs.samples < 0) { 61 | throw new IllegalArgumentException("Invalid samples count"); 62 | } 63 | if (attribs.profile != null && !atLeast32(attribs.majorVersion, attribs.minorVersion)) { 64 | throw new IllegalArgumentException("Context profiles are only defined for OpenGL version 3.2 and above"); 65 | } 66 | if (attribs.api == null) { 67 | throw new IllegalArgumentException("Unspecified client API"); 68 | } 69 | if (attribs.api == API.GL && !validVersionGL(attribs.majorVersion, attribs.minorVersion)) { 70 | throw new IllegalArgumentException("Invalid OpenGL version"); 71 | } 72 | if (attribs.api == API.GLES && !validVersionGLES(attribs.majorVersion, attribs.minorVersion)) { 73 | throw new IllegalArgumentException("Invalid OpenGL ES version"); 74 | } 75 | if (!attribs.doubleBuffer && attribs.swapInterval != null) { 76 | throw new IllegalArgumentException("Swap interval set but not using double buffering"); 77 | } 78 | if (attribs.colorSamplesNV < 0) { 79 | throw new IllegalArgumentException("Invalid color samples count"); 80 | } 81 | if (attribs.colorSamplesNV > attribs.samples) { 82 | throw new IllegalArgumentException("Color samples greater than number of (coverage) samples"); 83 | } 84 | if (attribs.swapGroupNV < 0) { 85 | throw new IllegalArgumentException("Invalid swap group"); 86 | } 87 | if (attribs.swapBarrierNV < 0) { 88 | throw new IllegalArgumentException("Invalid swap barrier"); 89 | } 90 | if ((attribs.swapGroupNV > 0 || attribs.swapBarrierNV > 0) && !attribs.doubleBuffer) { 91 | throw new IllegalArgumentException("Swap group or barrier requested but not using double buffering"); 92 | } 93 | if (attribs.swapBarrierNV > 0 && attribs.swapGroupNV == 0) { 94 | throw new IllegalArgumentException("Swap barrier requested but no valid swap group set"); 95 | } 96 | if (attribs.loseContextOnReset && !attribs.robustness) { 97 | throw new IllegalArgumentException("Lose context notification requested but not using robustness"); 98 | } 99 | if (attribs.contextResetIsolation && !attribs.robustness) { 100 | throw new IllegalArgumentException("Context reset isolation requested but not using robustness"); 101 | } 102 | } 103 | 104 | public int checkStyle(Composite parent, int style) { 105 | return style; 106 | } 107 | 108 | public void resetStyle(Composite parent) {} 109 | } 110 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.5"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/main/java/org/lwjgl/opengl/swt/GLCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.SWTException; 5 | import org.eclipse.swt.widgets.Canvas; 6 | import org.eclipse.swt.widgets.Composite; 7 | import org.lwjgl.system.Platform; 8 | 9 | /** 10 | * Drop-in replacement for SWT's {@link org.eclipse.swt.opengl.GLCanvas} class. 11 | *

12 | * It supports creating OpenGL 3.0 and 3.2 core/compatibility contexts as well as multisampled framebuffers. 13 | * 14 | * @author Kai Burjack 15 | */ 16 | public class GLCanvas extends Canvas { 17 | GLData effective; 18 | long context; 19 | long xWindow; 20 | long glWindow; 21 | 22 | private static PlatformGLCanvas platformCanvas; 23 | static { 24 | String platformClassName; 25 | switch (Platform.get()) { 26 | case WINDOWS: 27 | platformClassName = "org.lwjgl.opengl.swt.PlatformWin32GLCanvas"; 28 | break; 29 | case LINUX: 30 | platformClassName = "org.lwjgl.opengl.swt.PlatformLinuxGLCanvas"; 31 | break; 32 | case MACOSX: 33 | platformClassName = "org.lwjgl.opengl.swt.PlatformMacOSXGLCanvas"; 34 | break; 35 | default: 36 | throw new AssertionError("NYI"); 37 | } 38 | try { 39 | @SuppressWarnings("unchecked") 40 | Class clazz = (Class) GLCanvas.class.getClassLoader().loadClass(platformClassName); 41 | platformCanvas = clazz.newInstance(); 42 | } catch (ClassNotFoundException e) { 43 | throw new AssertionError("Platform-specific GLCanvas class not found: " + platformClassName); 44 | } catch (InstantiationException e) { 45 | throw new AssertionError("Could not instantiate platform-specific GLCanvas class: " + platformClassName); 46 | } catch (IllegalAccessException e) { 47 | throw new AssertionError("Could not instantiate platform-specific GLCanvas class: " + platformClassName); 48 | } 49 | } 50 | 51 | /** 52 | * Create a GLCanvas widget using the attributes described in the GLData 53 | * object provided. 54 | * 55 | * @param parent a composite widget 56 | * @param style the bitwise OR'ing of widget styles 57 | * @param data the requested attributes of the GLCanvas 58 | * 59 | * @exception IllegalArgumentException 60 | *

64 | */ 65 | public GLCanvas(Composite parent, int style, GLData data) { 66 | super(parent, platformCanvas.checkStyle(parent, style)); 67 | if (Platform.get() == Platform.WINDOWS) { 68 | platformCanvas.resetStyle(parent); 69 | } 70 | if (data == null) 71 | SWT.error(SWT.ERROR_NULL_ARGUMENT); 72 | effective = new GLData(); 73 | context = platformCanvas.create(this, data, effective); 74 | } 75 | 76 | /** 77 | * Returns a GLData object describing the created context. 78 | * 79 | * @return GLData description of the OpenGL context attributes 80 | * @exception SWTException 84 | */ 85 | public GLData getGLData() { 86 | checkWidget(); 87 | return effective; 88 | } 89 | 90 | /** 91 | * Returns a boolean indicating whether the receiver's OpenGL context 92 | * is the current context. 93 | * 94 | * @return true if the receiver holds the current OpenGL context, 95 | * false otherwise 96 | * @exception SWTException 100 | */ 101 | public boolean isCurrent() { 102 | checkWidget(); 103 | return platformCanvas.isCurrent(context); 104 | } 105 | 106 | /** 107 | * Sets the OpenGL context associated with this GLCanvas to be the 108 | * current GL context. 109 | * 110 | * @exception SWTException 114 | */ 115 | public void setCurrent() { 116 | checkWidget(); 117 | if (platformCanvas.isCurrent(context)) 118 | return; 119 | platformCanvas.makeCurrent(this, context); 120 | } 121 | 122 | /** 123 | * Swaps the front and back color buffers. 124 | * 125 | * @exception SWTException 129 | */ 130 | public void swapBuffers() { 131 | checkWidget(); 132 | platformCanvas.swapBuffers(this); 133 | } 134 | 135 | /** 136 | * Blocks until seconds seconds before a synchronized swap would occur. 137 | * 138 | * @param seconds 139 | * the seconds to wait until a synchronized swap would occur 140 | * @return true if the implementation had to wait for the synchronized swap; false otherwise 141 | */ 142 | public boolean delayBeforeSwapNV(float seconds) { 143 | checkWidget(); 144 | return platformCanvas.delayBeforeSwapNV(this, seconds); 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /lwjgl3-swt-common/src/main/java/org/lwjgl/opengl/swt/GLData.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | /** 4 | * Drop-in replacement for SWT's {@link org.eclipse.swt.opengl.GLData} class. 5 | * 6 | * @author Kai Burjack 7 | */ 8 | public class GLData { 9 | 10 | /* 11 | * The following fields are taken from SWT's original GLData 12 | */ 13 | 14 | /** 15 | * Whether to use double-buffering. It defaults to true. 16 | */ 17 | public boolean doubleBuffer = true; 18 | /** 19 | * Whether to use different LEFT and RIGHT backbuffers for stereo rendering. It defaults to false. 20 | */ 21 | public boolean stereo; 22 | /** 23 | * The number of bits for the red color channel. It defaults to 8. 24 | */ 25 | public int redSize = 8; 26 | /** 27 | * The number of bits for the green color channel. It defaults to 8. 28 | */ 29 | public int greenSize = 8; 30 | /** 31 | * The number of bits for the blue color channel. It defaults to 8. 32 | */ 33 | public int blueSize = 8; 34 | /** 35 | * The number of bits for the alpha color channel. It defaults to 8. 36 | */ 37 | public int alphaSize = 8; 38 | /** 39 | * The number of bits for the depth channel. It defaults to 24. 40 | */ 41 | public int depthSize = 24; 42 | /** 43 | * The number of bits for the stencil channel. It defaults to 0. 44 | */ 45 | public int stencilSize; 46 | /** 47 | * The number of bits for the red accumulator color channel. It defaults to 0. 48 | */ 49 | public int accumRedSize; 50 | /** 51 | * The number of bits for the green accumulator color channel. It defaults to 0. 52 | */ 53 | public int accumGreenSize; 54 | /** 55 | * The number of bits for the blue accumulator color channel. It defaults to 0. 56 | */ 57 | public int accumBlueSize; 58 | /** 59 | * The number of bits for the alpha accumulator color channel. It defaults to 0. 60 | */ 61 | public int accumAlphaSize; 62 | /** 63 | * This is ignored. It will implicitly be 1 if {@link #samples} is set to a value greater than or equal to 1. 64 | */ 65 | public int sampleBuffers; 66 | /** 67 | * The number of (coverage) samples for multisampling. Multisampling will only be requested for a value greater than or equal to 1. 68 | */ 69 | public int samples; 70 | /** 71 | * The {@link GLCanvas} whose context objects should be shared with the context created using this GLData. 72 | */ 73 | public GLCanvas shareContext; 74 | 75 | /* 76 | * New fields not in SWT's GLData 77 | */ 78 | 79 | public static enum Profile { 80 | CORE, COMPATIBILITY; 81 | } 82 | 83 | public static enum API { 84 | GL, GLES; 85 | } 86 | 87 | public static enum ReleaseBehavior { 88 | NONE, FLUSH; 89 | } 90 | 91 | /** 92 | * The major GL context version to use. It defaults to 0 for "not specified". 93 | */ 94 | public int majorVersion; 95 | /** 96 | * The minor GL context version to use. If {@link #majorVersion} is 0 this field is unused. 97 | */ 98 | public int minorVersion; 99 | /** 100 | * Whether a forward-compatible context should be created. This has only an effect when ({@link #majorVersion}.{@link #minorVersion}) is at least 3.2. 101 | */ 102 | public boolean forwardCompatible; 103 | /** 104 | * The profile to use. This is only valid when ({@link #majorVersion}.{@link #minorVersion}) is at least 3.0. 105 | */ 106 | public Profile profile; 107 | /** 108 | * The client API to use. It defaults to {@link API#GL OpenGL for Desktop}. 109 | */ 110 | public API api = API.GL; 111 | /** 112 | * Whether a debug context should be requested. 113 | */ 114 | public boolean debug; 115 | /** 116 | * Set the swap interval. It defaults to null for "not specified". 117 | */ 118 | public Integer swapInterval; 119 | /** 120 | * Whether to use sRGB color space. 121 | */ 122 | public boolean sRGB; 123 | /** 124 | * Whether to use a floating point pixel format. 125 | */ 126 | public boolean pixelFormatFloat; 127 | /** 128 | * Specify the behavior on context switch. Defaults to null for "not specified". 129 | */ 130 | public ReleaseBehavior contextReleaseBehavior; 131 | /** 132 | * The number of color samples per pixel. This is only valid when {@link #samples} is at least 1. 133 | */ 134 | public int colorSamplesNV; 135 | /** 136 | * The swap group index. Use this to synchronize buffer swaps across multiple windows on the same system. 137 | */ 138 | public int swapGroupNV; 139 | /** 140 | * The swap barrier index. Use this to synchronize buffer swaps across multiple systems. This requires a Nvidia G-Sync card. 141 | */ 142 | public int swapBarrierNV; 143 | /** 144 | * Whether robust buffer access should be used. 145 | */ 146 | public boolean robustness; 147 | /** 148 | * When {@link #robustness} is true then this specifies whether a GL_LOSE_CONTEXT_ON_RESET_ARB reset notification is sent, as described by GL_ARB_robustness. 149 | */ 150 | public boolean loseContextOnReset; 151 | /** 152 | * When {@link #robustness} is true and {@link #loseContextOnReset} is true then this specifies whether a graphics reset only affects 153 | * the current application and no other application in the system. 154 | */ 155 | public boolean contextResetIsolation; 156 | /** 157 | * Whether to use a "no error" context, as described in 158 | * ARB_create_context_no_error 159 | * and KHR_no_error. 160 | * The default is false. 161 | */ 162 | public boolean noErrorContext; 163 | 164 | } 165 | -------------------------------------------------------------------------------- /lwjgl3-swt-windows/src/test/java/org/lwjgl/opengl/swt/NvGLESDemo.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import static org.lwjgl.opengles.GLES20.*; 4 | 5 | import java.nio.FloatBuffer; 6 | import java.nio.IntBuffer; 7 | 8 | import org.eclipse.swt.SWT; 9 | import org.eclipse.swt.events.KeyEvent; 10 | import org.eclipse.swt.events.KeyAdapter; 11 | import org.eclipse.swt.graphics.Rectangle; 12 | import org.eclipse.swt.layout.FillLayout; 13 | import org.eclipse.swt.widgets.Display; 14 | import org.eclipse.swt.widgets.Event; 15 | import org.eclipse.swt.widgets.Listener; 16 | import org.eclipse.swt.widgets.Shell; 17 | import org.lwjgl.BufferUtils; 18 | import org.lwjgl.opengl.swt.GLData.API; 19 | import org.lwjgl.opengles.GLES; 20 | import org.lwjgl.system.Configuration; 21 | import org.lwjgl.system.Platform; 22 | 23 | /** 24 | * Shows how to use OpenGL ES with SWT. 25 | * 26 | * @author Kai Burjack 27 | */ 28 | public class NvGLESDemo { 29 | public static void main(String[] args) { 30 | final Display display = new Display(); 31 | final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE); 32 | shell.setLayout(new FillLayout()); 33 | shell.addKeyListener(new KeyAdapter() { 34 | public void keyPressed(KeyEvent e) { 35 | if (e.stateMask == SWT.ALT && (e.keyCode == SWT.KEYPAD_CR || e.keyCode == SWT.CR)) { 36 | if (Platform.get() == Platform.WINDOWS) { 37 | // Fix crappy/buggy fullscreen mode in SWT 38 | SwtHelperWin32.properFullscreen(shell); 39 | } else { 40 | shell.setFullScreen(!shell.getFullScreen()); 41 | } 42 | } 43 | } 44 | }); 45 | GLData data = new GLData(); 46 | data.api = API.GLES; 47 | data.majorVersion = 2; 48 | data.minorVersion = 0; 49 | data.samples = 4; 50 | data.swapInterval = 1; 51 | final GLCanvas canvas = new GLCanvas(shell, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE, data); 52 | canvas.setCurrent(); 53 | 54 | // Enable LWJGL3 to use GLES via GL library 55 | // From: http://bedroomcoders.co.uk/gles2-0-everywhere-thanks-to-lwjgl3/ 56 | if (Platform.get() == Platform.WINDOWS ) { 57 | // pretend we're using GLES in windows, instead use a subset of OpenGL 2.0 as GLES 2.0 58 | Configuration.OPENGLES_LIBRARY_NAME.set("OpenGL32"); 59 | Configuration.OPENGLES_EXPLICIT_INIT.set(true); 60 | org.lwjgl.opengles.GLES.create(org.lwjgl.opengl.GL.getFunctionProvider()); // omg?! 61 | } 62 | 63 | GLES.createCapabilities(); 64 | 65 | final Rectangle rect = new Rectangle(0, 0, 0, 0); 66 | canvas.addListener(SWT.Resize, new Listener() { 67 | public void handleEvent(@SuppressWarnings("unused") Event event) { 68 | Rectangle bounds = canvas.getBounds(); 69 | rect.width = bounds.width; 70 | rect.height = bounds.height; 71 | } 72 | }); 73 | shell.addListener(SWT.Traverse, new Listener() { 74 | public void handleEvent(Event event) { 75 | switch (event.detail) { 76 | case SWT.TRAVERSE_ESCAPE: 77 | shell.close(); 78 | event.detail = SWT.TRAVERSE_NONE; 79 | event.doit = false; 80 | break; 81 | } 82 | } 83 | }); 84 | 85 | glClearColor(0.3f, 0.5f, 0.8f, 1.0f); 86 | 87 | // Create a simple shader program 88 | int program = glCreateProgram(); 89 | int vs = glCreateShader(GL_VERTEX_SHADER); 90 | glShaderSource(vs, 91 | "#version 100\n" + 92 | "attribute vec3 vertex;" + 93 | "uniform float rot;" + 94 | "uniform float aspect;" + 95 | "void main(void) {" + 96 | " vec3 v = vertex * 0.5;" + 97 | " vec3 v_ = vec3(0.0, 0.0, 0.0);" + 98 | " v_.x = v.x * cos(rot) - v.y * sin(rot);" + 99 | " v_.y = v.y * cos(rot) + v.x * sin(rot);" + 100 | " v_.x /= aspect;" + 101 | " gl_Position = vec4(v_, 1.0);" + 102 | "}"); 103 | glCompileShader(vs); 104 | glAttachShader(program, vs); 105 | int fs = glCreateShader(GL_FRAGMENT_SHADER); 106 | glShaderSource(fs, 107 | "#version 100\n" + 108 | "precision mediump float;" + 109 | "void main(void) {" + 110 | " gl_FragColor = vec4(0.1, 0.3, 0.5, 1.0);" + 111 | "}"); 112 | glCompileShader(fs); 113 | glAttachShader(program, fs); 114 | glBindAttribLocation(program, 0, "vertex"); 115 | glLinkProgram(program); 116 | glUseProgram(program); 117 | final int rotLocation = glGetUniformLocation(program, "rot"); 118 | final int aspectLocation = glGetUniformLocation(program, "aspect"); 119 | 120 | // Create a simple quad 121 | int vbo = glGenBuffers(); 122 | int ibo = glGenBuffers(); 123 | float[] vertices = { 124 | -1, -1, 0, 125 | 1, -1, 0, 126 | 1, 1, 0, 127 | -1, 1, 0 128 | }; 129 | int[] indices = { 130 | 0, 1, 2, 131 | 2, 3, 0 132 | }; 133 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 134 | glBufferData(GL_ARRAY_BUFFER, (FloatBuffer) BufferUtils.createFloatBuffer(vertices.length).put(vertices).flip(), GL_STATIC_DRAW); 135 | glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L); 136 | glEnableVertexAttribArray(0); 137 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 138 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, (IntBuffer) BufferUtils.createIntBuffer(indices.length).put(indices).flip(), GL_STATIC_DRAW); 139 | 140 | shell.setSize(800, 600); 141 | shell.open(); 142 | 143 | display.asyncExec(new Runnable() { 144 | float rot; 145 | long lastTime = System.nanoTime(); 146 | public void run() { 147 | if (!canvas.isDisposed()) { 148 | canvas.setCurrent(); 149 | glClear(GL_COLOR_BUFFER_BIT); 150 | glViewport(0, 0, rect.width, rect.height); 151 | 152 | float aspect = (float) rect.width / rect.height; 153 | glUniform1f(aspectLocation, aspect); 154 | glUniform1f(rotLocation, rot); 155 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 156 | 157 | canvas.swapBuffers(); 158 | display.asyncExec(this); 159 | 160 | long thisTime = System.nanoTime(); 161 | float delta = (thisTime - lastTime) / 1E9f; 162 | rot += delta * 0.1f; 163 | if (rot > 2.0 * Math.PI) { 164 | rot -= 2.0f * (float) Math.PI; 165 | } 166 | lastTime = thisTime; 167 | } 168 | } 169 | }); 170 | 171 | while (!shell.isDisposed()) { 172 | if (!display.readAndDispatch()) 173 | display.sleep(); 174 | } 175 | display.dispose(); 176 | } 177 | } -------------------------------------------------------------------------------- /lwjgl3-swt-windows/src/test/java/org/lwjgl/opengl/swt/Swt33CoreMsDemo.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import static org.lwjgl.opengl.GL11.*; 4 | import static org.lwjgl.opengl.GL15.*; 5 | import static org.lwjgl.opengl.GL20.*; 6 | import static org.lwjgl.opengl.GL30.*; 7 | 8 | import java.nio.FloatBuffer; 9 | import java.nio.IntBuffer; 10 | 11 | import org.eclipse.swt.SWT; 12 | import org.eclipse.swt.events.KeyAdapter; 13 | import org.eclipse.swt.events.KeyEvent; 14 | import org.eclipse.swt.graphics.Rectangle; 15 | import org.eclipse.swt.layout.FillLayout; 16 | import org.eclipse.swt.widgets.Display; 17 | import org.eclipse.swt.widgets.Event; 18 | import org.eclipse.swt.widgets.Listener; 19 | import org.eclipse.swt.widgets.Shell; 20 | import org.lwjgl.BufferUtils; 21 | import org.lwjgl.opengl.GL; 22 | import org.lwjgl.opengl.GL11; 23 | import org.lwjgl.opengl.swt.GLCanvas; 24 | import org.lwjgl.opengl.swt.GLData; 25 | import org.lwjgl.opengl.swt.GLData.Profile; 26 | import org.lwjgl.system.Platform; 27 | 28 | /** 29 | * SWT with OpenGL 3.3 core, multisampling and v-sync. 30 | *

31 | * You can verify that a 3.3 core context is being created by removing/commenting 32 | * the call to glBindVertexArray and see that nothing gets drawn. 33 | * 34 | * @author Kai Burjack 35 | */ 36 | public class Swt33CoreMsDemo { 37 | public static void main(String[] args) { 38 | int minClientWidth = 640; 39 | int minClientHeight = 480; 40 | final Display display = new Display(); 41 | final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE); 42 | shell.setLayout(new FillLayout()); 43 | shell.addKeyListener(new KeyAdapter() { 44 | public void keyPressed(KeyEvent e) { 45 | if (e.stateMask == SWT.ALT && (e.keyCode == SWT.KEYPAD_CR || e.keyCode == SWT.CR)) { 46 | if (Platform.get() == Platform.WINDOWS) { 47 | // Fix crappy/buggy fullscreen mode in SWT 48 | SwtHelperWin32.properFullscreen(shell); 49 | } else { 50 | shell.setFullScreen(!shell.getFullScreen()); 51 | } 52 | } 53 | } 54 | }); 55 | int dw = shell.getSize().x - shell.getClientArea().width; 56 | int dh = shell.getSize().y - shell.getClientArea().height; 57 | shell.setMinimumSize(minClientWidth + dw, minClientHeight + dh); 58 | GLData data = new GLData(); 59 | data.majorVersion = 3; 60 | data.minorVersion = 3; 61 | data.profile = Profile.CORE; 62 | data.samples = 4; 63 | data.swapInterval = 1; 64 | final GLCanvas canvas = new GLCanvas(shell, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE, data); 65 | canvas.setCurrent(); 66 | 67 | final Rectangle rect = new Rectangle(0, 0, 0, 0); 68 | canvas.addListener(SWT.Resize, new Listener() { 69 | public void handleEvent(@SuppressWarnings("unused") Event event) { 70 | Rectangle bounds = canvas.getBounds(); 71 | rect.width = bounds.width; 72 | rect.height = bounds.height; 73 | } 74 | }); 75 | shell.addListener(SWT.Traverse, new Listener() { 76 | public void handleEvent(Event event) { 77 | switch (event.detail) { 78 | case SWT.TRAVERSE_ESCAPE: 79 | shell.close(); 80 | event.detail = SWT.TRAVERSE_NONE; 81 | event.doit = false; 82 | break; 83 | } 84 | } 85 | }); 86 | 87 | shell.setSize(800, 600); 88 | shell.open(); 89 | 90 | GL.createCapabilities(); 91 | glClearColor(0.3f, 0.5f, 0.8f, 1.0f); 92 | 93 | // Create a simple shader program 94 | int program = glCreateProgram(); 95 | int vs = glCreateShader(GL_VERTEX_SHADER); 96 | glShaderSource(vs, 97 | "#version 330 core\n" + 98 | "in vec3 vertex;" + 99 | "uniform float rot;" + 100 | "uniform float aspect;" + 101 | "void main(void) {" + 102 | " vec3 v = vertex * 0.5;" + 103 | " vec3 v_ = vec3(0.0, 0.0, 0.0);" + 104 | " v_.x = v.x * cos(rot) - v.y * sin(rot);" + 105 | " v_.y = v.y * cos(rot) + v.x * sin(rot);" + 106 | " v_.x /= aspect;" + 107 | " gl_Position = vec4(v_, 1.0);" + 108 | "}"); 109 | glCompileShader(vs); 110 | glAttachShader(program, vs); 111 | int fs = glCreateShader(GL_FRAGMENT_SHADER); 112 | glShaderSource(fs, 113 | "#version 330 core\n" + 114 | "out vec4 color;" + 115 | "void main(void) {" + 116 | " color = vec4(0.1, 0.3, 0.5, 1.0);" + 117 | "}"); 118 | glCompileShader(fs); 119 | glAttachShader(program, fs); 120 | glBindAttribLocation(program, 0, "vertex"); 121 | glBindFragDataLocation(program, 0, "color"); 122 | glLinkProgram(program); 123 | glUseProgram(program); 124 | final int rotLocation = glGetUniformLocation(program, "rot"); 125 | final int aspectLocation = glGetUniformLocation(program, "aspect"); 126 | 127 | // Create a simple quad 128 | int vbo = glGenBuffers(); 129 | int ibo = glGenBuffers(); 130 | int vao = glGenVertexArrays(); 131 | float[] vertices = { 132 | -1, -1, 0, 133 | 1, -1, 0, 134 | 1, 1, 0, 135 | -1, 1, 0 136 | }; 137 | int[] indices = { 138 | 0, 1, 2, 139 | 2, 3, 0 140 | }; 141 | glBindVertexArray(vao); 142 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 143 | glBufferData(GL_ARRAY_BUFFER, (FloatBuffer) BufferUtils.createFloatBuffer(vertices.length).put(vertices).flip(), GL_STATIC_DRAW); 144 | glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L); 145 | glEnableVertexAttribArray(0); 146 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 147 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, (IntBuffer) BufferUtils.createIntBuffer(indices.length).put(indices).flip(), GL_STATIC_DRAW); 148 | 149 | display.asyncExec(new Runnable() { 150 | float rot; 151 | long lastTime = System.nanoTime(); 152 | public void run() { 153 | if (!canvas.isDisposed()) { 154 | canvas.setCurrent(); 155 | glClear(GL_COLOR_BUFFER_BIT); 156 | glViewport(0, 0, rect.width, rect.height); 157 | 158 | float aspect = (float) rect.width / rect.height; 159 | glUniform1f(aspectLocation, aspect); 160 | glUniform1f(rotLocation, rot); 161 | glDrawElements(GL11.GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 162 | 163 | canvas.swapBuffers(); 164 | display.asyncExec(this); 165 | 166 | long thisTime = System.nanoTime(); 167 | float delta = (thisTime - lastTime) / 1E9f; 168 | rot += delta * 0.1f; 169 | if (rot > 2.0 * Math.PI) { 170 | rot -= 2.0f * (float) Math.PI; 171 | } 172 | lastTime = thisTime; 173 | } 174 | } 175 | }); 176 | 177 | while (!shell.isDisposed()) { 178 | if (!display.readAndDispatch()) 179 | display.sleep(); 180 | } 181 | display.dispose(); 182 | } 183 | } -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin, switch paths to Windows format before running java 129 | if $cygwin ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /lwjgl3-swt-windows/src/test/java/org/lwjgl/opengl/swt/SharedContextsDemo.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import static org.lwjgl.opengl.GL11.*; 4 | import static org.lwjgl.opengl.GL15.*; 5 | import static org.lwjgl.opengl.GL20.*; 6 | 7 | import java.nio.FloatBuffer; 8 | import java.nio.IntBuffer; 9 | 10 | import org.eclipse.swt.SWT; 11 | import org.eclipse.swt.events.KeyAdapter; 12 | import org.eclipse.swt.events.KeyEvent; 13 | import org.eclipse.swt.layout.GridData; 14 | import org.eclipse.swt.layout.GridLayout; 15 | import org.eclipse.swt.widgets.Display; 16 | import org.eclipse.swt.widgets.Event; 17 | import org.eclipse.swt.widgets.Listener; 18 | import org.eclipse.swt.widgets.Shell; 19 | import org.lwjgl.BufferUtils; 20 | import org.lwjgl.opengl.GL; 21 | import org.lwjgl.opengl.GL11; 22 | import org.lwjgl.opengl.swt.GLCanvas; 23 | import org.lwjgl.opengl.swt.GLData; 24 | import org.lwjgl.system.Platform; 25 | 26 | /** 27 | * Showcases context sharing. 28 | * 29 | * @author Kai Burjack 30 | */ 31 | public class SharedContextsDemo { 32 | public static void main(String[] args) { 33 | int minClientWidth = 600; 34 | int minClientHeight = 300; 35 | final Display display = new Display(); 36 | final Shell shell = new Shell(display, SWT.SHELL_TRIM); 37 | shell.addKeyListener(new KeyAdapter() { 38 | public void keyPressed(KeyEvent e) { 39 | if (e.stateMask == SWT.ALT && (e.keyCode == SWT.KEYPAD_CR || e.keyCode == SWT.CR)) { 40 | if (Platform.get() == Platform.WINDOWS) { 41 | // Fix crappy/buggy fullscreen mode in SWT 42 | SwtHelperWin32.properFullscreen(shell); 43 | } else { 44 | shell.setFullScreen(!shell.getFullScreen()); 45 | } 46 | } 47 | } 48 | }); 49 | GridLayout layout = new GridLayout(2, false); 50 | shell.setLayout(layout); 51 | int dw = shell.getSize().x - shell.getClientArea().width; 52 | int dh = shell.getSize().y - shell.getClientArea().height; 53 | shell.setMinimumSize(minClientWidth + dw, minClientHeight + dh); 54 | GLData data = new GLData(); 55 | data.doubleBuffer = true; 56 | data.swapInterval = 1; 57 | data.samples = 2; 58 | final GLCanvas canvas0 = new GLCanvas(shell, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE, data); 59 | canvas0.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 60 | data.shareContext = canvas0; 61 | final GLCanvas canvas1 = new GLCanvas(shell, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE, data); 62 | canvas1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 63 | final GLCanvas[] canvases = { canvas0, canvas1 }; 64 | 65 | shell.addListener(SWT.Traverse, new Listener() { 66 | public void handleEvent(Event event) { 67 | switch (event.detail) { 68 | case SWT.TRAVERSE_ESCAPE: 69 | shell.close(); 70 | event.detail = SWT.TRAVERSE_NONE; 71 | event.doit = false; 72 | break; 73 | } 74 | } 75 | }); 76 | 77 | shell.setSize(600, 300); 78 | shell.open(); 79 | 80 | // Create GLCapabilities in the first context 81 | canvas0.setCurrent(); 82 | GL.createCapabilities(); 83 | // Create resources in the first context 84 | // Create a simple shader program 85 | final int program = glCreateProgram(); 86 | int vs = glCreateShader(GL_VERTEX_SHADER); 87 | glShaderSource(vs, 88 | "uniform float rot;" + 89 | "uniform float aspect;" + 90 | "void main(void) {" + 91 | " vec4 v = gl_Vertex * 0.5;" + 92 | " vec4 v_ = vec4(0.0, 0.0, 0.0, 1.0);" + 93 | " v_.x = v.x * cos(rot) - v.y * sin(rot);" + 94 | " v_.y = v.y * cos(rot) + v.x * sin(rot);" + 95 | " v_.x /= aspect;" + 96 | " gl_Position = v_;" + 97 | "}"); 98 | glCompileShader(vs); 99 | glAttachShader(program, vs); 100 | int fs = glCreateShader(GL_FRAGMENT_SHADER); 101 | glShaderSource(fs, 102 | "void main(void) {" + 103 | " gl_FragColor = vec4(0.1, 0.3, 0.5, 1.0);" + 104 | "}"); 105 | glCompileShader(fs); 106 | glAttachShader(program, fs); 107 | glLinkProgram(program); 108 | glUseProgram(program); 109 | final int rotLocation = glGetUniformLocation(program, "rot"); 110 | final int aspectLocation = glGetUniformLocation(program, "aspect"); 111 | 112 | // Create a simple quad 113 | final int vbo = glGenBuffers(); 114 | final int ibo = glGenBuffers(); 115 | float[] vertices = { 116 | -1, -1, 0, 117 | 1, -1, 0, 118 | 1, 1, 0, 119 | -1, 1, 0 120 | }; 121 | int[] indices = { 122 | 0, 1, 2, 123 | 2, 3, 0 124 | }; 125 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 126 | glBufferData(GL_ARRAY_BUFFER, (FloatBuffer) BufferUtils.createFloatBuffer(vertices.length).put(vertices).flip(), GL_STATIC_DRAW); 127 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 128 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, (IntBuffer) BufferUtils.createIntBuffer(indices.length).put(indices).flip(), GL_STATIC_DRAW); 129 | 130 | // Bind objects in each context and set state 131 | for (GLCanvas canvas : canvases) { 132 | canvas.setCurrent(); 133 | glClearColor(0.4f, 0.6f, 0.9f, 1.0f); 134 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 135 | glVertexPointer(3, GL_FLOAT, 0, 0L); 136 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 137 | glEnableClientState(GL_VERTEX_ARRAY); 138 | glUseProgram(program); 139 | } 140 | 141 | display.asyncExec(new Runnable() { 142 | float rot; 143 | long lastTime = System.nanoTime(); 144 | 145 | public void run() { 146 | // Render in each context 147 | for (int i = 0; i < canvases.length; i++) { 148 | GLCanvas canvas = canvases[i]; 149 | if (canvas.isDisposed()) { 150 | return; 151 | } 152 | canvas.setCurrent(); 153 | glClear(GL_COLOR_BUFFER_BIT); 154 | glViewport(0, 0, canvas.getSize().x, canvas.getSize().y); 155 | float aspect = (float) canvas.getSize().x / canvas.getSize().y; 156 | glUniform1f(aspectLocation, aspect); 157 | glUniform1f(rotLocation, rot); 158 | glDrawElements(GL11.GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 159 | canvas.swapBuffers(); 160 | } 161 | display.asyncExec(this); 162 | 163 | long thisTime = System.nanoTime(); 164 | float delta = (thisTime - lastTime) / 1E9f; 165 | rot += delta * 0.1f; 166 | if (rot > 2.0 * Math.PI) { 167 | rot -= 2.0f * (float) Math.PI; 168 | } 169 | lastTime = thisTime; 170 | } 171 | }); 172 | 173 | while (!shell.isDisposed()) { 174 | if (!display.readAndDispatch()) 175 | display.sleep(); 176 | } 177 | display.dispose(); 178 | } 179 | } -------------------------------------------------------------------------------- /lwjgl3-swt-macos/src/main/java/org/lwjgl/opengl/swt/PlatformMacOSXGLCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.internal.cocoa.NSNotificationCenter; 5 | import org.eclipse.swt.internal.cocoa.NSOpenGLContext; 6 | import org.eclipse.swt.internal.cocoa.NSOpenGLPixelFormat; 7 | import org.eclipse.swt.internal.cocoa.NSView; 8 | import org.eclipse.swt.internal.cocoa.OS; 9 | import org.eclipse.swt.widgets.Listener; 10 | import org.lwjgl.opengl.swt.GLData.Profile; 11 | 12 | /** 13 | * OSX-specific implementation of methods for GLCanvas. 14 | * 15 | * @author Thomas Ibanez 16 | */ 17 | class PlatformMacOSXGLCanvas extends AbstractPlatformGLCanvas { 18 | 19 | private NSOpenGLContext context; 20 | private NSOpenGLPixelFormat pixelFormat; 21 | 22 | private static final int MAX_ATTRIB = 32; 23 | private static final String GLCONTEXT_KEY = "org.eclipse.swt.internal.cocoa.glcontext"; 24 | 25 | private NSView view; 26 | 27 | static final int NSOpenGLPFAOpenGLProfile = 99; 28 | static final int NSOpenGLProfileVersion3_2Core = 0x3200; 29 | static final int NSOpenGLProfileVersionLegacy = 0x1000; 30 | static final int NSOpenGLProfileVersion4_1Core = 0x4100; 31 | 32 | @Override 33 | /* 34 | * IMPORTANT: NSOpenGL/CoreOpenGL only supports specifying the total number 35 | * of bits in the size of the color component -> effective.redSize, 36 | * effective.blueSize and effective.greenSize won't be set ! 37 | * 38 | * IMPORTANT: NSOpenGL/CoreOpenGL only supports specifying the total number 39 | * of bits in the size of the color accumulator component. -> 40 | * effective.accumRedSize, effective.accumBlueSize, effective.accumGreenSize 41 | * and effective.accumAlphaSize won't be set ! 42 | */ 43 | public long create(GLCanvas canvas, GLData data, GLData effective) { 44 | 45 | if (data == null) 46 | SWT.error(SWT.ERROR_NULL_ARGUMENT); 47 | this.view = canvas.view; 48 | 49 | int attrib[] = new int[MAX_ATTRIB]; 50 | int pos = 0; 51 | 52 | if (data.doubleBuffer) 53 | attrib[pos++] = OS.NSOpenGLPFADoubleBuffer; 54 | 55 | if (data.stereo) 56 | attrib[pos++] = OS.NSOpenGLPFAStereo; 57 | 58 | /* 59 | * Feature in Cocoa: NSOpenGL/CoreOpenGL only supports specifying the 60 | * total number of bits in the size of the color component. If 61 | * specified, the color size is the sum of the red, green and blue 62 | * values in the GLData. 63 | */ 64 | if ((data.redSize + data.blueSize + data.greenSize) > 0) { 65 | attrib[pos++] = OS.NSOpenGLPFAColorSize; 66 | attrib[pos++] = data.redSize + data.greenSize + data.blueSize; 67 | } 68 | 69 | if (data.alphaSize > 0) { 70 | attrib[pos++] = OS.NSOpenGLPFAAlphaSize; 71 | attrib[pos++] = data.alphaSize; 72 | } 73 | 74 | if (data.depthSize > 0) { 75 | attrib[pos++] = OS.NSOpenGLPFADepthSize; 76 | attrib[pos++] = data.depthSize; 77 | } 78 | 79 | if (data.stencilSize > 0) { 80 | attrib[pos++] = OS.NSOpenGLPFAStencilSize; 81 | attrib[pos++] = data.stencilSize; 82 | } 83 | 84 | if (data.profile == Profile.CORE) { 85 | attrib[pos++] = NSOpenGLPFAOpenGLProfile; 86 | attrib[pos++] = NSOpenGLProfileVersion3_2Core; 87 | } 88 | if (data.profile == Profile.COMPATIBILITY) { 89 | attrib[pos++] = NSOpenGLPFAOpenGLProfile; 90 | attrib[pos++] = NSOpenGLProfileVersionLegacy; 91 | } else { 92 | if (data.majorVersion >= 4) { 93 | attrib[pos++] = NSOpenGLPFAOpenGLProfile; 94 | attrib[pos++] = NSOpenGLProfileVersion4_1Core; 95 | } else if (data.majorVersion >= 3) { 96 | attrib[pos++] = NSOpenGLPFAOpenGLProfile; 97 | attrib[pos++] = NSOpenGLProfileVersion3_2Core; 98 | } else { 99 | attrib[pos++] = NSOpenGLPFAOpenGLProfile; 100 | attrib[pos++] = NSOpenGLProfileVersionLegacy; 101 | } 102 | } 103 | 104 | /* 105 | * Feature in Cocoa: NSOpenGL/CoreOpenGL only supports specifying the 106 | * total number of bits in the size of the color accumulator component. 107 | * If specified, the color size is the sum of the red, green, blue and 108 | * alpha accum values in the GLData. 109 | */ 110 | if ((data.accumRedSize + data.accumBlueSize + data.accumGreenSize) > 0) { 111 | attrib[pos++] = OS.NSOpenGLPFAAccumSize; 112 | attrib[pos++] = data.accumRedSize + data.accumGreenSize + data.accumBlueSize + data.accumAlphaSize; 113 | } 114 | 115 | if (data.sampleBuffers > 0) { 116 | attrib[pos++] = OS.NSOpenGLPFASampleBuffers; 117 | attrib[pos++] = data.sampleBuffers; 118 | } 119 | 120 | if (data.samples > 0) { 121 | attrib[pos++] = OS.NSOpenGLPFASamples; 122 | attrib[pos++] = data.samples; 123 | } 124 | 125 | attrib[pos++] = 0; 126 | 127 | pixelFormat = (NSOpenGLPixelFormat) new NSOpenGLPixelFormat().alloc(); 128 | 129 | if (pixelFormat == null) { 130 | canvas.dispose(); 131 | SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); 132 | } 133 | pixelFormat.initWithAttributes(attrib); 134 | 135 | NSOpenGLContext ctx = data.shareContext != null ? new NSOpenGLContext(data.shareContext.context) : null; 136 | context = (NSOpenGLContext) new NSOpenGLContext().alloc(); 137 | if (context == null) { 138 | canvas.dispose(); 139 | SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); 140 | } 141 | context = context.initWithFormat(pixelFormat, ctx); 142 | if (data.swapInterval != null && data.swapInterval.intValue() > 0) 143 | context.setValues(new int[] { data.swapInterval.intValue() }, OS.NSOpenGLCPSwapInterval); 144 | 145 | context.setValues(new int[] { -1 }, OS.NSOpenGLCPSurfaceOrder); 146 | canvas.setData(GLCONTEXT_KEY, context); 147 | NSNotificationCenter.defaultCenter().addObserver(view, OS.sel_updateOpenGLContext_, OS.NSViewGlobalFrameDidChangeNotification, view); 148 | 149 | Listener listener = event -> { 150 | switch (event.type) { 151 | 152 | case SWT.Dispose: 153 | canvas.setData(GLCONTEXT_KEY, null); 154 | NSNotificationCenter.defaultCenter().removeObserver(view); 155 | 156 | if (context != null) { 157 | context.clearDrawable(); 158 | context.release(); 159 | } 160 | context = null; 161 | if (pixelFormat != null) 162 | pixelFormat.release(); 163 | pixelFormat = null; 164 | break; 165 | } 166 | }; 167 | canvas.addListener(SWT.Dispose, listener); 168 | 169 | long[] longptr = new long[1]; 170 | pixelFormat.getValues(longptr, OS.NSOpenGLPFAAlphaSize, 0); 171 | effective.alphaSize = (int) longptr[0]; 172 | pixelFormat.getValues(longptr, OS.NSOpenGLPFADepthSize, 0); 173 | effective.depthSize = (int) longptr[0]; 174 | pixelFormat.getValues(longptr, OS.NSOpenGLPFAStencilSize, 0); 175 | effective.stencilSize = (int) longptr[0]; 176 | pixelFormat.getValues(longptr, OS.NSOpenGLPFADoubleBuffer, 0); 177 | effective.doubleBuffer = longptr[0] == 1; 178 | pixelFormat.getValues(longptr, OS.NSOpenGLPFAStereo, 0); 179 | effective.stereo = longptr[0] == 1; 180 | 181 | pixelFormat.getValues(longptr, NSOpenGLPFAOpenGLProfile, 0); 182 | if (longptr[0] == NSOpenGLProfileVersion3_2Core) { 183 | effective.majorVersion = 3; 184 | effective.minorVersion = 2; 185 | effective.profile = Profile.CORE; 186 | } else if (longptr[0] == NSOpenGLProfileVersionLegacy) { 187 | effective.profile = Profile.COMPATIBILITY; 188 | } else if (longptr[0] == NSOpenGLProfileVersion4_1Core) { 189 | effective.majorVersion = 4; 190 | effective.minorVersion = 1; 191 | effective.profile = Profile.CORE; 192 | } 193 | 194 | pixelFormat.getValues(longptr, OS.NSOpenGLPFASampleBuffers, 0); 195 | data.sampleBuffers = (int) longptr[0]; 196 | 197 | pixelFormat.getValues(longptr, OS.NSOpenGLPFASamples, 0); 198 | data.samples = (int) longptr[0]; 199 | 200 | return context.id; 201 | } 202 | 203 | @Override 204 | public boolean isCurrent(long context) { 205 | NSOpenGLContext current = NSOpenGLContext.currentContext(); 206 | return current != null && current.id == context; 207 | } 208 | 209 | @Override 210 | public boolean makeCurrent(GLCanvas canvas, long context) { 211 | new NSOpenGLContext(context).makeCurrentContext(); 212 | return true; 213 | } 214 | 215 | @Override 216 | public boolean deleteContext(GLCanvas canvas, long context) { 217 | canvas.setData(GLCONTEXT_KEY, null); 218 | NSNotificationCenter.defaultCenter().removeObserver(view); 219 | NSOpenGLContext ctx = new NSOpenGLContext(context); 220 | if (ctx != null) { 221 | ctx.clearDrawable(); 222 | ctx.release(); 223 | } 224 | ctx = null; 225 | if (pixelFormat != null) 226 | pixelFormat.release(); 227 | pixelFormat = null; 228 | return true; 229 | } 230 | 231 | @Override 232 | public boolean swapBuffers(GLCanvas canvas) { 233 | new NSOpenGLContext(canvas.context).flushBuffer(); 234 | return true; 235 | } 236 | 237 | @Override 238 | public boolean delayBeforeSwapNV(GLCanvas canvas, float seconds) { 239 | // It seems that there's no support for this on OSX 240 | //https://github.com/LWJGL/lwjgl3/commit/c82cf46050ea6e1b891756cfec392c66186e87b1 241 | return false; 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | org.lwjglx 7 | lwjgl3-swt 8 | 1.0.0 9 | pom 10 | LWJGLX/lwjgl3-swt 11 | LWJGLX/lwjgl3-swt 12 | 2016 13 | https://lwjglx.org 14 | 15 | LWJGLX 16 | https://lwjglx.org 17 | 18 | 19 | 20 | kburjack 21 | Kai Burjack 22 | kburjack@googlemail.com 23 | LWJGLX 24 | https://lwjglx.org 25 | 26 | 27 | 28 | 29 | 30 | MIT License 31 | http://www.opensource.org/licenses/mit-license.php 32 | 33 | 34 | 35 | https://github.com/LWJGLX/lwjgl3-swt 36 | scm:git:https://github.com/LWJGLX/lwjgl3-swt.git 37 | scm:git:https://github.com/LWJGLX/lwjgl3-swt.git 38 | 39 | 40 | 41 | lwjgl3-swt-common 42 | lwjgl3-swt-windows 43 | lwjgl3-swt-linux 44 | lwjgl3-swt-macos 45 | 46 | 47 | 48 | UTF-8 49 | UTF-8 50 | 1.8 51 | 1.8 52 | 3.8.1 53 | 3.2.0 54 | 1.6 55 | 3.0.0-M1 56 | 3.2.0 57 | 3.2.0 58 | 3.0.0-M5 59 | 3.2.0 60 | 1.4 61 | 1.6.8 62 | 3.2.3 63 | 3.113.0 64 | 65 | 66 | 67 | 68 | 69 | maven-resources-plugin 70 | ${maven-resources-plugin.version} 71 | 72 | 73 | copy-resources 74 | validate 75 | 76 | copy-resources 77 | 78 | 79 | ${project.build.outputDirectory}/META-INF 80 | 81 | 82 | ${basedir} 83 | false 84 | LICENSE 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.codehaus.mojo 93 | buildnumber-maven-plugin 94 | ${buildnumber-maven-plugin.version} 95 | 96 | 97 | validate 98 | 99 | create 100 | 101 | 102 | 103 | 104 | false 105 | false 106 | 107 | 108 | 109 | maven-surefire-plugin 110 | ${maven-surefire-plugin.version} 111 | 112 | 113 | maven-source-plugin 114 | ${maven-source-plugin.version} 115 | 116 | 117 | package-sources 118 | 119 | jar 120 | 121 | 122 | 123 | 124 | 125 | maven-javadoc-plugin 126 | ${maven-javadoc-plugin.version} 127 | 128 | 129 | attach-javadocs 130 | 131 | jar 132 | 133 | 134 | 135 | 136 | false 137 | 138 | 139 | 140 | maven-jar-plugin 141 | ${maven-jar-plugin.version} 142 | 143 | 144 | 145 | true 146 | 147 | 148 | 149 | ${buildNumber} 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | jdk9 160 | 161 | [9,) 162 | 163 | 164 | 165 | 166 | maven-javadoc-plugin 167 | ${maven-javadoc-plugin.version} 168 | 169 | 170 | -html5 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | deploy 179 | 180 | 181 | 182 | maven-gpg-plugin 183 | ${maven-gpg-plugin.version} 184 | 185 | 186 | sign-artifacts 187 | verify 188 | 189 | sign 190 | 191 | 192 | 193 | 194 | --pinentry-mode 195 | loopback 196 | 197 | 198 | 199 | 200 | 201 | 202 | maven-deploy-plugin 203 | ${maven-deploy-plugin.version} 204 | 205 | true 206 | 207 | 208 | 209 | org.sonatype.plugins 210 | nexus-staging-maven-plugin 211 | ${nexus-staging-maven-plugin.version} 212 | true 213 | 214 | 215 | default-deploy 216 | deploy 217 | 218 | deploy 219 | 220 | 221 | 222 | 223 | ossrh 224 | https://oss.sonatype.org/ 225 | true 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | org.eclipse.platform 237 | org.eclipse.swt 238 | ${swt.version} 239 | 240 | 241 | org.eclipse.platform 242 | org.eclipse.swt.win32.win32.x86_64 243 | ${swt.version} 244 | 245 | 246 | org.eclipse.platform 247 | org.eclipse.swt.gtk.linux.x86_64 248 | ${swt.version} 249 | 250 | 251 | org.eclipse.platform 252 | org.eclipse.swt.cocoa.macosx.x86_64 253 | ${swt.version} 254 | 255 | 256 | org.lwjgl 257 | lwjgl 258 | ${lwjgl.version} 259 | 260 | 261 | org.lwjgl 262 | lwjgl-opengl 263 | ${lwjgl.version} 264 | 265 | 266 | org.lwjgl 267 | lwjgl-opengles 268 | ${lwjgl.version} 269 | 270 | 271 | org.lwjgl 272 | lwjgl-vulkan 273 | ${lwjgl.version} 274 | 275 | 276 | org.lwjgl 277 | lwjgl 278 | ${lwjgl.version} 279 | natives-linux 280 | 281 | 282 | org.lwjgl 283 | lwjgl-opengl 284 | ${lwjgl.version} 285 | natives-linux 286 | 287 | 288 | org.lwjgl 289 | lwjgl-opengles 290 | ${lwjgl.version} 291 | natives-linux 292 | 293 | 294 | org.lwjgl 295 | lwjgl 296 | ${lwjgl.version} 297 | natives-windows 298 | 299 | 300 | org.lwjgl 301 | lwjgl-opengl 302 | ${lwjgl.version} 303 | natives-windows 304 | 305 | 306 | org.lwjgl 307 | lwjgl-opengles 308 | ${lwjgl.version} 309 | natives-windows 310 | 311 | 312 | org.lwjgl 313 | lwjgl 314 | ${lwjgl.version} 315 | natives-macos 316 | 317 | 318 | org.lwjgl 319 | lwjgl-opengl 320 | ${lwjgl.version} 321 | natives-macos 322 | 323 | 324 | org.lwjgl 325 | lwjgl-opengles 326 | ${lwjgl.version} 327 | natives-macos 328 | 329 | 330 | 331 | 332 | 333 | 334 | oss.sonatype.org 335 | https://oss.sonatype.org/content/repositories/snapshots/ 336 | 337 | true 338 | 339 | 340 | 341 | 342 | 343 | 344 | ossrh 345 | Sonatype Snapshot Repository 346 | https://oss.sonatype.org/content/repositories/snapshots 347 | 348 | 349 | ossrh 350 | Sonatype Staging Repository 351 | https://oss.sonatype.org/service/local/staging/deploy/maven2 352 | 353 | 354 | 355 | 356 | 357 | org.lwjgl 358 | lwjgl 359 | 360 | 361 | org.lwjgl 362 | lwjgl-opengl 363 | 364 | 365 | org.lwjgl 366 | lwjgl-opengles 367 | 368 | 369 | org.lwjgl 370 | lwjgl-vulkan 371 | 372 | 373 | 374 | 375 | -------------------------------------------------------------------------------- /lwjgl3-swt-linux/src/main/java/org/lwjgl/opengl/swt/PlatformLinuxGLCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import static org.lwjgl.opengl.GLX.*; 4 | import static org.lwjgl.opengl.GLX13.*; 5 | import static org.lwjgl.opengl.GLXARBContextFlushControl.*; 6 | import static org.lwjgl.opengl.GLXARBCreateContext.*; 7 | import static org.lwjgl.opengl.GLXARBCreateContextNoError.*; 8 | import static org.lwjgl.opengl.GLXARBCreateContextProfile.*; 9 | import static org.lwjgl.opengl.GLXARBCreateContextRobustness.*; 10 | import static org.lwjgl.opengl.GLXARBMultisample.*; 11 | import static org.lwjgl.opengl.GLXARBRobustnessApplicationIsolation.*; 12 | import static org.lwjgl.opengl.GLXEXTCreateContextES2Profile.*; 13 | import static org.lwjgl.opengl.GLXEXTFramebufferSRGB.*; 14 | import static org.lwjgl.opengl.GLXNVDelayBeforeSwap.*; 15 | import static org.lwjgl.opengl.GLXNVMultisampleCoverage.*; 16 | 17 | import java.nio.IntBuffer; 18 | 19 | import org.eclipse.swt.SWT; 20 | import org.eclipse.swt.SWTException; 21 | import org.eclipse.swt.graphics.Rectangle; 22 | 23 | import org.eclipse.swt.internal.DPIUtil; 24 | import org.eclipse.swt.internal.gtk.GDK; 25 | import org.eclipse.swt.internal.gtk.GTK; 26 | import org.eclipse.swt.internal.gtk.GdkWindowAttr; 27 | 28 | import org.eclipse.swt.widgets.Listener; 29 | import org.lwjgl.BufferUtils; 30 | import org.lwjgl.PointerBuffer; 31 | import org.lwjgl.opengl.GL; 32 | import org.lwjgl.opengl.GLXCapabilities; 33 | import org.lwjgl.opengl.KHRNoError; 34 | import org.lwjgl.opengl.swt.GLData.API; 35 | import org.lwjgl.opengl.swt.GLData.Profile; 36 | import org.lwjgl.opengl.swt.GLData.ReleaseBehavior; 37 | import org.lwjgl.system.linux.XVisualInfo; 38 | 39 | /** 40 | * Linux-specific implementation of methods for GLCanvas. 41 | * 42 | * @author Joshua Slack 43 | */ 44 | class PlatformLinuxGLCanvas extends AbstractPlatformGLCanvas { 45 | 46 | @Override 47 | public long create(GLCanvas canvas, GLData data, GLData effective) { 48 | 49 | // Validate context attributes 50 | validateAttributes(data); 51 | 52 | // make sure our canvas has resources assigned 53 | GTK.gtk_widget_realize(canvas.handle); 54 | 55 | // grab handles to our window/display 56 | long window = GTK.gtk_widget_get_window(canvas.handle); 57 | long xDisplay = gdk_x11_display_get_xdisplay(window); 58 | 59 | // generate a list of config options for our frame buffer from the supplied data 60 | IntBuffer attribList = BufferUtils.createIntBuffer(64); 61 | populateFBConfigAttribs(data, attribList); 62 | 63 | // ask for matching frame buffer configs 64 | PointerBuffer fbCfg = glXChooseFBConfig(xDisplay, 0, attribList); 65 | if (fbCfg == null || !fbCfg.hasRemaining()) { 66 | canvas.dispose(); 67 | throw new SWTException("Unable to find matching FB Config"); 68 | } 69 | 70 | // convert our fbconfig to a visualinfo so we can apply it to the widget 71 | XVisualInfo viz = glXGetVisualFromFBConfig(xDisplay, fbCfg.get(0)); 72 | 73 | // grab our default screen for the default display 74 | long screen = GDK.gdk_screen_get_default(); 75 | 76 | // ask the screen for a GdkVisual that matches the given info 77 | long gdkvisual = GDK.gdk_x11_screen_lookup_visual(screen, (int) viz.visualid()); 78 | 79 | // put together attributes for a new window using the visual 80 | GdkWindowAttr winAttrs = new GdkWindowAttr(); 81 | winAttrs.width = 1; 82 | winAttrs.height = 1; 83 | winAttrs.event_mask = GDK.GDK_KEY_PRESS_MASK | GDK.GDK_KEY_RELEASE_MASK | GDK.GDK_FOCUS_CHANGE_MASK 84 | | GDK.GDK_POINTER_MOTION_MASK | GDK.GDK_BUTTON_PRESS_MASK | GDK.GDK_BUTTON_RELEASE_MASK 85 | | GDK.GDK_ENTER_NOTIFY_MASK | GDK.GDK_LEAVE_NOTIFY_MASK | GDK.GDK_EXPOSURE_MASK 86 | | GDK.GDK_POINTER_MOTION_HINT_MASK; 87 | winAttrs.window_type = GDK.GDK_WINDOW_CHILD; 88 | winAttrs.visual = gdkvisual; 89 | 90 | // create the new window - this gives us a glxdrawable too 91 | canvas.glWindow = GDK.gdk_window_new(window, winAttrs, GDK.GDK_WA_VISUAL); 92 | 93 | // sets the user data as the widget that owns the window - historical 94 | // see: https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-set-user-data 95 | GDK.gdk_window_set_user_data(canvas.glWindow, canvas.handle); 96 | 97 | // get the X id of the new window and call to show it 98 | canvas.xWindow = GDK.gdk_x11_window_get_xid(canvas.glWindow); 99 | GDK.gdk_window_show(canvas.glWindow); 100 | 101 | // context generation time - put we'll use our fbconfig here to get a core compatible context 102 | // start by generating our list of attributes 103 | attribList.rewind(); 104 | GLXCapabilities caps = GL.getCapabilitiesGLX(); 105 | populateContextAttribs(data, attribList, caps); 106 | 107 | // create the context... pass our display, fbconfig, attributes and any shared context 108 | long share = data.shareContext != null ? data.shareContext.context : 0; 109 | long context = glXCreateContextAttribsARB(xDisplay, fbCfg.get(0), share, true, attribList); 110 | if (context == 0) throw new SWTException("Unable to create context"); 111 | 112 | // Set up SWT event listeners to handle disposal and resize 113 | Listener listener = event -> { 114 | switch (event.type) { 115 | case SWT.Resize: 116 | Rectangle clientArea = DPIUtil.autoScaleUp(canvas.getClientArea()); 117 | GDK.gdk_window_move(canvas.glWindow, clientArea.x, clientArea.y); 118 | GDK.gdk_window_resize(canvas.glWindow, clientArea.width, clientArea.height); 119 | break; 120 | case SWT.Dispose: 121 | deleteContext(canvas, context); 122 | break; 123 | } 124 | }; 125 | canvas.addListener(SWT.Resize, listener); 126 | canvas.addListener(SWT.Dispose, listener); 127 | 128 | // Done! Return our context. 129 | return context; 130 | } 131 | 132 | private void populateFBConfigAttribs(GLData data, IntBuffer attribList) { 133 | if (data.redSize > 0) attribList.put(GLX_RED_SIZE).put(data.redSize); 134 | if (data.greenSize > 0) attribList.put(GLX_GREEN_SIZE).put(data.greenSize); 135 | if (data.blueSize > 0) attribList.put(GLX_BLUE_SIZE).put(data.blueSize); 136 | if (data.alphaSize > 0) attribList.put(GLX_ALPHA_SIZE).put(data.alphaSize); 137 | 138 | if (data.depthSize > 0) attribList.put(GLX_DEPTH_SIZE).put(data.depthSize); 139 | if (data.stencilSize > 0) attribList.put(GLX_STENCIL_SIZE).put(data.stencilSize); 140 | 141 | if (data.doubleBuffer) attribList.put(GLX_DOUBLEBUFFER).put(1); 142 | if (data.stereo) attribList.put(GLX_STEREO).put(1); 143 | if (data.sRGB) attribList.put(GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT).put(1); 144 | 145 | if (data.accumRedSize > 0) attribList.put(GLX_ACCUM_RED_SIZE).put(data.accumRedSize); 146 | if (data.accumGreenSize > 0) attribList.put(GLX_ACCUM_GREEN_SIZE).put(data.accumGreenSize); 147 | if (data.accumBlueSize > 0) attribList.put(GLX_ACCUM_BLUE_SIZE).put(data.accumBlueSize); 148 | if (data.accumAlphaSize > 0) attribList.put(GLX_ACCUM_ALPHA_SIZE).put(data.accumAlphaSize); 149 | 150 | if (data.samples > 0) { 151 | attribList.put(GLX_SAMPLE_BUFFERS_ARB).put(1); 152 | attribList.put(GLX_SAMPLES_ARB).put(data.samples); 153 | if (data.colorSamplesNV > 0) { 154 | attribList.put(GLX_COLOR_SAMPLES_NV).put(data.colorSamplesNV); 155 | } 156 | } 157 | 158 | attribList.put(0); 159 | attribList.flip(); 160 | } 161 | 162 | private void populateContextAttribs(GLData data, IntBuffer attribList, GLXCapabilities caps) { 163 | attribList.put(GLX_CONTEXT_MAJOR_VERSION_ARB).put(data.majorVersion); 164 | attribList.put(GLX_CONTEXT_MINOR_VERSION_ARB).put(data.minorVersion); 165 | 166 | 167 | int profile = 0; 168 | if (data.api == API.GL) { 169 | if (data.profile == Profile.COMPATIBILITY) { 170 | profile = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; 171 | } else if (data.profile == Profile.CORE) { 172 | profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; 173 | } 174 | } else if (data.api == API.GLES) { 175 | if (!caps.GLX_EXT_create_context_es2_profile) { 176 | throw new SWTException("OpenGL ES API requested but GLX_EXT_create_context_es2_profile is unavailable"); 177 | } 178 | profile = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; 179 | } 180 | if (profile > 0) { 181 | if (!caps.GLX_ARB_create_context_profile) { 182 | throw new SWTException("OpenGL profile requested but GLX_ARB_create_context_profile is unavailable"); 183 | } 184 | attribList.put(GLX_CONTEXT_PROFILE_MASK_ARB).put(profile); 185 | } 186 | 187 | // Context Flags 188 | int contextFlags = 0; 189 | if (data.debug) contextFlags |= GLX_CONTEXT_DEBUG_BIT_ARB; 190 | if (data.forwardCompatible) contextFlags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; 191 | if (data.noErrorContext) { 192 | contextFlags |= KHRNoError.GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR; 193 | attribList.put(GLX_CONTEXT_OPENGL_NO_ERROR_ARB).put(1); 194 | } 195 | if (data.robustness) { 196 | // Check for GLX_ARB_create_context_robustness 197 | if (!caps.GLX_ARB_create_context_robustness) { 198 | throw new SWTException("Context with robust buffer access requested but GLX_ARB_create_context_robustness is unavailable"); 199 | } 200 | contextFlags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; 201 | if (data.loseContextOnReset) { 202 | attribList.put(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB).put( 203 | GLX_LOSE_CONTEXT_ON_RESET_ARB); 204 | // Note: GLX_NO_RESET_NOTIFICATION_ARB is default behaviour and need not be specified. 205 | } 206 | if (data.contextResetIsolation) { 207 | // Check for GLX_ARB_robustness_application_isolation or GLX_ARB_robustness_share_group_isolation 208 | if (!caps.GLX_ARB_robustness_application_isolation && !caps.GLX_ARB_robustness_share_group_isolation) { 209 | throw new SWTException( 210 | "Robustness isolation requested but neither GLX_ARB_robustness_application_isolation nor GLX_ARB_robustness_share_group_isolation available"); 211 | } 212 | contextFlags |= GLX_CONTEXT_RESET_ISOLATION_BIT_ARB; 213 | } 214 | } 215 | if (contextFlags > 0) attribList.put(GLX_CONTEXT_FLAGS_ARB).put(contextFlags); 216 | 217 | // Release behavior 218 | if (data.contextReleaseBehavior != null) { 219 | if (!caps.GLX_ARB_context_flush_control) { 220 | throw new SWTException("Context release behavior requested but GLX_ARB_context_flush_control is unavailable"); 221 | } 222 | if (data.contextReleaseBehavior == ReleaseBehavior.NONE) 223 | attribList.put(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB).put(GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); 224 | else if (data.contextReleaseBehavior == ReleaseBehavior.FLUSH) 225 | attribList.put(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB).put(GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); 226 | } 227 | attribList.put(0); 228 | attribList.flip(); 229 | } 230 | 231 | @Override 232 | public boolean isCurrent(long context) { 233 | return glXGetCurrentContext () == context; 234 | } 235 | 236 | @Override 237 | public boolean makeCurrent(GLCanvas canvas, long context) { 238 | long window = GTK.gtk_widget_get_window(canvas.handle); 239 | long xDisplay = gdk_x11_display_get_xdisplay(window); 240 | return glXMakeCurrent(xDisplay, canvas.xWindow, context); 241 | } 242 | 243 | @Override 244 | public boolean deleteContext(GLCanvas canvas, long context) { 245 | long window = GTK.gtk_widget_get_window(canvas.handle); 246 | long xDisplay = gdk_x11_display_get_xdisplay(window); 247 | if (context != 0) { 248 | if (glXGetCurrentContext() == context) { 249 | glXMakeCurrent(xDisplay, 0, 0); 250 | } 251 | glXDestroyContext(xDisplay, context); 252 | canvas.context = 0; 253 | } 254 | if (canvas.glWindow != 0) { 255 | GDK.gdk_window_destroy(canvas.glWindow); 256 | canvas.glWindow = 0; 257 | } 258 | return true; 259 | } 260 | 261 | @Override 262 | public boolean swapBuffers(GLCanvas canvas) { 263 | long window = GTK.gtk_widget_get_window(canvas.handle); 264 | long xDisplay = gdk_x11_display_get_xdisplay(window); 265 | glXSwapBuffers(xDisplay, canvas.xWindow); 266 | return false; 267 | } 268 | 269 | @Override 270 | public boolean delayBeforeSwapNV(GLCanvas canvas, float seconds) { 271 | long window = GTK.gtk_widget_get_window(canvas.handle); 272 | long xDisplay = gdk_x11_display_get_xdisplay(window); 273 | return glXDelayBeforeSwapNV(xDisplay, canvas.xWindow, seconds); 274 | } 275 | 276 | private long gdk_x11_display_get_xdisplay(long window) { 277 | long display = GDK.gdk_window_get_display(window); 278 | return GDK.gdk_x11_display_get_xdisplay(display); 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /lwjgl3-swt-windows/src/main/java/org/lwjgl/opengl/swt/PlatformWin32GLCanvas.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.opengl.swt; 2 | 3 | import java.nio.IntBuffer; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | import org.eclipse.swt.SWT; 8 | import org.eclipse.swt.SWTException; 9 | import org.eclipse.swt.widgets.Canvas; 10 | import org.eclipse.swt.widgets.Composite; 11 | import org.eclipse.swt.widgets.Event; 12 | import org.eclipse.swt.widgets.Listener; 13 | import org.lwjgl.BufferUtils; 14 | import org.lwjgl.opengl.ARBMultisample; 15 | import org.lwjgl.opengl.ARBRobustness; 16 | import org.lwjgl.opengl.GL; 17 | import org.lwjgl.opengl.GL11; 18 | import org.lwjgl.opengl.GL30; 19 | import org.lwjgl.opengl.GL32; 20 | import org.lwjgl.opengl.GL43; 21 | import org.lwjgl.opengl.KHRNoError; 22 | import org.lwjgl.opengl.NVMultisampleCoverage; 23 | import org.lwjgl.opengl.WGL; 24 | import org.lwjgl.opengl.WGLARBContextFlushControl; 25 | import org.lwjgl.opengl.WGLARBCreateContext; 26 | import org.lwjgl.opengl.WGLARBCreateContextNoError; 27 | import org.lwjgl.opengl.WGLARBCreateContextProfile; 28 | import org.lwjgl.opengl.WGLARBCreateContextRobustness; 29 | import org.lwjgl.opengl.WGLARBMultisample; 30 | import org.lwjgl.opengl.WGLARBPixelFormat; 31 | import org.lwjgl.opengl.WGLARBPixelFormatFloat; 32 | import org.lwjgl.opengl.WGLARBRobustnessApplicationIsolation; 33 | import org.lwjgl.opengl.WGLEXTCreateContextES2Profile; 34 | import org.lwjgl.opengl.WGLEXTFramebufferSRGB; 35 | import org.lwjgl.opengl.WGLNVMultisampleCoverage; 36 | import org.lwjgl.opengl.swt.GLData.API; 37 | import org.lwjgl.opengl.swt.GLData.Profile; 38 | import org.lwjgl.opengl.swt.GLData.ReleaseBehavior; 39 | import org.lwjgl.system.APIUtil; 40 | import org.lwjgl.system.APIUtil.APIVersion; 41 | import org.lwjgl.system.Checks; 42 | import org.lwjgl.system.JNI; 43 | import org.lwjgl.system.MemoryStack; 44 | import org.lwjgl.system.MemoryUtil; 45 | import org.lwjgl.system.windows.GDI32; 46 | import org.lwjgl.system.windows.PIXELFORMATDESCRIPTOR; 47 | import org.lwjgl.system.windows.User32; 48 | 49 | /** 50 | * Windows-specific implementation of methods for GLCanvas. 51 | * 52 | * @author Kai Burjack 53 | */ 54 | class PlatformWin32GLCanvas extends AbstractPlatformGLCanvas { 55 | private static final String USE_OWNDC_KEY = "org.eclipse.swt.internal.win32.useOwnDC"; 56 | 57 | private long wglDelayBeforeSwapNVAddr = 0L; 58 | private boolean wglDelayBeforeSwapNVAddr_set = false; 59 | 60 | /** 61 | * Encode the pixel format attributes stored in the given {@link GLData} into the given {@link IntBuffer} for wglChoosePixelFormatARB to 62 | * consume. 63 | */ 64 | private void encodePixelFormatAttribs(IntBuffer ib, GLData attribs) { 65 | ib.put(WGLARBPixelFormat.WGL_DRAW_TO_WINDOW_ARB).put(1); 66 | ib.put(WGLARBPixelFormat.WGL_SUPPORT_OPENGL_ARB).put(1); 67 | ib.put(WGLARBPixelFormat.WGL_ACCELERATION_ARB).put(WGLARBPixelFormat.WGL_FULL_ACCELERATION_ARB); 68 | if (attribs.doubleBuffer) 69 | ib.put(WGLARBPixelFormat.WGL_DOUBLE_BUFFER_ARB).put(1); 70 | if (attribs.pixelFormatFloat) 71 | ib.put(WGLARBPixelFormat.WGL_PIXEL_TYPE_ARB).put(WGLARBPixelFormatFloat.WGL_TYPE_RGBA_FLOAT_ARB); 72 | else 73 | ib.put(WGLARBPixelFormat.WGL_PIXEL_TYPE_ARB).put(WGLARBPixelFormat.WGL_TYPE_RGBA_ARB); 74 | if (attribs.redSize > 0) 75 | ib.put(WGLARBPixelFormat.WGL_RED_BITS_ARB).put(attribs.redSize); 76 | if (attribs.greenSize > 0) 77 | ib.put(WGLARBPixelFormat.WGL_GREEN_BITS_ARB).put(attribs.greenSize); 78 | if (attribs.blueSize > 0) 79 | ib.put(WGLARBPixelFormat.WGL_BLUE_BITS_ARB).put(attribs.blueSize); 80 | if (attribs.alphaSize > 0) 81 | ib.put(WGLARBPixelFormat.WGL_ALPHA_BITS_ARB).put(attribs.alphaSize); 82 | if (attribs.depthSize > 0) 83 | ib.put(WGLARBPixelFormat.WGL_DEPTH_BITS_ARB).put(attribs.depthSize); 84 | if (attribs.stencilSize > 0) 85 | ib.put(WGLARBPixelFormat.WGL_STENCIL_BITS_ARB).put(attribs.stencilSize); 86 | if (attribs.accumRedSize > 0) 87 | ib.put(WGLARBPixelFormat.WGL_ACCUM_RED_BITS_ARB).put(attribs.accumRedSize); 88 | if (attribs.accumGreenSize > 0) 89 | ib.put(WGLARBPixelFormat.WGL_ACCUM_GREEN_BITS_ARB).put(attribs.accumGreenSize); 90 | if (attribs.accumBlueSize > 0) 91 | ib.put(WGLARBPixelFormat.WGL_ACCUM_BLUE_BITS_ARB).put(attribs.accumBlueSize); 92 | if (attribs.accumAlphaSize > 0) 93 | ib.put(WGLARBPixelFormat.WGL_ACCUM_ALPHA_BITS_ARB).put(attribs.accumAlphaSize); 94 | if (attribs.accumRedSize > 0 || attribs.accumGreenSize > 0 || attribs.accumBlueSize > 0 || attribs.accumAlphaSize > 0) 95 | ib.put(WGLARBPixelFormat.WGL_ACCUM_BITS_ARB).put(attribs.accumRedSize + attribs.accumGreenSize + attribs.accumBlueSize + attribs.accumAlphaSize); 96 | if (attribs.sRGB) 97 | ib.put(WGLEXTFramebufferSRGB.WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT).put(1); 98 | if (attribs.samples > 0) { 99 | ib.put(WGLARBMultisample.WGL_SAMPLE_BUFFERS_ARB).put(1); 100 | ib.put(WGLARBMultisample.WGL_SAMPLES_ARB).put(attribs.samples); 101 | if (attribs.colorSamplesNV > 0) { 102 | ib.put(WGLNVMultisampleCoverage.WGL_COLOR_SAMPLES_NV).put(attribs.colorSamplesNV); 103 | } 104 | } 105 | ib.put(0); 106 | } 107 | 108 | public int checkStyle(Composite parent, int style) { 109 | // Somehow we need to temporarily set 'org.eclipse.swt.internal.win32.useOwnDC' 110 | // to true or else context creation on Windows fails... 111 | if (parent != null) { 112 | // Removed windows version check - SWT dropped support for windows before Vista 113 | // https://github.com/eclipse/eclipse.platform.swt/commit/84c9e305cb087110cb300a5e58f86583cf80914d#diff-bb4584995e162b851fafacf3b046cc35 114 | parent.getDisplay().setData(USE_OWNDC_KEY, Boolean.TRUE); 115 | } 116 | return style; 117 | } 118 | 119 | public void resetStyle(Composite parent) { 120 | parent.getDisplay().setData(USE_OWNDC_KEY, Boolean.FALSE); 121 | } 122 | 123 | public long create(GLCanvas canvas, GLData attribs, GLData effective) { 124 | Canvas dummycanvas = new Canvas(canvas.getParent(), checkStyle(canvas.getParent(), canvas.getStyle())); 125 | long context = 0L; 126 | MemoryStack stack = MemoryStack.stackGet(); int ptr = stack.getPointer(); 127 | try { 128 | context = create(canvas.handle, dummycanvas.handle, attribs, effective); 129 | } catch (SWTException e) { 130 | stack.setPointer(ptr); 131 | SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH, e); 132 | } 133 | final long finalContext = context; 134 | dummycanvas.dispose(); 135 | Listener listener = new Listener() { 136 | public void handleEvent(Event event) { 137 | switch (event.type) { 138 | case SWT.Dispose: 139 | deleteContext(canvas, finalContext); 140 | break; 141 | } 142 | } 143 | }; 144 | canvas.addListener(SWT.Dispose, listener); 145 | return context; 146 | } 147 | 148 | private long create(long windowHandle, long dummyWindowHandle, GLData attribs, GLData effective) throws SWTException { 149 | MemoryStack stack = MemoryStack.stackGet(); 150 | long bufferAddr = stack.nmalloc(4, (4*2) << 2); 151 | 152 | // Validate context attributes 153 | validateAttributes(attribs); 154 | 155 | // Find this exact pixel format, though for now without multisampling. This comes later! 156 | PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.callocStack(); 157 | pfd.nSize((short) PIXELFORMATDESCRIPTOR.SIZEOF); 158 | pfd.nVersion((short) 1); // this should always be 1 159 | pfd.dwLayerMask(GDI32.PFD_MAIN_PLANE); 160 | pfd.iPixelType(GDI32.PFD_TYPE_RGBA); 161 | int flags = GDI32.PFD_DRAW_TO_WINDOW | GDI32.PFD_SUPPORT_OPENGL; 162 | if (attribs.doubleBuffer) 163 | flags |= GDI32.PFD_DOUBLEBUFFER; 164 | if (attribs.stereo) 165 | flags |= GDI32.PFD_STEREO; 166 | pfd.dwFlags(flags); 167 | pfd.cRedBits((byte) attribs.redSize); 168 | pfd.cGreenBits((byte) attribs.greenSize); 169 | pfd.cBlueBits((byte) attribs.blueSize); 170 | pfd.cAlphaBits((byte) attribs.alphaSize); 171 | pfd.cDepthBits((byte) attribs.depthSize); 172 | pfd.cStencilBits((byte) attribs.stencilSize); 173 | pfd.cAccumRedBits((byte) attribs.accumRedSize); 174 | pfd.cAccumGreenBits((byte) attribs.accumGreenSize); 175 | pfd.cAccumBlueBits((byte) attribs.accumBlueSize); 176 | pfd.cAccumAlphaBits((byte) attribs.accumAlphaSize); 177 | pfd.cAccumBits((byte) (attribs.accumRedSize + attribs.accumGreenSize + attribs.accumBlueSize + attribs.accumAlphaSize)); 178 | long hDCdummy = User32.GetDC(dummyWindowHandle); 179 | int pixelFormat = GDI32.ChoosePixelFormat(hDCdummy, pfd); 180 | if (pixelFormat == 0 || !GDI32.SetPixelFormat(hDCdummy, pixelFormat, pfd)) { 181 | // Pixel format unsupported 182 | User32.ReleaseDC(dummyWindowHandle, hDCdummy); 183 | throw new SWTException("Unsupported pixel format"); 184 | } 185 | 186 | /* 187 | * Next, create a dummy context using Opengl32.lib's wglCreateContext. This should ALWAYS work, but won't give us a "new"/"core" context if we requested 188 | * that and also does not support multisampling. But we use this "dummy" context then to request the required WGL function pointers to create a new 189 | * OpenGL >= 3.0 context and with optional multisampling. 190 | */ 191 | long dummyContext = WGL.wglCreateContext(hDCdummy); 192 | if (dummyContext == 0L) { 193 | User32.ReleaseDC(dummyWindowHandle, hDCdummy); 194 | throw new SWTException("Failed to create OpenGL context"); 195 | } 196 | 197 | // Save current context to restore it later 198 | final long currentContext = WGL.wglGetCurrentContext(); 199 | final long currentDc = WGL.wglGetCurrentDC(); 200 | 201 | // Make the new dummy context current 202 | boolean success = WGL.wglMakeCurrent(hDCdummy, dummyContext); 203 | if (!success) { 204 | User32.ReleaseDC(dummyWindowHandle, hDCdummy); 205 | WGL.wglDeleteContext(dummyContext); 206 | throw new SWTException("Failed to make OpenGL context current"); 207 | } 208 | 209 | // Query supported WGL extensions 210 | String wglExtensions = null; 211 | long wglGetExtensionsStringARBAddr = WGL.wglGetProcAddress("wglGetExtensionsStringARB"); 212 | if (wglGetExtensionsStringARBAddr != 0L) { 213 | long str = JNI.callPP(hDCdummy, wglGetExtensionsStringARBAddr); 214 | if (str != 0L) { 215 | wglExtensions = MemoryUtil.memASCII(str); 216 | } else { 217 | wglExtensions = ""; 218 | } 219 | } else { 220 | // Try the EXT extension 221 | long wglGetExtensionsStringEXTAddr = WGL.wglGetProcAddress("wglGetExtensionsStringEXT"); 222 | if (wglGetExtensionsStringEXTAddr != 0L) { 223 | long str = JNI.callP(wglGetExtensionsStringEXTAddr); 224 | if (str != 0L) { 225 | wglExtensions = MemoryUtil.memASCII(str); 226 | } else { 227 | wglExtensions = ""; 228 | } 229 | } else { 230 | wglExtensions = ""; 231 | } 232 | } 233 | String[] splitted = wglExtensions.split(" "); 234 | Set wglExtensionsList = new HashSet(splitted.length); 235 | for (String str : splitted) { 236 | wglExtensionsList.add(str); 237 | } 238 | success = User32.ReleaseDC(dummyWindowHandle, hDCdummy); 239 | if (!success) { 240 | WGL.wglDeleteContext(dummyContext); 241 | WGL.wglMakeCurrent(currentDc, currentContext); 242 | throw new SWTException("Could not release dummy DC"); 243 | } 244 | 245 | // For some constellations of context attributes, we can stop right here. 246 | if (!atLeast30(attribs.majorVersion, attribs.minorVersion) && attribs.samples == 0 && !attribs.sRGB && !attribs.pixelFormatFloat 247 | && attribs.contextReleaseBehavior == null && !attribs.robustness && attribs.api != API.GLES) { 248 | /* Finally, create the real context on the real window */ 249 | long hDC = User32.GetDC(windowHandle); 250 | GDI32.SetPixelFormat(hDC, pixelFormat, pfd); 251 | success = WGL.wglDeleteContext(dummyContext); 252 | if (!success) { 253 | User32.ReleaseDC(windowHandle, hDC); 254 | WGL.wglMakeCurrent(currentDc, currentContext); 255 | throw new SWTException("Could not delete dummy GL context"); 256 | } 257 | long context = WGL.wglCreateContext(hDC); 258 | 259 | if (attribs.swapInterval != null) { 260 | boolean has_WGL_EXT_swap_control = wglExtensionsList.contains("WGL_EXT_swap_control"); 261 | if (!has_WGL_EXT_swap_control) { 262 | User32.ReleaseDC(windowHandle, hDC); 263 | WGL.wglMakeCurrent(currentDc, currentContext); 264 | WGL.wglDeleteContext(context); 265 | throw new SWTException("Swap interval requested but WGL_EXT_swap_control is unavailable"); 266 | } 267 | if (attribs.swapInterval < 0) { 268 | // Only allowed if WGL_EXT_swap_control_tear is available 269 | boolean has_WGL_EXT_swap_control_tear = wglExtensionsList.contains("WGL_EXT_swap_control_tear"); 270 | if (!has_WGL_EXT_swap_control_tear) { 271 | User32.ReleaseDC(windowHandle, hDC); 272 | WGL.wglMakeCurrent(currentDc, currentContext); 273 | WGL.wglDeleteContext(context); 274 | throw new SWTException("Negative swap interval requested but WGL_EXT_swap_control_tear is unavailable"); 275 | } 276 | } 277 | // Make context current to set the swap interval 278 | success = WGL.wglMakeCurrent(hDC, context); 279 | if (!success) { 280 | User32.ReleaseDC(windowHandle, hDC); 281 | WGL.wglMakeCurrent(currentDc, currentContext); 282 | WGL.wglDeleteContext(context); 283 | throw new SWTException("Could not make GL context current"); 284 | } 285 | long wglSwapIntervalEXTAddr = WGL.wglGetProcAddress("wglSwapIntervalEXT"); 286 | if (wglSwapIntervalEXTAddr != 0L) { 287 | JNI.callI(attribs.swapInterval, wglSwapIntervalEXTAddr); 288 | } 289 | } 290 | 291 | if (attribs.swapGroupNV > 0 || attribs.swapBarrierNV > 0) { 292 | // Only allowed if WGL_NV_swap_group is available 293 | boolean has_WGL_NV_swap_group = wglExtensionsList.contains("WGL_NV_swap_group"); 294 | if (!has_WGL_NV_swap_group) { 295 | User32.ReleaseDC(windowHandle, hDC); 296 | WGL.wglMakeCurrent(currentDc, currentContext); 297 | WGL.wglDeleteContext(context); 298 | throw new SWTException("Swap group or barrier requested but WGL_NV_swap_group is unavailable"); 299 | } 300 | // Make context current to join swap group and/or barrier 301 | success = WGL.wglMakeCurrent(hDC, context); 302 | try { 303 | wglNvSwapGroupAndBarrier(attribs, stack.getAddress() + stack.getPointer(), hDC); 304 | } catch (SWTException e) { 305 | User32.ReleaseDC(windowHandle, hDC); 306 | WGL.wglMakeCurrent(currentDc, currentContext); 307 | WGL.wglDeleteContext(context); 308 | throw e; 309 | } 310 | } 311 | 312 | /* Check if we want to share context */ 313 | if (attribs.shareContext != null) { 314 | success = WGL.wglShareLists(context, attribs.shareContext.context); 315 | if (!success) { 316 | User32.ReleaseDC(windowHandle, hDC); 317 | WGL.wglMakeCurrent(currentDc, currentContext); 318 | WGL.wglDeleteContext(context); 319 | throw new SWTException("Failed while configuring context sharing"); 320 | } 321 | } 322 | 323 | // Describe pixel format 324 | int pixFmtIndex = GDI32.DescribePixelFormat(hDC, pixelFormat, pfd); 325 | if (pixFmtIndex == 0) { 326 | User32.ReleaseDC(windowHandle, hDC); 327 | WGL.wglMakeCurrent(currentDc, currentContext); 328 | WGL.wglDeleteContext(context); 329 | throw new SWTException("Failed to describe pixel format"); 330 | } 331 | success = User32.ReleaseDC(windowHandle, hDC); 332 | if (!success) { 333 | WGL.wglMakeCurrent(currentDc, currentContext); 334 | WGL.wglDeleteContext(context); 335 | throw new SWTException("Could not release DC"); 336 | } 337 | effective.redSize = pfd.cRedBits(); 338 | effective.greenSize = pfd.cGreenBits(); 339 | effective.blueSize = pfd.cBlueBits(); 340 | effective.alphaSize = pfd.cAlphaBits(); 341 | effective.depthSize = pfd.cDepthBits(); 342 | effective.stencilSize = pfd.cStencilBits(); 343 | int pixelFormatFlags = pfd.dwFlags(); 344 | effective.doubleBuffer = (pixelFormatFlags & GDI32.PFD_DOUBLEBUFFER) != 0; 345 | effective.stereo = (pixelFormatFlags & GDI32.PFD_STEREO) != 0; 346 | effective.accumRedSize = pfd.cAccumRedBits(); 347 | effective.accumGreenSize = pfd.cAccumGreenBits(); 348 | effective.accumBlueSize = pfd.cAccumBlueBits(); 349 | effective.accumAlphaSize = pfd.cAccumAlphaBits(); 350 | 351 | // Restore old context 352 | WGL.wglMakeCurrent(currentDc, currentContext); 353 | return context; 354 | } 355 | 356 | // Check for WGL_ARB_create_context support 357 | if (!wglExtensionsList.contains("WGL_ARB_create_context")) { 358 | WGL.wglDeleteContext(dummyContext); 359 | WGL.wglMakeCurrent(currentDc, currentContext); 360 | throw new SWTException("Extended context attributes requested but WGL_ARB_create_context is unavailable"); 361 | } 362 | 363 | // Obtain wglCreateContextAttribsARB function pointer 364 | long wglCreateContextAttribsARBAddr = WGL.wglGetProcAddress("wglCreateContextAttribsARB"); 365 | if (wglCreateContextAttribsARBAddr == 0L) { 366 | WGL.wglDeleteContext(dummyContext); 367 | WGL.wglMakeCurrent(currentDc, currentContext); 368 | throw new SWTException("WGL_ARB_create_context available but wglCreateContextAttribsARB is NULL"); 369 | } 370 | 371 | IntBuffer attribList = BufferUtils.createIntBuffer(64); 372 | long attribListAddr = MemoryUtil.memAddress(attribList); 373 | long hDC = User32.GetDC(windowHandle); 374 | 375 | // Obtain wglChoosePixelFormatARB if multisampling or sRGB or floating point pixel format is requested 376 | if (attribs.samples > 0 || attribs.sRGB || attribs.pixelFormatFloat) { 377 | long wglChoosePixelFormatAddr = WGL.wglGetProcAddress("wglChoosePixelFormatARB"); 378 | if (wglChoosePixelFormatAddr == 0L) { 379 | // Try EXT function (the WGL constants are the same in both extensions) 380 | wglChoosePixelFormatAddr = WGL.wglGetProcAddress("wglChoosePixelFormatEXT"); 381 | if (wglChoosePixelFormatAddr == 0L) { 382 | User32.ReleaseDC(windowHandle, hDC); 383 | WGL.wglDeleteContext(dummyContext); 384 | WGL.wglMakeCurrent(currentDc, currentContext); 385 | throw new SWTException("No support for wglChoosePixelFormatARB/EXT. Cannot query supported pixel formats."); 386 | } 387 | } 388 | if (attribs.samples > 0) { 389 | // Check for ARB or EXT extension (their WGL constants have the same value) 390 | boolean has_WGL_ARB_multisample = wglExtensionsList.contains("WGL_ARB_multisample"); 391 | boolean has_WGL_EXT_multisample = wglExtensionsList.contains("WGL_EXT_multisample"); 392 | if (!has_WGL_ARB_multisample && !has_WGL_EXT_multisample) { 393 | User32.ReleaseDC(windowHandle, hDC); 394 | WGL.wglDeleteContext(dummyContext); 395 | WGL.wglMakeCurrent(currentDc, currentContext); 396 | throw new SWTException("Multisampling requested but neither WGL_ARB_multisample nor WGL_EXT_multisample available"); 397 | } 398 | if (attribs.colorSamplesNV > 0) { 399 | boolean has_WGL_NV_multisample_coverage = wglExtensionsList.contains("WGL_NV_multisample_coverage"); 400 | if (!has_WGL_NV_multisample_coverage) { 401 | User32.ReleaseDC(windowHandle, hDC); 402 | WGL.wglDeleteContext(dummyContext); 403 | WGL.wglMakeCurrent(currentDc, currentContext); 404 | throw new SWTException("Color samples requested but WGL_NV_multisample_coverage is unavailable"); 405 | } 406 | } 407 | } 408 | if (attribs.sRGB) { 409 | // Check for WGL_EXT_framebuffer_sRGB 410 | boolean has_WGL_EXT_framebuffer_sRGB = wglExtensionsList.contains("WGL_EXT_framebuffer_sRGB"); 411 | if (!has_WGL_EXT_framebuffer_sRGB) { 412 | User32.ReleaseDC(windowHandle, hDC); 413 | WGL.wglDeleteContext(dummyContext); 414 | WGL.wglMakeCurrent(currentDc, currentContext); 415 | throw new SWTException("sRGB color space requested but WGL_EXT_framebuffer_sRGB is unavailable"); 416 | } 417 | } 418 | if (attribs.pixelFormatFloat) { 419 | // Check for WGL_ARB_pixel_format_float 420 | boolean has_WGL_ARB_pixel_format_float = wglExtensionsList.contains("WGL_ARB_pixel_format_float"); 421 | if (!has_WGL_ARB_pixel_format_float) { 422 | User32.ReleaseDC(windowHandle, hDC); 423 | WGL.wglDeleteContext(dummyContext); 424 | WGL.wglMakeCurrent(currentDc, currentContext); 425 | throw new SWTException("Floating-point format requested but WGL_ARB_pixel_format_float is unavailable"); 426 | } 427 | } 428 | // Query matching pixel formats 429 | encodePixelFormatAttribs(attribList, attribs); 430 | success = JNI.callPPPPPI(hDC, attribListAddr, 0L, 1, bufferAddr + 4, bufferAddr, wglChoosePixelFormatAddr) == 1; 431 | int numFormats = MemoryUtil.memGetInt(bufferAddr); 432 | if (!success || numFormats == 0) { 433 | User32.ReleaseDC(windowHandle, hDC); 434 | WGL.wglDeleteContext(dummyContext); 435 | WGL.wglMakeCurrent(currentDc, currentContext); 436 | throw new SWTException("No supported pixel format found."); 437 | } 438 | pixelFormat = MemoryUtil.memGetInt(bufferAddr + 4); 439 | // Describe pixel format for the PIXELFORMATDESCRIPTOR to match the chosen format 440 | int pixFmtIndex = GDI32.DescribePixelFormat(hDC, pixelFormat, pfd); 441 | if (pixFmtIndex == 0) { 442 | User32.ReleaseDC(windowHandle, hDC); 443 | WGL.wglDeleteContext(dummyContext); 444 | WGL.wglMakeCurrent(currentDc, currentContext); 445 | throw new SWTException("Failed to validate supported pixel format."); 446 | } 447 | // Obtain extended pixel format attributes 448 | long wglGetPixelFormatAttribivAddr = WGL.wglGetProcAddress("wglGetPixelFormatAttribivARB"); 449 | if (wglGetPixelFormatAttribivAddr == 0L) { 450 | // Try EXT function (function signature is the same) 451 | wglGetPixelFormatAttribivAddr = WGL.wglGetProcAddress("wglGetPixelFormatAttribivEXT"); 452 | if (wglGetPixelFormatAttribivAddr == 0L) { 453 | User32.ReleaseDC(windowHandle, hDC); 454 | WGL.wglDeleteContext(dummyContext); 455 | WGL.wglMakeCurrent(currentDc, currentContext); 456 | throw new SWTException("No support for wglGetPixelFormatAttribivARB/EXT. Cannot get effective pixel format attributes."); 457 | } 458 | } 459 | attribList.rewind(); 460 | attribList.put(WGLARBPixelFormat.WGL_DOUBLE_BUFFER_ARB); 461 | attribList.put(WGLARBPixelFormat.WGL_STEREO_ARB); 462 | attribList.put(WGLARBPixelFormat.WGL_PIXEL_TYPE_ARB); 463 | attribList.put(WGLARBPixelFormat.WGL_RED_BITS_ARB); 464 | attribList.put(WGLARBPixelFormat.WGL_GREEN_BITS_ARB); 465 | attribList.put(WGLARBPixelFormat.WGL_BLUE_BITS_ARB); 466 | attribList.put(WGLARBPixelFormat.WGL_ALPHA_BITS_ARB); 467 | attribList.put(WGLARBPixelFormat.WGL_ACCUM_RED_BITS_ARB); 468 | attribList.put(WGLARBPixelFormat.WGL_ACCUM_GREEN_BITS_ARB); 469 | attribList.put(WGLARBPixelFormat.WGL_ACCUM_BLUE_BITS_ARB); 470 | attribList.put(WGLARBPixelFormat.WGL_ACCUM_ALPHA_BITS_ARB); 471 | attribList.put(WGLARBPixelFormat.WGL_DEPTH_BITS_ARB); 472 | attribList.put(WGLARBPixelFormat.WGL_STENCIL_BITS_ARB); 473 | IntBuffer attribValues = BufferUtils.createIntBuffer(attribList.position()); 474 | long attribValuesAddr = MemoryUtil.memAddress(attribValues); 475 | success = JNI.callPPPI(hDC, pixelFormat, GDI32.PFD_MAIN_PLANE, attribList.position(), attribListAddr, 476 | attribValuesAddr, wglGetPixelFormatAttribivAddr) == 1; 477 | if (!success) { 478 | User32.ReleaseDC(windowHandle, hDC); 479 | WGL.wglDeleteContext(dummyContext); 480 | WGL.wglMakeCurrent(currentDc, currentContext); 481 | throw new SWTException("Failed to get pixel format attributes."); 482 | } 483 | effective.doubleBuffer = attribValues.get(0) == 1; 484 | effective.stereo = attribValues.get(1) == 1; 485 | int pixelType = attribValues.get(2); 486 | effective.pixelFormatFloat = pixelType == WGLARBPixelFormatFloat.WGL_TYPE_RGBA_FLOAT_ARB; 487 | effective.redSize = attribValues.get(3); 488 | effective.greenSize = attribValues.get(4); 489 | effective.blueSize = attribValues.get(5); 490 | effective.alphaSize = attribValues.get(6); 491 | effective.accumRedSize = attribValues.get(7); 492 | effective.accumGreenSize = attribValues.get(8); 493 | effective.accumBlueSize = attribValues.get(9); 494 | effective.accumAlphaSize = attribValues.get(10); 495 | effective.depthSize = attribValues.get(11); 496 | effective.stencilSize = attribValues.get(12); 497 | } 498 | 499 | // Compose the attributes list 500 | attribList.rewind(); 501 | if (attribs.api == API.GL && atLeast30(attribs.majorVersion, attribs.minorVersion) || attribs.api == API.GLES && attribs.majorVersion > 0) { 502 | attribList.put(WGLARBCreateContext.WGL_CONTEXT_MAJOR_VERSION_ARB).put(attribs.majorVersion); 503 | attribList.put(WGLARBCreateContext.WGL_CONTEXT_MINOR_VERSION_ARB).put(attribs.minorVersion); 504 | } 505 | int profile = 0; 506 | if (attribs.api == API.GL) { 507 | if (attribs.profile == Profile.COMPATIBILITY) { 508 | profile = WGLARBCreateContextProfile.WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; 509 | } else if (attribs.profile == Profile.CORE) { 510 | profile = WGLARBCreateContextProfile.WGL_CONTEXT_CORE_PROFILE_BIT_ARB; 511 | } 512 | } else if (attribs.api == API.GLES) { 513 | boolean has_WGL_EXT_create_context_es2_profile = wglExtensionsList.contains("WGL_EXT_create_context_es2_profile"); 514 | if (!has_WGL_EXT_create_context_es2_profile) { 515 | User32.ReleaseDC(windowHandle, hDC); 516 | WGL.wglDeleteContext(dummyContext); 517 | WGL.wglMakeCurrent(currentDc, currentContext); 518 | throw new SWTException("OpenGL ES API requested but WGL_EXT_create_context_es2_profile is unavailable"); 519 | } 520 | profile = WGLEXTCreateContextES2Profile.WGL_CONTEXT_ES2_PROFILE_BIT_EXT; 521 | } 522 | if (profile > 0) { 523 | boolean has_WGL_ARB_create_context_profile = wglExtensionsList.contains("WGL_ARB_create_context_profile"); 524 | if (!has_WGL_ARB_create_context_profile) { 525 | User32.ReleaseDC(windowHandle, hDC); 526 | WGL.wglDeleteContext(dummyContext); 527 | WGL.wglMakeCurrent(currentDc, currentContext); 528 | throw new SWTException("OpenGL profile requested but WGL_ARB_create_context_profile is unavailable"); 529 | } 530 | attribList.put(WGLARBCreateContextProfile.WGL_CONTEXT_PROFILE_MASK_ARB).put(profile); 531 | } 532 | int contextFlags = 0; 533 | if (attribs.debug) { 534 | contextFlags |= WGLARBCreateContext.WGL_CONTEXT_DEBUG_BIT_ARB; 535 | } 536 | if (attribs.forwardCompatible) { 537 | contextFlags |= WGLARBCreateContext.WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; 538 | } 539 | if (attribs.noErrorContext) { 540 | contextFlags |= KHRNoError.GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR; 541 | attribList.put(WGLARBCreateContextNoError.WGL_CONTEXT_OPENGL_NO_ERROR_ARB).put(1); 542 | } 543 | if (attribs.robustness) { 544 | // Check for WGL_ARB_create_context_robustness 545 | boolean has_WGL_ARB_create_context_robustness = wglExtensions.contains("WGL_ARB_create_context_robustness"); 546 | if (!has_WGL_ARB_create_context_robustness) { 547 | User32.ReleaseDC(windowHandle, hDC); 548 | WGL.wglDeleteContext(dummyContext); 549 | WGL.wglMakeCurrent(currentDc, currentContext); 550 | throw new SWTException("Context with robust buffer access requested but WGL_ARB_create_context_robustness is unavailable"); 551 | } 552 | contextFlags |= WGLARBCreateContextRobustness.WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; 553 | if (attribs.loseContextOnReset) { 554 | attribList.put(WGLARBCreateContextRobustness.WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB).put( 555 | WGLARBCreateContextRobustness.WGL_LOSE_CONTEXT_ON_RESET_ARB); 556 | // Note: WGL_NO_RESET_NOTIFICATION_ARB is default behaviour and need not be specified. 557 | } 558 | if (attribs.contextResetIsolation) { 559 | // Check for WGL_ARB_robustness_application_isolation or WGL_ARB_robustness_share_group_isolation 560 | boolean has_WGL_ARB_robustness_application_isolation = wglExtensions.contains("WGL_ARB_robustness_application_isolation"); 561 | boolean has_WGL_ARB_robustness_share_group_isolation = wglExtensions.contains("WGL_ARB_robustness_share_group_isolation"); 562 | if (!has_WGL_ARB_robustness_application_isolation && !has_WGL_ARB_robustness_share_group_isolation) { 563 | User32.ReleaseDC(windowHandle, hDC); 564 | WGL.wglDeleteContext(dummyContext); 565 | WGL.wglMakeCurrent(currentDc, currentContext); 566 | throw new SWTException( 567 | "Robustness isolation requested but neither WGL_ARB_robustness_application_isolation nor WGL_ARB_robustness_share_group_isolation available"); 568 | } 569 | contextFlags |= WGLARBRobustnessApplicationIsolation.WGL_CONTEXT_RESET_ISOLATION_BIT_ARB; 570 | } 571 | } 572 | if (contextFlags > 0) 573 | attribList.put(WGLARBCreateContext.WGL_CONTEXT_FLAGS_ARB).put(contextFlags); 574 | if (attribs.contextReleaseBehavior != null) { 575 | boolean has_WGL_ARB_context_flush_control = wglExtensionsList.contains("WGL_ARB_context_flush_control"); 576 | if (!has_WGL_ARB_context_flush_control) { 577 | User32.ReleaseDC(windowHandle, hDC); 578 | WGL.wglDeleteContext(dummyContext); 579 | WGL.wglMakeCurrent(currentDc, currentContext); 580 | throw new SWTException("Context release behavior requested but WGL_ARB_context_flush_control is unavailable"); 581 | } 582 | if (attribs.contextReleaseBehavior == ReleaseBehavior.NONE) 583 | attribList.put(WGLARBContextFlushControl.WGL_CONTEXT_RELEASE_BEHAVIOR_ARB).put(WGLARBContextFlushControl.WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); 584 | else if (attribs.contextReleaseBehavior == ReleaseBehavior.FLUSH) 585 | attribList.put(WGLARBContextFlushControl.WGL_CONTEXT_RELEASE_BEHAVIOR_ARB) 586 | .put(WGLARBContextFlushControl.WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); 587 | } 588 | attribList.put(0).put(0); 589 | // Set pixelformat 590 | success = GDI32.SetPixelFormat(hDC, pixelFormat, pfd); 591 | if (!success) { 592 | User32.ReleaseDC(windowHandle, hDC); 593 | WGL.wglDeleteContext(dummyContext); 594 | WGL.wglMakeCurrent(currentDc, currentContext); 595 | throw new SWTException("Failed to set pixel format."); 596 | } 597 | // And create new context with it 598 | long newCtx = JNI.callPPPP(hDC, attribs.shareContext != null ? attribs.shareContext.context : 0L, attribListAddr, wglCreateContextAttribsARBAddr); 599 | WGL.wglDeleteContext(dummyContext); 600 | if (newCtx == 0L) { 601 | User32.ReleaseDC(windowHandle, hDC); 602 | WGL.wglMakeCurrent(currentDc, currentContext); 603 | throw new SWTException("Failed to create OpenGL context."); 604 | } 605 | // Make context current for next operations 606 | WGL.wglMakeCurrent(hDC, newCtx); 607 | if (attribs.swapInterval != null) { 608 | boolean has_WGL_EXT_swap_control = wglExtensionsList.contains("WGL_EXT_swap_control"); 609 | if (!has_WGL_EXT_swap_control) { 610 | User32.ReleaseDC(windowHandle, hDC); 611 | WGL.wglMakeCurrent(currentDc, currentContext); 612 | WGL.wglDeleteContext(newCtx); 613 | throw new SWTException("Swap interval requested but WGL_EXT_swap_control is unavailable"); 614 | } 615 | if (attribs.swapInterval < 0) { 616 | // Only allowed if WGL_EXT_swap_control_tear is available 617 | boolean has_WGL_EXT_swap_control_tear = wglExtensionsList.contains("WGL_EXT_swap_control_tear"); 618 | if (!has_WGL_EXT_swap_control_tear) { 619 | User32.ReleaseDC(windowHandle, hDC); 620 | WGL.wglMakeCurrent(currentDc, currentContext); 621 | WGL.wglDeleteContext(newCtx); 622 | throw new SWTException("Negative swap interval requested but WGL_EXT_swap_control_tear is unavailable"); 623 | } 624 | } 625 | long wglSwapIntervalEXTAddr = WGL.wglGetProcAddress("wglSwapIntervalEXT"); 626 | if (wglSwapIntervalEXTAddr != 0L) { 627 | JNI.callI(attribs.swapInterval, wglSwapIntervalEXTAddr); 628 | } 629 | } 630 | if (attribs.swapGroupNV > 0 || attribs.swapBarrierNV > 0) { 631 | // Only allowed if WGL_NV_swap_group is available 632 | boolean has_WGL_NV_swap_group = wglExtensionsList.contains("WGL_NV_swap_group"); 633 | if (!has_WGL_NV_swap_group) { 634 | User32.ReleaseDC(windowHandle, hDC); 635 | WGL.wglMakeCurrent(currentDc, currentContext); 636 | WGL.wglDeleteContext(newCtx); 637 | throw new SWTException("Swap group or barrier requested but WGL_NV_swap_group is unavailable"); 638 | } 639 | try { 640 | wglNvSwapGroupAndBarrier(attribs, bufferAddr, hDC); 641 | } catch (SWTException e) { 642 | User32.ReleaseDC(windowHandle, hDC); 643 | WGL.wglMakeCurrent(currentDc, currentContext); 644 | WGL.wglDeleteContext(newCtx); 645 | throw e; 646 | } 647 | } 648 | User32.ReleaseDC(windowHandle, hDC); 649 | long getInteger = GL.getFunctionProvider().getFunctionAddress("glGetIntegerv"); 650 | long getString = GL.getFunctionProvider().getFunctionAddress("glGetString"); 651 | effective.api = attribs.api; 652 | if (atLeast30(attribs.majorVersion, attribs.minorVersion)) { 653 | JNI.callPV(GL30.GL_MAJOR_VERSION, bufferAddr, getInteger); 654 | effective.majorVersion = MemoryUtil.memGetInt(bufferAddr); 655 | JNI.callPV(GL30.GL_MINOR_VERSION, bufferAddr, getInteger); 656 | effective.minorVersion = MemoryUtil.memGetInt(bufferAddr); 657 | JNI.callPV(GL30.GL_CONTEXT_FLAGS, bufferAddr, getInteger); 658 | int effectiveContextFlags = MemoryUtil.memGetInt(bufferAddr); 659 | effective.debug = (effectiveContextFlags & GL43.GL_CONTEXT_FLAG_DEBUG_BIT) != 0; 660 | effective.forwardCompatible = (effectiveContextFlags & GL30.GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) != 0; 661 | effective.robustness = (effectiveContextFlags & ARBRobustness.GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB) != 0; 662 | } else if (attribs.api == API.GL) { 663 | APIVersion version = APIUtil.apiParseVersion(MemoryUtil.memUTF8(Checks.check(JNI.callP(GL11.GL_VERSION, getString)))); 664 | effective.majorVersion = version.major; 665 | effective.minorVersion = version.minor; 666 | } else if (attribs.api == API.GLES) { 667 | APIVersion version = APIUtil.apiParseVersion(MemoryUtil.memUTF8(Checks.check(JNI.callP(GL11.GL_VERSION, getString))), "OpenGL ES"); 668 | effective.majorVersion = version.major; 669 | effective.minorVersion = version.minor; 670 | } 671 | if (attribs.api == API.GL && atLeast32(effective.majorVersion, effective.minorVersion)) { 672 | JNI.callPV(GL32.GL_CONTEXT_PROFILE_MASK, bufferAddr, getInteger); 673 | int effectiveProfileMask = MemoryUtil.memGetInt(bufferAddr); 674 | boolean core = (effectiveProfileMask & GL32.GL_CONTEXT_CORE_PROFILE_BIT) != 0; 675 | boolean comp = (effectiveProfileMask & GL32.GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0; 676 | if (comp) { 677 | effective.profile = Profile.COMPATIBILITY; 678 | } else if (core) { 679 | effective.profile = Profile.CORE; 680 | } else { 681 | effective.profile = null; 682 | } 683 | } 684 | if (attribs.samples >= 1) { 685 | JNI.callPV(ARBMultisample.GL_SAMPLES_ARB, bufferAddr, getInteger); 686 | effective.samples = MemoryUtil.memGetInt(bufferAddr); 687 | JNI.callPV(ARBMultisample.GL_SAMPLE_BUFFERS_ARB, bufferAddr, getInteger); 688 | effective.sampleBuffers = MemoryUtil.memGetInt(bufferAddr); 689 | boolean has_WGL_NV_multisample_coverage = wglExtensionsList.contains("WGL_NV_multisample_coverage"); 690 | if (has_WGL_NV_multisample_coverage) { 691 | JNI.callPV(NVMultisampleCoverage.GL_COLOR_SAMPLES_NV, bufferAddr, getInteger); 692 | effective.colorSamplesNV = MemoryUtil.memGetInt(bufferAddr); 693 | } 694 | } 695 | // Restore old context 696 | WGL.wglMakeCurrent(currentDc, currentContext); 697 | return newCtx; 698 | } 699 | 700 | private void wglNvSwapGroupAndBarrier(GLData attribs, long bufferAddr, long hDC) throws SWTException { 701 | int success; 702 | long wglQueryMaxSwapGroupsNVAddr = WGL.wglGetProcAddress("wglQueryMaxSwapGroupsNV"); 703 | success = JNI.callPPPI(hDC, bufferAddr, bufferAddr + 4, wglQueryMaxSwapGroupsNVAddr); 704 | int maxGroups = MemoryUtil.memGetInt(bufferAddr); 705 | if (maxGroups < attribs.swapGroupNV) { 706 | throw new SWTException("Swap group exceeds maximum group index"); 707 | } 708 | int maxBarriers = MemoryUtil.memGetInt(bufferAddr + 4); 709 | if (maxBarriers < attribs.swapBarrierNV) { 710 | throw new SWTException("Swap barrier exceeds maximum barrier index"); 711 | } 712 | if (attribs.swapGroupNV > 0) { 713 | long wglJoinSwapGroupNVAddr = WGL.wglGetProcAddress("wglJoinSwapGroupNV"); 714 | if (wglJoinSwapGroupNVAddr == 0L) { 715 | throw new SWTException("WGL_NV_swap_group available but wglJoinSwapGroupNV is NULL"); 716 | } 717 | success = JNI.callPI(hDC, attribs.swapGroupNV, wglJoinSwapGroupNVAddr); 718 | if (success == 0) { 719 | throw new SWTException("Failed to join swap group"); 720 | } 721 | if (attribs.swapBarrierNV > 0) { 722 | long wglBindSwapBarrierNVAddr = WGL.wglGetProcAddress("wglBindSwapBarrierNV"); 723 | if (wglBindSwapBarrierNVAddr == 0L) { 724 | throw new SWTException("WGL_NV_swap_group available but wglBindSwapBarrierNV is NULL"); 725 | } 726 | success = JNI.callI(attribs.swapGroupNV, attribs.swapBarrierNV, wglBindSwapBarrierNVAddr); 727 | if (success == 0) { 728 | throw new SWTException("Failed to bind swap barrier. Probably no G-Sync card installed."); 729 | } 730 | } 731 | } 732 | } 733 | 734 | public boolean isCurrent(long context) { 735 | long ret = WGL.wglGetCurrentContext(); 736 | return ret == context; 737 | } 738 | 739 | public boolean makeCurrent(GLCanvas canvas, long context) { 740 | long hDC = User32.GetDC(canvas.handle); 741 | boolean ret = WGL.wglMakeCurrent(hDC, context); 742 | User32.ReleaseDC(canvas.handle, hDC); 743 | return ret; 744 | } 745 | 746 | public boolean deleteContext(GLCanvas canvas, long context) { 747 | boolean ret = WGL.wglDeleteContext(context); 748 | return ret; 749 | } 750 | 751 | public boolean swapBuffers(GLCanvas canvas) { 752 | long hDC = User32.GetDC(canvas.handle); 753 | boolean ret = GDI32.SwapBuffers(hDC); 754 | User32.ReleaseDC(canvas.handle, hDC); 755 | return ret; 756 | } 757 | 758 | public boolean delayBeforeSwapNV(GLCanvas canvas, float seconds) { 759 | if (!wglDelayBeforeSwapNVAddr_set) { 760 | wglDelayBeforeSwapNVAddr = WGL.wglGetProcAddress("wglDelayBeforeSwapNV"); 761 | wglDelayBeforeSwapNVAddr_set = true; 762 | } 763 | if (wglDelayBeforeSwapNVAddr == 0L) { 764 | throw new UnsupportedOperationException("wglDelayBeforeSwapNV is unavailable"); 765 | } 766 | long hDC = User32.GetDC(canvas.handle); 767 | int ret = JNI.callPI(hDC, seconds, wglDelayBeforeSwapNVAddr); 768 | User32.ReleaseDC(canvas.handle, hDC); 769 | return ret == 1; 770 | } 771 | 772 | } 773 | --------------------------------------------------------------------------------