mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 19:28:57 +01:00
internal/glfw: use a pure Go implementation of GLFW
This change removes internal/glfw/glfw, that is a DLL loader, and replaces the usages with internal/glfwwin, that is a pure Go implementation of GLFW for Windows. The build tag `ebitenexternaldll` is also removed. Closes #1764
This commit is contained in:
parent
edd617f80e
commit
f67b4cc1d6
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +0,0 @@
|
|||||||
internal/glfw/glfw/** linguist-vendored
|
|
20
doc.go
20
doc.go
@ -91,24 +91,4 @@
|
|||||||
// to manage threads yourself. Functions like IsKeyPressed will no longer be concurrent-safe with this build tag.
|
// to manage threads yourself. Functions like IsKeyPressed will no longer be concurrent-safe with this build tag.
|
||||||
// They must be called from the main thread or the same goroutine as the given game's callback functions like Update
|
// They must be called from the main thread or the same goroutine as the given game's callback functions like Update
|
||||||
// to RunGame.
|
// to RunGame.
|
||||||
//
|
|
||||||
// `ebitenexternaldll` stops embedding DLL file in a Windows executable.
|
|
||||||
// `ebitenexternaldll` works only for Windows.
|
|
||||||
// The executable will require a DLL file at the working directory. Copy them from Ebiten repository's `internal/glfw`:
|
|
||||||
//
|
|
||||||
// * `glfw_windows_386.dll` for Windows GOARCH=386
|
|
||||||
// * `glfw_windows_amd64.dll` for Windows GOARCH=amd64
|
|
||||||
//
|
|
||||||
// The directory path can be obtained by Go commands. For example, on PowerShell:
|
|
||||||
//
|
|
||||||
// $dir = go list -f '{{.Dir}}' github.com/hajimehoshi/ebiten/v2/internal/glfw
|
|
||||||
// echo $dir\glfw_windows_amd64.dll
|
|
||||||
//
|
|
||||||
// and on shell:
|
|
||||||
//
|
|
||||||
// echo $(go list -f '{{.Dir}}' github.com/hajimehoshi/ebiten/v2/internal/glfw)/glfw_windows_amd64.dll
|
|
||||||
//
|
|
||||||
// Embedding a DLL and extracting it on the fly might be problematic on Windows since the application might be
|
|
||||||
// unexpectedly recognized as a virus by some virus checkers.
|
|
||||||
// `ebitenexternaldll` is useful for such cases. See #1832 for the discussion.
|
|
||||||
package ebiten
|
package ebiten
|
||||||
|
3
go.mod
3
go.mod
@ -4,7 +4,6 @@ go 1.15
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958
|
||||||
github.com/gofrs/flock v0.8.1
|
|
||||||
github.com/hajimehoshi/bitmapfont/v2 v2.2.0
|
github.com/hajimehoshi/bitmapfont/v2 v2.2.0
|
||||||
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41
|
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41
|
||||||
github.com/hajimehoshi/go-mp3 v0.3.3
|
github.com/hajimehoshi/go-mp3 v0.3.3
|
||||||
@ -14,8 +13,6 @@ require (
|
|||||||
github.com/jfreymuth/oggvorbis v1.0.3
|
github.com/jfreymuth/oggvorbis v1.0.3
|
||||||
golang.org/x/image v0.0.0-20220321031419-a8550c1d254a
|
golang.org/x/image v0.0.0-20220321031419-a8550c1d254a
|
||||||
golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd
|
golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
|
||||||
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f
|
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f
|
||||||
golang.org/x/tools v0.1.10
|
golang.org/x/tools v0.1.10
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
)
|
)
|
||||||
|
10
go.sum
10
go.sum
@ -1,8 +1,6 @@
|
|||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958 h1:TL70PMkdPCt9cRhKTqsm+giRpgrd0IGEj763nNr2VFY=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958 h1:TL70PMkdPCt9cRhKTqsm+giRpgrd0IGEj763nNr2VFY=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
|
||||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
|
||||||
github.com/hajimehoshi/bitmapfont/v2 v2.2.0 h1:E6vzlchynZj6OVohVKFqWkKW348EmDW62K5zPXDi7A8=
|
github.com/hajimehoshi/bitmapfont/v2 v2.2.0 h1:E6vzlchynZj6OVohVKFqWkKW348EmDW62K5zPXDi7A8=
|
||||||
github.com/hajimehoshi/bitmapfont/v2 v2.2.0/go.mod h1:Llj2wTYXMuCTJEw2ATNIO6HbFPOoBYPs08qLdFAxOsQ=
|
github.com/hajimehoshi/bitmapfont/v2 v2.2.0/go.mod h1:Llj2wTYXMuCTJEw2ATNIO6HbFPOoBYPs08qLdFAxOsQ=
|
||||||
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 h1:s01qIIRG7vN/5ndLwkDktjx44ulFk6apvAjVBYR50Yo=
|
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 h1:s01qIIRG7vN/5ndLwkDktjx44ulFk6apvAjVBYR50Yo=
|
||||||
@ -21,11 +19,6 @@ github.com/jfreymuth/oggvorbis v1.0.3 h1:MLNGGyhOMiVcvea9Dp5+gbs2SAwqwQbtrWnonYa
|
|||||||
github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
||||||
github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE=
|
github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE=
|
||||||
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
@ -56,7 +49,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -86,5 +78,3 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
|||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
FROM debian:buster
|
|
||||||
|
|
||||||
# For the version of gcc-mingw-w64, see https://packages.debian.org/buster/gcc-mingw-w64-x86-64
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
git \
|
|
||||||
ca-certificates \
|
|
||||||
golang \
|
|
||||||
gcc-mingw-w64=8.3.0-6+21.3~deb10u2 \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /work
|
|
@ -15,85 +15,59 @@
|
|||||||
package glfw
|
package glfw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/sys/windows"
|
"github.com/hajimehoshi/ebiten/v2/internal/glfwwin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var uniquePtrToCallback = map[uniquePtr]uintptr{}
|
|
||||||
|
|
||||||
func ToCharModsCallback(cb func(window *Window, char rune, mods ModifierKey)) CharModsCallback {
|
func ToCharModsCallback(cb func(window *Window, char rune, mods ModifierKey)) CharModsCallback {
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ptr := uniquePtr(new(byte))
|
return func(window *glfwwin.Window, char rune, mods glfwwin.ModifierKey) {
|
||||||
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, char rune, mods ModifierKey) uintptr {
|
cb((*Window)(window), char, ModifierKey(mods))
|
||||||
cb(theGLFWWindows.get(window), char, mods)
|
}
|
||||||
return 0
|
|
||||||
})
|
|
||||||
return CharModsCallback(ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToCloseCallback(cb func(window *Window)) CloseCallback {
|
func ToCloseCallback(cb func(window *Window)) CloseCallback {
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ptr := uniquePtr(new(byte))
|
return func(window *glfwwin.Window) {
|
||||||
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr) uintptr {
|
cb((*Window)(window))
|
||||||
cb(theGLFWWindows.get(window))
|
}
|
||||||
return 0
|
|
||||||
})
|
|
||||||
return CloseCallback(ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback {
|
func ToFramebufferSizeCallback(cb func(window *Window, width int, height int)) FramebufferSizeCallback {
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ptr := uniquePtr(new(byte))
|
return func(window *glfwwin.Window, width int, height int) {
|
||||||
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, width int, height int) uintptr {
|
cb((*Window)(window), width, height)
|
||||||
cb(theGLFWWindows.get(window), width, height)
|
}
|
||||||
return 0
|
|
||||||
})
|
|
||||||
return FramebufferSizeCallback(ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback {
|
func ToMonitorCallback(cb func(monitor *Monitor, event PeripheralEvent)) MonitorCallback {
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ptr := uniquePtr(new(byte))
|
return func(monitor *glfwwin.Monitor, event glfwwin.PeripheralEvent) {
|
||||||
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(monitor uintptr, event PeripheralEvent) uintptr {
|
cb((*Monitor)(monitor), PeripheralEvent(event))
|
||||||
var m *Monitor
|
|
||||||
if monitor != 0 {
|
|
||||||
m = &Monitor{monitor}
|
|
||||||
}
|
}
|
||||||
cb(m, event)
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
return MonitorCallback(ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback {
|
func ToScrollCallback(cb func(window *Window, xoff float64, yoff float64)) ScrollCallback {
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ptr := uniquePtr(new(byte))
|
return func(window *glfwwin.Window, xoff float64, yoff float64) {
|
||||||
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, xoff *float64, yoff *float64) uintptr {
|
cb((*Window)(window), xoff, yoff)
|
||||||
// xoff and yoff were originally float64, but there is no good way to pass them on 32bit
|
}
|
||||||
// machines via NewCallback. We've fixed GLFW side to use pointer values.
|
|
||||||
cb(theGLFWWindows.get(window), *xoff, *yoff)
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
return ScrollCallback(ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback {
|
func ToSizeCallback(cb func(window *Window, width int, height int)) SizeCallback {
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ptr := uniquePtr(new(byte))
|
return func(window *glfwwin.Window, width int, height int) {
|
||||||
uniquePtrToCallback[ptr] = windows.NewCallbackCDecl(func(window uintptr, width int, height int) uintptr {
|
cb((*Window)(window), width, height)
|
||||||
cb(theGLFWWindows.get(window), width, height)
|
}
|
||||||
return 0
|
|
||||||
})
|
|
||||||
return SizeCallback(ptr)
|
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2021 The Ebiten Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
//go:build ebitenexternaldll
|
|
||||||
// +build ebitenexternaldll
|
|
||||||
|
|
||||||
package glfw
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
func loadDLL() (*dll, error) {
|
|
||||||
name := "glfw_windows_" + runtime.GOARCH + ".dll"
|
|
||||||
d := windows.NewLazyDLL(name)
|
|
||||||
if err := d.Load(); err != nil {
|
|
||||||
return nil, fmt.Errorf("glfw: failed to load %s: %w", name, err)
|
|
||||||
}
|
|
||||||
return &dll{
|
|
||||||
d: d,
|
|
||||||
}, nil
|
|
||||||
}
|
|
@ -1,172 +0,0 @@
|
|||||||
// Copyright 2018 The Ebiten Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
//go:build ignore
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/file2byteslice"
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
|
||||||
|
|
||||||
type arch string
|
|
||||||
|
|
||||||
const (
|
|
||||||
archAmd64 arch = "amd64"
|
|
||||||
arch386 arch = "386"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a arch) gcc() string {
|
|
||||||
switch a {
|
|
||||||
case archAmd64:
|
|
||||||
return "x86_64-w64-mingw32-gcc"
|
|
||||||
case arch386:
|
|
||||||
return "i686-w64-mingw32-gcc"
|
|
||||||
default:
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func c2o(str string) string {
|
|
||||||
return strings.TrimSuffix(filepath.Base(str), ".c") + ".o"
|
|
||||||
}
|
|
||||||
|
|
||||||
func execCommand(name string, args ...string) error {
|
|
||||||
cmd := exec.Command(name, args...)
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
return cmd.Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
func run() error {
|
|
||||||
srcs, err := filepath.Glob(filepath.Join("glfw", "src", "*.c"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sort.Strings(srcs)
|
|
||||||
|
|
||||||
for _, arch := range []arch{archAmd64, arch386} {
|
|
||||||
g := errgroup.Group{}
|
|
||||||
for _, s := range srcs {
|
|
||||||
s := s
|
|
||||||
g.Go(func() error {
|
|
||||||
args := []string{
|
|
||||||
"-c",
|
|
||||||
"-o",
|
|
||||||
c2o(s),
|
|
||||||
"-D_GLFW_WIN32",
|
|
||||||
"-D_GLFW_BUILD_DLL",
|
|
||||||
"-Iglfw/deps/mingw",
|
|
||||||
"-g",
|
|
||||||
"-Os",
|
|
||||||
s,
|
|
||||||
}
|
|
||||||
if err := execCommand(arch.gcc(), args...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if err := g.Wait(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
objs := []string{}
|
|
||||||
for _, s := range srcs {
|
|
||||||
objs = append(objs, c2o(s))
|
|
||||||
}
|
|
||||||
dll := fmt.Sprintf("glfw_windows_%s.dll", arch)
|
|
||||||
args := []string{
|
|
||||||
"-shared",
|
|
||||||
"-o",
|
|
||||||
dll,
|
|
||||||
"-Wl,--no-insert-timestamp",
|
|
||||||
}
|
|
||||||
args = append(args, objs...)
|
|
||||||
args = append(args, "-lopengl32", "-lgdi32")
|
|
||||||
if err := execCommand(arch.gcc(), args...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
dllf, err := os.Open(dll)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer dllf.Close()
|
|
||||||
|
|
||||||
hash := sha256.New()
|
|
||||||
in := io.TeeReader(dllf, hash)
|
|
||||||
|
|
||||||
out, err := os.Create(fmt.Sprintf("glfwdll_windows_%s.go", arch))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
// As the file name already specified the build environment, buildtags are not requried.
|
|
||||||
if err := file2byteslice.Write(out, in, true, "!ebitenexternaldll", "glfw", "glfwDLLCompressed"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dump the hash
|
|
||||||
hashout, err := os.Create(fmt.Sprintf("glfwdllhash_windows_%s.go", arch))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer hashout.Close()
|
|
||||||
|
|
||||||
hashsum := hash.Sum(nil)
|
|
||||||
if _, err := fmt.Fprintf(hashout, `// Code generated by gen.go. DO NOT EDIT.
|
|
||||||
|
|
||||||
//go:build !ebitenexternaldll
|
|
||||||
// +build !ebitenexternaldll
|
|
||||||
|
|
||||||
package glfw
|
|
||||||
|
|
||||||
const glfwDLLHash = "%s"
|
|
||||||
`, hex.EncodeToString(hashsum[:])); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up the files.
|
|
||||||
for _, o := range objs {
|
|
||||||
if err := os.Remove(o); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := execCommand("gofmt", "-s", "-w", "."); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := run(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
docker run --rm --volume $(pwd)/../..:/work $(docker build -q . | head -n1) /bin/sh -c "cd ./internal/glfw; go run gen.go"
|
|
@ -1,19 +0,0 @@
|
|||||||
// Copyright 2018 The Ebiten Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// +bulid !js
|
|
||||||
|
|
||||||
//go:generate sh ./gen.sh
|
|
||||||
|
|
||||||
package glfw
|
|
@ -1,22 +0,0 @@
|
|||||||
Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would
|
|
||||||
be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
These files are basically copy of github.com/v3.3/glfw/glfw.
|
|
||||||
|
|
||||||
There are some changes from the original files.
|
|
||||||
|
|
||||||
`GLFWscrollfun` takes pointers instead of values since all arguments of C functions have to be 32bit on 32bit Windows machine.
|
|
||||||
|
|
||||||
```diff
|
|
||||||
diff --git a/tmp/glfw-3.3.3/include/GLFW/glfw3.h b/./internal/glfw/glfw/include/GLFW/glfw3.h
|
|
||||||
index 35bbf075..b41c0dca 100644
|
|
||||||
--- a/tmp/glfw-3.3.3/include/GLFW/glfw3.h
|
|
||||||
+++ b/./internal/glfw/glfw/include/GLFW/glfw3.h
|
|
||||||
@@ -1496,7 +1496,7 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
|
|
||||||
*
|
|
||||||
* @ingroup input
|
|
||||||
*/
|
|
||||||
-typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
|
|
||||||
+typedef void (* GLFWscrollfun)(GLFWwindow*,double*,double*);
|
|
||||||
|
|
||||||
/*! @brief The function pointer type for keyboard key callbacks.
|
|
||||||
*
|
|
||||||
```
|
|
||||||
|
|
||||||
```diff
|
|
||||||
diff --git a/tmp/glfw-3.3.3/src/input.c b/./internal/glfw/glfw/src/input.c
|
|
||||||
index 337d5cf0..4ac555cb 100644
|
|
||||||
--- a/tmp/glfw-3.3.3/src/input.c
|
|
||||||
+++ b/./internal/glfw/glfw/src/input.c
|
|
||||||
@@ -312,7 +312,7 @@ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWb
|
|
||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
|
||||||
{
|
|
||||||
if (window->callbacks.scroll)
|
|
||||||
- window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
|
|
||||||
+ window->callbacks.scroll((GLFWwindow*) window, &xoffset, &yoffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notifies shared code of a mouse button click event
|
|
||||||
```
|
|
||||||
|
|
||||||
A fullscreened window doesn't float (#1506, glfw/glfw#1967).
|
|
||||||
|
|
||||||
```diff
|
|
||||||
diff --git a/tmp/glfw-3.3.4/src/win32_window.c b/./internal/glfw/glfw/src/win32_window.c
|
|
||||||
index d17b6da4..17e2f842 100644
|
|
||||||
--- a/tmp/glfw-3.3.4/src/win32_window.c
|
|
||||||
+++ b/./internal/glfw/glfw/src/win32_window.c
|
|
||||||
@@ -68,7 +68,7 @@ static DWORD getWindowExStyle(const _GLFWwindow* window)
|
|
||||||
{
|
|
||||||
DWORD style = WS_EX_APPWINDOW;
|
|
||||||
|
|
||||||
- if (window->monitor || window->floating)
|
|
||||||
+ if (window->floating)
|
|
||||||
style |= WS_EX_TOPMOST;
|
|
||||||
|
|
||||||
return style;
|
|
||||||
@@ -436,7 +436,7 @@ static void fitToMonitor(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
MONITORINFO mi = { sizeof(mi) };
|
|
||||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
|
||||||
- SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
|
||||||
+ SetWindowPos(window->win32.handle, window->floating ? HWND_TOPMOST : HWND_NOTOPMOST,
|
|
||||||
mi.rcMonitor.left,
|
|
||||||
mi.rcMonitor.top,
|
|
||||||
mi.rcMonitor.right - mi.rcMonitor.left,
|
|
||||||
@@ -1756,7 +1756,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|
||||||
acquireMonitor(window);
|
|
||||||
|
|
||||||
GetMonitorInfo(window->monitor->win32.handle, &mi);
|
|
||||||
- SetWindowPos(window->win32.handle, HWND_TOPMOST,
|
|
||||||
+ SetWindowPos(window->win32.handle, window->floating ? HWND_TOPMOST : HWND_NOTOPMOST,
|
|
||||||
mi.rcMonitor.left,
|
|
||||||
mi.rcMonitor.top,
|
|
||||||
mi.rcMonitor.right - mi.rcMonitor.left,
|
|
||||||
```
|
|
@ -1,117 +0,0 @@
|
|||||||
/**
|
|
||||||
* This file has no copyright assigned and is placed in the Public Domain.
|
|
||||||
* This file is part of the mingw-w64 runtime package.
|
|
||||||
* No warranty is given; refer to the file DISCLAIMER within this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
|
|
||||||
#define NONAMELESSUNION 1
|
|
||||||
#endif
|
|
||||||
#if defined(NONAMELESSSTRUCT) && \
|
|
||||||
!defined(NONAMELESSUNION)
|
|
||||||
#define NONAMELESSUNION 1
|
|
||||||
#endif
|
|
||||||
#if defined(NONAMELESSUNION) && \
|
|
||||||
!defined(NONAMELESSSTRUCT)
|
|
||||||
#define NONAMELESSSTRUCT 1
|
|
||||||
#endif
|
|
||||||
#if !defined(__GNU_EXTENSION)
|
|
||||||
#if defined(__GNUC__) || defined(__GNUG__)
|
|
||||||
#define __GNU_EXTENSION __extension__
|
|
||||||
#else
|
|
||||||
#define __GNU_EXTENSION
|
|
||||||
#endif
|
|
||||||
#endif /* __extension__ */
|
|
||||||
|
|
||||||
#ifndef __ANONYMOUS_DEFINED
|
|
||||||
#define __ANONYMOUS_DEFINED
|
|
||||||
#if defined(__GNUC__) || defined(__GNUG__)
|
|
||||||
#define _ANONYMOUS_UNION __extension__
|
|
||||||
#define _ANONYMOUS_STRUCT __extension__
|
|
||||||
#else
|
|
||||||
#define _ANONYMOUS_UNION
|
|
||||||
#define _ANONYMOUS_STRUCT
|
|
||||||
#endif
|
|
||||||
#ifndef NONAMELESSUNION
|
|
||||||
#define _UNION_NAME(x)
|
|
||||||
#define _STRUCT_NAME(x)
|
|
||||||
#else /* NONAMELESSUNION */
|
|
||||||
#define _UNION_NAME(x) x
|
|
||||||
#define _STRUCT_NAME(x) x
|
|
||||||
#endif
|
|
||||||
#endif /* __ANONYMOUS_DEFINED */
|
|
||||||
|
|
||||||
#ifndef DUMMYUNIONNAME
|
|
||||||
# ifdef NONAMELESSUNION
|
|
||||||
# define DUMMYUNIONNAME u
|
|
||||||
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
|
|
||||||
# define DUMMYUNIONNAME2 u2
|
|
||||||
# define DUMMYUNIONNAME3 u3
|
|
||||||
# define DUMMYUNIONNAME4 u4
|
|
||||||
# define DUMMYUNIONNAME5 u5
|
|
||||||
# define DUMMYUNIONNAME6 u6
|
|
||||||
# define DUMMYUNIONNAME7 u7
|
|
||||||
# define DUMMYUNIONNAME8 u8
|
|
||||||
# define DUMMYUNIONNAME9 u9
|
|
||||||
# else /* NONAMELESSUNION */
|
|
||||||
# define DUMMYUNIONNAME
|
|
||||||
# define DUMMYUNIONNAME1 /* Wine uses this variant */
|
|
||||||
# define DUMMYUNIONNAME2
|
|
||||||
# define DUMMYUNIONNAME3
|
|
||||||
# define DUMMYUNIONNAME4
|
|
||||||
# define DUMMYUNIONNAME5
|
|
||||||
# define DUMMYUNIONNAME6
|
|
||||||
# define DUMMYUNIONNAME7
|
|
||||||
# define DUMMYUNIONNAME8
|
|
||||||
# define DUMMYUNIONNAME9
|
|
||||||
# endif
|
|
||||||
#endif /* DUMMYUNIONNAME */
|
|
||||||
|
|
||||||
#if !defined(DUMMYUNIONNAME1) /* MinGW does not define this one */
|
|
||||||
# ifdef NONAMELESSUNION
|
|
||||||
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
|
|
||||||
# else
|
|
||||||
# define DUMMYUNIONNAME1 /* Wine uses this variant */
|
|
||||||
# endif
|
|
||||||
#endif /* DUMMYUNIONNAME1 */
|
|
||||||
|
|
||||||
#ifndef DUMMYSTRUCTNAME
|
|
||||||
# ifdef NONAMELESSUNION
|
|
||||||
# define DUMMYSTRUCTNAME s
|
|
||||||
# define DUMMYSTRUCTNAME1 s1 /* Wine uses this variant */
|
|
||||||
# define DUMMYSTRUCTNAME2 s2
|
|
||||||
# define DUMMYSTRUCTNAME3 s3
|
|
||||||
# define DUMMYSTRUCTNAME4 s4
|
|
||||||
# define DUMMYSTRUCTNAME5 s5
|
|
||||||
# else
|
|
||||||
# define DUMMYSTRUCTNAME
|
|
||||||
# define DUMMYSTRUCTNAME1 /* Wine uses this variant */
|
|
||||||
# define DUMMYSTRUCTNAME2
|
|
||||||
# define DUMMYSTRUCTNAME3
|
|
||||||
# define DUMMYSTRUCTNAME4
|
|
||||||
# define DUMMYSTRUCTNAME5
|
|
||||||
# endif
|
|
||||||
#endif /* DUMMYSTRUCTNAME */
|
|
||||||
|
|
||||||
/* These are for compatibility with the Wine source tree */
|
|
||||||
|
|
||||||
#ifndef WINELIB_NAME_AW
|
|
||||||
# ifdef __MINGW_NAME_AW
|
|
||||||
# define WINELIB_NAME_AW __MINGW_NAME_AW
|
|
||||||
# else
|
|
||||||
# ifdef UNICODE
|
|
||||||
# define WINELIB_NAME_AW(func) func##W
|
|
||||||
# else
|
|
||||||
# define WINELIB_NAME_AW(func) func##A
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
#endif /* WINELIB_NAME_AW */
|
|
||||||
|
|
||||||
#ifndef DECL_WINELIB_TYPE_AW
|
|
||||||
# ifdef __MINGW_TYPEDEF_AW
|
|
||||||
# define DECL_WINELIB_TYPE_AW __MINGW_TYPEDEF_AW
|
|
||||||
# else
|
|
||||||
# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type;
|
|
||||||
# endif
|
|
||||||
#endif /* DECL_WINELIB_TYPE_AW */
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,239 +0,0 @@
|
|||||||
/*
|
|
||||||
* The Wine project - Xinput Joystick Library
|
|
||||||
* Copyright 2008 Andrew Fenn
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __WINE_XINPUT_H
|
|
||||||
#define __WINE_XINPUT_H
|
|
||||||
|
|
||||||
#include <windef.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bitmasks for the joysticks buttons, determines what has
|
|
||||||
* been pressed on the joystick, these need to be mapped
|
|
||||||
* to whatever device you're using instead of an xbox 360
|
|
||||||
* joystick
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define XINPUT_GAMEPAD_DPAD_UP 0x0001
|
|
||||||
#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002
|
|
||||||
#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004
|
|
||||||
#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008
|
|
||||||
#define XINPUT_GAMEPAD_START 0x0010
|
|
||||||
#define XINPUT_GAMEPAD_BACK 0x0020
|
|
||||||
#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040
|
|
||||||
#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080
|
|
||||||
#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
|
|
||||||
#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
|
|
||||||
#define XINPUT_GAMEPAD_A 0x1000
|
|
||||||
#define XINPUT_GAMEPAD_B 0x2000
|
|
||||||
#define XINPUT_GAMEPAD_X 0x4000
|
|
||||||
#define XINPUT_GAMEPAD_Y 0x8000
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the flags used to determine if the user is pushing
|
|
||||||
* down on a button, not holding a button, etc
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define XINPUT_KEYSTROKE_KEYDOWN 0x0001
|
|
||||||
#define XINPUT_KEYSTROKE_KEYUP 0x0002
|
|
||||||
#define XINPUT_KEYSTROKE_REPEAT 0x0004
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the codes which are returned by XInputGetKeystroke
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define VK_PAD_A 0x5800
|
|
||||||
#define VK_PAD_B 0x5801
|
|
||||||
#define VK_PAD_X 0x5802
|
|
||||||
#define VK_PAD_Y 0x5803
|
|
||||||
#define VK_PAD_RSHOULDER 0x5804
|
|
||||||
#define VK_PAD_LSHOULDER 0x5805
|
|
||||||
#define VK_PAD_LTRIGGER 0x5806
|
|
||||||
#define VK_PAD_RTRIGGER 0x5807
|
|
||||||
#define VK_PAD_DPAD_UP 0x5810
|
|
||||||
#define VK_PAD_DPAD_DOWN 0x5811
|
|
||||||
#define VK_PAD_DPAD_LEFT 0x5812
|
|
||||||
#define VK_PAD_DPAD_RIGHT 0x5813
|
|
||||||
#define VK_PAD_START 0x5814
|
|
||||||
#define VK_PAD_BACK 0x5815
|
|
||||||
#define VK_PAD_LTHUMB_PRESS 0x5816
|
|
||||||
#define VK_PAD_RTHUMB_PRESS 0x5817
|
|
||||||
#define VK_PAD_LTHUMB_UP 0x5820
|
|
||||||
#define VK_PAD_LTHUMB_DOWN 0x5821
|
|
||||||
#define VK_PAD_LTHUMB_RIGHT 0x5822
|
|
||||||
#define VK_PAD_LTHUMB_LEFT 0x5823
|
|
||||||
#define VK_PAD_LTHUMB_UPLEFT 0x5824
|
|
||||||
#define VK_PAD_LTHUMB_UPRIGHT 0x5825
|
|
||||||
#define VK_PAD_LTHUMB_DOWNRIGHT 0x5826
|
|
||||||
#define VK_PAD_LTHUMB_DOWNLEFT 0x5827
|
|
||||||
#define VK_PAD_RTHUMB_UP 0x5830
|
|
||||||
#define VK_PAD_RTHUMB_DOWN 0x5831
|
|
||||||
#define VK_PAD_RTHUMB_RIGHT 0x5832
|
|
||||||
#define VK_PAD_RTHUMB_LEFT 0x5833
|
|
||||||
#define VK_PAD_RTHUMB_UPLEFT 0x5834
|
|
||||||
#define VK_PAD_RTHUMB_UPRIGHT 0x5835
|
|
||||||
#define VK_PAD_RTHUMB_DOWNRIGHT 0x5836
|
|
||||||
#define VK_PAD_RTHUMB_DOWNLEFT 0x5837
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deadzones are for analogue joystick controls on the joypad
|
|
||||||
* which determine when input should be assumed to be in the
|
|
||||||
* middle of the pad. This is a threshold to stop a joypad
|
|
||||||
* controlling the game when the player isn't touching the
|
|
||||||
* controls.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
|
|
||||||
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
|
||||||
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines what type of abilities the type of joystick has
|
|
||||||
* DEVTYPE_GAMEPAD is available for all joysticks, however
|
|
||||||
* there may be more specific identifiers for other joysticks
|
|
||||||
* which are being used.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define XINPUT_DEVTYPE_GAMEPAD 0x01
|
|
||||||
#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
|
|
||||||
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
|
||||||
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
|
||||||
#define XINPUT_DEVSUBTYPE_FLIGHT_SICK 0x04
|
|
||||||
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
|
||||||
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
|
||||||
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These are used with the XInputGetCapabilities function to
|
|
||||||
* determine the abilities to the joystick which has been
|
|
||||||
* plugged in.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define XINPUT_CAPS_VOICE_SUPPORTED 0x0004
|
|
||||||
#define XINPUT_FLAG_GAMEPAD 0x00000001
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the status of the battery if one is used in the
|
|
||||||
* attached joystick. The first two define if the joystick
|
|
||||||
* supports a battery. Disconnected means that the joystick
|
|
||||||
* isn't connected. Wired shows that the joystick is a wired
|
|
||||||
* joystick.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define BATTERY_DEVTYPE_GAMEPAD 0x00
|
|
||||||
#define BATTERY_DEVTYPE_HEADSET 0x01
|
|
||||||
#define BATTERY_TYPE_DISCONNECTED 0x00
|
|
||||||
#define BATTERY_TYPE_WIRED 0x01
|
|
||||||
#define BATTERY_TYPE_ALKALINE 0x02
|
|
||||||
#define BATTERY_TYPE_NIMH 0x03
|
|
||||||
#define BATTERY_TYPE_UNKNOWN 0xFF
|
|
||||||
#define BATTERY_LEVEL_EMPTY 0x00
|
|
||||||
#define BATTERY_LEVEL_LOW 0x01
|
|
||||||
#define BATTERY_LEVEL_MEDIUM 0x02
|
|
||||||
#define BATTERY_LEVEL_FULL 0x03
|
|
||||||
|
|
||||||
/*
|
|
||||||
* How many joysticks can be used with this library. Games that
|
|
||||||
* use the xinput library will not go over this number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define XUSER_MAX_COUNT 4
|
|
||||||
#define XUSER_INDEX_ANY 0x000000FF
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the structure of an xbox 360 joystick.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _XINPUT_GAMEPAD {
|
|
||||||
WORD wButtons;
|
|
||||||
BYTE bLeftTrigger;
|
|
||||||
BYTE bRightTrigger;
|
|
||||||
SHORT sThumbLX;
|
|
||||||
SHORT sThumbLY;
|
|
||||||
SHORT sThumbRX;
|
|
||||||
SHORT sThumbRY;
|
|
||||||
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
|
|
||||||
|
|
||||||
typedef struct _XINPUT_STATE {
|
|
||||||
DWORD dwPacketNumber;
|
|
||||||
XINPUT_GAMEPAD Gamepad;
|
|
||||||
} XINPUT_STATE, *PXINPUT_STATE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the structure of how much vibration is set on both the
|
|
||||||
* right and left motors in a joystick. If you're not using a 360
|
|
||||||
* joystick you will have to map these to your device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _XINPUT_VIBRATION {
|
|
||||||
WORD wLeftMotorSpeed;
|
|
||||||
WORD wRightMotorSpeed;
|
|
||||||
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the structure for what kind of abilities the joystick has
|
|
||||||
* such abilities are things such as if the joystick has the ability
|
|
||||||
* to send and receive audio, if the joystick is in fact a driving
|
|
||||||
* wheel or perhaps if the joystick is some kind of dance pad or
|
|
||||||
* guitar.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _XINPUT_CAPABILITIES {
|
|
||||||
BYTE Type;
|
|
||||||
BYTE SubType;
|
|
||||||
WORD Flags;
|
|
||||||
XINPUT_GAMEPAD Gamepad;
|
|
||||||
XINPUT_VIBRATION Vibration;
|
|
||||||
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the structure for a joystick input event which is
|
|
||||||
* retrieved using the function XInputGetKeystroke
|
|
||||||
*/
|
|
||||||
typedef struct _XINPUT_KEYSTROKE {
|
|
||||||
WORD VirtualKey;
|
|
||||||
WCHAR Unicode;
|
|
||||||
WORD Flags;
|
|
||||||
BYTE UserIndex;
|
|
||||||
BYTE HidCode;
|
|
||||||
} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;
|
|
||||||
|
|
||||||
typedef struct _XINPUT_BATTERY_INFORMATION
|
|
||||||
{
|
|
||||||
BYTE BatteryType;
|
|
||||||
BYTE BatteryLevel;
|
|
||||||
} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void WINAPI XInputEnable(WINBOOL);
|
|
||||||
DWORD WINAPI XInputSetState(DWORD, XINPUT_VIBRATION*);
|
|
||||||
DWORD WINAPI XInputGetState(DWORD, XINPUT_STATE*);
|
|
||||||
DWORD WINAPI XInputGetKeystroke(DWORD, DWORD, PXINPUT_KEYSTROKE);
|
|
||||||
DWORD WINAPI XInputGetCapabilities(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
|
||||||
DWORD WINAPI XInputGetDSoundAudioDeviceGuids(DWORD, GUID*, GUID*);
|
|
||||||
DWORD WINAPI XInputGetBatteryInformation(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __WINE_XINPUT_H */
|
|
File diff suppressed because it is too large
Load Diff
@ -1,594 +0,0 @@
|
|||||||
/*************************************************************************
|
|
||||||
* GLFW 3.3 - www.glfw.org
|
|
||||||
* A library for OpenGL, window and input
|
|
||||||
*------------------------------------------------------------------------
|
|
||||||
* Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
* Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
|
||||||
* including commercial applications, and to alter it and redistribute it
|
|
||||||
* freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
* claim that you wrote the original software. If you use this software
|
|
||||||
* in a product, an acknowledgment in the product documentation would
|
|
||||||
* be appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
* be misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source
|
|
||||||
* distribution.
|
|
||||||
*
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _glfw3_native_h_
|
|
||||||
#define _glfw3_native_h_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Doxygen documentation
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
/*! @file glfw3native.h
|
|
||||||
* @brief The header of the native access functions.
|
|
||||||
*
|
|
||||||
* This is the header file of the native access functions. See @ref native for
|
|
||||||
* more information.
|
|
||||||
*/
|
|
||||||
/*! @defgroup native Native access
|
|
||||||
* @brief Functions related to accessing native handles.
|
|
||||||
*
|
|
||||||
* **By using the native access functions you assert that you know what you're
|
|
||||||
* doing and how to fix problems caused by using them. If you don't, you
|
|
||||||
* shouldn't be using them.**
|
|
||||||
*
|
|
||||||
* Before the inclusion of @ref glfw3native.h, you may define zero or more
|
|
||||||
* window system API macro and zero or more context creation API macros.
|
|
||||||
*
|
|
||||||
* The chosen backends must match those the library was compiled for. Failure
|
|
||||||
* to do this will cause a link-time error.
|
|
||||||
*
|
|
||||||
* The available window API macros are:
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_WIN32`
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_COCOA`
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_X11`
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_WAYLAND`
|
|
||||||
*
|
|
||||||
* The available context API macros are:
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_WGL`
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_NSGL`
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_GLX`
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_EGL`
|
|
||||||
* * `GLFW_EXPOSE_NATIVE_OSMESA`
|
|
||||||
*
|
|
||||||
* These macros select which of the native access functions that are declared
|
|
||||||
* and which platform-specific headers to include. It is then up your (by
|
|
||||||
* definition platform-specific) code to handle which of these should be
|
|
||||||
* defined.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* System headers and types
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
|
|
||||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
|
||||||
// example to allow applications to correctly declare a GL_KHR_debug callback)
|
|
||||||
// but windows.h assumes no one will define APIENTRY before it does
|
|
||||||
#if defined(GLFW_APIENTRY_DEFINED)
|
|
||||||
#undef APIENTRY
|
|
||||||
#undef GLFW_APIENTRY_DEFINED
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
|
|
||||||
#if defined(__OBJC__)
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#else
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
|
||||||
typedef void* id;
|
|
||||||
#endif
|
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/extensions/Xrandr.h>
|
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
|
||||||
/* WGL is declared by windows.h */
|
|
||||||
#endif
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
|
||||||
/* NSGL is declared by Cocoa.h */
|
|
||||||
#endif
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
|
||||||
#include <GL/glx.h>
|
|
||||||
#endif
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
|
||||||
#include <EGL/egl.h>
|
|
||||||
#endif
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
|
||||||
#include <GL/osmesa.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Functions
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
|
|
||||||
/*! @brief Returns the adapter device name of the specified monitor.
|
|
||||||
*
|
|
||||||
* @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
|
|
||||||
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
|
|
||||||
* occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.1.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
/*! @brief Returns the display device name of the specified monitor.
|
|
||||||
*
|
|
||||||
* @return The UTF-8 encoded display device name (for example
|
|
||||||
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.1.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
/*! @brief Returns the `HWND` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `HWND` of the specified window, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @remark The `HDC` associated with the window can be queried with the
|
|
||||||
* [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
|
|
||||||
* function.
|
|
||||||
* @code
|
|
||||||
* HDC dc = GetDC(glfwGetWin32Window(window));
|
|
||||||
* @endcode
|
|
||||||
* This DC is private and does not need to be released.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
|
||||||
/*! @brief Returns the `HGLRC` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `HGLRC` of the specified window, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @remark The `HDC` associated with the window can be queried with the
|
|
||||||
* [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
|
|
||||||
* function.
|
|
||||||
* @code
|
|
||||||
* HDC dc = GetDC(glfwGetWin32Window(window));
|
|
||||||
* @endcode
|
|
||||||
* This DC is private and does not need to be released.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
|
|
||||||
/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
|
|
||||||
*
|
|
||||||
* @return The `CGDirectDisplayID` of the specified monitor, or
|
|
||||||
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.1.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
/*! @brief Returns the `NSWindow` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `NSWindow` of the specified window, or `nil` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
|
||||||
/*! @brief Returns the `NSOpenGLContext` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `NSOpenGLContext` of the specified window, or `nil` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_X11)
|
|
||||||
/*! @brief Returns the `Display` used by GLFW.
|
|
||||||
*
|
|
||||||
* @return The `Display` used by GLFW, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI Display* glfwGetX11Display(void);
|
|
||||||
|
|
||||||
/*! @brief Returns the `RRCrtc` of the specified monitor.
|
|
||||||
*
|
|
||||||
* @return The `RRCrtc` of the specified monitor, or `None` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.1.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
/*! @brief Returns the `RROutput` of the specified monitor.
|
|
||||||
*
|
|
||||||
* @return The `RROutput` of the specified monitor, or `None` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.1.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
/*! @brief Returns the `Window` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `Window` of the specified window, or `None` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
|
||||||
|
|
||||||
/*! @brief Sets the current primary selection to the specified string.
|
|
||||||
*
|
|
||||||
* @param[in] string A UTF-8 encoded string.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
|
||||||
* GLFW_PLATFORM_ERROR.
|
|
||||||
*
|
|
||||||
* @pointer_lifetime The specified string is copied before this function
|
|
||||||
* returns.
|
|
||||||
*
|
|
||||||
* @thread_safety This function must only be called from the main thread.
|
|
||||||
*
|
|
||||||
* @sa @ref clipboard
|
|
||||||
* @sa glfwGetX11SelectionString
|
|
||||||
* @sa glfwSetClipboardString
|
|
||||||
*
|
|
||||||
* @since Added in version 3.3.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI void glfwSetX11SelectionString(const char* string);
|
|
||||||
|
|
||||||
/*! @brief Returns the contents of the current primary selection as a string.
|
|
||||||
*
|
|
||||||
* If the selection is empty or if its contents cannot be converted, `NULL`
|
|
||||||
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
|
|
||||||
*
|
|
||||||
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
|
|
||||||
* if an [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
|
||||||
* GLFW_PLATFORM_ERROR.
|
|
||||||
*
|
|
||||||
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
|
||||||
* should not free it yourself. It is valid until the next call to @ref
|
|
||||||
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
|
|
||||||
* library is terminated.
|
|
||||||
*
|
|
||||||
* @thread_safety This function must only be called from the main thread.
|
|
||||||
*
|
|
||||||
* @sa @ref clipboard
|
|
||||||
* @sa glfwSetX11SelectionString
|
|
||||||
* @sa glfwGetClipboardString
|
|
||||||
*
|
|
||||||
* @since Added in version 3.3.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI const char* glfwGetX11SelectionString(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
|
||||||
/*! @brief Returns the `GLXContext` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `GLXContext` of the specified window, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
|
|
||||||
|
|
||||||
/*! @brief Returns the `GLXWindow` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `GLXWindow` of the specified window, or `None` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.2.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
|
||||||
/*! @brief Returns the `struct wl_display*` used by GLFW.
|
|
||||||
*
|
|
||||||
* @return The `struct wl_display*` used by GLFW, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.2.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
|
|
||||||
|
|
||||||
/*! @brief Returns the `struct wl_output*` of the specified monitor.
|
|
||||||
*
|
|
||||||
* @return The `struct wl_output*` of the specified monitor, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.2.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
/*! @brief Returns the main `struct wl_surface*` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The main `struct wl_surface*` of the specified window, or `NULL` if
|
|
||||||
* an [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.2.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
|
||||||
/*! @brief Returns the `EGLDisplay` used by GLFW.
|
|
||||||
*
|
|
||||||
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
|
|
||||||
|
|
||||||
/*! @brief Returns the `EGLContext` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
|
||||||
|
|
||||||
/*! @brief Returns the `EGLSurface` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.0.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
|
||||||
/*! @brief Retrieves the color buffer associated with the specified window.
|
|
||||||
*
|
|
||||||
* @param[in] window The window whose color buffer to retrieve.
|
|
||||||
* @param[out] width Where to store the width of the color buffer, or `NULL`.
|
|
||||||
* @param[out] height Where to store the height of the color buffer, or `NULL`.
|
|
||||||
* @param[out] format Where to store the OSMesa pixel format of the color
|
|
||||||
* buffer, or `NULL`.
|
|
||||||
* @param[out] buffer Where to store the address of the color buffer, or
|
|
||||||
* `NULL`.
|
|
||||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.3.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
|
|
||||||
|
|
||||||
/*! @brief Retrieves the depth buffer associated with the specified window.
|
|
||||||
*
|
|
||||||
* @param[in] window The window whose depth buffer to retrieve.
|
|
||||||
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
|
|
||||||
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
|
|
||||||
* @param[out] bytesPerValue Where to store the number of bytes per depth
|
|
||||||
* buffer element, or `NULL`.
|
|
||||||
* @param[out] buffer Where to store the address of the depth buffer, or
|
|
||||||
* `NULL`.
|
|
||||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.3.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
|
|
||||||
|
|
||||||
/*! @brief Returns the `OSMesaContext` of the specified window.
|
|
||||||
*
|
|
||||||
* @return The `OSMesaContext` of the specified window, or `NULL` if an
|
|
||||||
* [error](@ref error_handling) occurred.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref
|
|
||||||
* GLFW_NOT_INITIALIZED.
|
|
||||||
*
|
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
|
||||||
* synchronized.
|
|
||||||
*
|
|
||||||
* @since Added in version 3.3.
|
|
||||||
*
|
|
||||||
* @ingroup native
|
|
||||||
*/
|
|
||||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _glfw3_native_h_ */
|
|
||||||
|
|
@ -1,756 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Checks whether the desired context attributes are valid
|
|
||||||
//
|
|
||||||
// This function checks things like whether the specified client API version
|
|
||||||
// exists and whether all relevant options have supported and non-conflicting
|
|
||||||
// values
|
|
||||||
//
|
|
||||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|
||||||
{
|
|
||||||
if (ctxconfig->share)
|
|
||||||
{
|
|
||||||
if (ctxconfig->client == GLFW_NO_API ||
|
|
||||||
ctxconfig->share->context.client == GLFW_NO_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
|
|
||||||
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
|
|
||||||
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
|
||||||
"Invalid context creation API 0x%08X",
|
|
||||||
ctxconfig->source);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API &&
|
|
||||||
ctxconfig->client != GLFW_OPENGL_API &&
|
|
||||||
ctxconfig->client != GLFW_OPENGL_ES_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
|
||||||
"Invalid client API 0x%08X",
|
|
||||||
ctxconfig->client);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
|
|
||||||
(ctxconfig->major == 1 && ctxconfig->minor > 5) ||
|
|
||||||
(ctxconfig->major == 2 && ctxconfig->minor > 1) ||
|
|
||||||
(ctxconfig->major == 3 && ctxconfig->minor > 3))
|
|
||||||
{
|
|
||||||
// OpenGL 1.0 is the smallest valid version
|
|
||||||
// OpenGL 1.x series ended with version 1.5
|
|
||||||
// OpenGL 2.x series ended with version 2.1
|
|
||||||
// OpenGL 3.x series ended with version 3.3
|
|
||||||
// For now, let everything else through
|
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"Invalid OpenGL version %i.%i",
|
|
||||||
ctxconfig->major, ctxconfig->minor);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->profile)
|
|
||||||
{
|
|
||||||
if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
|
|
||||||
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
|
||||||
"Invalid OpenGL profile 0x%08X",
|
|
||||||
ctxconfig->profile);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->major <= 2 ||
|
|
||||||
(ctxconfig->major == 3 && ctxconfig->minor < 2))
|
|
||||||
{
|
|
||||||
// Desktop OpenGL context profiles are only defined for version 3.2
|
|
||||||
// and above
|
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"Context profiles are only defined for OpenGL version 3.2 and above");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->forward && ctxconfig->major <= 2)
|
|
||||||
{
|
|
||||||
// Forward-compatible contexts are only defined for OpenGL version 3.0 and above
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"Forward-compatibility is only defined for OpenGL version 3.0 and above");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
|
|
||||||
(ctxconfig->major == 1 && ctxconfig->minor > 1) ||
|
|
||||||
(ctxconfig->major == 2 && ctxconfig->minor > 0))
|
|
||||||
{
|
|
||||||
// OpenGL ES 1.0 is the smallest valid version
|
|
||||||
// OpenGL ES 1.x series ended with version 1.1
|
|
||||||
// OpenGL ES 2.x series ended with version 2.0
|
|
||||||
// For now, let everything else through
|
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"Invalid OpenGL ES version %i.%i",
|
|
||||||
ctxconfig->major, ctxconfig->minor);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->robustness)
|
|
||||||
{
|
|
||||||
if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
|
|
||||||
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
|
||||||
"Invalid context robustness mode 0x%08X",
|
|
||||||
ctxconfig->robustness);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->release)
|
|
||||||
{
|
|
||||||
if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
|
|
||||||
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
|
||||||
"Invalid context release behavior 0x%08X",
|
|
||||||
ctxconfig->release);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chooses the framebuffer config that best matches the desired one
|
|
||||||
//
|
|
||||||
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
|
||||||
const _GLFWfbconfig* alternatives,
|
|
||||||
unsigned int count)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int missing, leastMissing = UINT_MAX;
|
|
||||||
unsigned int colorDiff, leastColorDiff = UINT_MAX;
|
|
||||||
unsigned int extraDiff, leastExtraDiff = UINT_MAX;
|
|
||||||
const _GLFWfbconfig* current;
|
|
||||||
const _GLFWfbconfig* closest = NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
current = alternatives + i;
|
|
||||||
|
|
||||||
if (desired->stereo > 0 && current->stereo == 0)
|
|
||||||
{
|
|
||||||
// Stereo is a hard constraint
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count number of missing buffers
|
|
||||||
{
|
|
||||||
missing = 0;
|
|
||||||
|
|
||||||
if (desired->alphaBits > 0 && current->alphaBits == 0)
|
|
||||||
missing++;
|
|
||||||
|
|
||||||
if (desired->depthBits > 0 && current->depthBits == 0)
|
|
||||||
missing++;
|
|
||||||
|
|
||||||
if (desired->stencilBits > 0 && current->stencilBits == 0)
|
|
||||||
missing++;
|
|
||||||
|
|
||||||
if (desired->auxBuffers > 0 &&
|
|
||||||
current->auxBuffers < desired->auxBuffers)
|
|
||||||
{
|
|
||||||
missing += desired->auxBuffers - current->auxBuffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->samples > 0 && current->samples == 0)
|
|
||||||
{
|
|
||||||
// Technically, several multisampling buffers could be
|
|
||||||
// involved, but that's a lower level implementation detail and
|
|
||||||
// not important to us here, so we count them as one
|
|
||||||
missing++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->transparent != current->transparent)
|
|
||||||
missing++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These polynomials make many small channel size differences matter
|
|
||||||
// less than one large channel size difference
|
|
||||||
|
|
||||||
// Calculate color channel size difference value
|
|
||||||
{
|
|
||||||
colorDiff = 0;
|
|
||||||
|
|
||||||
if (desired->redBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
colorDiff += (desired->redBits - current->redBits) *
|
|
||||||
(desired->redBits - current->redBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->greenBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
colorDiff += (desired->greenBits - current->greenBits) *
|
|
||||||
(desired->greenBits - current->greenBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->blueBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
colorDiff += (desired->blueBits - current->blueBits) *
|
|
||||||
(desired->blueBits - current->blueBits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate non-color channel size difference value
|
|
||||||
{
|
|
||||||
extraDiff = 0;
|
|
||||||
|
|
||||||
if (desired->alphaBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->alphaBits - current->alphaBits) *
|
|
||||||
(desired->alphaBits - current->alphaBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->depthBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->depthBits - current->depthBits) *
|
|
||||||
(desired->depthBits - current->depthBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->stencilBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->stencilBits - current->stencilBits) *
|
|
||||||
(desired->stencilBits - current->stencilBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumRedBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumRedBits - current->accumRedBits) *
|
|
||||||
(desired->accumRedBits - current->accumRedBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumGreenBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
|
|
||||||
(desired->accumGreenBits - current->accumGreenBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumBlueBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
|
|
||||||
(desired->accumBlueBits - current->accumBlueBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->accumAlphaBits != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
|
|
||||||
(desired->accumAlphaBits - current->accumAlphaBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->samples != GLFW_DONT_CARE)
|
|
||||||
{
|
|
||||||
extraDiff += (desired->samples - current->samples) *
|
|
||||||
(desired->samples - current->samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired->sRGB && !current->sRGB)
|
|
||||||
extraDiff++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out if the current one is better than the best one found so far
|
|
||||||
// Least number of missing buffers is the most important heuristic,
|
|
||||||
// then color buffer size match and lastly size match for other buffers
|
|
||||||
|
|
||||||
if (missing < leastMissing)
|
|
||||||
closest = current;
|
|
||||||
else if (missing == leastMissing)
|
|
||||||
{
|
|
||||||
if ((colorDiff < leastColorDiff) ||
|
|
||||||
(colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
|
|
||||||
{
|
|
||||||
closest = current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == closest)
|
|
||||||
{
|
|
||||||
leastMissing = missing;
|
|
||||||
leastColorDiff = colorDiff;
|
|
||||||
leastExtraDiff = extraDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves the attributes of the current context
|
|
||||||
//
|
|
||||||
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
_GLFWwindow* previous;
|
|
||||||
const char* version;
|
|
||||||
const char* prefixes[] =
|
|
||||||
{
|
|
||||||
"OpenGL ES-CM ",
|
|
||||||
"OpenGL ES-CL ",
|
|
||||||
"OpenGL ES ",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
window->context.source = ctxconfig->source;
|
|
||||||
window->context.client = GLFW_OPENGL_API;
|
|
||||||
|
|
||||||
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) window);
|
|
||||||
|
|
||||||
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
|
||||||
window->context.getProcAddress("glGetIntegerv");
|
|
||||||
window->context.GetString = (PFNGLGETSTRINGPROC)
|
|
||||||
window->context.getProcAddress("glGetString");
|
|
||||||
if (!window->context.GetIntegerv || !window->context.GetString)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
version = (const char*) window->context.GetString(GL_VERSION);
|
|
||||||
if (!version)
|
|
||||||
{
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"OpenGL version string retrieval is broken");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"OpenGL ES version string retrieval is broken");
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; prefixes[i]; i++)
|
|
||||||
{
|
|
||||||
const size_t length = strlen(prefixes[i]);
|
|
||||||
|
|
||||||
if (strncmp(version, prefixes[i], length) == 0)
|
|
||||||
{
|
|
||||||
version += length;
|
|
||||||
window->context.client = GLFW_OPENGL_ES_API;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sscanf(version, "%d.%d.%d",
|
|
||||||
&window->context.major,
|
|
||||||
&window->context.minor,
|
|
||||||
&window->context.revision))
|
|
||||||
{
|
|
||||||
if (window->context.client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"No version found in OpenGL version string");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"No version found in OpenGL ES version string");
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.major < ctxconfig->major ||
|
|
||||||
(window->context.major == ctxconfig->major &&
|
|
||||||
window->context.minor < ctxconfig->minor))
|
|
||||||
{
|
|
||||||
// The desired OpenGL version is greater than the actual version
|
|
||||||
// This only happens if the machine lacks {GLX|WGL}_ARB_create_context
|
|
||||||
// /and/ the user has requested an OpenGL version greater than 1.0
|
|
||||||
|
|
||||||
// For API consistency, we emulate the behavior of the
|
|
||||||
// {GLX|WGL}_ARB_create_context extension and fail here
|
|
||||||
|
|
||||||
if (window->context.client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"Requested OpenGL version %i.%i, got version %i.%i",
|
|
||||||
ctxconfig->major, ctxconfig->minor,
|
|
||||||
window->context.major, window->context.minor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"Requested OpenGL ES version %i.%i, got version %i.%i",
|
|
||||||
ctxconfig->major, ctxconfig->minor,
|
|
||||||
window->context.major, window->context.minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.major >= 3)
|
|
||||||
{
|
|
||||||
// OpenGL 3.0+ uses a different function for extension string retrieval
|
|
||||||
// We cache it here instead of in glfwExtensionSupported mostly to alert
|
|
||||||
// users as early as possible that their build may be broken
|
|
||||||
|
|
||||||
window->context.GetStringi = (PFNGLGETSTRINGIPROC)
|
|
||||||
window->context.getProcAddress("glGetStringi");
|
|
||||||
if (!window->context.GetStringi)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Entry point retrieval is broken");
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
// Read back context flags (OpenGL 3.0 and above)
|
|
||||||
if (window->context.major >= 3)
|
|
||||||
{
|
|
||||||
GLint flags;
|
|
||||||
window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
|
||||||
window->context.forward = GLFW_TRUE;
|
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
|
|
||||||
window->context.debug = GLFW_TRUE;
|
|
||||||
else if (glfwExtensionSupported("GL_ARB_debug_output") &&
|
|
||||||
ctxconfig->debug)
|
|
||||||
{
|
|
||||||
// HACK: This is a workaround for older drivers (pre KHR_debug)
|
|
||||||
// not setting the debug bit in the context flags for
|
|
||||||
// debug contexts
|
|
||||||
window->context.debug = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
|
|
||||||
window->context.noerror = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read back OpenGL context profile (OpenGL 3.2 and above)
|
|
||||||
if (window->context.major >= 4 ||
|
|
||||||
(window->context.major == 3 && window->context.minor >= 2))
|
|
||||||
{
|
|
||||||
GLint mask;
|
|
||||||
window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
|
||||||
|
|
||||||
if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
|
|
||||||
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
|
|
||||||
else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
|
|
||||||
window->context.profile = GLFW_OPENGL_CORE_PROFILE;
|
|
||||||
else if (glfwExtensionSupported("GL_ARB_compatibility"))
|
|
||||||
{
|
|
||||||
// HACK: This is a workaround for the compatibility profile bit
|
|
||||||
// not being set in the context flags if an OpenGL 3.2+
|
|
||||||
// context was created without having requested a specific
|
|
||||||
// version
|
|
||||||
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read back robustness strategy
|
|
||||||
if (glfwExtensionSupported("GL_ARB_robustness"))
|
|
||||||
{
|
|
||||||
// NOTE: We avoid using the context flags for detection, as they are
|
|
||||||
// only present from 3.0 while the extension applies from 1.1
|
|
||||||
|
|
||||||
GLint strategy;
|
|
||||||
window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
|
|
||||||
&strategy);
|
|
||||||
|
|
||||||
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
|
||||||
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
|
||||||
else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
|
|
||||||
window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Read back robustness strategy
|
|
||||||
if (glfwExtensionSupported("GL_EXT_robustness"))
|
|
||||||
{
|
|
||||||
// NOTE: The values of these constants match those of the OpenGL ARB
|
|
||||||
// one, so we can reuse them here
|
|
||||||
|
|
||||||
GLint strategy;
|
|
||||||
window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
|
|
||||||
&strategy);
|
|
||||||
|
|
||||||
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
|
||||||
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
|
||||||
else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
|
|
||||||
window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glfwExtensionSupported("GL_KHR_context_flush_control"))
|
|
||||||
{
|
|
||||||
GLint behavior;
|
|
||||||
window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
|
|
||||||
|
|
||||||
if (behavior == GL_NONE)
|
|
||||||
window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
|
|
||||||
else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
|
|
||||||
window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clearing the front buffer to black to avoid garbage pixels left over from
|
|
||||||
// previous uses of our bit of VRAM
|
|
||||||
{
|
|
||||||
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
|
|
||||||
window->context.getProcAddress("glClear");
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
if (window->doublebuffer)
|
|
||||||
window->context.swapBuffers(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Searches an extension string for the specified extension
|
|
||||||
//
|
|
||||||
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
|
|
||||||
{
|
|
||||||
const char* start = extensions;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
const char* where;
|
|
||||||
const char* terminator;
|
|
||||||
|
|
||||||
where = strstr(start, string);
|
|
||||||
if (!where)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
terminator = where + strlen(string);
|
|
||||||
if (where == start || *(where - 1) == ' ')
|
|
||||||
{
|
|
||||||
if (*terminator == ' ' || *terminator == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = terminator;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW public API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
if (window && window->context.client == GLFW_NO_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
|
||||||
"Cannot make current with a window that has no OpenGL or OpenGL ES context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous)
|
|
||||||
{
|
|
||||||
if (!window || window->context.source != previous->context.source)
|
|
||||||
previous->context.makeCurrent(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window)
|
|
||||||
window->context.makeCurrent(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
return _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
assert(window != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
if (window->context.client == GLFW_NO_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
|
||||||
"Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.swapBuffers(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwSwapInterval(int interval)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
|
||||||
"Cannot set swap interval without a current OpenGL or OpenGL ES context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.swapInterval(interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI int glfwExtensionSupported(const char* extension)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window;
|
|
||||||
assert(extension != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
|
||||||
|
|
||||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
|
||||||
"Cannot query extension without a current OpenGL or OpenGL ES context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*extension == '\0')
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.major >= 3)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
GLint count;
|
|
||||||
|
|
||||||
// Check if extension is in the modern OpenGL extensions string list
|
|
||||||
|
|
||||||
window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const char* en = (const char*)
|
|
||||||
window->context.GetStringi(GL_EXTENSIONS, i);
|
|
||||||
if (!en)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Extension string retrieval is broken");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(en, extension) == 0)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if extension is in the old style OpenGL extensions string
|
|
||||||
|
|
||||||
const char* extensions = (const char*)
|
|
||||||
window->context.GetString(GL_EXTENSIONS);
|
|
||||||
if (!extensions)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Extension string retrieval is broken");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if extension is in the platform-specific string
|
|
||||||
return window->context.extensionSupported(extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window;
|
|
||||||
assert(procname != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
|
||||||
"Cannot query entry point without a current OpenGL or OpenGL ES context");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window->context.getProcAddress(procname);
|
|
||||||
}
|
|
||||||
|
|
@ -1,790 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 EGL - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Return a description of the specified EGL error
|
|
||||||
//
|
|
||||||
static const char* getEGLErrorString(EGLint error)
|
|
||||||
{
|
|
||||||
switch (error)
|
|
||||||
{
|
|
||||||
case EGL_SUCCESS:
|
|
||||||
return "Success";
|
|
||||||
case EGL_NOT_INITIALIZED:
|
|
||||||
return "EGL is not or could not be initialized";
|
|
||||||
case EGL_BAD_ACCESS:
|
|
||||||
return "EGL cannot access a requested resource";
|
|
||||||
case EGL_BAD_ALLOC:
|
|
||||||
return "EGL failed to allocate resources for the requested operation";
|
|
||||||
case EGL_BAD_ATTRIBUTE:
|
|
||||||
return "An unrecognized attribute or attribute value was passed in the attribute list";
|
|
||||||
case EGL_BAD_CONTEXT:
|
|
||||||
return "An EGLContext argument does not name a valid EGL rendering context";
|
|
||||||
case EGL_BAD_CONFIG:
|
|
||||||
return "An EGLConfig argument does not name a valid EGL frame buffer configuration";
|
|
||||||
case EGL_BAD_CURRENT_SURFACE:
|
|
||||||
return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid";
|
|
||||||
case EGL_BAD_DISPLAY:
|
|
||||||
return "An EGLDisplay argument does not name a valid EGL display connection";
|
|
||||||
case EGL_BAD_SURFACE:
|
|
||||||
return "An EGLSurface argument does not name a valid surface configured for GL rendering";
|
|
||||||
case EGL_BAD_MATCH:
|
|
||||||
return "Arguments are inconsistent";
|
|
||||||
case EGL_BAD_PARAMETER:
|
|
||||||
return "One or more argument values are invalid";
|
|
||||||
case EGL_BAD_NATIVE_PIXMAP:
|
|
||||||
return "A NativePixmapType argument does not refer to a valid native pixmap";
|
|
||||||
case EGL_BAD_NATIVE_WINDOW:
|
|
||||||
return "A NativeWindowType argument does not refer to a valid native window";
|
|
||||||
case EGL_CONTEXT_LOST:
|
|
||||||
return "The application must destroy all contexts and reinitialise";
|
|
||||||
default:
|
|
||||||
return "ERROR: UNKNOWN EGL ERROR";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the specified attribute of the specified EGLConfig
|
|
||||||
//
|
|
||||||
static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
|
||||||
{
|
|
||||||
int value;
|
|
||||||
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the EGLConfig most closely matching the specified hints
|
|
||||||
//
|
|
||||||
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* desired,
|
|
||||||
EGLConfig* result)
|
|
||||||
{
|
|
||||||
EGLConfig* nativeConfigs;
|
|
||||||
_GLFWfbconfig* usableConfigs;
|
|
||||||
const _GLFWfbconfig* closest;
|
|
||||||
int i, nativeCount, usableCount;
|
|
||||||
|
|
||||||
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
|
|
||||||
if (!nativeCount)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
|
||||||
eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
|
|
||||||
|
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
|
||||||
usableCount = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < nativeCount; i++)
|
|
||||||
{
|
|
||||||
const EGLConfig n = nativeConfigs[i];
|
|
||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
|
||||||
|
|
||||||
// Only consider RGB(A) EGLConfigs
|
|
||||||
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Only consider window EGLConfigs
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
|
||||||
{
|
|
||||||
XVisualInfo vi = {0};
|
|
||||||
|
|
||||||
// Only consider EGLConfigs with associated Visuals
|
|
||||||
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
|
||||||
if (!vi.visualid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (desired->transparent)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
XVisualInfo* vis =
|
|
||||||
XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
|
|
||||||
if (vis)
|
|
||||||
{
|
|
||||||
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
|
||||||
XFree(vis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // _GLFW_X11
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->major == 1)
|
|
||||||
{
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
|
|
||||||
u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
|
|
||||||
u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
|
|
||||||
|
|
||||||
u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
|
|
||||||
u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
|
|
||||||
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
|
||||||
|
|
||||||
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
|
||||||
u->doublebuffer = desired->doublebuffer;
|
|
||||||
|
|
||||||
u->handle = (uintptr_t) n;
|
|
||||||
usableCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
|
||||||
if (closest)
|
|
||||||
*result = (EGLConfig) closest->handle;
|
|
||||||
|
|
||||||
free(nativeConfigs);
|
|
||||||
free(usableConfigs);
|
|
||||||
|
|
||||||
return closest != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void makeContextCurrentEGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window)
|
|
||||||
{
|
|
||||||
if (!eglMakeCurrent(_glfw.egl.display,
|
|
||||||
window->context.egl.surface,
|
|
||||||
window->context.egl.surface,
|
|
||||||
window->context.egl.handle))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"EGL: Failed to make context current: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!eglMakeCurrent(_glfw.egl.display,
|
|
||||||
EGL_NO_SURFACE,
|
|
||||||
EGL_NO_SURFACE,
|
|
||||||
EGL_NO_CONTEXT))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"EGL: Failed to clear current context: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapBuffersEGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"EGL: The context must be current on the calling thread when swapping buffers");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapIntervalEGL(int interval)
|
|
||||||
{
|
|
||||||
eglSwapInterval(_glfw.egl.display, interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int extensionSupportedEGL(const char* extension)
|
|
||||||
{
|
|
||||||
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
|
|
||||||
if (extensions)
|
|
||||||
{
|
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLFWglproc getProcAddressEGL(const char* procname)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
|
|
||||||
if (window->context.egl.client)
|
|
||||||
{
|
|
||||||
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
|
|
||||||
procname);
|
|
||||||
if (proc)
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return eglGetProcAddress(procname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroyContextEGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
#if defined(_GLFW_X11)
|
|
||||||
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
|
|
||||||
// as it will make XCloseDisplay segfault
|
|
||||||
if (window->context.client != GLFW_OPENGL_API)
|
|
||||||
#endif // _GLFW_X11
|
|
||||||
{
|
|
||||||
if (window->context.egl.client)
|
|
||||||
{
|
|
||||||
_glfw_dlclose(window->context.egl.client);
|
|
||||||
window->context.egl.client = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.egl.surface)
|
|
||||||
{
|
|
||||||
eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
|
|
||||||
window->context.egl.surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.egl.handle)
|
|
||||||
{
|
|
||||||
eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
|
|
||||||
window->context.egl.handle = EGL_NO_CONTEXT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialize EGL
|
|
||||||
//
|
|
||||||
GLFWbool _glfwInitEGL(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char* sonames[] =
|
|
||||||
{
|
|
||||||
#if defined(_GLFW_EGL_LIBRARY)
|
|
||||||
_GLFW_EGL_LIBRARY,
|
|
||||||
#elif defined(_GLFW_WIN32)
|
|
||||||
"libEGL.dll",
|
|
||||||
"EGL.dll",
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
"libEGL.dylib",
|
|
||||||
#elif defined(__CYGWIN__)
|
|
||||||
"libEGL-1.so",
|
|
||||||
#else
|
|
||||||
"libEGL.so.1",
|
|
||||||
#endif
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_glfw.egl.handle)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
for (i = 0; sonames[i]; i++)
|
|
||||||
{
|
|
||||||
_glfw.egl.handle = _glfw_dlopen(sonames[i]);
|
|
||||||
if (_glfw.egl.handle)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_glfw.egl.handle)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
|
||||||
|
|
||||||
_glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
|
|
||||||
_glfw.egl.GetConfigs = (PFN_eglGetConfigs)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
|
|
||||||
_glfw.egl.GetDisplay = (PFN_eglGetDisplay)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
|
|
||||||
_glfw.egl.GetError = (PFN_eglGetError)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
|
|
||||||
_glfw.egl.Initialize = (PFN_eglInitialize)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
|
|
||||||
_glfw.egl.Terminate = (PFN_eglTerminate)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
|
|
||||||
_glfw.egl.BindAPI = (PFN_eglBindAPI)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
|
|
||||||
_glfw.egl.CreateContext = (PFN_eglCreateContext)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
|
|
||||||
_glfw.egl.DestroySurface = (PFN_eglDestroySurface)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
|
|
||||||
_glfw.egl.DestroyContext = (PFN_eglDestroyContext)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
|
|
||||||
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
|
|
||||||
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
|
|
||||||
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
|
|
||||||
_glfw.egl.SwapInterval = (PFN_eglSwapInterval)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
|
|
||||||
_glfw.egl.QueryString = (PFN_eglQueryString)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
|
|
||||||
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
|
|
||||||
|
|
||||||
if (!_glfw.egl.GetConfigAttrib ||
|
|
||||||
!_glfw.egl.GetConfigs ||
|
|
||||||
!_glfw.egl.GetDisplay ||
|
|
||||||
!_glfw.egl.GetError ||
|
|
||||||
!_glfw.egl.Initialize ||
|
|
||||||
!_glfw.egl.Terminate ||
|
|
||||||
!_glfw.egl.BindAPI ||
|
|
||||||
!_glfw.egl.CreateContext ||
|
|
||||||
!_glfw.egl.DestroySurface ||
|
|
||||||
!_glfw.egl.DestroyContext ||
|
|
||||||
!_glfw.egl.CreateWindowSurface ||
|
|
||||||
!_glfw.egl.MakeCurrent ||
|
|
||||||
!_glfw.egl.SwapBuffers ||
|
|
||||||
!_glfw.egl.SwapInterval ||
|
|
||||||
!_glfw.egl.QueryString ||
|
|
||||||
!_glfw.egl.GetProcAddress)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"EGL: Failed to load required entry points");
|
|
||||||
|
|
||||||
_glfwTerminateEGL();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
|
||||||
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"EGL: Failed to get EGL display: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
|
|
||||||
_glfwTerminateEGL();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"EGL: Failed to initialize EGL: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
|
|
||||||
_glfwTerminateEGL();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.egl.KHR_create_context =
|
|
||||||
extensionSupportedEGL("EGL_KHR_create_context");
|
|
||||||
_glfw.egl.KHR_create_context_no_error =
|
|
||||||
extensionSupportedEGL("EGL_KHR_create_context_no_error");
|
|
||||||
_glfw.egl.KHR_gl_colorspace =
|
|
||||||
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
|
||||||
_glfw.egl.KHR_get_all_proc_addresses =
|
|
||||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
|
||||||
_glfw.egl.KHR_context_flush_control =
|
|
||||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminate EGL
|
|
||||||
//
|
|
||||||
void _glfwTerminateEGL(void)
|
|
||||||
{
|
|
||||||
if (_glfw.egl.display)
|
|
||||||
{
|
|
||||||
eglTerminate(_glfw.egl.display);
|
|
||||||
_glfw.egl.display = EGL_NO_DISPLAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.egl.handle)
|
|
||||||
{
|
|
||||||
_glfw_dlclose(_glfw.egl.handle);
|
|
||||||
_glfw.egl.handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setAttrib(a, v) \
|
|
||||||
{ \
|
|
||||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
|
||||||
attribs[index++] = a; \
|
|
||||||
attribs[index++] = v; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
|
||||||
//
|
|
||||||
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig)
|
|
||||||
{
|
|
||||||
EGLint attribs[40];
|
|
||||||
EGLConfig config;
|
|
||||||
EGLContext share = NULL;
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (!_glfw.egl.display)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->share)
|
|
||||||
share = ctxconfig->share->context.egl.handle;
|
|
||||||
|
|
||||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
|
||||||
"EGL: Failed to find a suitable EGLConfig");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
|
||||||
{
|
|
||||||
if (!eglBindAPI(EGL_OPENGL_ES_API))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"EGL: Failed to bind OpenGL ES: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!eglBindAPI(EGL_OPENGL_API))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"EGL: Failed to bind OpenGL: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.egl.KHR_create_context)
|
|
||||||
{
|
|
||||||
int mask = 0, flags = 0;
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->forward)
|
|
||||||
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
|
||||||
|
|
||||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
|
||||||
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
|
||||||
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->debug)
|
|
||||||
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
|
||||||
|
|
||||||
if (ctxconfig->robustness)
|
|
||||||
{
|
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
|
||||||
{
|
|
||||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
|
||||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
|
||||||
}
|
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
|
||||||
{
|
|
||||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
|
||||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
|
||||||
}
|
|
||||||
|
|
||||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->noerror)
|
|
||||||
{
|
|
||||||
if (_glfw.egl.KHR_create_context_no_error)
|
|
||||||
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
|
||||||
{
|
|
||||||
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
|
||||||
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask)
|
|
||||||
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
|
||||||
|
|
||||||
if (flags)
|
|
||||||
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
|
||||||
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.egl.KHR_context_flush_control)
|
|
||||||
{
|
|
||||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
|
||||||
{
|
|
||||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
|
||||||
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
|
||||||
}
|
|
||||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
|
||||||
{
|
|
||||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
|
||||||
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setAttrib(EGL_NONE, EGL_NONE);
|
|
||||||
|
|
||||||
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
|
||||||
config, share, attribs);
|
|
||||||
|
|
||||||
if (window->context.egl.handle == EGL_NO_CONTEXT)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"EGL: Failed to create context: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up attributes for surface creation
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
if (fbconfig->sRGB)
|
|
||||||
{
|
|
||||||
if (_glfw.egl.KHR_gl_colorspace)
|
|
||||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fbconfig->doublebuffer)
|
|
||||||
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
|
|
||||||
|
|
||||||
setAttrib(EGL_NONE, EGL_NONE);
|
|
||||||
|
|
||||||
window->context.egl.surface =
|
|
||||||
eglCreateWindowSurface(_glfw.egl.display,
|
|
||||||
config,
|
|
||||||
_GLFW_EGL_NATIVE_WINDOW,
|
|
||||||
attribs);
|
|
||||||
if (window->context.egl.surface == EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"EGL: Failed to create window surface: %s",
|
|
||||||
getEGLErrorString(eglGetError()));
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.egl.config = config;
|
|
||||||
|
|
||||||
// Load the appropriate client library
|
|
||||||
if (!_glfw.egl.KHR_get_all_proc_addresses)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char** sonames;
|
|
||||||
const char* es1sonames[] =
|
|
||||||
{
|
|
||||||
#if defined(_GLFW_GLESV1_LIBRARY)
|
|
||||||
_GLFW_GLESV1_LIBRARY,
|
|
||||||
#elif defined(_GLFW_WIN32)
|
|
||||||
"GLESv1_CM.dll",
|
|
||||||
"libGLES_CM.dll",
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
"libGLESv1_CM.dylib",
|
|
||||||
#else
|
|
||||||
"libGLESv1_CM.so.1",
|
|
||||||
"libGLES_CM.so.1",
|
|
||||||
#endif
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
const char* es2sonames[] =
|
|
||||||
{
|
|
||||||
#if defined(_GLFW_GLESV2_LIBRARY)
|
|
||||||
_GLFW_GLESV2_LIBRARY,
|
|
||||||
#elif defined(_GLFW_WIN32)
|
|
||||||
"GLESv2.dll",
|
|
||||||
"libGLESv2.dll",
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
"libGLESv2.dylib",
|
|
||||||
#elif defined(__CYGWIN__)
|
|
||||||
"libGLESv2-2.so",
|
|
||||||
#else
|
|
||||||
"libGLESv2.so.2",
|
|
||||||
#endif
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
const char* glsonames[] =
|
|
||||||
{
|
|
||||||
#if defined(_GLFW_OPENGL_LIBRARY)
|
|
||||||
_GLFW_OPENGL_LIBRARY,
|
|
||||||
#elif defined(_GLFW_WIN32)
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
#else
|
|
||||||
"libGL.so.1",
|
|
||||||
#endif
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->major == 1)
|
|
||||||
sonames = es1sonames;
|
|
||||||
else
|
|
||||||
sonames = es2sonames;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sonames = glsonames;
|
|
||||||
|
|
||||||
for (i = 0; sonames[i]; i++)
|
|
||||||
{
|
|
||||||
// HACK: Match presence of lib prefix to increase chance of finding
|
|
||||||
// a matching pair in the jungle that is Win32 EGL/GLES
|
|
||||||
if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
window->context.egl.client = _glfw_dlopen(sonames[i]);
|
|
||||||
if (window->context.egl.client)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!window->context.egl.client)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"EGL: Failed to load client library");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentEGL;
|
|
||||||
window->context.swapBuffers = swapBuffersEGL;
|
|
||||||
window->context.swapInterval = swapIntervalEGL;
|
|
||||||
window->context.extensionSupported = extensionSupportedEGL;
|
|
||||||
window->context.getProcAddress = getProcAddressEGL;
|
|
||||||
window->context.destroy = destroyContextEGL;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef setAttrib
|
|
||||||
|
|
||||||
// Returns the Visual and depth of the chosen EGLConfig
|
|
||||||
//
|
|
||||||
#if defined(_GLFW_X11)
|
|
||||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig,
|
|
||||||
Visual** visual, int* depth)
|
|
||||||
{
|
|
||||||
XVisualInfo* result;
|
|
||||||
XVisualInfo desired;
|
|
||||||
EGLConfig native;
|
|
||||||
EGLint visualID = 0, count = 0;
|
|
||||||
const long vimask = VisualScreenMask | VisualIDMask;
|
|
||||||
|
|
||||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
|
||||||
"EGL: Failed to find a suitable EGLConfig");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
eglGetConfigAttrib(_glfw.egl.display, native,
|
|
||||||
EGL_NATIVE_VISUAL_ID, &visualID);
|
|
||||||
|
|
||||||
desired.screen = _glfw.x11.screen;
|
|
||||||
desired.visualid = visualID;
|
|
||||||
|
|
||||||
result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"EGL: Failed to retrieve Visual for EGLConfig");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*visual = result->visual;
|
|
||||||
*depth = result->depth;
|
|
||||||
|
|
||||||
XFree(result);
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
#endif // _GLFW_X11
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW native API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
|
|
||||||
return _glfw.egl.display;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
|
|
||||||
|
|
||||||
if (window->context.source != GLFW_EGL_CONTEXT_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return EGL_NO_CONTEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window->context.egl.handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
|
|
||||||
|
|
||||||
if (window->context.source != GLFW_EGL_CONTEXT_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window->context.egl.surface;
|
|
||||||
}
|
|
||||||
|
|
@ -1,215 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 EGL - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
|
||||||
#include <EGL/eglplatform.h>
|
|
||||||
#elif defined(_GLFW_WIN32)
|
|
||||||
#define EGLAPIENTRY __stdcall
|
|
||||||
typedef HDC EGLNativeDisplayType;
|
|
||||||
typedef HWND EGLNativeWindowType;
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
#define EGLAPIENTRY
|
|
||||||
typedef void* EGLNativeDisplayType;
|
|
||||||
typedef id EGLNativeWindowType;
|
|
||||||
#elif defined(_GLFW_X11)
|
|
||||||
#define EGLAPIENTRY
|
|
||||||
typedef Display* EGLNativeDisplayType;
|
|
||||||
typedef Window EGLNativeWindowType;
|
|
||||||
#elif defined(_GLFW_WAYLAND)
|
|
||||||
#define EGLAPIENTRY
|
|
||||||
typedef struct wl_display* EGLNativeDisplayType;
|
|
||||||
typedef struct wl_egl_window* EGLNativeWindowType;
|
|
||||||
#else
|
|
||||||
#error "No supported EGL platform selected"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define EGL_SUCCESS 0x3000
|
|
||||||
#define EGL_NOT_INITIALIZED 0x3001
|
|
||||||
#define EGL_BAD_ACCESS 0x3002
|
|
||||||
#define EGL_BAD_ALLOC 0x3003
|
|
||||||
#define EGL_BAD_ATTRIBUTE 0x3004
|
|
||||||
#define EGL_BAD_CONFIG 0x3005
|
|
||||||
#define EGL_BAD_CONTEXT 0x3006
|
|
||||||
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
|
||||||
#define EGL_BAD_DISPLAY 0x3008
|
|
||||||
#define EGL_BAD_MATCH 0x3009
|
|
||||||
#define EGL_BAD_NATIVE_PIXMAP 0x300a
|
|
||||||
#define EGL_BAD_NATIVE_WINDOW 0x300b
|
|
||||||
#define EGL_BAD_PARAMETER 0x300c
|
|
||||||
#define EGL_BAD_SURFACE 0x300d
|
|
||||||
#define EGL_CONTEXT_LOST 0x300e
|
|
||||||
#define EGL_COLOR_BUFFER_TYPE 0x303f
|
|
||||||
#define EGL_RGB_BUFFER 0x308e
|
|
||||||
#define EGL_SURFACE_TYPE 0x3033
|
|
||||||
#define EGL_WINDOW_BIT 0x0004
|
|
||||||
#define EGL_RENDERABLE_TYPE 0x3040
|
|
||||||
#define EGL_OPENGL_ES_BIT 0x0001
|
|
||||||
#define EGL_OPENGL_ES2_BIT 0x0004
|
|
||||||
#define EGL_OPENGL_BIT 0x0008
|
|
||||||
#define EGL_ALPHA_SIZE 0x3021
|
|
||||||
#define EGL_BLUE_SIZE 0x3022
|
|
||||||
#define EGL_GREEN_SIZE 0x3023
|
|
||||||
#define EGL_RED_SIZE 0x3024
|
|
||||||
#define EGL_DEPTH_SIZE 0x3025
|
|
||||||
#define EGL_STENCIL_SIZE 0x3026
|
|
||||||
#define EGL_SAMPLES 0x3031
|
|
||||||
#define EGL_OPENGL_ES_API 0x30a0
|
|
||||||
#define EGL_OPENGL_API 0x30a2
|
|
||||||
#define EGL_NONE 0x3038
|
|
||||||
#define EGL_RENDER_BUFFER 0x3086
|
|
||||||
#define EGL_SINGLE_BUFFER 0x3085
|
|
||||||
#define EGL_EXTENSIONS 0x3055
|
|
||||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
|
||||||
#define EGL_NATIVE_VISUAL_ID 0x302e
|
|
||||||
#define EGL_NO_SURFACE ((EGLSurface) 0)
|
|
||||||
#define EGL_NO_DISPLAY ((EGLDisplay) 0)
|
|
||||||
#define EGL_NO_CONTEXT ((EGLContext) 0)
|
|
||||||
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
|
|
||||||
|
|
||||||
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
|
||||||
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
|
||||||
#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
|
|
||||||
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
|
||||||
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd
|
|
||||||
#define EGL_NO_RESET_NOTIFICATION_KHR 0x31be
|
|
||||||
#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf
|
|
||||||
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
|
|
||||||
#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
|
|
||||||
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb
|
|
||||||
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd
|
|
||||||
#define EGL_CONTEXT_FLAGS_KHR 0x30fc
|
|
||||||
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
|
||||||
#define EGL_GL_COLORSPACE_KHR 0x309d
|
|
||||||
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
|
||||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
|
||||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
|
||||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
|
||||||
|
|
||||||
typedef int EGLint;
|
|
||||||
typedef unsigned int EGLBoolean;
|
|
||||||
typedef unsigned int EGLenum;
|
|
||||||
typedef void* EGLConfig;
|
|
||||||
typedef void* EGLContext;
|
|
||||||
typedef void* EGLDisplay;
|
|
||||||
typedef void* EGLSurface;
|
|
||||||
|
|
||||||
// EGL function pointer typedefs
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
|
||||||
typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
|
|
||||||
typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
|
|
||||||
typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
|
|
||||||
typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
|
|
||||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
|
|
||||||
typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
|
|
||||||
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
|
||||||
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
|
||||||
#define eglGetConfigs _glfw.egl.GetConfigs
|
|
||||||
#define eglGetDisplay _glfw.egl.GetDisplay
|
|
||||||
#define eglGetError _glfw.egl.GetError
|
|
||||||
#define eglInitialize _glfw.egl.Initialize
|
|
||||||
#define eglTerminate _glfw.egl.Terminate
|
|
||||||
#define eglBindAPI _glfw.egl.BindAPI
|
|
||||||
#define eglCreateContext _glfw.egl.CreateContext
|
|
||||||
#define eglDestroySurface _glfw.egl.DestroySurface
|
|
||||||
#define eglDestroyContext _glfw.egl.DestroyContext
|
|
||||||
#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface
|
|
||||||
#define eglMakeCurrent _glfw.egl.MakeCurrent
|
|
||||||
#define eglSwapBuffers _glfw.egl.SwapBuffers
|
|
||||||
#define eglSwapInterval _glfw.egl.SwapInterval
|
|
||||||
#define eglQueryString _glfw.egl.QueryString
|
|
||||||
#define eglGetProcAddress _glfw.egl.GetProcAddress
|
|
||||||
|
|
||||||
#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
|
|
||||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
|
|
||||||
|
|
||||||
|
|
||||||
// EGL-specific per-context data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWcontextEGL
|
|
||||||
{
|
|
||||||
EGLConfig config;
|
|
||||||
EGLContext handle;
|
|
||||||
EGLSurface surface;
|
|
||||||
|
|
||||||
void* client;
|
|
||||||
} _GLFWcontextEGL;
|
|
||||||
|
|
||||||
// EGL-specific global data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWlibraryEGL
|
|
||||||
{
|
|
||||||
EGLDisplay display;
|
|
||||||
EGLint major, minor;
|
|
||||||
GLFWbool prefix;
|
|
||||||
|
|
||||||
GLFWbool KHR_create_context;
|
|
||||||
GLFWbool KHR_create_context_no_error;
|
|
||||||
GLFWbool KHR_gl_colorspace;
|
|
||||||
GLFWbool KHR_get_all_proc_addresses;
|
|
||||||
GLFWbool KHR_context_flush_control;
|
|
||||||
|
|
||||||
void* handle;
|
|
||||||
|
|
||||||
PFN_eglGetConfigAttrib GetConfigAttrib;
|
|
||||||
PFN_eglGetConfigs GetConfigs;
|
|
||||||
PFN_eglGetDisplay GetDisplay;
|
|
||||||
PFN_eglGetError GetError;
|
|
||||||
PFN_eglInitialize Initialize;
|
|
||||||
PFN_eglTerminate Terminate;
|
|
||||||
PFN_eglBindAPI BindAPI;
|
|
||||||
PFN_eglCreateContext CreateContext;
|
|
||||||
PFN_eglDestroySurface DestroySurface;
|
|
||||||
PFN_eglDestroyContext DestroyContext;
|
|
||||||
PFN_eglCreateWindowSurface CreateWindowSurface;
|
|
||||||
PFN_eglMakeCurrent MakeCurrent;
|
|
||||||
PFN_eglSwapBuffers SwapBuffers;
|
|
||||||
PFN_eglSwapInterval SwapInterval;
|
|
||||||
PFN_eglQueryString QueryString;
|
|
||||||
PFN_eglGetProcAddress GetProcAddress;
|
|
||||||
} _GLFWlibraryEGL;
|
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitEGL(void);
|
|
||||||
void _glfwTerminateEGL(void);
|
|
||||||
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig);
|
|
||||||
#if defined(_GLFW_X11)
|
|
||||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig,
|
|
||||||
Visual** visual, int* depth);
|
|
||||||
#endif /*_GLFW_X11*/
|
|
||||||
|
|
@ -1,326 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE: The global variables below comprise all mutable global data in GLFW
|
|
||||||
// Any other mutable global variable is a bug
|
|
||||||
|
|
||||||
// This contains all mutable state shared between compilation units of GLFW
|
|
||||||
//
|
|
||||||
_GLFWlibrary _glfw = { GLFW_FALSE };
|
|
||||||
|
|
||||||
// These are outside of _glfw so they can be used before initialization and
|
|
||||||
// after termination without special handling when _glfw is cleared to zero
|
|
||||||
//
|
|
||||||
static _GLFWerror _glfwMainThreadError;
|
|
||||||
static GLFWerrorfun _glfwErrorCallback;
|
|
||||||
static _GLFWinitconfig _glfwInitHints =
|
|
||||||
{
|
|
||||||
GLFW_TRUE, // hat buttons
|
|
||||||
{
|
|
||||||
GLFW_TRUE, // macOS menu bar
|
|
||||||
GLFW_TRUE // macOS bundle chdir
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Terminate the library
|
|
||||||
//
|
|
||||||
static void terminate(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
|
|
||||||
|
|
||||||
while (_glfw.windowListHead)
|
|
||||||
glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
|
|
||||||
|
|
||||||
while (_glfw.cursorListHead)
|
|
||||||
glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
|
|
||||||
|
|
||||||
for (i = 0; i < _glfw.monitorCount; i++)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = _glfw.monitors[i];
|
|
||||||
if (monitor->originalRamp.size)
|
|
||||||
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
|
|
||||||
_glfwFreeMonitor(monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(_glfw.monitors);
|
|
||||||
_glfw.monitors = NULL;
|
|
||||||
_glfw.monitorCount = 0;
|
|
||||||
|
|
||||||
free(_glfw.mappings);
|
|
||||||
_glfw.mappings = NULL;
|
|
||||||
_glfw.mappingCount = 0;
|
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
|
||||||
_glfwPlatformTerminate();
|
|
||||||
|
|
||||||
_glfw.initialized = GLFW_FALSE;
|
|
||||||
|
|
||||||
while (_glfw.errorListHead)
|
|
||||||
{
|
|
||||||
_GLFWerror* error = _glfw.errorListHead;
|
|
||||||
_glfw.errorListHead = error->next;
|
|
||||||
free(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformDestroyTls(&_glfw.contextSlot);
|
|
||||||
_glfwPlatformDestroyTls(&_glfw.errorSlot);
|
|
||||||
_glfwPlatformDestroyMutex(&_glfw.errorLock);
|
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
char* _glfw_strdup(const char* source)
|
|
||||||
{
|
|
||||||
const size_t length = strlen(source);
|
|
||||||
char* result = calloc(length + 1, 1);
|
|
||||||
strcpy(result, source);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
float _glfw_fminf(float a, float b)
|
|
||||||
{
|
|
||||||
if (a != a)
|
|
||||||
return b;
|
|
||||||
else if (b != b)
|
|
||||||
return a;
|
|
||||||
else if (a < b)
|
|
||||||
return a;
|
|
||||||
else
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
float _glfw_fmaxf(float a, float b)
|
|
||||||
{
|
|
||||||
if (a != a)
|
|
||||||
return b;
|
|
||||||
else if (b != b)
|
|
||||||
return a;
|
|
||||||
else if (a > b)
|
|
||||||
return a;
|
|
||||||
else
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW event API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Notifies shared code of an error
|
|
||||||
//
|
|
||||||
void _glfwInputError(int code, const char* format, ...)
|
|
||||||
{
|
|
||||||
_GLFWerror* error;
|
|
||||||
char description[_GLFW_MESSAGE_SIZE];
|
|
||||||
|
|
||||||
if (format)
|
|
||||||
{
|
|
||||||
va_list vl;
|
|
||||||
|
|
||||||
va_start(vl, format);
|
|
||||||
vsnprintf(description, sizeof(description), format, vl);
|
|
||||||
va_end(vl);
|
|
||||||
|
|
||||||
description[sizeof(description) - 1] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (code == GLFW_NOT_INITIALIZED)
|
|
||||||
strcpy(description, "The GLFW library is not initialized");
|
|
||||||
else if (code == GLFW_NO_CURRENT_CONTEXT)
|
|
||||||
strcpy(description, "There is no current context");
|
|
||||||
else if (code == GLFW_INVALID_ENUM)
|
|
||||||
strcpy(description, "Invalid argument for enum parameter");
|
|
||||||
else if (code == GLFW_INVALID_VALUE)
|
|
||||||
strcpy(description, "Invalid value for parameter");
|
|
||||||
else if (code == GLFW_OUT_OF_MEMORY)
|
|
||||||
strcpy(description, "Out of memory");
|
|
||||||
else if (code == GLFW_API_UNAVAILABLE)
|
|
||||||
strcpy(description, "The requested API is unavailable");
|
|
||||||
else if (code == GLFW_VERSION_UNAVAILABLE)
|
|
||||||
strcpy(description, "The requested API version is unavailable");
|
|
||||||
else if (code == GLFW_PLATFORM_ERROR)
|
|
||||||
strcpy(description, "A platform-specific error occurred");
|
|
||||||
else if (code == GLFW_FORMAT_UNAVAILABLE)
|
|
||||||
strcpy(description, "The requested format is unavailable");
|
|
||||||
else if (code == GLFW_NO_WINDOW_CONTEXT)
|
|
||||||
strcpy(description, "The specified window has no context");
|
|
||||||
else
|
|
||||||
strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.initialized)
|
|
||||||
{
|
|
||||||
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
|
||||||
if (!error)
|
|
||||||
{
|
|
||||||
error = calloc(1, sizeof(_GLFWerror));
|
|
||||||
_glfwPlatformSetTls(&_glfw.errorSlot, error);
|
|
||||||
_glfwPlatformLockMutex(&_glfw.errorLock);
|
|
||||||
error->next = _glfw.errorListHead;
|
|
||||||
_glfw.errorListHead = error;
|
|
||||||
_glfwPlatformUnlockMutex(&_glfw.errorLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
error = &_glfwMainThreadError;
|
|
||||||
|
|
||||||
error->code = code;
|
|
||||||
strcpy(error->description, description);
|
|
||||||
|
|
||||||
if (_glfwErrorCallback)
|
|
||||||
_glfwErrorCallback(code, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW public API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI int glfwInit(void)
|
|
||||||
{
|
|
||||||
if (_glfw.initialized)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
|
||||||
_glfw.hints.init = _glfwInitHints;
|
|
||||||
|
|
||||||
if (!_glfwPlatformInit())
|
|
||||||
{
|
|
||||||
terminate();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
|
|
||||||
!_glfwPlatformCreateTls(&_glfw.errorSlot) ||
|
|
||||||
!_glfwPlatformCreateTls(&_glfw.contextSlot))
|
|
||||||
{
|
|
||||||
terminate();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
|
||||||
|
|
||||||
_glfwInitGamepadMappings();
|
|
||||||
|
|
||||||
_glfw.initialized = GLFW_TRUE;
|
|
||||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
|
||||||
|
|
||||||
glfwDefaultWindowHints();
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwTerminate(void)
|
|
||||||
{
|
|
||||||
if (!_glfw.initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwInitHint(int hint, int value)
|
|
||||||
{
|
|
||||||
switch (hint)
|
|
||||||
{
|
|
||||||
case GLFW_JOYSTICK_HAT_BUTTONS:
|
|
||||||
_glfwInitHints.hatButtons = value;
|
|
||||||
return;
|
|
||||||
case GLFW_COCOA_CHDIR_RESOURCES:
|
|
||||||
_glfwInitHints.ns.chdir = value;
|
|
||||||
return;
|
|
||||||
case GLFW_COCOA_MENUBAR:
|
|
||||||
_glfwInitHints.ns.menubar = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
|
||||||
"Invalid init hint 0x%08X", hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
|
|
||||||
{
|
|
||||||
if (major != NULL)
|
|
||||||
*major = GLFW_VERSION_MAJOR;
|
|
||||||
if (minor != NULL)
|
|
||||||
*minor = GLFW_VERSION_MINOR;
|
|
||||||
if (rev != NULL)
|
|
||||||
*rev = GLFW_VERSION_REVISION;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetVersionString(void)
|
|
||||||
{
|
|
||||||
return _glfwPlatformGetVersionString();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI int glfwGetError(const char** description)
|
|
||||||
{
|
|
||||||
_GLFWerror* error;
|
|
||||||
int code = GLFW_NO_ERROR;
|
|
||||||
|
|
||||||
if (description)
|
|
||||||
*description = NULL;
|
|
||||||
|
|
||||||
if (_glfw.initialized)
|
|
||||||
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
|
||||||
else
|
|
||||||
error = &_glfwMainThreadError;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
code = error->code;
|
|
||||||
error->code = GLFW_NO_ERROR;
|
|
||||||
if (description && code)
|
|
||||||
*description = error->description;
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
|
||||||
{
|
|
||||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
|
||||||
return cbfun;
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,780 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_CONFIG_H)
|
|
||||||
#include "glfw_config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(GLFW_INCLUDE_GLCOREARB) || \
|
|
||||||
defined(GLFW_INCLUDE_ES1) || \
|
|
||||||
defined(GLFW_INCLUDE_ES2) || \
|
|
||||||
defined(GLFW_INCLUDE_ES3) || \
|
|
||||||
defined(GLFW_INCLUDE_ES31) || \
|
|
||||||
defined(GLFW_INCLUDE_ES32) || \
|
|
||||||
defined(GLFW_INCLUDE_NONE) || \
|
|
||||||
defined(GLFW_INCLUDE_GLEXT) || \
|
|
||||||
defined(GLFW_INCLUDE_GLU) || \
|
|
||||||
defined(GLFW_INCLUDE_VULKAN) || \
|
|
||||||
defined(GLFW_DLL)
|
|
||||||
#error "You must not define any header option macros when compiling GLFW"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GLFW_INCLUDE_NONE
|
|
||||||
#include "../include/GLFW/glfw3.h"
|
|
||||||
|
|
||||||
#define _GLFW_INSERT_FIRST 0
|
|
||||||
#define _GLFW_INSERT_LAST 1
|
|
||||||
|
|
||||||
#define _GLFW_POLL_PRESENCE 0
|
|
||||||
#define _GLFW_POLL_AXES 1
|
|
||||||
#define _GLFW_POLL_BUTTONS 2
|
|
||||||
#define _GLFW_POLL_ALL (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
|
|
||||||
|
|
||||||
#define _GLFW_MESSAGE_SIZE 1024
|
|
||||||
|
|
||||||
typedef int GLFWbool;
|
|
||||||
|
|
||||||
typedef struct _GLFWerror _GLFWerror;
|
|
||||||
typedef struct _GLFWinitconfig _GLFWinitconfig;
|
|
||||||
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
|
||||||
typedef struct _GLFWctxconfig _GLFWctxconfig;
|
|
||||||
typedef struct _GLFWfbconfig _GLFWfbconfig;
|
|
||||||
typedef struct _GLFWcontext _GLFWcontext;
|
|
||||||
typedef struct _GLFWwindow _GLFWwindow;
|
|
||||||
typedef struct _GLFWlibrary _GLFWlibrary;
|
|
||||||
typedef struct _GLFWmonitor _GLFWmonitor;
|
|
||||||
typedef struct _GLFWcursor _GLFWcursor;
|
|
||||||
typedef struct _GLFWmapelement _GLFWmapelement;
|
|
||||||
typedef struct _GLFWmapping _GLFWmapping;
|
|
||||||
typedef struct _GLFWjoystick _GLFWjoystick;
|
|
||||||
typedef struct _GLFWtls _GLFWtls;
|
|
||||||
typedef struct _GLFWmutex _GLFWmutex;
|
|
||||||
|
|
||||||
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
|
||||||
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
|
||||||
typedef void (* _GLFWswapintervalfun)(int);
|
|
||||||
typedef int (* _GLFWextensionsupportedfun)(const char*);
|
|
||||||
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
|
|
||||||
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
|
||||||
|
|
||||||
#define GL_VERSION 0x1f02
|
|
||||||
#define GL_NONE 0
|
|
||||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
|
||||||
#define GL_UNSIGNED_BYTE 0x1401
|
|
||||||
#define GL_EXTENSIONS 0x1f03
|
|
||||||
#define GL_NUM_EXTENSIONS 0x821d
|
|
||||||
#define GL_CONTEXT_FLAGS 0x821e
|
|
||||||
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
|
|
||||||
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
|
|
||||||
#define GL_CONTEXT_PROFILE_MASK 0x9126
|
|
||||||
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
|
|
||||||
#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
|
|
||||||
#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
|
||||||
#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
|
||||||
#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
|
|
||||||
#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82fb
|
|
||||||
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc
|
|
||||||
#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
|
|
||||||
|
|
||||||
typedef int GLint;
|
|
||||||
typedef unsigned int GLuint;
|
|
||||||
typedef unsigned int GLenum;
|
|
||||||
typedef unsigned int GLbitfield;
|
|
||||||
typedef unsigned char GLubyte;
|
|
||||||
|
|
||||||
typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
|
|
||||||
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
|
|
||||||
typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
|
|
||||||
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
|
|
||||||
|
|
||||||
#define VK_NULL_HANDLE 0
|
|
||||||
|
|
||||||
typedef void* VkInstance;
|
|
||||||
typedef void* VkPhysicalDevice;
|
|
||||||
typedef uint64_t VkSurfaceKHR;
|
|
||||||
typedef uint32_t VkFlags;
|
|
||||||
typedef uint32_t VkBool32;
|
|
||||||
|
|
||||||
typedef enum VkStructureType
|
|
||||||
{
|
|
||||||
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
|
|
||||||
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
|
|
||||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
|
||||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
|
||||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
|
||||||
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
|
|
||||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
|
||||||
} VkStructureType;
|
|
||||||
|
|
||||||
typedef enum VkResult
|
|
||||||
{
|
|
||||||
VK_SUCCESS = 0,
|
|
||||||
VK_NOT_READY = 1,
|
|
||||||
VK_TIMEOUT = 2,
|
|
||||||
VK_EVENT_SET = 3,
|
|
||||||
VK_EVENT_RESET = 4,
|
|
||||||
VK_INCOMPLETE = 5,
|
|
||||||
VK_ERROR_OUT_OF_HOST_MEMORY = -1,
|
|
||||||
VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
|
|
||||||
VK_ERROR_INITIALIZATION_FAILED = -3,
|
|
||||||
VK_ERROR_DEVICE_LOST = -4,
|
|
||||||
VK_ERROR_MEMORY_MAP_FAILED = -5,
|
|
||||||
VK_ERROR_LAYER_NOT_PRESENT = -6,
|
|
||||||
VK_ERROR_EXTENSION_NOT_PRESENT = -7,
|
|
||||||
VK_ERROR_FEATURE_NOT_PRESENT = -8,
|
|
||||||
VK_ERROR_INCOMPATIBLE_DRIVER = -9,
|
|
||||||
VK_ERROR_TOO_MANY_OBJECTS = -10,
|
|
||||||
VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
|
|
||||||
VK_ERROR_SURFACE_LOST_KHR = -1000000000,
|
|
||||||
VK_SUBOPTIMAL_KHR = 1000001003,
|
|
||||||
VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
|
|
||||||
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
|
|
||||||
VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
|
|
||||||
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
|
|
||||||
VK_RESULT_MAX_ENUM = 0x7FFFFFFF
|
|
||||||
} VkResult;
|
|
||||||
|
|
||||||
typedef struct VkAllocationCallbacks VkAllocationCallbacks;
|
|
||||||
|
|
||||||
typedef struct VkExtensionProperties
|
|
||||||
{
|
|
||||||
char extensionName[256];
|
|
||||||
uint32_t specVersion;
|
|
||||||
} VkExtensionProperties;
|
|
||||||
|
|
||||||
typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|
||||||
|
|
||||||
#if defined(_GLFW_VULKAN_STATIC)
|
|
||||||
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*);
|
|
||||||
VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*);
|
|
||||||
#else
|
|
||||||
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
|
|
||||||
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
|
|
||||||
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
|
|
||||||
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_GLFW_COCOA)
|
|
||||||
#include "cocoa_platform.h"
|
|
||||||
#elif defined(_GLFW_WIN32)
|
|
||||||
#include "win32_platform.h"
|
|
||||||
#elif defined(_GLFW_X11)
|
|
||||||
#include "x11_platform.h"
|
|
||||||
#elif defined(_GLFW_WAYLAND)
|
|
||||||
#include "wl_platform.h"
|
|
||||||
#elif defined(_GLFW_OSMESA)
|
|
||||||
#include "null_platform.h"
|
|
||||||
#else
|
|
||||||
#error "No supported window creation API selected"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Constructs a version number string from the public header macros
|
|
||||||
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
|
||||||
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
|
||||||
#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \
|
|
||||||
GLFW_VERSION_MINOR, \
|
|
||||||
GLFW_VERSION_REVISION)
|
|
||||||
|
|
||||||
// Checks for whether the library has been initialized
|
|
||||||
#define _GLFW_REQUIRE_INIT() \
|
|
||||||
if (!_glfw.initialized) \
|
|
||||||
{ \
|
|
||||||
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
|
|
||||||
return; \
|
|
||||||
}
|
|
||||||
#define _GLFW_REQUIRE_INIT_OR_RETURN(x) \
|
|
||||||
if (!_glfw.initialized) \
|
|
||||||
{ \
|
|
||||||
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
|
|
||||||
return x; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swaps the provided pointers
|
|
||||||
#define _GLFW_SWAP_POINTERS(x, y) \
|
|
||||||
{ \
|
|
||||||
void* t; \
|
|
||||||
t = x; \
|
|
||||||
x = y; \
|
|
||||||
y = t; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per-thread error structure
|
|
||||||
//
|
|
||||||
struct _GLFWerror
|
|
||||||
{
|
|
||||||
_GLFWerror* next;
|
|
||||||
int code;
|
|
||||||
char description[_GLFW_MESSAGE_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialization configuration
|
|
||||||
//
|
|
||||||
// Parameters relating to the initialization of the library
|
|
||||||
//
|
|
||||||
struct _GLFWinitconfig
|
|
||||||
{
|
|
||||||
GLFWbool hatButtons;
|
|
||||||
struct {
|
|
||||||
GLFWbool menubar;
|
|
||||||
GLFWbool chdir;
|
|
||||||
} ns;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Window configuration
|
|
||||||
//
|
|
||||||
// Parameters relating to the creation of the window but not directly related
|
|
||||||
// to the framebuffer. This is used to pass window creation parameters from
|
|
||||||
// shared code to the platform API.
|
|
||||||
//
|
|
||||||
struct _GLFWwndconfig
|
|
||||||
{
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
const char* title;
|
|
||||||
GLFWbool resizable;
|
|
||||||
GLFWbool visible;
|
|
||||||
GLFWbool decorated;
|
|
||||||
GLFWbool focused;
|
|
||||||
GLFWbool autoIconify;
|
|
||||||
GLFWbool floating;
|
|
||||||
GLFWbool maximized;
|
|
||||||
GLFWbool centerCursor;
|
|
||||||
GLFWbool focusOnShow;
|
|
||||||
GLFWbool scaleToMonitor;
|
|
||||||
struct {
|
|
||||||
GLFWbool retina;
|
|
||||||
char frameName[256];
|
|
||||||
} ns;
|
|
||||||
struct {
|
|
||||||
char className[256];
|
|
||||||
char instanceName[256];
|
|
||||||
} x11;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Context configuration
|
|
||||||
//
|
|
||||||
// Parameters relating to the creation of the context but not directly related
|
|
||||||
// to the framebuffer. This is used to pass context creation parameters from
|
|
||||||
// shared code to the platform API.
|
|
||||||
//
|
|
||||||
struct _GLFWctxconfig
|
|
||||||
{
|
|
||||||
int client;
|
|
||||||
int source;
|
|
||||||
int major;
|
|
||||||
int minor;
|
|
||||||
GLFWbool forward;
|
|
||||||
GLFWbool debug;
|
|
||||||
GLFWbool noerror;
|
|
||||||
int profile;
|
|
||||||
int robustness;
|
|
||||||
int release;
|
|
||||||
_GLFWwindow* share;
|
|
||||||
struct {
|
|
||||||
GLFWbool offline;
|
|
||||||
} nsgl;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Framebuffer configuration
|
|
||||||
//
|
|
||||||
// This describes buffers and their sizes. It also contains
|
|
||||||
// a platform-specific ID used to map back to the backend API object.
|
|
||||||
//
|
|
||||||
// It is used to pass framebuffer parameters from shared code to the platform
|
|
||||||
// API and also to enumerate and select available framebuffer configs.
|
|
||||||
//
|
|
||||||
struct _GLFWfbconfig
|
|
||||||
{
|
|
||||||
int redBits;
|
|
||||||
int greenBits;
|
|
||||||
int blueBits;
|
|
||||||
int alphaBits;
|
|
||||||
int depthBits;
|
|
||||||
int stencilBits;
|
|
||||||
int accumRedBits;
|
|
||||||
int accumGreenBits;
|
|
||||||
int accumBlueBits;
|
|
||||||
int accumAlphaBits;
|
|
||||||
int auxBuffers;
|
|
||||||
GLFWbool stereo;
|
|
||||||
int samples;
|
|
||||||
GLFWbool sRGB;
|
|
||||||
GLFWbool doublebuffer;
|
|
||||||
GLFWbool transparent;
|
|
||||||
uintptr_t handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Context structure
|
|
||||||
//
|
|
||||||
struct _GLFWcontext
|
|
||||||
{
|
|
||||||
int client;
|
|
||||||
int source;
|
|
||||||
int major, minor, revision;
|
|
||||||
GLFWbool forward, debug, noerror;
|
|
||||||
int profile;
|
|
||||||
int robustness;
|
|
||||||
int release;
|
|
||||||
|
|
||||||
PFNGLGETSTRINGIPROC GetStringi;
|
|
||||||
PFNGLGETINTEGERVPROC GetIntegerv;
|
|
||||||
PFNGLGETSTRINGPROC GetString;
|
|
||||||
|
|
||||||
_GLFWmakecontextcurrentfun makeCurrent;
|
|
||||||
_GLFWswapbuffersfun swapBuffers;
|
|
||||||
_GLFWswapintervalfun swapInterval;
|
|
||||||
_GLFWextensionsupportedfun extensionSupported;
|
|
||||||
_GLFWgetprocaddressfun getProcAddress;
|
|
||||||
_GLFWdestroycontextfun destroy;
|
|
||||||
|
|
||||||
// This is defined in the context API's context.h
|
|
||||||
_GLFW_PLATFORM_CONTEXT_STATE;
|
|
||||||
// This is defined in egl_context.h
|
|
||||||
_GLFW_EGL_CONTEXT_STATE;
|
|
||||||
// This is defined in osmesa_context.h
|
|
||||||
_GLFW_OSMESA_CONTEXT_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Window and context structure
|
|
||||||
//
|
|
||||||
struct _GLFWwindow
|
|
||||||
{
|
|
||||||
struct _GLFWwindow* next;
|
|
||||||
|
|
||||||
// Window settings and state
|
|
||||||
GLFWbool resizable;
|
|
||||||
GLFWbool decorated;
|
|
||||||
GLFWbool autoIconify;
|
|
||||||
GLFWbool floating;
|
|
||||||
GLFWbool focusOnShow;
|
|
||||||
GLFWbool shouldClose;
|
|
||||||
void* userPointer;
|
|
||||||
GLFWbool doublebuffer;
|
|
||||||
GLFWvidmode videoMode;
|
|
||||||
_GLFWmonitor* monitor;
|
|
||||||
_GLFWcursor* cursor;
|
|
||||||
|
|
||||||
int minwidth, minheight;
|
|
||||||
int maxwidth, maxheight;
|
|
||||||
int numer, denom;
|
|
||||||
|
|
||||||
GLFWbool stickyKeys;
|
|
||||||
GLFWbool stickyMouseButtons;
|
|
||||||
GLFWbool lockKeyMods;
|
|
||||||
int cursorMode;
|
|
||||||
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
|
||||||
char keys[GLFW_KEY_LAST + 1];
|
|
||||||
// Virtual cursor position when cursor is disabled
|
|
||||||
double virtualCursorPosX, virtualCursorPosY;
|
|
||||||
GLFWbool rawMouseMotion;
|
|
||||||
|
|
||||||
_GLFWcontext context;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
GLFWwindowposfun pos;
|
|
||||||
GLFWwindowsizefun size;
|
|
||||||
GLFWwindowclosefun close;
|
|
||||||
GLFWwindowrefreshfun refresh;
|
|
||||||
GLFWwindowfocusfun focus;
|
|
||||||
GLFWwindowiconifyfun iconify;
|
|
||||||
GLFWwindowmaximizefun maximize;
|
|
||||||
GLFWframebuffersizefun fbsize;
|
|
||||||
GLFWwindowcontentscalefun scale;
|
|
||||||
GLFWmousebuttonfun mouseButton;
|
|
||||||
GLFWcursorposfun cursorPos;
|
|
||||||
GLFWcursorenterfun cursorEnter;
|
|
||||||
GLFWscrollfun scroll;
|
|
||||||
GLFWkeyfun key;
|
|
||||||
GLFWcharfun character;
|
|
||||||
GLFWcharmodsfun charmods;
|
|
||||||
GLFWdropfun drop;
|
|
||||||
} callbacks;
|
|
||||||
|
|
||||||
// This is defined in the window API's platform.h
|
|
||||||
_GLFW_PLATFORM_WINDOW_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Monitor structure
|
|
||||||
//
|
|
||||||
struct _GLFWmonitor
|
|
||||||
{
|
|
||||||
char name[128];
|
|
||||||
void* userPointer;
|
|
||||||
|
|
||||||
// Physical dimensions in millimeters.
|
|
||||||
int widthMM, heightMM;
|
|
||||||
|
|
||||||
// The window whose video mode is current on this monitor
|
|
||||||
_GLFWwindow* window;
|
|
||||||
|
|
||||||
GLFWvidmode* modes;
|
|
||||||
int modeCount;
|
|
||||||
GLFWvidmode currentMode;
|
|
||||||
|
|
||||||
GLFWgammaramp originalRamp;
|
|
||||||
GLFWgammaramp currentRamp;
|
|
||||||
|
|
||||||
// This is defined in the window API's platform.h
|
|
||||||
_GLFW_PLATFORM_MONITOR_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cursor structure
|
|
||||||
//
|
|
||||||
struct _GLFWcursor
|
|
||||||
{
|
|
||||||
_GLFWcursor* next;
|
|
||||||
|
|
||||||
// This is defined in the window API's platform.h
|
|
||||||
_GLFW_PLATFORM_CURSOR_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gamepad mapping element structure
|
|
||||||
//
|
|
||||||
struct _GLFWmapelement
|
|
||||||
{
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t index;
|
|
||||||
int8_t axisScale;
|
|
||||||
int8_t axisOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gamepad mapping structure
|
|
||||||
//
|
|
||||||
struct _GLFWmapping
|
|
||||||
{
|
|
||||||
char name[128];
|
|
||||||
char guid[33];
|
|
||||||
_GLFWmapelement buttons[15];
|
|
||||||
_GLFWmapelement axes[6];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Joystick structure
|
|
||||||
//
|
|
||||||
struct _GLFWjoystick
|
|
||||||
{
|
|
||||||
GLFWbool present;
|
|
||||||
float* axes;
|
|
||||||
int axisCount;
|
|
||||||
unsigned char* buttons;
|
|
||||||
int buttonCount;
|
|
||||||
unsigned char* hats;
|
|
||||||
int hatCount;
|
|
||||||
char name[128];
|
|
||||||
void* userPointer;
|
|
||||||
char guid[33];
|
|
||||||
_GLFWmapping* mapping;
|
|
||||||
|
|
||||||
// This is defined in the joystick API's joystick.h
|
|
||||||
_GLFW_PLATFORM_JOYSTICK_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Thread local storage structure
|
|
||||||
//
|
|
||||||
struct _GLFWtls
|
|
||||||
{
|
|
||||||
// This is defined in the platform's thread.h
|
|
||||||
_GLFW_PLATFORM_TLS_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Mutex structure
|
|
||||||
//
|
|
||||||
struct _GLFWmutex
|
|
||||||
{
|
|
||||||
// This is defined in the platform's thread.h
|
|
||||||
_GLFW_PLATFORM_MUTEX_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Library global data
|
|
||||||
//
|
|
||||||
struct _GLFWlibrary
|
|
||||||
{
|
|
||||||
GLFWbool initialized;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
_GLFWinitconfig init;
|
|
||||||
_GLFWfbconfig framebuffer;
|
|
||||||
_GLFWwndconfig window;
|
|
||||||
_GLFWctxconfig context;
|
|
||||||
int refreshRate;
|
|
||||||
} hints;
|
|
||||||
|
|
||||||
_GLFWerror* errorListHead;
|
|
||||||
_GLFWcursor* cursorListHead;
|
|
||||||
_GLFWwindow* windowListHead;
|
|
||||||
|
|
||||||
_GLFWmonitor** monitors;
|
|
||||||
int monitorCount;
|
|
||||||
|
|
||||||
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
|
||||||
_GLFWmapping* mappings;
|
|
||||||
int mappingCount;
|
|
||||||
|
|
||||||
_GLFWtls errorSlot;
|
|
||||||
_GLFWtls contextSlot;
|
|
||||||
_GLFWmutex errorLock;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint64_t offset;
|
|
||||||
// This is defined in the platform's time.h
|
|
||||||
_GLFW_PLATFORM_LIBRARY_TIMER_STATE;
|
|
||||||
} timer;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
GLFWbool available;
|
|
||||||
void* handle;
|
|
||||||
char* extensions[2];
|
|
||||||
#if !defined(_GLFW_VULKAN_STATIC)
|
|
||||||
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
|
||||||
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
|
||||||
#endif
|
|
||||||
GLFWbool KHR_surface;
|
|
||||||
#if defined(_GLFW_WIN32)
|
|
||||||
GLFWbool KHR_win32_surface;
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
GLFWbool MVK_macos_surface;
|
|
||||||
GLFWbool EXT_metal_surface;
|
|
||||||
#elif defined(_GLFW_X11)
|
|
||||||
GLFWbool KHR_xlib_surface;
|
|
||||||
GLFWbool KHR_xcb_surface;
|
|
||||||
#elif defined(_GLFW_WAYLAND)
|
|
||||||
GLFWbool KHR_wayland_surface;
|
|
||||||
#endif
|
|
||||||
} vk;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
GLFWmonitorfun monitor;
|
|
||||||
GLFWjoystickfun joystick;
|
|
||||||
} callbacks;
|
|
||||||
|
|
||||||
// This is defined in the window API's platform.h
|
|
||||||
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
|
||||||
// This is defined in the context API's context.h
|
|
||||||
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
|
|
||||||
// This is defined in the platform's joystick.h
|
|
||||||
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
|
|
||||||
// This is defined in egl_context.h
|
|
||||||
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
|
||||||
// This is defined in osmesa_context.h
|
|
||||||
_GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Global state shared between compilation units of GLFW
|
|
||||||
//
|
|
||||||
extern _GLFWlibrary _glfw;
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int _glfwPlatformInit(void);
|
|
||||||
void _glfwPlatformTerminate(void);
|
|
||||||
const char* _glfwPlatformGetVersionString(void);
|
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
|
|
||||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
|
||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
|
||||||
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled);
|
|
||||||
GLFWbool _glfwPlatformRawMouseMotionSupported(void);
|
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|
||||||
const GLFWimage* image, int xhot, int yhot);
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
|
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
|
||||||
|
|
||||||
const char* _glfwPlatformGetScancodeName(int scancode);
|
|
||||||
int _glfwPlatformGetKeyScancode(int key);
|
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
|
||||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|
||||||
float* xscale, float* yscale);
|
|
||||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height);
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
|
||||||
|
|
||||||
void _glfwPlatformSetClipboardString(const char* string);
|
|
||||||
const char* _glfwPlatformGetClipboardString(void);
|
|
||||||
|
|
||||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
|
|
||||||
void _glfwPlatformUpdateGamepadGUID(char* guid);
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void);
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void);
|
|
||||||
|
|
||||||
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|
||||||
const _GLFWwndconfig* wndconfig,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig);
|
|
||||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
|
|
||||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
|
||||||
int count, const GLFWimage* images);
|
|
||||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
|
|
||||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
|
||||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
|
|
||||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
|
|
||||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|
||||||
int minwidth, int minheight,
|
|
||||||
int maxwidth, int maxheight);
|
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
|
||||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
|
||||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|
||||||
int* left, int* top,
|
|
||||||
int* right, int* bottom);
|
|
||||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
|
||||||
float* xscale, float* yscale);
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
|
|
||||||
int xpos, int ypos, int width, int height,
|
|
||||||
int refreshRate);
|
|
||||||
int _glfwPlatformWindowFocused(_GLFWwindow* window);
|
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
|
||||||
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
|
||||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
|
||||||
int _glfwPlatformWindowHovered(_GLFWwindow* window);
|
|
||||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
|
|
||||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
|
|
||||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
|
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void);
|
|
||||||
void _glfwPlatformWaitEvents(void);
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout);
|
|
||||||
void _glfwPlatformPostEmptyEvent(void);
|
|
||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
|
||||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|
||||||
VkPhysicalDevice device,
|
|
||||||
uint32_t queuefamily);
|
|
||||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|
||||||
_GLFWwindow* window,
|
|
||||||
const VkAllocationCallbacks* allocator,
|
|
||||||
VkSurfaceKHR* surface);
|
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
|
|
||||||
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
|
||||||
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
|
||||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
|
|
||||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
|
|
||||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex);
|
|
||||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW event API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
|
|
||||||
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
|
||||||
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
|
||||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
|
||||||
void _glfwInputWindowContentScale(_GLFWwindow* window,
|
|
||||||
float xscale, float yscale);
|
|
||||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
|
|
||||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
|
|
||||||
void _glfwInputWindowDamage(_GLFWwindow* window);
|
|
||||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
|
||||||
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
void _glfwInputKey(_GLFWwindow* window,
|
|
||||||
int key, int scancode, int action, int mods);
|
|
||||||
void _glfwInputChar(_GLFWwindow* window,
|
|
||||||
unsigned int codepoint, int mods, GLFWbool plain);
|
|
||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
|
|
||||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
|
|
||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
|
||||||
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
|
||||||
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
|
||||||
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
|
|
||||||
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
|
|
||||||
|
|
||||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
|
|
||||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
void _glfwInputError(int code, const char* format, ...)
|
|
||||||
__attribute__((format(printf, 2, 3)));
|
|
||||||
#else
|
|
||||||
void _glfwInputError(int code, const char* format, ...);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
|
|
||||||
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
|
||||||
const _GLFWfbconfig* alternatives,
|
|
||||||
unsigned int count);
|
|
||||||
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig);
|
|
||||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
|
||||||
|
|
||||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
|
||||||
const GLFWvidmode* desired);
|
|
||||||
int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
|
|
||||||
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
|
|
||||||
void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
|
||||||
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
|
|
||||||
void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
|
|
||||||
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
|
|
||||||
|
|
||||||
void _glfwInitGamepadMappings(void);
|
|
||||||
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
|
||||||
const char* guid,
|
|
||||||
int axisCount,
|
|
||||||
int buttonCount,
|
|
||||||
int hatCount);
|
|
||||||
void _glfwFreeJoystick(_GLFWjoystick* js);
|
|
||||||
void _glfwCenterCursorInContentArea(_GLFWwindow* window);
|
|
||||||
|
|
||||||
GLFWbool _glfwInitVulkan(int mode);
|
|
||||||
void _glfwTerminateVulkan(void);
|
|
||||||
const char* _glfwGetVulkanResultString(VkResult result);
|
|
||||||
|
|
||||||
char* _glfw_strdup(const char* source);
|
|
||||||
float _glfw_fminf(float a, float b);
|
|
||||||
float _glfw_fmaxf(float a, float b);
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,542 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <float.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Lexically compare video modes, used by qsort
|
|
||||||
//
|
|
||||||
static int compareVideoModes(const void* fp, const void* sp)
|
|
||||||
{
|
|
||||||
const GLFWvidmode* fm = fp;
|
|
||||||
const GLFWvidmode* sm = sp;
|
|
||||||
const int fbpp = fm->redBits + fm->greenBits + fm->blueBits;
|
|
||||||
const int sbpp = sm->redBits + sm->greenBits + sm->blueBits;
|
|
||||||
const int farea = fm->width * fm->height;
|
|
||||||
const int sarea = sm->width * sm->height;
|
|
||||||
|
|
||||||
// First sort on color bits per pixel
|
|
||||||
if (fbpp != sbpp)
|
|
||||||
return fbpp - sbpp;
|
|
||||||
|
|
||||||
// Then sort on screen area
|
|
||||||
if (farea != sarea)
|
|
||||||
return farea - sarea;
|
|
||||||
|
|
||||||
// Then sort on width
|
|
||||||
if (fm->width != sm->width)
|
|
||||||
return fm->width - sm->width;
|
|
||||||
|
|
||||||
// Lastly sort on refresh rate
|
|
||||||
return fm->refreshRate - sm->refreshRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves the available modes for the specified monitor
|
|
||||||
//
|
|
||||||
static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
|
||||||
{
|
|
||||||
int modeCount;
|
|
||||||
GLFWvidmode* modes;
|
|
||||||
|
|
||||||
if (monitor->modes)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
|
|
||||||
if (!modes)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
|
|
||||||
|
|
||||||
free(monitor->modes);
|
|
||||||
monitor->modes = modes;
|
|
||||||
monitor->modeCount = modeCount;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW event API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Notifies shared code of a monitor connection or disconnection
|
|
||||||
//
|
|
||||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
|
||||||
{
|
|
||||||
if (action == GLFW_CONNECTED)
|
|
||||||
{
|
|
||||||
_glfw.monitorCount++;
|
|
||||||
_glfw.monitors =
|
|
||||||
realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
|
|
||||||
|
|
||||||
if (placement == _GLFW_INSERT_FIRST)
|
|
||||||
{
|
|
||||||
memmove(_glfw.monitors + 1,
|
|
||||||
_glfw.monitors,
|
|
||||||
((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
|
||||||
_glfw.monitors[0] = monitor;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
|
|
||||||
}
|
|
||||||
else if (action == GLFW_DISCONNECTED)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
_GLFWwindow* window;
|
|
||||||
|
|
||||||
for (window = _glfw.windowListHead; window; window = window->next)
|
|
||||||
{
|
|
||||||
if (window->monitor == monitor)
|
|
||||||
{
|
|
||||||
int width, height, xoff, yoff;
|
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
|
||||||
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
|
|
||||||
_glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
|
|
||||||
_glfwPlatformSetWindowPos(window, xoff, yoff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < _glfw.monitorCount; i++)
|
|
||||||
{
|
|
||||||
if (_glfw.monitors[i] == monitor)
|
|
||||||
{
|
|
||||||
_glfw.monitorCount--;
|
|
||||||
memmove(_glfw.monitors + i,
|
|
||||||
_glfw.monitors + i + 1,
|
|
||||||
((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.callbacks.monitor)
|
|
||||||
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
|
|
||||||
|
|
||||||
if (action == GLFW_DISCONNECTED)
|
|
||||||
_glfwFreeMonitor(monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notifies shared code that a full screen window has acquired or released
|
|
||||||
// a monitor
|
|
||||||
//
|
|
||||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
|
|
||||||
{
|
|
||||||
monitor->window = window;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Allocates and returns a monitor object with the specified name and dimensions
|
|
||||||
//
|
|
||||||
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
|
||||||
monitor->widthMM = widthMM;
|
|
||||||
monitor->heightMM = heightMM;
|
|
||||||
|
|
||||||
strncpy(monitor->name, name, sizeof(monitor->name) - 1);
|
|
||||||
|
|
||||||
return monitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frees a monitor object and any data associated with it
|
|
||||||
//
|
|
||||||
void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
|
||||||
{
|
|
||||||
if (monitor == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_glfwPlatformFreeMonitor(monitor);
|
|
||||||
|
|
||||||
_glfwFreeGammaArrays(&monitor->originalRamp);
|
|
||||||
_glfwFreeGammaArrays(&monitor->currentRamp);
|
|
||||||
|
|
||||||
free(monitor->modes);
|
|
||||||
free(monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocates red, green and blue value arrays of the specified size
|
|
||||||
//
|
|
||||||
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
|
|
||||||
{
|
|
||||||
ramp->red = calloc(size, sizeof(unsigned short));
|
|
||||||
ramp->green = calloc(size, sizeof(unsigned short));
|
|
||||||
ramp->blue = calloc(size, sizeof(unsigned short));
|
|
||||||
ramp->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frees the red, green and blue value arrays and clears the struct
|
|
||||||
//
|
|
||||||
void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
|
||||||
{
|
|
||||||
free(ramp->red);
|
|
||||||
free(ramp->green);
|
|
||||||
free(ramp->blue);
|
|
||||||
|
|
||||||
memset(ramp, 0, sizeof(GLFWgammaramp));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chooses the video mode most closely matching the desired one
|
|
||||||
//
|
|
||||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
|
||||||
const GLFWvidmode* desired)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
|
|
||||||
unsigned int rateDiff, leastRateDiff = UINT_MAX;
|
|
||||||
unsigned int colorDiff, leastColorDiff = UINT_MAX;
|
|
||||||
const GLFWvidmode* current;
|
|
||||||
const GLFWvidmode* closest = NULL;
|
|
||||||
|
|
||||||
if (!refreshVideoModes(monitor))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < monitor->modeCount; i++)
|
|
||||||
{
|
|
||||||
current = monitor->modes + i;
|
|
||||||
|
|
||||||
colorDiff = 0;
|
|
||||||
|
|
||||||
if (desired->redBits != GLFW_DONT_CARE)
|
|
||||||
colorDiff += abs(current->redBits - desired->redBits);
|
|
||||||
if (desired->greenBits != GLFW_DONT_CARE)
|
|
||||||
colorDiff += abs(current->greenBits - desired->greenBits);
|
|
||||||
if (desired->blueBits != GLFW_DONT_CARE)
|
|
||||||
colorDiff += abs(current->blueBits - desired->blueBits);
|
|
||||||
|
|
||||||
sizeDiff = abs((current->width - desired->width) *
|
|
||||||
(current->width - desired->width) +
|
|
||||||
(current->height - desired->height) *
|
|
||||||
(current->height - desired->height));
|
|
||||||
|
|
||||||
if (desired->refreshRate != GLFW_DONT_CARE)
|
|
||||||
rateDiff = abs(current->refreshRate - desired->refreshRate);
|
|
||||||
else
|
|
||||||
rateDiff = UINT_MAX - current->refreshRate;
|
|
||||||
|
|
||||||
if ((colorDiff < leastColorDiff) ||
|
|
||||||
(colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
|
|
||||||
(colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
|
|
||||||
{
|
|
||||||
closest = current;
|
|
||||||
leastSizeDiff = sizeDiff;
|
|
||||||
leastRateDiff = rateDiff;
|
|
||||||
leastColorDiff = colorDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Performs lexical comparison between two @ref GLFWvidmode structures
|
|
||||||
//
|
|
||||||
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
|
|
||||||
{
|
|
||||||
return compareVideoModes(fm, sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Splits a color depth into red, green and blue bit depths
|
|
||||||
//
|
|
||||||
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
|
|
||||||
{
|
|
||||||
int delta;
|
|
||||||
|
|
||||||
// We assume that by 32 the user really meant 24
|
|
||||||
if (bpp == 32)
|
|
||||||
bpp = 24;
|
|
||||||
|
|
||||||
// Convert "bits per pixel" to red, green & blue sizes
|
|
||||||
|
|
||||||
*red = *green = *blue = bpp / 3;
|
|
||||||
delta = bpp - (*red * 3);
|
|
||||||
if (delta >= 1)
|
|
||||||
*green = *green + 1;
|
|
||||||
|
|
||||||
if (delta == 2)
|
|
||||||
*red = *red + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW public API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
|
|
||||||
{
|
|
||||||
assert(count != NULL);
|
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
*count = _glfw.monitorCount;
|
|
||||||
return (GLFWmonitor**) _glfw.monitors;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
if (!_glfw.monitorCount)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return (GLFWmonitor*) _glfw.monitors[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
if (xpos)
|
|
||||||
*xpos = 0;
|
|
||||||
if (ypos)
|
|
||||||
*ypos = 0;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
_glfwPlatformGetMonitorPos(monitor, xpos, ypos);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
|
|
||||||
int* xpos, int* ypos,
|
|
||||||
int* width, int* height)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
if (xpos)
|
|
||||||
*xpos = 0;
|
|
||||||
if (ypos)
|
|
||||||
*ypos = 0;
|
|
||||||
if (width)
|
|
||||||
*width = 0;
|
|
||||||
if (height)
|
|
||||||
*height = 0;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
_glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
if (widthMM)
|
|
||||||
*widthMM = 0;
|
|
||||||
if (heightMM)
|
|
||||||
*heightMM = 0;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
if (widthMM)
|
|
||||||
*widthMM = monitor->widthMM;
|
|
||||||
if (heightMM)
|
|
||||||
*heightMM = monitor->heightMM;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
|
|
||||||
float* xscale, float* yscale)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
if (xscale)
|
|
||||||
*xscale = 0.f;
|
|
||||||
if (yscale)
|
|
||||||
*yscale = 0.f;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
_glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
return monitor->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
monitor->userPointer = pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
return monitor->userPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun);
|
|
||||||
return cbfun;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
assert(count != NULL);
|
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
if (!refreshVideoModes(monitor))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = monitor->modeCount;
|
|
||||||
return monitor->modes;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
_glfwPlatformGetVideoMode(monitor, &monitor->currentMode);
|
|
||||||
return &monitor->currentMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned short* values;
|
|
||||||
GLFWgammaramp ramp;
|
|
||||||
const GLFWgammaramp* original;
|
|
||||||
assert(handle != NULL);
|
|
||||||
assert(gamma > 0.f);
|
|
||||||
assert(gamma <= FLT_MAX);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
original = glfwGetGammaRamp(handle);
|
|
||||||
if (!original)
|
|
||||||
return;
|
|
||||||
|
|
||||||
values = calloc(original->size, sizeof(unsigned short));
|
|
||||||
|
|
||||||
for (i = 0; i < original->size; i++)
|
|
||||||
{
|
|
||||||
float value;
|
|
||||||
|
|
||||||
// Calculate intensity
|
|
||||||
value = i / (float) (original->size - 1);
|
|
||||||
// Apply gamma curve
|
|
||||||
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
|
||||||
// Clamp to value range
|
|
||||||
value = _glfw_fminf(value, 65535.f);
|
|
||||||
|
|
||||||
values[i] = (unsigned short) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
ramp.red = values;
|
|
||||||
ramp.green = values;
|
|
||||||
ramp.blue = values;
|
|
||||||
ramp.size = original->size;
|
|
||||||
|
|
||||||
glfwSetGammaRamp(handle, &ramp);
|
|
||||||
free(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
_glfwFreeGammaArrays(&monitor->currentRamp);
|
|
||||||
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return &monitor->currentRamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
assert(monitor != NULL);
|
|
||||||
assert(ramp != NULL);
|
|
||||||
assert(ramp->size > 0);
|
|
||||||
assert(ramp->red != NULL);
|
|
||||||
assert(ramp->green != NULL);
|
|
||||||
assert(ramp->blue != NULL);
|
|
||||||
|
|
||||||
if (ramp->size <= 0)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"Invalid gamma ramp size %i",
|
|
||||||
ramp->size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
if (!monitor->originalRamp.size)
|
|
||||||
{
|
|
||||||
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformSetGammaRamp(monitor, ramp);
|
|
||||||
}
|
|
||||||
|
|
@ -1,384 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 OSMesa - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2016 Google Inc.
|
|
||||||
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
|
|
||||||
static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window)
|
|
||||||
{
|
|
||||||
int width, height;
|
|
||||||
_glfwPlatformGetFramebufferSize(window, &width, &height);
|
|
||||||
|
|
||||||
// Check to see if we need to allocate a new buffer
|
|
||||||
if ((window->context.osmesa.buffer == NULL) ||
|
|
||||||
(width != window->context.osmesa.width) ||
|
|
||||||
(height != window->context.osmesa.height))
|
|
||||||
{
|
|
||||||
free(window->context.osmesa.buffer);
|
|
||||||
|
|
||||||
// Allocate the new buffer (width * height * 8-bit RGBA)
|
|
||||||
window->context.osmesa.buffer = calloc(4, (size_t) width * height);
|
|
||||||
window->context.osmesa.width = width;
|
|
||||||
window->context.osmesa.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
|
||||||
window->context.osmesa.buffer,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
width, height))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"OSMesa: Failed to make context current");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
|
||||||
{
|
|
||||||
return (GLFWglproc) OSMesaGetProcAddress(procname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroyContextOSMesa(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window->context.osmesa.handle)
|
|
||||||
{
|
|
||||||
OSMesaDestroyContext(window->context.osmesa.handle);
|
|
||||||
window->context.osmesa.handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.osmesa.buffer)
|
|
||||||
{
|
|
||||||
free(window->context.osmesa.buffer);
|
|
||||||
window->context.osmesa.width = 0;
|
|
||||||
window->context.osmesa.height = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapBuffersOSMesa(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
// No double buffering on OSMesa
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapIntervalOSMesa(int interval)
|
|
||||||
{
|
|
||||||
// No swap interval on OSMesa
|
|
||||||
}
|
|
||||||
|
|
||||||
static int extensionSupportedOSMesa(const char* extension)
|
|
||||||
{
|
|
||||||
// OSMesa does not have extensions
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWbool _glfwInitOSMesa(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char* sonames[] =
|
|
||||||
{
|
|
||||||
#if defined(_GLFW_OSMESA_LIBRARY)
|
|
||||||
_GLFW_OSMESA_LIBRARY,
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
"libOSMesa.dll",
|
|
||||||
"OSMesa.dll",
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
"libOSMesa.8.dylib",
|
|
||||||
#elif defined(__CYGWIN__)
|
|
||||||
"libOSMesa-8.so",
|
|
||||||
#else
|
|
||||||
"libOSMesa.so.8",
|
|
||||||
"libOSMesa.so.6",
|
|
||||||
#endif
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_glfw.osmesa.handle)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
for (i = 0; sonames[i]; i++)
|
|
||||||
{
|
|
||||||
_glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
|
|
||||||
if (_glfw.osmesa.handle)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_glfw.osmesa.handle)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
|
|
||||||
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
|
|
||||||
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
|
|
||||||
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
|
|
||||||
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
|
|
||||||
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
|
|
||||||
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
|
|
||||||
|
|
||||||
if (!_glfw.osmesa.CreateContextExt ||
|
|
||||||
!_glfw.osmesa.DestroyContext ||
|
|
||||||
!_glfw.osmesa.MakeCurrent ||
|
|
||||||
!_glfw.osmesa.GetColorBuffer ||
|
|
||||||
!_glfw.osmesa.GetDepthBuffer ||
|
|
||||||
!_glfw.osmesa.GetProcAddress)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"OSMesa: Failed to load required entry points");
|
|
||||||
|
|
||||||
_glfwTerminateOSMesa();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwTerminateOSMesa(void)
|
|
||||||
{
|
|
||||||
if (_glfw.osmesa.handle)
|
|
||||||
{
|
|
||||||
_glfw_dlclose(_glfw.osmesa.handle);
|
|
||||||
_glfw.osmesa.handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setAttrib(a, v) \
|
|
||||||
{ \
|
|
||||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
|
||||||
attribs[index++] = a; \
|
|
||||||
attribs[index++] = v; \
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig)
|
|
||||||
{
|
|
||||||
OSMesaContext share = NULL;
|
|
||||||
const int accumBits = fbconfig->accumRedBits +
|
|
||||||
fbconfig->accumGreenBits +
|
|
||||||
fbconfig->accumBlueBits +
|
|
||||||
fbconfig->accumAlphaBits;
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"OSMesa: OpenGL ES is not available on OSMesa");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->share)
|
|
||||||
share = ctxconfig->share->context.osmesa.handle;
|
|
||||||
|
|
||||||
if (OSMesaCreateContextAttribs)
|
|
||||||
{
|
|
||||||
int index = 0, attribs[40];
|
|
||||||
|
|
||||||
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
|
|
||||||
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
|
|
||||||
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
|
|
||||||
setAttrib(OSMESA_ACCUM_BITS, accumBits);
|
|
||||||
|
|
||||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
|
||||||
{
|
|
||||||
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
|
|
||||||
}
|
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
|
||||||
{
|
|
||||||
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
|
||||||
{
|
|
||||||
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
|
|
||||||
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->forward)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"OSMesa: Forward-compatible contexts not supported");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAttrib(0, 0);
|
|
||||||
|
|
||||||
window->context.osmesa.handle =
|
|
||||||
OSMesaCreateContextAttribs(attribs, share);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ctxconfig->profile)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"OSMesa: OpenGL profiles unavailable");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.osmesa.handle =
|
|
||||||
OSMesaCreateContextExt(OSMESA_RGBA,
|
|
||||||
fbconfig->depthBits,
|
|
||||||
fbconfig->stencilBits,
|
|
||||||
accumBits,
|
|
||||||
share);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.osmesa.handle == NULL)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"OSMesa: Failed to create context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentOSMesa;
|
|
||||||
window->context.swapBuffers = swapBuffersOSMesa;
|
|
||||||
window->context.swapInterval = swapIntervalOSMesa;
|
|
||||||
window->context.extensionSupported = extensionSupportedOSMesa;
|
|
||||||
window->context.getProcAddress = getProcAddressOSMesa;
|
|
||||||
window->context.destroy = destroyContextOSMesa;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef setAttrib
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW native API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
|
||||||
int* height, int* format, void** buffer)
|
|
||||||
{
|
|
||||||
void* mesaBuffer;
|
|
||||||
GLint mesaWidth, mesaHeight, mesaFormat;
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
assert(window != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
|
||||||
|
|
||||||
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
|
|
||||||
&mesaWidth, &mesaHeight,
|
|
||||||
&mesaFormat, &mesaBuffer))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"OSMesa: Failed to retrieve color buffer");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (width)
|
|
||||||
*width = mesaWidth;
|
|
||||||
if (height)
|
|
||||||
*height = mesaHeight;
|
|
||||||
if (format)
|
|
||||||
*format = mesaFormat;
|
|
||||||
if (buffer)
|
|
||||||
*buffer = mesaBuffer;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
|
||||||
int* width, int* height,
|
|
||||||
int* bytesPerValue,
|
|
||||||
void** buffer)
|
|
||||||
{
|
|
||||||
void* mesaBuffer;
|
|
||||||
GLint mesaWidth, mesaHeight, mesaBytes;
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
assert(window != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
|
||||||
|
|
||||||
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
|
|
||||||
&mesaWidth, &mesaHeight,
|
|
||||||
&mesaBytes, &mesaBuffer))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"OSMesa: Failed to retrieve depth buffer");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (width)
|
|
||||||
*width = mesaWidth;
|
|
||||||
if (height)
|
|
||||||
*height = mesaHeight;
|
|
||||||
if (bytesPerValue)
|
|
||||||
*bytesPerValue = mesaBytes;
|
|
||||||
if (buffer)
|
|
||||||
*buffer = mesaBuffer;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window->context.osmesa.handle;
|
|
||||||
}
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 OSMesa - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2016 Google Inc.
|
|
||||||
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#define OSMESA_RGBA 0x1908
|
|
||||||
#define OSMESA_FORMAT 0x22
|
|
||||||
#define OSMESA_DEPTH_BITS 0x30
|
|
||||||
#define OSMESA_STENCIL_BITS 0x31
|
|
||||||
#define OSMESA_ACCUM_BITS 0x32
|
|
||||||
#define OSMESA_PROFILE 0x33
|
|
||||||
#define OSMESA_CORE_PROFILE 0x34
|
|
||||||
#define OSMESA_COMPAT_PROFILE 0x35
|
|
||||||
#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
|
|
||||||
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
|
|
||||||
|
|
||||||
typedef void* OSMesaContext;
|
|
||||||
typedef void (*OSMESAproc)(void);
|
|
||||||
|
|
||||||
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
|
|
||||||
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
|
|
||||||
typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext);
|
|
||||||
typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int);
|
|
||||||
typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**);
|
|
||||||
typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**);
|
|
||||||
typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
|
|
||||||
#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
|
|
||||||
#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
|
|
||||||
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
|
|
||||||
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
|
|
||||||
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
|
|
||||||
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
|
||||||
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
|
||||||
|
|
||||||
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
|
||||||
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
|
||||||
|
|
||||||
|
|
||||||
// OSMesa-specific per-context data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWcontextOSMesa
|
|
||||||
{
|
|
||||||
OSMesaContext handle;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
void* buffer;
|
|
||||||
} _GLFWcontextOSMesa;
|
|
||||||
|
|
||||||
// OSMesa-specific global data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWlibraryOSMesa
|
|
||||||
{
|
|
||||||
void* handle;
|
|
||||||
|
|
||||||
PFN_OSMesaCreateContextExt CreateContextExt;
|
|
||||||
PFN_OSMesaCreateContextAttribs CreateContextAttribs;
|
|
||||||
PFN_OSMesaDestroyContext DestroyContext;
|
|
||||||
PFN_OSMesaMakeCurrent MakeCurrent;
|
|
||||||
PFN_OSMesaGetColorBuffer GetColorBuffer;
|
|
||||||
PFN_OSMesaGetDepthBuffer GetDepthBuffer;
|
|
||||||
PFN_OSMesaGetProcAddress GetProcAddress;
|
|
||||||
} _GLFWlibraryOSMesa;
|
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitOSMesa(void);
|
|
||||||
void _glfwTerminateOSMesa(void);
|
|
||||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig);
|
|
||||||
|
|
@ -1,332 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define _GLFW_FIND_LOADER 1
|
|
||||||
#define _GLFW_REQUIRE_LOADER 2
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWbool _glfwInitVulkan(int mode)
|
|
||||||
{
|
|
||||||
VkResult err;
|
|
||||||
VkExtensionProperties* ep;
|
|
||||||
uint32_t i, count;
|
|
||||||
|
|
||||||
if (_glfw.vk.available)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
#if !defined(_GLFW_VULKAN_STATIC)
|
|
||||||
#if defined(_GLFW_VULKAN_LIBRARY)
|
|
||||||
_glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
|
|
||||||
#elif defined(_GLFW_WIN32)
|
|
||||||
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
|
||||||
if (!_glfw.vk.handle)
|
|
||||||
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
|
||||||
#else
|
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
|
||||||
#endif
|
|
||||||
if (!_glfw.vk.handle)
|
|
||||||
{
|
|
||||||
if (mode == _GLFW_REQUIRE_LOADER)
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
|
||||||
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
|
||||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
|
||||||
if (!_glfw.vk.GetInstanceProcAddr)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
|
|
||||||
vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
|
|
||||||
if (!_glfw.vk.EnumerateInstanceExtensionProperties)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
|
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
#endif // _GLFW_VULKAN_STATIC
|
|
||||||
|
|
||||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
// NOTE: This happens on systems with a loader but without any Vulkan ICD
|
|
||||||
if (mode == _GLFW_REQUIRE_LOADER)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"Vulkan: Failed to query instance extension count: %s",
|
|
||||||
_glfwGetVulkanResultString(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ep = calloc(count, sizeof(VkExtensionProperties));
|
|
||||||
|
|
||||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"Vulkan: Failed to query instance extensions: %s",
|
|
||||||
_glfwGetVulkanResultString(err));
|
|
||||||
|
|
||||||
free(ep);
|
|
||||||
_glfwTerminateVulkan();
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
|
|
||||||
_glfw.vk.KHR_surface = GLFW_TRUE;
|
|
||||||
#if defined(_GLFW_WIN32)
|
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
|
||||||
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
|
||||||
#elif defined(_GLFW_COCOA)
|
|
||||||
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
|
||||||
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
|
|
||||||
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
|
|
||||||
_glfw.vk.EXT_metal_surface = GLFW_TRUE;
|
|
||||||
#elif defined(_GLFW_X11)
|
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
|
||||||
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
|
|
||||||
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
|
|
||||||
#elif defined(_GLFW_WAYLAND)
|
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
|
||||||
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ep);
|
|
||||||
|
|
||||||
_glfw.vk.available = GLFW_TRUE;
|
|
||||||
|
|
||||||
_glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwTerminateVulkan(void)
|
|
||||||
{
|
|
||||||
#if !defined(_GLFW_VULKAN_STATIC)
|
|
||||||
if (_glfw.vk.handle)
|
|
||||||
_glfw_dlclose(_glfw.vk.handle);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* _glfwGetVulkanResultString(VkResult result)
|
|
||||||
{
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
case VK_SUCCESS:
|
|
||||||
return "Success";
|
|
||||||
case VK_NOT_READY:
|
|
||||||
return "A fence or query has not yet completed";
|
|
||||||
case VK_TIMEOUT:
|
|
||||||
return "A wait operation has not completed in the specified time";
|
|
||||||
case VK_EVENT_SET:
|
|
||||||
return "An event is signaled";
|
|
||||||
case VK_EVENT_RESET:
|
|
||||||
return "An event is unsignaled";
|
|
||||||
case VK_INCOMPLETE:
|
|
||||||
return "A return array was too small for the result";
|
|
||||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
|
||||||
return "A host memory allocation has failed";
|
|
||||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
|
||||||
return "A device memory allocation has failed";
|
|
||||||
case VK_ERROR_INITIALIZATION_FAILED:
|
|
||||||
return "Initialization of an object could not be completed for implementation-specific reasons";
|
|
||||||
case VK_ERROR_DEVICE_LOST:
|
|
||||||
return "The logical or physical device has been lost";
|
|
||||||
case VK_ERROR_MEMORY_MAP_FAILED:
|
|
||||||
return "Mapping of a memory object has failed";
|
|
||||||
case VK_ERROR_LAYER_NOT_PRESENT:
|
|
||||||
return "A requested layer is not present or could not be loaded";
|
|
||||||
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
|
||||||
return "A requested extension is not supported";
|
|
||||||
case VK_ERROR_FEATURE_NOT_PRESENT:
|
|
||||||
return "A requested feature is not supported";
|
|
||||||
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
|
||||||
return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
|
|
||||||
case VK_ERROR_TOO_MANY_OBJECTS:
|
|
||||||
return "Too many objects of the type have already been created";
|
|
||||||
case VK_ERROR_FORMAT_NOT_SUPPORTED:
|
|
||||||
return "A requested format is not supported on this device";
|
|
||||||
case VK_ERROR_SURFACE_LOST_KHR:
|
|
||||||
return "A surface is no longer available";
|
|
||||||
case VK_SUBOPTIMAL_KHR:
|
|
||||||
return "A swapchain no longer matches the surface properties exactly, but can still be used";
|
|
||||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
|
||||||
return "A surface has changed in such a way that it is no longer compatible with the swapchain";
|
|
||||||
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
|
|
||||||
return "The display used by a swapchain does not use the same presentable image layout";
|
|
||||||
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
|
|
||||||
return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
|
|
||||||
case VK_ERROR_VALIDATION_FAILED_EXT:
|
|
||||||
return "A validation layer found an error";
|
|
||||||
default:
|
|
||||||
return "ERROR: UNKNOWN VULKAN ERROR";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW public API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI int glfwVulkanSupported(void)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
|
||||||
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
|
||||||
{
|
|
||||||
assert(count != NULL);
|
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!_glfw.vk.extensions[0])
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = 2;
|
|
||||||
return (const char**) _glfw.vk.extensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
|
||||||
const char* procname)
|
|
||||||
{
|
|
||||||
GLFWvkproc proc;
|
|
||||||
assert(procname != NULL);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
|
||||||
#if defined(_GLFW_VULKAN_STATIC)
|
|
||||||
if (!proc)
|
|
||||||
{
|
|
||||||
if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
|
|
||||||
return (GLFWvkproc) vkGetInstanceProcAddr;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (!proc)
|
|
||||||
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|
||||||
VkPhysicalDevice device,
|
|
||||||
uint32_t queuefamily)
|
|
||||||
{
|
|
||||||
assert(instance != VK_NULL_HANDLE);
|
|
||||||
assert(device != VK_NULL_HANDLE);
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
|
||||||
|
|
||||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!_glfw.vk.extensions[0])
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"Vulkan: Window surface creation extensions not found");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
|
|
||||||
device,
|
|
||||||
queuefamily);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
|
||||||
GLFWwindow* handle,
|
|
||||||
const VkAllocationCallbacks* allocator,
|
|
||||||
VkSurfaceKHR* surface)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
assert(instance != VK_NULL_HANDLE);
|
|
||||||
assert(window != NULL);
|
|
||||||
assert(surface != NULL);
|
|
||||||
|
|
||||||
*surface = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
|
||||||
|
|
||||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
|
||||||
return VK_ERROR_INITIALIZATION_FAILED;
|
|
||||||
|
|
||||||
if (!_glfw.vk.extensions[0])
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"Vulkan: Window surface creation extensions not found");
|
|
||||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->context.client != GLFW_NO_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
|
|
||||||
return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
|
|
||||||
}
|
|
||||||
|
|
@ -1,798 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 WGL - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
// Return the value corresponding to the specified attribute
|
|
||||||
//
|
|
||||||
static int findPixelFormatAttribValue(const int* attribs,
|
|
||||||
int attribCount,
|
|
||||||
const int* values,
|
|
||||||
int attrib)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < attribCount; i++)
|
|
||||||
{
|
|
||||||
if (attribs[i] == attrib)
|
|
||||||
return values[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Unknown pixel format attribute requested");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define addAttrib(a) \
|
|
||||||
{ \
|
|
||||||
assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
|
|
||||||
attribs[attribCount++] = a; \
|
|
||||||
}
|
|
||||||
#define findAttribValue(a) \
|
|
||||||
findPixelFormatAttribValue(attribs, attribCount, values, a)
|
|
||||||
|
|
||||||
// Return a list of available and usable framebuffer configs
|
|
||||||
//
|
|
||||||
static int choosePixelFormat(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig)
|
|
||||||
{
|
|
||||||
_GLFWfbconfig* usableConfigs;
|
|
||||||
const _GLFWfbconfig* closest;
|
|
||||||
int i, pixelFormat, nativeCount, usableCount = 0, attribCount = 0;
|
|
||||||
int attribs[40];
|
|
||||||
int values[sizeof(attribs) / sizeof(attribs[0])];
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_pixel_format)
|
|
||||||
{
|
|
||||||
const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
|
|
||||||
|
|
||||||
if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
|
|
||||||
1, 0, 1, &attrib, &nativeCount))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to retrieve pixel format attribute");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
addAttrib(WGL_SUPPORT_OPENGL_ARB);
|
|
||||||
addAttrib(WGL_DRAW_TO_WINDOW_ARB);
|
|
||||||
addAttrib(WGL_PIXEL_TYPE_ARB);
|
|
||||||
addAttrib(WGL_ACCELERATION_ARB);
|
|
||||||
addAttrib(WGL_RED_BITS_ARB);
|
|
||||||
addAttrib(WGL_RED_SHIFT_ARB);
|
|
||||||
addAttrib(WGL_GREEN_BITS_ARB);
|
|
||||||
addAttrib(WGL_GREEN_SHIFT_ARB);
|
|
||||||
addAttrib(WGL_BLUE_BITS_ARB);
|
|
||||||
addAttrib(WGL_BLUE_SHIFT_ARB);
|
|
||||||
addAttrib(WGL_ALPHA_BITS_ARB);
|
|
||||||
addAttrib(WGL_ALPHA_SHIFT_ARB);
|
|
||||||
addAttrib(WGL_DEPTH_BITS_ARB);
|
|
||||||
addAttrib(WGL_STENCIL_BITS_ARB);
|
|
||||||
addAttrib(WGL_ACCUM_BITS_ARB);
|
|
||||||
addAttrib(WGL_ACCUM_RED_BITS_ARB);
|
|
||||||
addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
|
|
||||||
addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
|
|
||||||
addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
|
|
||||||
addAttrib(WGL_AUX_BUFFERS_ARB);
|
|
||||||
addAttrib(WGL_STEREO_ARB);
|
|
||||||
addAttrib(WGL_DOUBLE_BUFFER_ARB);
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_multisample)
|
|
||||||
addAttrib(WGL_SAMPLES_ARB);
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
|
|
||||||
addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.EXT_colorspace)
|
|
||||||
addAttrib(WGL_COLORSPACE_EXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nativeCount = DescribePixelFormat(window->context.wgl.dc,
|
|
||||||
1,
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
|
||||||
|
|
||||||
for (i = 0; i < nativeCount; i++)
|
|
||||||
{
|
|
||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
|
||||||
pixelFormat = i + 1;
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_pixel_format)
|
|
||||||
{
|
|
||||||
// Get pixel format attributes through "modern" extension
|
|
||||||
|
|
||||||
if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
|
|
||||||
pixelFormat, 0,
|
|
||||||
attribCount,
|
|
||||||
attribs, values))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to retrieve pixel format attributes");
|
|
||||||
|
|
||||||
free(usableConfigs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
|
|
||||||
!findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (findAttribValue(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
u->redBits = findAttribValue(WGL_RED_BITS_ARB);
|
|
||||||
u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
|
|
||||||
u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
|
|
||||||
u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
|
|
||||||
|
|
||||||
u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
|
|
||||||
u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
|
|
||||||
|
|
||||||
u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
|
|
||||||
u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
|
|
||||||
u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
|
|
||||||
u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
|
|
||||||
|
|
||||||
u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
|
|
||||||
|
|
||||||
if (findAttribValue(WGL_STEREO_ARB))
|
|
||||||
u->stereo = GLFW_TRUE;
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_multisample)
|
|
||||||
u->samples = findAttribValue(WGL_SAMPLES_ARB);
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
|
||||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
|
||||||
{
|
|
||||||
if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
|
||||||
u->sRGB = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.EXT_colorspace)
|
|
||||||
{
|
|
||||||
if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
|
|
||||||
u->sRGB = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get pixel format attributes through legacy PFDs
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
|
||||||
|
|
||||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
|
||||||
pixelFormat,
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
|
||||||
&pfd))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to describe pixel format");
|
|
||||||
|
|
||||||
free(usableConfigs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
|
|
||||||
!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
|
|
||||||
(pfd.dwFlags & PFD_GENERIC_FORMAT))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd.iPixelType != PFD_TYPE_RGBA)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!!(pfd.dwFlags & PFD_DOUBLEBUFFER) != fbconfig->doublebuffer)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
u->redBits = pfd.cRedBits;
|
|
||||||
u->greenBits = pfd.cGreenBits;
|
|
||||||
u->blueBits = pfd.cBlueBits;
|
|
||||||
u->alphaBits = pfd.cAlphaBits;
|
|
||||||
|
|
||||||
u->depthBits = pfd.cDepthBits;
|
|
||||||
u->stencilBits = pfd.cStencilBits;
|
|
||||||
|
|
||||||
u->accumRedBits = pfd.cAccumRedBits;
|
|
||||||
u->accumGreenBits = pfd.cAccumGreenBits;
|
|
||||||
u->accumBlueBits = pfd.cAccumBlueBits;
|
|
||||||
u->accumAlphaBits = pfd.cAccumAlphaBits;
|
|
||||||
|
|
||||||
u->auxBuffers = pfd.cAuxBuffers;
|
|
||||||
|
|
||||||
if (pfd.dwFlags & PFD_STEREO)
|
|
||||||
u->stereo = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
u->handle = pixelFormat;
|
|
||||||
usableCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usableCount)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"WGL: The driver does not appear to support OpenGL");
|
|
||||||
|
|
||||||
free(usableConfigs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
|
|
||||||
if (!closest)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
|
||||||
"WGL: Failed to find a suitable pixel format");
|
|
||||||
|
|
||||||
free(usableConfigs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixelFormat = (int) closest->handle;
|
|
||||||
free(usableConfigs);
|
|
||||||
|
|
||||||
return pixelFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef addAttrib
|
|
||||||
#undef findAttribValue
|
|
||||||
|
|
||||||
static void makeContextCurrentWGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window)
|
|
||||||
{
|
|
||||||
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to make context current");
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!wglMakeCurrent(NULL, NULL))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to clear current context");
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapBuffersWGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (!window->monitor)
|
|
||||||
{
|
|
||||||
if (IsWindowsVistaOrGreater())
|
|
||||||
{
|
|
||||||
// DWM Composition is always enabled on Win8+
|
|
||||||
BOOL enabled = IsWindows8OrGreater();
|
|
||||||
|
|
||||||
// HACK: Use DwmFlush when desktop composition is enabled
|
|
||||||
if (enabled ||
|
|
||||||
(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
|
|
||||||
{
|
|
||||||
int count = abs(window->context.wgl.interval);
|
|
||||||
while (count--)
|
|
||||||
DwmFlush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapBuffers(window->context.wgl.dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapIntervalWGL(int interval)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
|
|
||||||
window->context.wgl.interval = interval;
|
|
||||||
|
|
||||||
if (!window->monitor)
|
|
||||||
{
|
|
||||||
if (IsWindowsVistaOrGreater())
|
|
||||||
{
|
|
||||||
// DWM Composition is always enabled on Win8+
|
|
||||||
BOOL enabled = IsWindows8OrGreater();
|
|
||||||
|
|
||||||
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
|
||||||
// avoid interfering with DWM vsync
|
|
||||||
if (enabled ||
|
|
||||||
(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
|
|
||||||
interval = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wgl.EXT_swap_control)
|
|
||||||
wglSwapIntervalEXT(interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int extensionSupportedWGL(const char* extension)
|
|
||||||
{
|
|
||||||
const char* extensions = NULL;
|
|
||||||
|
|
||||||
if (_glfw.wgl.GetExtensionsStringARB)
|
|
||||||
extensions = wglGetExtensionsStringARB(wglGetCurrentDC());
|
|
||||||
else if (_glfw.wgl.GetExtensionsStringEXT)
|
|
||||||
extensions = wglGetExtensionsStringEXT();
|
|
||||||
|
|
||||||
if (!extensions)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
return _glfwStringInExtensionString(extension, extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLFWglproc getProcAddressWGL(const char* procname)
|
|
||||||
{
|
|
||||||
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
|
|
||||||
if (proc)
|
|
||||||
return proc;
|
|
||||||
|
|
||||||
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroyContextWGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window->context.wgl.handle)
|
|
||||||
{
|
|
||||||
wglDeleteContext(window->context.wgl.handle);
|
|
||||||
window->context.wgl.handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialize WGL
|
|
||||||
//
|
|
||||||
GLFWbool _glfwInitWGL(void)
|
|
||||||
{
|
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
|
||||||
HGLRC prc, rc;
|
|
||||||
HDC pdc, dc;
|
|
||||||
|
|
||||||
if (_glfw.wgl.instance)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
|
||||||
if (!_glfw.wgl.instance)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to load opengl32.dll");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
|
|
||||||
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
|
|
||||||
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
|
|
||||||
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
|
|
||||||
_glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
|
|
||||||
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
|
|
||||||
_glfw.wgl.ShareLists = (PFN_wglShareLists)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
|
|
||||||
|
|
||||||
// NOTE: A dummy context has to be created for opengl32.dll to load the
|
|
||||||
// OpenGL ICD, from which we can then query WGL extensions
|
|
||||||
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
|
||||||
// creation failure occurs during manual pixel format enumeration
|
|
||||||
|
|
||||||
dc = GetDC(_glfw.win32.helperWindowHandle);
|
|
||||||
|
|
||||||
ZeroMemory(&pfd, sizeof(pfd));
|
|
||||||
pfd.nSize = sizeof(pfd);
|
|
||||||
pfd.nVersion = 1;
|
|
||||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
|
||||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
|
||||||
pfd.cColorBits = 24;
|
|
||||||
|
|
||||||
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to set pixel format for dummy context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = wglCreateContext(dc);
|
|
||||||
if (!rc)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to create dummy context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdc = wglGetCurrentDC();
|
|
||||||
prc = wglGetCurrentContext();
|
|
||||||
|
|
||||||
if (!wglMakeCurrent(dc, rc))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to make dummy context current");
|
|
||||||
wglMakeCurrent(pdc, prc);
|
|
||||||
wglDeleteContext(rc);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
|
||||||
// extension string that tells us whether the functions are supported
|
|
||||||
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
|
|
||||||
wglGetProcAddress("wglGetExtensionsStringEXT");
|
|
||||||
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
|
|
||||||
wglGetProcAddress("wglGetExtensionsStringARB");
|
|
||||||
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
|
|
||||||
wglGetProcAddress("wglCreateContextAttribsARB");
|
|
||||||
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
|
|
||||||
wglGetProcAddress("wglSwapIntervalEXT");
|
|
||||||
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
|
|
||||||
wglGetProcAddress("wglGetPixelFormatAttribivARB");
|
|
||||||
|
|
||||||
// NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
|
|
||||||
// checked below as we are already using them
|
|
||||||
_glfw.wgl.ARB_multisample =
|
|
||||||
extensionSupportedWGL("WGL_ARB_multisample");
|
|
||||||
_glfw.wgl.ARB_framebuffer_sRGB =
|
|
||||||
extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
|
|
||||||
_glfw.wgl.EXT_framebuffer_sRGB =
|
|
||||||
extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
|
|
||||||
_glfw.wgl.ARB_create_context =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context");
|
|
||||||
_glfw.wgl.ARB_create_context_profile =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context_profile");
|
|
||||||
_glfw.wgl.EXT_create_context_es2_profile =
|
|
||||||
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
|
|
||||||
_glfw.wgl.ARB_create_context_robustness =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context_robustness");
|
|
||||||
_glfw.wgl.ARB_create_context_no_error =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context_no_error");
|
|
||||||
_glfw.wgl.EXT_swap_control =
|
|
||||||
extensionSupportedWGL("WGL_EXT_swap_control");
|
|
||||||
_glfw.wgl.EXT_colorspace =
|
|
||||||
extensionSupportedWGL("WGL_EXT_colorspace");
|
|
||||||
_glfw.wgl.ARB_pixel_format =
|
|
||||||
extensionSupportedWGL("WGL_ARB_pixel_format");
|
|
||||||
_glfw.wgl.ARB_context_flush_control =
|
|
||||||
extensionSupportedWGL("WGL_ARB_context_flush_control");
|
|
||||||
|
|
||||||
wglMakeCurrent(pdc, prc);
|
|
||||||
wglDeleteContext(rc);
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminate WGL
|
|
||||||
//
|
|
||||||
void _glfwTerminateWGL(void)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.instance)
|
|
||||||
FreeLibrary(_glfw.wgl.instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setAttrib(a, v) \
|
|
||||||
{ \
|
|
||||||
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
|
||||||
attribs[index++] = a; \
|
|
||||||
attribs[index++] = v; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
|
||||||
//
|
|
||||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig)
|
|
||||||
{
|
|
||||||
int attribs[40];
|
|
||||||
int pixelFormat;
|
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
|
||||||
HGLRC share = NULL;
|
|
||||||
|
|
||||||
if (ctxconfig->share)
|
|
||||||
share = ctxconfig->share->context.wgl.handle;
|
|
||||||
|
|
||||||
window->context.wgl.dc = GetDC(window->win32.handle);
|
|
||||||
if (!window->context.wgl.dc)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to retrieve DC for window");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
|
||||||
if (!pixelFormat)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
|
||||||
pixelFormat, sizeof(pfd), &pfd))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to set selected pixel format");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->forward)
|
|
||||||
{
|
|
||||||
if (!_glfw.wgl.ARB_create_context)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->profile)
|
|
||||||
{
|
|
||||||
if (!_glfw.wgl.ARB_create_context_profile)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!_glfw.wgl.ARB_create_context ||
|
|
||||||
!_glfw.wgl.ARB_create_context_profile ||
|
|
||||||
!_glfw.wgl.EXT_create_context_es2_profile)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_create_context)
|
|
||||||
{
|
|
||||||
int index = 0, mask = 0, flags = 0;
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->forward)
|
|
||||||
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
|
||||||
|
|
||||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
|
||||||
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
|
||||||
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
|
|
||||||
|
|
||||||
if (ctxconfig->debug)
|
|
||||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
|
||||||
|
|
||||||
if (ctxconfig->robustness)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_create_context_robustness)
|
|
||||||
{
|
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
|
||||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
|
||||||
}
|
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
|
||||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
|
||||||
}
|
|
||||||
|
|
||||||
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->release)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_context_flush_control)
|
|
||||||
{
|
|
||||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
|
||||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
|
||||||
}
|
|
||||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
|
||||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->noerror)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_create_context_no_error)
|
|
||||||
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
|
||||||
// explicitly requesting version 1.0 does not always return the
|
|
||||||
// highest version supported by the driver
|
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
|
||||||
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags)
|
|
||||||
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
|
||||||
|
|
||||||
if (mask)
|
|
||||||
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
|
||||||
|
|
||||||
setAttrib(0, 0);
|
|
||||||
|
|
||||||
window->context.wgl.handle =
|
|
||||||
wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
|
|
||||||
if (!window->context.wgl.handle)
|
|
||||||
{
|
|
||||||
const DWORD error = GetLastError();
|
|
||||||
|
|
||||||
if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
|
|
||||||
{
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Driver does not support OpenGL version %i.%i",
|
|
||||||
ctxconfig->major,
|
|
||||||
ctxconfig->minor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Driver does not support OpenGL ES version %i.%i",
|
|
||||||
ctxconfig->major,
|
|
||||||
ctxconfig->minor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Driver does not support the requested OpenGL profile");
|
|
||||||
}
|
|
||||||
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"WGL: The share context is not compatible with the requested context");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Failed to create OpenGL context");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Failed to create OpenGL ES context");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
|
|
||||||
if (!window->context.wgl.handle)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Failed to create OpenGL context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (share)
|
|
||||||
{
|
|
||||||
if (!wglShareLists(share, window->context.wgl.handle))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentWGL;
|
|
||||||
window->context.swapBuffers = swapBuffersWGL;
|
|
||||||
window->context.swapInterval = swapIntervalWGL;
|
|
||||||
window->context.extensionSupported = extensionSupportedWGL;
|
|
||||||
window->context.getProcAddress = getProcAddressWGL;
|
|
||||||
window->context.destroy = destroyContextWGL;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef setAttrib
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW native API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
if (window->context.source != GLFW_NATIVE_CONTEXT_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window->context.wgl.handle;
|
|
||||||
}
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 WGL - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
|
||||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
|
||||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
|
||||||
#define WGL_PIXEL_TYPE_ARB 0x2013
|
|
||||||
#define WGL_TYPE_RGBA_ARB 0x202b
|
|
||||||
#define WGL_ACCELERATION_ARB 0x2003
|
|
||||||
#define WGL_NO_ACCELERATION_ARB 0x2025
|
|
||||||
#define WGL_RED_BITS_ARB 0x2015
|
|
||||||
#define WGL_RED_SHIFT_ARB 0x2016
|
|
||||||
#define WGL_GREEN_BITS_ARB 0x2017
|
|
||||||
#define WGL_GREEN_SHIFT_ARB 0x2018
|
|
||||||
#define WGL_BLUE_BITS_ARB 0x2019
|
|
||||||
#define WGL_BLUE_SHIFT_ARB 0x201a
|
|
||||||
#define WGL_ALPHA_BITS_ARB 0x201b
|
|
||||||
#define WGL_ALPHA_SHIFT_ARB 0x201c
|
|
||||||
#define WGL_ACCUM_BITS_ARB 0x201d
|
|
||||||
#define WGL_ACCUM_RED_BITS_ARB 0x201e
|
|
||||||
#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
|
|
||||||
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
|
|
||||||
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
|
|
||||||
#define WGL_DEPTH_BITS_ARB 0x2022
|
|
||||||
#define WGL_STENCIL_BITS_ARB 0x2023
|
|
||||||
#define WGL_AUX_BUFFERS_ARB 0x2024
|
|
||||||
#define WGL_STEREO_ARB 0x2012
|
|
||||||
#define WGL_DOUBLE_BUFFER_ARB 0x2011
|
|
||||||
#define WGL_SAMPLES_ARB 0x2042
|
|
||||||
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
|
|
||||||
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
|
|
||||||
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
|
|
||||||
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
|
|
||||||
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
|
||||||
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
|
||||||
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
|
||||||
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
|
||||||
#define WGL_CONTEXT_FLAGS_ARB 0x2094
|
|
||||||
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
|
|
||||||
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
|
|
||||||
#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
|
||||||
#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
|
||||||
#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
|
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
|
||||||
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
|
||||||
#define WGL_COLORSPACE_EXT 0x309d
|
|
||||||
#define WGL_COLORSPACE_SRGB_EXT 0x3089
|
|
||||||
|
|
||||||
#define ERROR_INVALID_VERSION_ARB 0x2095
|
|
||||||
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
|
||||||
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
|
|
||||||
|
|
||||||
// WGL extension pointer typedefs
|
|
||||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
|
||||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
|
||||||
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
|
|
||||||
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
|
|
||||||
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
|
|
||||||
#define wglSwapIntervalEXT _glfw.wgl.SwapIntervalEXT
|
|
||||||
#define wglGetPixelFormatAttribivARB _glfw.wgl.GetPixelFormatAttribivARB
|
|
||||||
#define wglGetExtensionsStringEXT _glfw.wgl.GetExtensionsStringEXT
|
|
||||||
#define wglGetExtensionsStringARB _glfw.wgl.GetExtensionsStringARB
|
|
||||||
#define wglCreateContextAttribsARB _glfw.wgl.CreateContextAttribsARB
|
|
||||||
|
|
||||||
// opengl32.dll function pointer typedefs
|
|
||||||
typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
|
|
||||||
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
|
|
||||||
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
|
|
||||||
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
|
|
||||||
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
|
|
||||||
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
|
|
||||||
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
|
||||||
#define wglCreateContext _glfw.wgl.CreateContext
|
|
||||||
#define wglDeleteContext _glfw.wgl.DeleteContext
|
|
||||||
#define wglGetProcAddress _glfw.wgl.GetProcAddress
|
|
||||||
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
|
|
||||||
#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
|
|
||||||
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
|
||||||
#define wglShareLists _glfw.wgl.ShareLists
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
|
|
||||||
|
|
||||||
|
|
||||||
// WGL-specific per-context data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWcontextWGL
|
|
||||||
{
|
|
||||||
HDC dc;
|
|
||||||
HGLRC handle;
|
|
||||||
int interval;
|
|
||||||
} _GLFWcontextWGL;
|
|
||||||
|
|
||||||
// WGL-specific global data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWlibraryWGL
|
|
||||||
{
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_wglCreateContext CreateContext;
|
|
||||||
PFN_wglDeleteContext DeleteContext;
|
|
||||||
PFN_wglGetProcAddress GetProcAddress;
|
|
||||||
PFN_wglGetCurrentDC GetCurrentDC;
|
|
||||||
PFN_wglGetCurrentContext GetCurrentContext;
|
|
||||||
PFN_wglMakeCurrent MakeCurrent;
|
|
||||||
PFN_wglShareLists ShareLists;
|
|
||||||
|
|
||||||
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
|
||||||
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
|
|
||||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
|
||||||
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
|
||||||
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
|
||||||
GLFWbool EXT_swap_control;
|
|
||||||
GLFWbool EXT_colorspace;
|
|
||||||
GLFWbool ARB_multisample;
|
|
||||||
GLFWbool ARB_framebuffer_sRGB;
|
|
||||||
GLFWbool EXT_framebuffer_sRGB;
|
|
||||||
GLFWbool ARB_pixel_format;
|
|
||||||
GLFWbool ARB_create_context;
|
|
||||||
GLFWbool ARB_create_context_profile;
|
|
||||||
GLFWbool EXT_create_context_es2_profile;
|
|
||||||
GLFWbool ARB_create_context_robustness;
|
|
||||||
GLFWbool ARB_create_context_no_error;
|
|
||||||
GLFWbool ARB_context_flush_control;
|
|
||||||
} _GLFWlibraryWGL;
|
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitWGL(void);
|
|
||||||
void _glfwTerminateWGL(void);
|
|
||||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig);
|
|
||||||
|
|
@ -1,623 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
static const GUID _glfw_GUID_DEVINTERFACE_HID =
|
|
||||||
{0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
|
|
||||||
|
|
||||||
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
|
||||||
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
|
||||||
#pragma message("These symbols must be exported by the executable and have no effect in a DLL")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Executables (but not DLLs) exporting this symbol with this value will be
|
|
||||||
// automatically directed to the high-performance GPU on Nvidia Optimus systems
|
|
||||||
// with up-to-date drivers
|
|
||||||
//
|
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
|
||||||
|
|
||||||
// Executables (but not DLLs) exporting this symbol with this value will be
|
|
||||||
// automatically directed to the high-performance GPU on AMD PowerXpress systems
|
|
||||||
// with up-to-date drivers
|
|
||||||
//
|
|
||||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
|
||||||
|
|
||||||
#endif // _GLFW_USE_HYBRID_HPG
|
|
||||||
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
|
||||||
|
|
||||||
// GLFW DLL entry point
|
|
||||||
//
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _GLFW_BUILD_DLL
|
|
||||||
|
|
||||||
// Load necessary libraries (DLLs)
|
|
||||||
//
|
|
||||||
static GLFWbool loadLibraries(void)
|
|
||||||
{
|
|
||||||
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
|
||||||
if (!_glfw.win32.user32.instance)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to load user32.dll");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
|
|
||||||
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
|
||||||
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
|
|
||||||
_glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
|
|
||||||
_glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
|
|
||||||
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
|
||||||
|
|
||||||
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
|
||||||
if (_glfw.win32.dinput8.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
|
|
||||||
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char* names[] =
|
|
||||||
{
|
|
||||||
"xinput1_4.dll",
|
|
||||||
"xinput1_3.dll",
|
|
||||||
"xinput9_1_0.dll",
|
|
||||||
"xinput1_2.dll",
|
|
||||||
"xinput1_1.dll",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; names[i]; i++)
|
|
||||||
{
|
|
||||||
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
|
||||||
if (_glfw.win32.xinput.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
|
|
||||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
|
|
||||||
_glfw.win32.xinput.GetState = (PFN_XInputGetState)
|
|
||||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
|
||||||
if (_glfw.win32.dwmapi.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
|
||||||
_glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
|
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
|
||||||
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
|
||||||
_glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)
|
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
|
||||||
if (_glfw.win32.shcore.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
|
|
||||||
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
|
||||||
_glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
|
|
||||||
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
|
|
||||||
if (_glfw.win32.ntdll.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
|
|
||||||
GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unload used libraries (DLLs)
|
|
||||||
//
|
|
||||||
static void freeLibraries(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.xinput.instance)
|
|
||||||
FreeLibrary(_glfw.win32.xinput.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.instance)
|
|
||||||
FreeLibrary(_glfw.win32.dinput8.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.user32.instance)
|
|
||||||
FreeLibrary(_glfw.win32.user32.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.dwmapi.instance)
|
|
||||||
FreeLibrary(_glfw.win32.dwmapi.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.shcore.instance)
|
|
||||||
FreeLibrary(_glfw.win32.shcore.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.ntdll.instance)
|
|
||||||
FreeLibrary(_glfw.win32.ntdll.instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create key code translation tables
|
|
||||||
//
|
|
||||||
static void createKeyTables(void)
|
|
||||||
{
|
|
||||||
int scancode;
|
|
||||||
|
|
||||||
memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
|
|
||||||
memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
|
|
||||||
|
|
||||||
_glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
|
|
||||||
_glfw.win32.keycodes[0x002] = GLFW_KEY_1;
|
|
||||||
_glfw.win32.keycodes[0x003] = GLFW_KEY_2;
|
|
||||||
_glfw.win32.keycodes[0x004] = GLFW_KEY_3;
|
|
||||||
_glfw.win32.keycodes[0x005] = GLFW_KEY_4;
|
|
||||||
_glfw.win32.keycodes[0x006] = GLFW_KEY_5;
|
|
||||||
_glfw.win32.keycodes[0x007] = GLFW_KEY_6;
|
|
||||||
_glfw.win32.keycodes[0x008] = GLFW_KEY_7;
|
|
||||||
_glfw.win32.keycodes[0x009] = GLFW_KEY_8;
|
|
||||||
_glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
|
|
||||||
_glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
|
|
||||||
_glfw.win32.keycodes[0x030] = GLFW_KEY_B;
|
|
||||||
_glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
|
|
||||||
_glfw.win32.keycodes[0x020] = GLFW_KEY_D;
|
|
||||||
_glfw.win32.keycodes[0x012] = GLFW_KEY_E;
|
|
||||||
_glfw.win32.keycodes[0x021] = GLFW_KEY_F;
|
|
||||||
_glfw.win32.keycodes[0x022] = GLFW_KEY_G;
|
|
||||||
_glfw.win32.keycodes[0x023] = GLFW_KEY_H;
|
|
||||||
_glfw.win32.keycodes[0x017] = GLFW_KEY_I;
|
|
||||||
_glfw.win32.keycodes[0x024] = GLFW_KEY_J;
|
|
||||||
_glfw.win32.keycodes[0x025] = GLFW_KEY_K;
|
|
||||||
_glfw.win32.keycodes[0x026] = GLFW_KEY_L;
|
|
||||||
_glfw.win32.keycodes[0x032] = GLFW_KEY_M;
|
|
||||||
_glfw.win32.keycodes[0x031] = GLFW_KEY_N;
|
|
||||||
_glfw.win32.keycodes[0x018] = GLFW_KEY_O;
|
|
||||||
_glfw.win32.keycodes[0x019] = GLFW_KEY_P;
|
|
||||||
_glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
|
|
||||||
_glfw.win32.keycodes[0x013] = GLFW_KEY_R;
|
|
||||||
_glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
|
|
||||||
_glfw.win32.keycodes[0x014] = GLFW_KEY_T;
|
|
||||||
_glfw.win32.keycodes[0x016] = GLFW_KEY_U;
|
|
||||||
_glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
|
|
||||||
_glfw.win32.keycodes[0x011] = GLFW_KEY_W;
|
|
||||||
_glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
|
|
||||||
_glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
|
|
||||||
_glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
|
|
||||||
|
|
||||||
_glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
|
|
||||||
_glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
|
|
||||||
_glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
|
|
||||||
_glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
|
|
||||||
_glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
|
|
||||||
_glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
|
|
||||||
_glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
|
|
||||||
_glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
|
|
||||||
_glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
|
|
||||||
_glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
|
|
||||||
_glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
|
|
||||||
_glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
|
|
||||||
|
|
||||||
_glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
|
|
||||||
_glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
|
|
||||||
_glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
|
|
||||||
_glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
|
|
||||||
_glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
|
|
||||||
_glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
|
|
||||||
_glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
|
|
||||||
_glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
|
|
||||||
_glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
|
|
||||||
_glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
|
|
||||||
_glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
|
|
||||||
_glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
|
|
||||||
_glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
|
|
||||||
_glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
|
|
||||||
_glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
|
|
||||||
_glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
|
|
||||||
_glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
|
|
||||||
_glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
|
|
||||||
_glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
|
|
||||||
_glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
|
|
||||||
_glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
|
|
||||||
_glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
|
|
||||||
_glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
|
|
||||||
_glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
|
|
||||||
_glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
|
|
||||||
_glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
|
|
||||||
_glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
|
|
||||||
_glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
|
|
||||||
_glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
|
|
||||||
_glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
|
|
||||||
_glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
|
|
||||||
_glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
|
|
||||||
_glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
|
|
||||||
_glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
|
|
||||||
_glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
|
|
||||||
_glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
|
|
||||||
_glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
|
|
||||||
_glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
|
|
||||||
_glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
|
|
||||||
_glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
|
|
||||||
_glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
|
|
||||||
_glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
|
|
||||||
_glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
|
|
||||||
_glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
|
|
||||||
_glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
|
|
||||||
_glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
|
|
||||||
_glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
|
|
||||||
_glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
|
|
||||||
_glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
|
|
||||||
_glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
|
|
||||||
_glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
|
|
||||||
_glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
|
|
||||||
_glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
|
|
||||||
_glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
|
|
||||||
|
|
||||||
_glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
|
|
||||||
_glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
|
|
||||||
_glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
|
|
||||||
_glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
|
|
||||||
_glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
|
|
||||||
_glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
|
|
||||||
_glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
|
|
||||||
_glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
|
|
||||||
_glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
|
|
||||||
_glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
|
|
||||||
_glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
|
|
||||||
_glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
|
|
||||||
_glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
|
|
||||||
_glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
|
|
||||||
_glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
|
|
||||||
_glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
|
|
||||||
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
|
|
||||||
|
|
||||||
for (scancode = 0; scancode < 512; scancode++)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.keycodes[scancode] > 0)
|
|
||||||
_glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a dummy window for behind-the-scenes work
|
|
||||||
//
|
|
||||||
static GLFWbool createHelperWindow(void)
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
_glfw.win32.helperWindowHandle =
|
|
||||||
CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
|
||||||
_GLFW_WNDCLASSNAME,
|
|
||||||
L"GLFW message window",
|
|
||||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
|
||||||
0, 0, 1, 1,
|
|
||||||
NULL, NULL,
|
|
||||||
GetModuleHandleW(NULL),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!_glfw.win32.helperWindowHandle)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to create helper window");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: The command to the first ShowWindow call is ignored if the parent
|
|
||||||
// process passed along a STARTUPINFO, so clear that with a no-op call
|
|
||||||
ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
|
|
||||||
|
|
||||||
// Register for HID device notifications
|
|
||||||
{
|
|
||||||
DEV_BROADCAST_DEVICEINTERFACE_W dbi;
|
|
||||||
ZeroMemory(&dbi, sizeof(dbi));
|
|
||||||
dbi.dbcc_size = sizeof(dbi);
|
|
||||||
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
||||||
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
|
||||||
|
|
||||||
_glfw.win32.deviceNotificationHandle =
|
|
||||||
RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle,
|
|
||||||
(DEV_BROADCAST_HDR*) &dbi,
|
|
||||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessageW(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Returns a wide string version of the specified UTF-8 string
|
|
||||||
//
|
|
||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
|
||||||
{
|
|
||||||
WCHAR* target;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
|
||||||
if (!count)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string from UTF-8");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
target = calloc(count, sizeof(WCHAR));
|
|
||||||
|
|
||||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string from UTF-8");
|
|
||||||
free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a UTF-8 string version of the specified wide string
|
|
||||||
//
|
|
||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
|
||||||
{
|
|
||||||
char* target;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
|
||||||
if (!size)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string to UTF-8");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
target = calloc(size, 1);
|
|
||||||
|
|
||||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string to UTF-8");
|
|
||||||
free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reports the specified error, appending information about the last Win32 error
|
|
||||||
//
|
|
||||||
void _glfwInputErrorWin32(int error, const char* description)
|
|
||||||
{
|
|
||||||
WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
|
|
||||||
char message[_GLFW_MESSAGE_SIZE] = "";
|
|
||||||
|
|
||||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
|
||||||
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
|
||||||
NULL,
|
|
||||||
GetLastError() & 0xffff,
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
buffer,
|
|
||||||
sizeof(buffer) / sizeof(WCHAR),
|
|
||||||
NULL);
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
|
|
||||||
|
|
||||||
_glfwInputError(error, "%s: %s", description, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates key names according to the current keyboard layout
|
|
||||||
//
|
|
||||||
void _glfwUpdateKeyNamesWin32(void)
|
|
||||||
{
|
|
||||||
int key;
|
|
||||||
BYTE state[256] = {0};
|
|
||||||
|
|
||||||
memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
|
|
||||||
|
|
||||||
for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++)
|
|
||||||
{
|
|
||||||
UINT vk;
|
|
||||||
int scancode, length;
|
|
||||||
WCHAR chars[16];
|
|
||||||
|
|
||||||
scancode = _glfw.win32.scancodes[key];
|
|
||||||
if (scancode == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
|
|
||||||
{
|
|
||||||
const UINT vks[] = {
|
|
||||||
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
|
|
||||||
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
|
|
||||||
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
|
|
||||||
VK_MULTIPLY, VK_SUBTRACT, VK_ADD
|
|
||||||
};
|
|
||||||
|
|
||||||
vk = vks[key - GLFW_KEY_KP_0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
|
|
||||||
|
|
||||||
length = ToUnicode(vk, scancode, state,
|
|
||||||
chars, sizeof(chars) / sizeof(WCHAR),
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (length == -1)
|
|
||||||
{
|
|
||||||
length = ToUnicode(vk, scancode, state,
|
|
||||||
chars, sizeof(chars) / sizeof(WCHAR),
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length < 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, chars, 1,
|
|
||||||
_glfw.win32.keynames[key],
|
|
||||||
sizeof(_glfw.win32.keynames[key]),
|
|
||||||
NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
|
|
||||||
//
|
|
||||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
|
||||||
{
|
|
||||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
|
|
||||||
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
|
|
||||||
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
|
||||||
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
|
|
||||||
// latter lies unless the user knew to embed a non-default manifest
|
|
||||||
// announcing support for Windows 10 via supportedOS GUID
|
|
||||||
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks whether we are on at least the specified build of Windows 10
|
|
||||||
//
|
|
||||||
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
|
|
||||||
{
|
|
||||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
|
|
||||||
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
|
|
||||||
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
|
||||||
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
|
|
||||||
// latter lies unless the user knew to embed a non-default manifest
|
|
||||||
// announcing support for Windows 10 via supportedOS GUID
|
|
||||||
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int _glfwPlatformInit(void)
|
|
||||||
{
|
|
||||||
// To make SetForegroundWindow work as we want, we need to fiddle
|
|
||||||
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
|
||||||
// as possible in the hope of still being the foreground process)
|
|
||||||
SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
|
|
||||||
&_glfw.win32.foregroundLockTimeout, 0);
|
|
||||||
SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
|
|
||||||
SPIF_SENDCHANGE);
|
|
||||||
|
|
||||||
if (!loadLibraries())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
createKeyTables();
|
|
||||||
_glfwUpdateKeyNamesWin32();
|
|
||||||
|
|
||||||
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
|
|
||||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
|
||||||
else if (IsWindows8Point1OrGreater())
|
|
||||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
|
||||||
else if (IsWindowsVistaOrGreater())
|
|
||||||
SetProcessDPIAware();
|
|
||||||
|
|
||||||
if (!_glfwRegisterWindowClassWin32())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!createHelperWindow())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
_glfwInitTimerWin32();
|
|
||||||
_glfwInitJoysticksWin32();
|
|
||||||
|
|
||||||
_glfwPollMonitorsWin32();
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.deviceNotificationHandle)
|
|
||||||
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
|
||||||
|
|
||||||
if (_glfw.win32.helperWindowHandle)
|
|
||||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
|
||||||
|
|
||||||
_glfwUnregisterWindowClassWin32();
|
|
||||||
|
|
||||||
// Restore previous foreground lock timeout system setting
|
|
||||||
SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
|
|
||||||
UIntToPtr(_glfw.win32.foregroundLockTimeout),
|
|
||||||
SPIF_SENDCHANGE);
|
|
||||||
|
|
||||||
free(_glfw.win32.clipboardString);
|
|
||||||
free(_glfw.win32.rawInput);
|
|
||||||
|
|
||||||
_glfwTerminateWGL();
|
|
||||||
_glfwTerminateEGL();
|
|
||||||
|
|
||||||
_glfwTerminateJoysticksWin32();
|
|
||||||
|
|
||||||
freeLibraries();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
|
||||||
{
|
|
||||||
return _GLFW_VERSION_NUMBER " Win32 WGL EGL OSMesa"
|
|
||||||
#if defined(__MINGW32__)
|
|
||||||
" MinGW"
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
" VisualC"
|
|
||||||
#endif
|
|
||||||
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
|
||||||
" hybrid-GPU"
|
|
||||||
#endif
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
|
||||||
" DLL"
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
@ -1,755 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#define _GLFW_TYPE_AXIS 0
|
|
||||||
#define _GLFW_TYPE_SLIDER 1
|
|
||||||
#define _GLFW_TYPE_BUTTON 2
|
|
||||||
#define _GLFW_TYPE_POV 3
|
|
||||||
|
|
||||||
// Data produced with DirectInput device object enumeration
|
|
||||||
//
|
|
||||||
typedef struct _GLFWobjenumWin32
|
|
||||||
{
|
|
||||||
IDirectInputDevice8W* device;
|
|
||||||
_GLFWjoyobjectWin32* objects;
|
|
||||||
int objectCount;
|
|
||||||
int axisCount;
|
|
||||||
int sliderCount;
|
|
||||||
int buttonCount;
|
|
||||||
int povCount;
|
|
||||||
} _GLFWobjenumWin32;
|
|
||||||
|
|
||||||
// Define local copies of the necessary GUIDs
|
|
||||||
//
|
|
||||||
static const GUID _glfw_IID_IDirectInput8W =
|
|
||||||
{0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
|
|
||||||
static const GUID _glfw_GUID_XAxis =
|
|
||||||
{0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
static const GUID _glfw_GUID_YAxis =
|
|
||||||
{0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
static const GUID _glfw_GUID_ZAxis =
|
|
||||||
{0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
static const GUID _glfw_GUID_RxAxis =
|
|
||||||
{0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
static const GUID _glfw_GUID_RyAxis =
|
|
||||||
{0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
static const GUID _glfw_GUID_RzAxis =
|
|
||||||
{0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
static const GUID _glfw_GUID_Slider =
|
|
||||||
{0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
static const GUID _glfw_GUID_POV =
|
|
||||||
{0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
|
||||||
|
|
||||||
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
|
|
||||||
#define GUID_XAxis _glfw_GUID_XAxis
|
|
||||||
#define GUID_YAxis _glfw_GUID_YAxis
|
|
||||||
#define GUID_ZAxis _glfw_GUID_ZAxis
|
|
||||||
#define GUID_RxAxis _glfw_GUID_RxAxis
|
|
||||||
#define GUID_RyAxis _glfw_GUID_RyAxis
|
|
||||||
#define GUID_RzAxis _glfw_GUID_RzAxis
|
|
||||||
#define GUID_Slider _glfw_GUID_Slider
|
|
||||||
#define GUID_POV _glfw_GUID_POV
|
|
||||||
|
|
||||||
// Object data array for our clone of c_dfDIJoystick
|
|
||||||
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
|
||||||
//
|
|
||||||
static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
|
|
||||||
{
|
|
||||||
{ &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
// Our clone of c_dfDIJoystick
|
|
||||||
//
|
|
||||||
static const DIDATAFORMAT _glfwDataFormat =
|
|
||||||
{
|
|
||||||
sizeof(DIDATAFORMAT),
|
|
||||||
sizeof(DIOBJECTDATAFORMAT),
|
|
||||||
DIDFT_ABSAXIS,
|
|
||||||
sizeof(DIJOYSTATE),
|
|
||||||
sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
|
|
||||||
_glfwObjectDataFormats
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns a description fitting the specified XInput capabilities
|
|
||||||
//
|
|
||||||
static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
|
||||||
{
|
|
||||||
switch (xic->SubType)
|
|
||||||
{
|
|
||||||
case XINPUT_DEVSUBTYPE_WHEEL:
|
|
||||||
return "XInput Wheel";
|
|
||||||
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
|
||||||
return "XInput Arcade Stick";
|
|
||||||
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
|
||||||
return "XInput Flight Stick";
|
|
||||||
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
|
||||||
return "XInput Dance Pad";
|
|
||||||
case XINPUT_DEVSUBTYPE_GUITAR:
|
|
||||||
return "XInput Guitar";
|
|
||||||
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
|
||||||
return "XInput Drum Kit";
|
|
||||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
|
||||||
{
|
|
||||||
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
|
||||||
return "Wireless Xbox Controller";
|
|
||||||
else
|
|
||||||
return "Xbox Controller";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Unknown XInput Device";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lexically compare device objects
|
|
||||||
//
|
|
||||||
static int compareJoystickObjects(const void* first, const void* second)
|
|
||||||
{
|
|
||||||
const _GLFWjoyobjectWin32* fo = first;
|
|
||||||
const _GLFWjoyobjectWin32* so = second;
|
|
||||||
|
|
||||||
if (fo->type != so->type)
|
|
||||||
return fo->type - so->type;
|
|
||||||
|
|
||||||
return fo->offset - so->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks whether the specified device supports XInput
|
|
||||||
// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
|
|
||||||
//
|
|
||||||
static GLFWbool supportsXInput(const GUID* guid)
|
|
||||||
{
|
|
||||||
UINT i, count = 0;
|
|
||||||
RAWINPUTDEVICELIST* ridl;
|
|
||||||
GLFWbool result = GLFW_FALSE;
|
|
||||||
|
|
||||||
if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
|
|
||||||
|
|
||||||
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
|
|
||||||
{
|
|
||||||
free(ridl);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
RID_DEVICE_INFO rdi;
|
|
||||||
char name[256];
|
|
||||||
UINT size;
|
|
||||||
|
|
||||||
if (ridl[i].dwType != RIM_TYPEHID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ZeroMemory(&rdi, sizeof(rdi));
|
|
||||||
rdi.cbSize = sizeof(rdi);
|
|
||||||
size = sizeof(rdi);
|
|
||||||
|
|
||||||
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
|
||||||
RIDI_DEVICEINFO,
|
|
||||||
&rdi, &size) == -1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
memset(name, 0, sizeof(name));
|
|
||||||
size = sizeof(name);
|
|
||||||
|
|
||||||
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
|
||||||
RIDI_DEVICENAME,
|
|
||||||
name, &size) == -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
name[sizeof(name) - 1] = '\0';
|
|
||||||
if (strstr(name, "IG_"))
|
|
||||||
{
|
|
||||||
result = GLFW_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ridl);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frees all resources associated with the specified joystick
|
|
||||||
//
|
|
||||||
static void closeJoystick(_GLFWjoystick* js)
|
|
||||||
{
|
|
||||||
if (js->win32.device)
|
|
||||||
{
|
|
||||||
IDirectInputDevice8_Unacquire(js->win32.device);
|
|
||||||
IDirectInputDevice8_Release(js->win32.device);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(js->win32.objects);
|
|
||||||
|
|
||||||
_glfwFreeJoystick(js);
|
|
||||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DirectInput device object enumeration callback
|
|
||||||
// Insights gleaned from SDL
|
|
||||||
//
|
|
||||||
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
|
||||||
void* user)
|
|
||||||
{
|
|
||||||
_GLFWobjenumWin32* data = user;
|
|
||||||
_GLFWjoyobjectWin32* object = data->objects + data->objectCount;
|
|
||||||
|
|
||||||
if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
|
|
||||||
{
|
|
||||||
DIPROPRANGE dipr;
|
|
||||||
|
|
||||||
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_SLIDER(data->sliderCount);
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_X;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_Y;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_Z;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_RX;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_RY;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_RZ;
|
|
||||||
else
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
|
|
||||||
ZeroMemory(&dipr, sizeof(dipr));
|
|
||||||
dipr.diph.dwSize = sizeof(dipr);
|
|
||||||
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
|
|
||||||
dipr.diph.dwObj = doi->dwType;
|
|
||||||
dipr.diph.dwHow = DIPH_BYID;
|
|
||||||
dipr.lMin = -32768;
|
|
||||||
dipr.lMax = 32767;
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_SetProperty(data->device,
|
|
||||||
DIPROP_RANGE,
|
|
||||||
&dipr.diph)))
|
|
||||||
{
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
|
||||||
{
|
|
||||||
object->type = _GLFW_TYPE_SLIDER;
|
|
||||||
data->sliderCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
object->type = _GLFW_TYPE_AXIS;
|
|
||||||
data->axisCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
|
|
||||||
{
|
|
||||||
object->offset = DIJOFS_BUTTON(data->buttonCount);
|
|
||||||
object->type = _GLFW_TYPE_BUTTON;
|
|
||||||
data->buttonCount++;
|
|
||||||
}
|
|
||||||
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
|
|
||||||
{
|
|
||||||
object->offset = DIJOFS_POV(data->povCount);
|
|
||||||
object->type = _GLFW_TYPE_POV;
|
|
||||||
data->povCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->objectCount++;
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DirectInput device enumeration callback
|
|
||||||
//
|
|
||||||
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|
||||||
{
|
|
||||||
int jid = 0;
|
|
||||||
DIDEVCAPS dc;
|
|
||||||
DIPROPDWORD dipd;
|
|
||||||
IDirectInputDevice8* device;
|
|
||||||
_GLFWobjenumWin32 data;
|
|
||||||
_GLFWjoystick* js;
|
|
||||||
char guid[33];
|
|
||||||
char name[256];
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
js = _glfw.joysticks + jid;
|
|
||||||
if (js->present)
|
|
||||||
{
|
|
||||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportsXInput(&di->guidProduct))
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
|
|
||||||
if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
|
|
||||||
&di->guidInstance,
|
|
||||||
&device,
|
|
||||||
NULL)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to set device data format");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMemory(&dc, sizeof(dc));
|
|
||||||
dc.dwSize = sizeof(dc);
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to query device capabilities");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMemory(&dipd, sizeof(dipd));
|
|
||||||
dipd.diph.dwSize = sizeof(dipd);
|
|
||||||
dipd.diph.dwHeaderSize = sizeof(dipd.diph);
|
|
||||||
dipd.diph.dwHow = DIPH_DEVICE;
|
|
||||||
dipd.dwData = DIPROPAXISMODE_ABS;
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_SetProperty(device,
|
|
||||||
DIPROP_AXISMODE,
|
|
||||||
&dipd.diph)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to set device axis mode");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&data, 0, sizeof(data));
|
|
||||||
data.device = device;
|
|
||||||
data.objects = calloc(dc.dwAxes + (size_t) dc.dwButtons + dc.dwPOVs,
|
|
||||||
sizeof(_GLFWjoyobjectWin32));
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_EnumObjects(device,
|
|
||||||
deviceObjectCallback,
|
|
||||||
&data,
|
|
||||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to enumerate device objects");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
free(data.objects);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(data.objects, data.objectCount,
|
|
||||||
sizeof(_GLFWjoyobjectWin32),
|
|
||||||
compareJoystickObjects);
|
|
||||||
|
|
||||||
if (!WideCharToMultiByte(CP_UTF8, 0,
|
|
||||||
di->tszInstanceName, -1,
|
|
||||||
name, sizeof(name),
|
|
||||||
NULL, NULL))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert joystick name to UTF-8");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
free(data.objects);
|
|
||||||
return DIENUM_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
|
||||||
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
|
|
||||||
{
|
|
||||||
sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
|
|
||||||
(uint8_t) di->guidProduct.Data1,
|
|
||||||
(uint8_t) (di->guidProduct.Data1 >> 8),
|
|
||||||
(uint8_t) (di->guidProduct.Data1 >> 16),
|
|
||||||
(uint8_t) (di->guidProduct.Data1 >> 24));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
|
||||||
name[0], name[1], name[2], name[3],
|
|
||||||
name[4], name[5], name[6], name[7],
|
|
||||||
name[8], name[9], name[10]);
|
|
||||||
}
|
|
||||||
|
|
||||||
js = _glfwAllocJoystick(name, guid,
|
|
||||||
data.axisCount + data.sliderCount,
|
|
||||||
data.buttonCount,
|
|
||||||
data.povCount);
|
|
||||||
if (!js)
|
|
||||||
{
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
free(data.objects);
|
|
||||||
return DIENUM_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
js->win32.device = device;
|
|
||||||
js->win32.guid = di->guidInstance;
|
|
||||||
js->win32.objects = data.objects;
|
|
||||||
js->win32.objectCount = data.objectCount;
|
|
||||||
|
|
||||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialize joystick interface
|
|
||||||
//
|
|
||||||
void _glfwInitJoysticksWin32(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.dinput8.instance)
|
|
||||||
{
|
|
||||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
|
||||||
DIRECTINPUT_VERSION,
|
|
||||||
&IID_IDirectInput8W,
|
|
||||||
(void**) &_glfw.win32.dinput8.api,
|
|
||||||
NULL)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to create interface");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwDetectJoystickConnectionWin32();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close all opened joystick handles
|
|
||||||
//
|
|
||||||
void _glfwTerminateJoysticksWin32(void)
|
|
||||||
{
|
|
||||||
int jid;
|
|
||||||
|
|
||||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
closeJoystick(_glfw.joysticks + jid);
|
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.api)
|
|
||||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks for new joysticks after DBT_DEVICEARRIVAL
|
|
||||||
//
|
|
||||||
void _glfwDetectJoystickConnectionWin32(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.xinput.instance)
|
|
||||||
{
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
for (index = 0; index < XUSER_MAX_COUNT; index++)
|
|
||||||
{
|
|
||||||
int jid;
|
|
||||||
char guid[33];
|
|
||||||
XINPUT_CAPABILITIES xic;
|
|
||||||
_GLFWjoystick* js;
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
if (_glfw.joysticks[jid].present &&
|
|
||||||
_glfw.joysticks[jid].win32.device == NULL &&
|
|
||||||
_glfw.joysticks[jid].win32.index == index)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jid <= GLFW_JOYSTICK_LAST)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
|
||||||
sprintf(guid, "78696e707574%02x000000000000000000",
|
|
||||||
xic.SubType & 0xff);
|
|
||||||
|
|
||||||
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
|
|
||||||
if (!js)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
js->win32.index = index;
|
|
||||||
|
|
||||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.api)
|
|
||||||
{
|
|
||||||
if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
|
|
||||||
DI8DEVCLASS_GAMECTRL,
|
|
||||||
deviceCallback,
|
|
||||||
NULL,
|
|
||||||
DIEDFL_ALLDEVICES)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Failed to enumerate DirectInput8 devices");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
|
|
||||||
//
|
|
||||||
void _glfwDetectJoystickDisconnectionWin32(void)
|
|
||||||
{
|
|
||||||
int jid;
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
|
||||||
if (js->present)
|
|
||||||
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
|
||||||
{
|
|
||||||
if (js->win32.device)
|
|
||||||
{
|
|
||||||
int i, ai = 0, bi = 0, pi = 0;
|
|
||||||
HRESULT result;
|
|
||||||
DIJOYSTATE state;
|
|
||||||
|
|
||||||
IDirectInputDevice8_Poll(js->win32.device);
|
|
||||||
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
|
||||||
sizeof(state),
|
|
||||||
&state);
|
|
||||||
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
|
||||||
{
|
|
||||||
IDirectInputDevice8_Acquire(js->win32.device);
|
|
||||||
IDirectInputDevice8_Poll(js->win32.device);
|
|
||||||
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
|
||||||
sizeof(state),
|
|
||||||
&state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
closeJoystick(js);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == _GLFW_POLL_PRESENCE)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
for (i = 0; i < js->win32.objectCount; i++)
|
|
||||||
{
|
|
||||||
const void* data = (char*) &state + js->win32.objects[i].offset;
|
|
||||||
|
|
||||||
switch (js->win32.objects[i].type)
|
|
||||||
{
|
|
||||||
case _GLFW_TYPE_AXIS:
|
|
||||||
case _GLFW_TYPE_SLIDER:
|
|
||||||
{
|
|
||||||
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
|
|
||||||
_glfwInputJoystickAxis(js, ai, value);
|
|
||||||
ai++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case _GLFW_TYPE_BUTTON:
|
|
||||||
{
|
|
||||||
const char value = (*((BYTE*) data) & 0x80) != 0;
|
|
||||||
_glfwInputJoystickButton(js, bi, value);
|
|
||||||
bi++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case _GLFW_TYPE_POV:
|
|
||||||
{
|
|
||||||
const int states[9] =
|
|
||||||
{
|
|
||||||
GLFW_HAT_UP,
|
|
||||||
GLFW_HAT_RIGHT_UP,
|
|
||||||
GLFW_HAT_RIGHT,
|
|
||||||
GLFW_HAT_RIGHT_DOWN,
|
|
||||||
GLFW_HAT_DOWN,
|
|
||||||
GLFW_HAT_LEFT_DOWN,
|
|
||||||
GLFW_HAT_LEFT,
|
|
||||||
GLFW_HAT_LEFT_UP,
|
|
||||||
GLFW_HAT_CENTERED
|
|
||||||
};
|
|
||||||
|
|
||||||
// Screams of horror are appropriate at this point
|
|
||||||
int stateIndex = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
|
||||||
if (stateIndex < 0 || stateIndex > 8)
|
|
||||||
stateIndex = 8;
|
|
||||||
|
|
||||||
_glfwInputJoystickHat(js, pi, states[stateIndex]);
|
|
||||||
pi++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i, dpad = 0;
|
|
||||||
DWORD result;
|
|
||||||
XINPUT_STATE xis;
|
|
||||||
const WORD buttons[10] =
|
|
||||||
{
|
|
||||||
XINPUT_GAMEPAD_A,
|
|
||||||
XINPUT_GAMEPAD_B,
|
|
||||||
XINPUT_GAMEPAD_X,
|
|
||||||
XINPUT_GAMEPAD_Y,
|
|
||||||
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
|
||||||
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
|
||||||
XINPUT_GAMEPAD_BACK,
|
|
||||||
XINPUT_GAMEPAD_START,
|
|
||||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
|
||||||
XINPUT_GAMEPAD_RIGHT_THUMB
|
|
||||||
};
|
|
||||||
|
|
||||||
result = XInputGetState(js->win32.index, &xis);
|
|
||||||
if (result != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
|
||||||
closeJoystick(js);
|
|
||||||
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == _GLFW_POLL_PRESENCE)
|
|
||||||
return GLFW_TRUE;
|
|
||||||
|
|
||||||
_glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
|
|
||||||
_glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++)
|
|
||||||
{
|
|
||||||
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
|
||||||
_glfwInputJoystickButton(js, i, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
|
|
||||||
dpad |= GLFW_HAT_UP;
|
|
||||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
|
|
||||||
dpad |= GLFW_HAT_RIGHT;
|
|
||||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
|
|
||||||
dpad |= GLFW_HAT_DOWN;
|
|
||||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
|
|
||||||
dpad |= GLFW_HAT_LEFT;
|
|
||||||
|
|
||||||
_glfwInputJoystickHat(js, 0, dpad);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
|
||||||
{
|
|
||||||
if (strcmp(guid + 20, "504944564944") == 0)
|
|
||||||
{
|
|
||||||
char original[33];
|
|
||||||
strncpy(original, guid, sizeof(original) - 1);
|
|
||||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
|
||||||
original, original + 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
|
|
||||||
#define GLFW_BUILD_WIN32_MAPPINGS
|
|
||||||
|
|
||||||
// Joystick element (axis, button or slider)
|
|
||||||
//
|
|
||||||
typedef struct _GLFWjoyobjectWin32
|
|
||||||
{
|
|
||||||
int offset;
|
|
||||||
int type;
|
|
||||||
} _GLFWjoyobjectWin32;
|
|
||||||
|
|
||||||
// Win32-specific per-joystick data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWjoystickWin32
|
|
||||||
{
|
|
||||||
_GLFWjoyobjectWin32* objects;
|
|
||||||
int objectCount;
|
|
||||||
IDirectInputDevice8W* device;
|
|
||||||
DWORD index;
|
|
||||||
GUID guid;
|
|
||||||
} _GLFWjoystickWin32;
|
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitJoysticksWin32(void);
|
|
||||||
void _glfwTerminateJoysticksWin32(void);
|
|
||||||
void _glfwDetectJoystickConnectionWin32(void);
|
|
||||||
void _glfwDetectJoystickDisconnectionWin32(void);
|
|
||||||
|
|
@ -1,548 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <wchar.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Callback for EnumDisplayMonitors in createMonitor
|
|
||||||
//
|
|
||||||
static BOOL CALLBACK monitorCallback(HMONITOR handle,
|
|
||||||
HDC dc,
|
|
||||||
RECT* rect,
|
|
||||||
LPARAM data)
|
|
||||||
{
|
|
||||||
MONITORINFOEXW mi;
|
|
||||||
ZeroMemory(&mi, sizeof(mi));
|
|
||||||
mi.cbSize = sizeof(mi);
|
|
||||||
|
|
||||||
if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) data;
|
|
||||||
if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
|
|
||||||
monitor->win32.handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create monitor from an adapter and (optionally) a display
|
|
||||||
//
|
|
||||||
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
|
||||||
DISPLAY_DEVICEW* display)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor;
|
|
||||||
int widthMM, heightMM;
|
|
||||||
char* name;
|
|
||||||
HDC dc;
|
|
||||||
DEVMODEW dm;
|
|
||||||
RECT rect;
|
|
||||||
|
|
||||||
if (display)
|
|
||||||
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
|
||||||
else
|
|
||||||
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
|
||||||
if (!name)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
|
|
||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
|
||||||
|
|
||||||
if (IsWindows8Point1OrGreater())
|
|
||||||
{
|
|
||||||
widthMM = GetDeviceCaps(dc, HORZSIZE);
|
|
||||||
heightMM = GetDeviceCaps(dc, VERTSIZE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
|
|
||||||
heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteDC(dc);
|
|
||||||
|
|
||||||
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
|
|
||||||
free(name);
|
|
||||||
|
|
||||||
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
|
||||||
monitor->win32.modesPruned = GLFW_TRUE;
|
|
||||||
|
|
||||||
wcscpy(monitor->win32.adapterName, adapter->DeviceName);
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0,
|
|
||||||
adapter->DeviceName, -1,
|
|
||||||
monitor->win32.publicAdapterName,
|
|
||||||
sizeof(monitor->win32.publicAdapterName),
|
|
||||||
NULL, NULL);
|
|
||||||
|
|
||||||
if (display)
|
|
||||||
{
|
|
||||||
wcscpy(monitor->win32.displayName, display->DeviceName);
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0,
|
|
||||||
display->DeviceName, -1,
|
|
||||||
monitor->win32.publicDisplayName,
|
|
||||||
sizeof(monitor->win32.publicDisplayName),
|
|
||||||
NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.left = dm.dmPosition.x;
|
|
||||||
rect.top = dm.dmPosition.y;
|
|
||||||
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
|
|
||||||
rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
|
|
||||||
|
|
||||||
EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
|
|
||||||
return monitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Poll for changes in the set of connected monitors
|
|
||||||
//
|
|
||||||
void _glfwPollMonitorsWin32(void)
|
|
||||||
{
|
|
||||||
int i, disconnectedCount;
|
|
||||||
_GLFWmonitor** disconnected = NULL;
|
|
||||||
DWORD adapterIndex, displayIndex;
|
|
||||||
DISPLAY_DEVICEW adapter, display;
|
|
||||||
_GLFWmonitor* monitor;
|
|
||||||
|
|
||||||
disconnectedCount = _glfw.monitorCount;
|
|
||||||
if (disconnectedCount)
|
|
||||||
{
|
|
||||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
|
||||||
memcpy(disconnected,
|
|
||||||
_glfw.monitors,
|
|
||||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (adapterIndex = 0; ; adapterIndex++)
|
|
||||||
{
|
|
||||||
int type = _GLFW_INSERT_LAST;
|
|
||||||
|
|
||||||
ZeroMemory(&adapter, sizeof(adapter));
|
|
||||||
adapter.cb = sizeof(adapter);
|
|
||||||
|
|
||||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
|
||||||
type = _GLFW_INSERT_FIRST;
|
|
||||||
|
|
||||||
for (displayIndex = 0; ; displayIndex++)
|
|
||||||
{
|
|
||||||
ZeroMemory(&display, sizeof(display));
|
|
||||||
display.cb = sizeof(display);
|
|
||||||
|
|
||||||
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (i = 0; i < disconnectedCount; i++)
|
|
||||||
{
|
|
||||||
if (disconnected[i] &&
|
|
||||||
wcscmp(disconnected[i]->win32.displayName,
|
|
||||||
display.DeviceName) == 0)
|
|
||||||
{
|
|
||||||
disconnected[i] = NULL;
|
|
||||||
// handle may have changed, update
|
|
||||||
EnumDisplayMonitors(NULL, NULL, monitorCallback, (LPARAM) _glfw.monitors[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < disconnectedCount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
monitor = createMonitor(&adapter, &display);
|
|
||||||
if (!monitor)
|
|
||||||
{
|
|
||||||
free(disconnected);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
|
||||||
|
|
||||||
type = _GLFW_INSERT_LAST;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: If an active adapter does not have any display devices
|
|
||||||
// (as sometimes happens), add it directly as a monitor
|
|
||||||
if (displayIndex == 0)
|
|
||||||
{
|
|
||||||
for (i = 0; i < disconnectedCount; i++)
|
|
||||||
{
|
|
||||||
if (disconnected[i] &&
|
|
||||||
wcscmp(disconnected[i]->win32.adapterName,
|
|
||||||
adapter.DeviceName) == 0)
|
|
||||||
{
|
|
||||||
disconnected[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < disconnectedCount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
monitor = createMonitor(&adapter, NULL);
|
|
||||||
if (!monitor)
|
|
||||||
{
|
|
||||||
free(disconnected);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < disconnectedCount; i++)
|
|
||||||
{
|
|
||||||
if (disconnected[i])
|
|
||||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(disconnected);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the current video mode
|
|
||||||
//
|
|
||||||
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|
||||||
{
|
|
||||||
GLFWvidmode current;
|
|
||||||
const GLFWvidmode* best;
|
|
||||||
DEVMODEW dm;
|
|
||||||
LONG result;
|
|
||||||
|
|
||||||
best = _glfwChooseVideoMode(monitor, desired);
|
|
||||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
|
||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
|
|
||||||
DM_DISPLAYFREQUENCY;
|
|
||||||
dm.dmPelsWidth = best->width;
|
|
||||||
dm.dmPelsHeight = best->height;
|
|
||||||
dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits;
|
|
||||||
dm.dmDisplayFrequency = best->refreshRate;
|
|
||||||
|
|
||||||
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
|
|
||||||
dm.dmBitsPerPel = 32;
|
|
||||||
|
|
||||||
result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
&dm,
|
|
||||||
NULL,
|
|
||||||
CDS_FULLSCREEN,
|
|
||||||
NULL);
|
|
||||||
if (result == DISP_CHANGE_SUCCESSFUL)
|
|
||||||
monitor->win32.modeChanged = GLFW_TRUE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char* description = "Unknown error";
|
|
||||||
|
|
||||||
if (result == DISP_CHANGE_BADDUALVIEW)
|
|
||||||
description = "The system uses DualView";
|
|
||||||
else if (result == DISP_CHANGE_BADFLAGS)
|
|
||||||
description = "Invalid flags";
|
|
||||||
else if (result == DISP_CHANGE_BADMODE)
|
|
||||||
description = "Graphics mode not supported";
|
|
||||||
else if (result == DISP_CHANGE_BADPARAM)
|
|
||||||
description = "Invalid parameter";
|
|
||||||
else if (result == DISP_CHANGE_FAILED)
|
|
||||||
description = "Graphics mode failed";
|
|
||||||
else if (result == DISP_CHANGE_NOTUPDATED)
|
|
||||||
description = "Failed to write to registry";
|
|
||||||
else if (result == DISP_CHANGE_RESTART)
|
|
||||||
description = "Computer restart required";
|
|
||||||
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to set video mode: %s",
|
|
||||||
description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the previously saved (original) video mode
|
|
||||||
//
|
|
||||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
|
|
||||||
{
|
|
||||||
if (monitor->win32.modeChanged)
|
|
||||||
{
|
|
||||||
ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
NULL, NULL, CDS_FULLSCREEN, NULL);
|
|
||||||
monitor->win32.modeChanged = GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
|
|
||||||
{
|
|
||||||
UINT xdpi, ydpi;
|
|
||||||
|
|
||||||
if (xscale)
|
|
||||||
*xscale = 0.f;
|
|
||||||
if (yscale)
|
|
||||||
*yscale = 0.f;
|
|
||||||
|
|
||||||
if (IsWindows8Point1OrGreater())
|
|
||||||
{
|
|
||||||
if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const HDC dc = GetDC(NULL);
|
|
||||||
xdpi = GetDeviceCaps(dc, LOGPIXELSX);
|
|
||||||
ydpi = GetDeviceCaps(dc, LOGPIXELSY);
|
|
||||||
ReleaseDC(NULL, dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xscale)
|
|
||||||
*xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
|
|
||||||
if (yscale)
|
|
||||||
*yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|
||||||
{
|
|
||||||
DEVMODEW dm;
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
|
|
||||||
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
ENUM_CURRENT_SETTINGS,
|
|
||||||
&dm,
|
|
||||||
EDS_ROTATEDMODE);
|
|
||||||
|
|
||||||
if (xpos)
|
|
||||||
*xpos = dm.dmPosition.x;
|
|
||||||
if (ypos)
|
|
||||||
*ypos = dm.dmPosition.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|
||||||
float* xscale, float* yscale)
|
|
||||||
{
|
|
||||||
_glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
|
||||||
int* xpos, int* ypos,
|
|
||||||
int* width, int* height)
|
|
||||||
{
|
|
||||||
MONITORINFO mi = { sizeof(mi) };
|
|
||||||
GetMonitorInfo(monitor->win32.handle, &mi);
|
|
||||||
|
|
||||||
if (xpos)
|
|
||||||
*xpos = mi.rcWork.left;
|
|
||||||
if (ypos)
|
|
||||||
*ypos = mi.rcWork.top;
|
|
||||||
if (width)
|
|
||||||
*width = mi.rcWork.right - mi.rcWork.left;
|
|
||||||
if (height)
|
|
||||||
*height = mi.rcWork.bottom - mi.rcWork.top;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|
||||||
{
|
|
||||||
int modeIndex = 0, size = 0;
|
|
||||||
GLFWvidmode* result = NULL;
|
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
GLFWvidmode mode;
|
|
||||||
DEVMODEW dm;
|
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
|
|
||||||
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
|
|
||||||
break;
|
|
||||||
|
|
||||||
modeIndex++;
|
|
||||||
|
|
||||||
// Skip modes with less than 15 BPP
|
|
||||||
if (dm.dmBitsPerPel < 15)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mode.width = dm.dmPelsWidth;
|
|
||||||
mode.height = dm.dmPelsHeight;
|
|
||||||
mode.refreshRate = dm.dmDisplayFrequency;
|
|
||||||
_glfwSplitBPP(dm.dmBitsPerPel,
|
|
||||||
&mode.redBits,
|
|
||||||
&mode.greenBits,
|
|
||||||
&mode.blueBits);
|
|
||||||
|
|
||||||
for (i = 0; i < *count; i++)
|
|
||||||
{
|
|
||||||
if (_glfwCompareVideoModes(result + i, &mode) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip duplicate modes
|
|
||||||
if (i < *count)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (monitor->win32.modesPruned)
|
|
||||||
{
|
|
||||||
// Skip modes not supported by the connected displays
|
|
||||||
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
&dm,
|
|
||||||
NULL,
|
|
||||||
CDS_TEST,
|
|
||||||
NULL) != DISP_CHANGE_SUCCESSFUL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*count == size)
|
|
||||||
{
|
|
||||||
size += 128;
|
|
||||||
result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
|
|
||||||
}
|
|
||||||
|
|
||||||
(*count)++;
|
|
||||||
result[*count - 1] = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*count)
|
|
||||||
{
|
|
||||||
// HACK: Report the current mode if no valid modes were found
|
|
||||||
result = calloc(1, sizeof(GLFWvidmode));
|
|
||||||
_glfwPlatformGetVideoMode(monitor, result);
|
|
||||||
*count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|
||||||
{
|
|
||||||
DEVMODEW dm;
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
|
|
||||||
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
|
|
||||||
|
|
||||||
mode->width = dm.dmPelsWidth;
|
|
||||||
mode->height = dm.dmPelsHeight;
|
|
||||||
mode->refreshRate = dm.dmDisplayFrequency;
|
|
||||||
_glfwSplitBPP(dm.dmBitsPerPel,
|
|
||||||
&mode->redBits,
|
|
||||||
&mode->greenBits,
|
|
||||||
&mode->blueBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|
||||||
{
|
|
||||||
HDC dc;
|
|
||||||
WORD values[3][256];
|
|
||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
|
|
||||||
GetDeviceGammaRamp(dc, values);
|
|
||||||
DeleteDC(dc);
|
|
||||||
|
|
||||||
_glfwAllocGammaArrays(ramp, 256);
|
|
||||||
|
|
||||||
memcpy(ramp->red, values[0], sizeof(values[0]));
|
|
||||||
memcpy(ramp->green, values[1], sizeof(values[1]));
|
|
||||||
memcpy(ramp->blue, values[2], sizeof(values[2]));
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
|
||||||
{
|
|
||||||
HDC dc;
|
|
||||||
WORD values[3][256];
|
|
||||||
|
|
||||||
if (ramp->size != 256)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Gamma ramp size must be 256");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(values[0], ramp->red, sizeof(values[0]));
|
|
||||||
memcpy(values[1], ramp->green, sizeof(values[1]));
|
|
||||||
memcpy(values[2], ramp->blue, sizeof(values[2]));
|
|
||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
|
|
||||||
SetDeviceGammaRamp(dc, values);
|
|
||||||
DeleteDC(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW native API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
return monitor->win32.publicAdapterName;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
return monitor->win32.publicDisplayName;
|
|
||||||
}
|
|
||||||
|
|
@ -1,452 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
// We don't need all the fancy stuff
|
|
||||||
#ifndef NOMINMAX
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef VC_EXTRALEAN
|
|
||||||
#define VC_EXTRALEAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
|
||||||
// example to allow applications to correctly declare a GL_KHR_debug callback)
|
|
||||||
// but windows.h assumes no one will define APIENTRY before it does
|
|
||||||
#undef APIENTRY
|
|
||||||
|
|
||||||
// GLFW on Windows is Unicode only and does not work in MBCS mode
|
|
||||||
#ifndef UNICODE
|
|
||||||
#define UNICODE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GLFW requires Windows XP or later
|
|
||||||
#if WINVER < 0x0501
|
|
||||||
#undef WINVER
|
|
||||||
#define WINVER 0x0501
|
|
||||||
#endif
|
|
||||||
#if _WIN32_WINNT < 0x0501
|
|
||||||
#undef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x0501
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GLFW uses DirectInput8 interfaces
|
|
||||||
#define DIRECTINPUT_VERSION 0x0800
|
|
||||||
|
|
||||||
// GLFW uses OEM cursor resources
|
|
||||||
#define OEMRESOURCE
|
|
||||||
|
|
||||||
#include <wctype.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <dinput.h>
|
|
||||||
#include <xinput.h>
|
|
||||||
#include <dbt.h>
|
|
||||||
|
|
||||||
// HACK: Define macros that some windows.h variants don't
|
|
||||||
#ifndef WM_MOUSEHWHEEL
|
|
||||||
#define WM_MOUSEHWHEEL 0x020E
|
|
||||||
#endif
|
|
||||||
#ifndef WM_DWMCOMPOSITIONCHANGED
|
|
||||||
#define WM_DWMCOMPOSITIONCHANGED 0x031E
|
|
||||||
#endif
|
|
||||||
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
|
|
||||||
#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
|
|
||||||
#endif
|
|
||||||
#ifndef WM_COPYGLOBALDATA
|
|
||||||
#define WM_COPYGLOBALDATA 0x0049
|
|
||||||
#endif
|
|
||||||
#ifndef WM_UNICHAR
|
|
||||||
#define WM_UNICHAR 0x0109
|
|
||||||
#endif
|
|
||||||
#ifndef UNICODE_NOCHAR
|
|
||||||
#define UNICODE_NOCHAR 0xFFFF
|
|
||||||
#endif
|
|
||||||
#ifndef WM_DPICHANGED
|
|
||||||
#define WM_DPICHANGED 0x02E0
|
|
||||||
#endif
|
|
||||||
#ifndef GET_XBUTTON_WPARAM
|
|
||||||
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
|
|
||||||
#endif
|
|
||||||
#ifndef EDS_ROTATEDMODE
|
|
||||||
#define EDS_ROTATEDMODE 0x00000004
|
|
||||||
#endif
|
|
||||||
#ifndef DISPLAY_DEVICE_ACTIVE
|
|
||||||
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
|
||||||
#endif
|
|
||||||
#ifndef _WIN32_WINNT_WINBLUE
|
|
||||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
|
||||||
#endif
|
|
||||||
#ifndef _WIN32_WINNT_WIN8
|
|
||||||
#define _WIN32_WINNT_WIN8 0x0602
|
|
||||||
#endif
|
|
||||||
#ifndef WM_GETDPISCALEDSIZE
|
|
||||||
#define WM_GETDPISCALEDSIZE 0x02e4
|
|
||||||
#endif
|
|
||||||
#ifndef USER_DEFAULT_SCREEN_DPI
|
|
||||||
#define USER_DEFAULT_SCREEN_DPI 96
|
|
||||||
#endif
|
|
||||||
#ifndef OCR_HAND
|
|
||||||
#define OCR_HAND 32649
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WINVER < 0x0601
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
DWORD cbSize;
|
|
||||||
DWORD ExtStatus;
|
|
||||||
} CHANGEFILTERSTRUCT;
|
|
||||||
#ifndef MSGFLT_ALLOW
|
|
||||||
#define MSGFLT_ALLOW 1
|
|
||||||
#endif
|
|
||||||
#endif /*Windows 7*/
|
|
||||||
|
|
||||||
#if WINVER < 0x0600
|
|
||||||
#define DWM_BB_ENABLE 0x00000001
|
|
||||||
#define DWM_BB_BLURREGION 0x00000002
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
DWORD dwFlags;
|
|
||||||
BOOL fEnable;
|
|
||||||
HRGN hRgnBlur;
|
|
||||||
BOOL fTransitionOnMaximized;
|
|
||||||
} DWM_BLURBEHIND;
|
|
||||||
#else
|
|
||||||
#include <dwmapi.h>
|
|
||||||
#endif /*Windows Vista*/
|
|
||||||
|
|
||||||
#ifndef DPI_ENUMS_DECLARED
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
PROCESS_DPI_UNAWARE = 0,
|
|
||||||
PROCESS_SYSTEM_DPI_AWARE = 1,
|
|
||||||
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
|
||||||
} PROCESS_DPI_AWARENESS;
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
MDT_EFFECTIVE_DPI = 0,
|
|
||||||
MDT_ANGULAR_DPI = 1,
|
|
||||||
MDT_RAW_DPI = 2,
|
|
||||||
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
|
||||||
} MONITOR_DPI_TYPE;
|
|
||||||
#endif /*DPI_ENUMS_DECLARED*/
|
|
||||||
|
|
||||||
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
|
|
||||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
|
|
||||||
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
|
||||||
|
|
||||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
|
||||||
#define IsWindowsXPOrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
|
||||||
#define IsWindowsVistaOrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
|
||||||
#define IsWindows7OrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN7), 0)
|
|
||||||
#define IsWindows8OrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN8), 0)
|
|
||||||
#define IsWindows8Point1OrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
|
|
||||||
|
|
||||||
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
|
|
||||||
_glfwIsWindows10BuildOrGreaterWin32(14393)
|
|
||||||
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
|
|
||||||
_glfwIsWindows10BuildOrGreaterWin32(15063)
|
|
||||||
|
|
||||||
// HACK: Define macros that some xinput.h variants don't
|
|
||||||
#ifndef XINPUT_CAPS_WIRELESS
|
|
||||||
#define XINPUT_CAPS_WIRELESS 0x0002
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_WHEEL
|
|
||||||
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
|
|
||||||
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
|
|
||||||
#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
|
|
||||||
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR
|
|
||||||
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
|
|
||||||
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
|
|
||||||
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
|
||||||
#endif
|
|
||||||
#ifndef XUSER_MAX_COUNT
|
|
||||||
#define XUSER_MAX_COUNT 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// HACK: Define macros that some dinput.h variants don't
|
|
||||||
#ifndef DIDFT_OPTIONAL
|
|
||||||
#define DIDFT_OPTIONAL 0x80000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// xinput.dll function pointer typedefs
|
|
||||||
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
|
||||||
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
|
|
||||||
#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
|
|
||||||
#define XInputGetState _glfw.win32.xinput.GetState
|
|
||||||
|
|
||||||
// dinput8.dll function pointer typedefs
|
|
||||||
typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
|
||||||
#define DirectInput8Create _glfw.win32.dinput8.Create
|
|
||||||
|
|
||||||
// user32.dll function pointer typedefs
|
|
||||||
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
|
|
||||||
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
|
|
||||||
typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
|
|
||||||
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
|
|
||||||
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
|
||||||
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
|
||||||
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
|
||||||
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
|
||||||
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
|
||||||
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
|
||||||
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
|
||||||
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
|
||||||
|
|
||||||
// dwmapi.dll function pointer typedefs
|
|
||||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
|
||||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
|
||||||
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
|
||||||
typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*);
|
|
||||||
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
|
||||||
#define DwmFlush _glfw.win32.dwmapi.Flush
|
|
||||||
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
|
||||||
#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor
|
|
||||||
|
|
||||||
// shcore.dll function pointer typedefs
|
|
||||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
|
||||||
typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
|
|
||||||
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
|
|
||||||
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
|
|
||||||
|
|
||||||
// ntdll.dll function pointer typedefs
|
|
||||||
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
|
||||||
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
|
||||||
|
|
||||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
|
||||||
|
|
||||||
typedef struct VkWin32SurfaceCreateInfoKHR
|
|
||||||
{
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkWin32SurfaceCreateFlagsKHR flags;
|
|
||||||
HINSTANCE hinstance;
|
|
||||||
HWND hwnd;
|
|
||||||
} VkWin32SurfaceCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
|
||||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
|
|
||||||
|
|
||||||
#include "win32_joystick.h"
|
|
||||||
#include "wgl_context.h"
|
|
||||||
#include "egl_context.h"
|
|
||||||
#include "osmesa_context.h"
|
|
||||||
|
|
||||||
#if !defined(_GLFW_WNDCLASSNAME)
|
|
||||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
|
||||||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
|
||||||
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
|
||||||
|
|
||||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
|
|
||||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
|
|
||||||
|
|
||||||
|
|
||||||
// Win32-specific per-window data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWwindowWin32
|
|
||||||
{
|
|
||||||
HWND handle;
|
|
||||||
HICON bigIcon;
|
|
||||||
HICON smallIcon;
|
|
||||||
|
|
||||||
GLFWbool cursorTracked;
|
|
||||||
GLFWbool frameAction;
|
|
||||||
GLFWbool iconified;
|
|
||||||
GLFWbool maximized;
|
|
||||||
// Whether to enable framebuffer transparency on DWM
|
|
||||||
GLFWbool transparent;
|
|
||||||
GLFWbool scaleToMonitor;
|
|
||||||
|
|
||||||
// Cached size used to filter out duplicate events
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
// The last received cursor position, regardless of source
|
|
||||||
int lastCursorPosX, lastCursorPosY;
|
|
||||||
// The last recevied high surrogate when decoding pairs of UTF-16 messages
|
|
||||||
WCHAR highSurrogate;
|
|
||||||
} _GLFWwindowWin32;
|
|
||||||
|
|
||||||
// Win32-specific global data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWlibraryWin32
|
|
||||||
{
|
|
||||||
HWND helperWindowHandle;
|
|
||||||
HDEVNOTIFY deviceNotificationHandle;
|
|
||||||
DWORD foregroundLockTimeout;
|
|
||||||
int acquiredMonitorCount;
|
|
||||||
char* clipboardString;
|
|
||||||
short int keycodes[512];
|
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
|
||||||
char keynames[GLFW_KEY_LAST + 1][5];
|
|
||||||
// Where to place the cursor when re-enabled
|
|
||||||
double restoreCursorPosX, restoreCursorPosY;
|
|
||||||
// The window whose disabled cursor mode is active
|
|
||||||
_GLFWwindow* disabledCursorWindow;
|
|
||||||
RAWINPUT* rawInput;
|
|
||||||
int rawInputSize;
|
|
||||||
UINT mouseTrailSize;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_DirectInput8Create Create;
|
|
||||||
IDirectInput8W* api;
|
|
||||||
} dinput8;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_XInputGetCapabilities GetCapabilities;
|
|
||||||
PFN_XInputGetState GetState;
|
|
||||||
} xinput;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_SetProcessDPIAware SetProcessDPIAware_;
|
|
||||||
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
|
|
||||||
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
|
|
||||||
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
|
||||||
PFN_GetDpiForWindow GetDpiForWindow_;
|
|
||||||
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
|
||||||
} user32;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
|
||||||
PFN_DwmFlush Flush;
|
|
||||||
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
|
||||||
PFN_DwmGetColorizationColor GetColorizationColor;
|
|
||||||
} dwmapi;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
|
|
||||||
PFN_GetDpiForMonitor GetDpiForMonitor_;
|
|
||||||
} shcore;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
|
||||||
} ntdll;
|
|
||||||
} _GLFWlibraryWin32;
|
|
||||||
|
|
||||||
// Win32-specific per-monitor data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWmonitorWin32
|
|
||||||
{
|
|
||||||
HMONITOR handle;
|
|
||||||
// This size matches the static size of DISPLAY_DEVICE.DeviceName
|
|
||||||
WCHAR adapterName[32];
|
|
||||||
WCHAR displayName[32];
|
|
||||||
char publicAdapterName[32];
|
|
||||||
char publicDisplayName[32];
|
|
||||||
GLFWbool modesPruned;
|
|
||||||
GLFWbool modeChanged;
|
|
||||||
} _GLFWmonitorWin32;
|
|
||||||
|
|
||||||
// Win32-specific per-cursor data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWcursorWin32
|
|
||||||
{
|
|
||||||
HCURSOR handle;
|
|
||||||
} _GLFWcursorWin32;
|
|
||||||
|
|
||||||
// Win32-specific global timer data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWtimerWin32
|
|
||||||
{
|
|
||||||
uint64_t frequency;
|
|
||||||
} _GLFWtimerWin32;
|
|
||||||
|
|
||||||
// Win32-specific thread local storage data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWtlsWin32
|
|
||||||
{
|
|
||||||
GLFWbool allocated;
|
|
||||||
DWORD index;
|
|
||||||
} _GLFWtlsWin32;
|
|
||||||
|
|
||||||
// Win32-specific mutex data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWmutexWin32
|
|
||||||
{
|
|
||||||
GLFWbool allocated;
|
|
||||||
CRITICAL_SECTION section;
|
|
||||||
} _GLFWmutexWin32;
|
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
|
||||||
void _glfwUnregisterWindowClassWin32(void);
|
|
||||||
|
|
||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
|
||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
|
||||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
|
|
||||||
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
|
|
||||||
void _glfwInputErrorWin32(int error, const char* description);
|
|
||||||
void _glfwUpdateKeyNamesWin32(void);
|
|
||||||
|
|
||||||
void _glfwInitTimerWin32(void);
|
|
||||||
|
|
||||||
void _glfwPollMonitorsWin32(void);
|
|
||||||
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
|
||||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
|
||||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
|
||||||
{
|
|
||||||
assert(tls->win32.allocated == GLFW_FALSE);
|
|
||||||
|
|
||||||
tls->win32.index = TlsAlloc();
|
|
||||||
if (tls->win32.index == TLS_OUT_OF_INDEXES)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to allocate TLS index");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
tls->win32.allocated = GLFW_TRUE;
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
|
||||||
{
|
|
||||||
if (tls->win32.allocated)
|
|
||||||
TlsFree(tls->win32.index);
|
|
||||||
memset(tls, 0, sizeof(_GLFWtls));
|
|
||||||
}
|
|
||||||
|
|
||||||
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
|
||||||
{
|
|
||||||
assert(tls->win32.allocated == GLFW_TRUE);
|
|
||||||
return TlsGetValue(tls->win32.index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
|
||||||
{
|
|
||||||
assert(tls->win32.allocated == GLFW_TRUE);
|
|
||||||
TlsSetValue(tls->win32.index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
|
||||||
{
|
|
||||||
assert(mutex->win32.allocated == GLFW_FALSE);
|
|
||||||
InitializeCriticalSection(&mutex->win32.section);
|
|
||||||
return mutex->win32.allocated = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
|
||||||
{
|
|
||||||
if (mutex->win32.allocated)
|
|
||||||
DeleteCriticalSection(&mutex->win32.section);
|
|
||||||
memset(mutex, 0, sizeof(_GLFWmutex));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
|
||||||
{
|
|
||||||
assert(mutex->win32.allocated == GLFW_TRUE);
|
|
||||||
EnterCriticalSection(&mutex->win32.section);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
|
||||||
{
|
|
||||||
assert(mutex->win32.allocated == GLFW_TRUE);
|
|
||||||
LeaveCriticalSection(&mutex->win32.section);
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
// Please use C89 style variable declarations in this file because VS 2010
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialise timer
|
|
||||||
//
|
|
||||||
void _glfwInitTimerWin32(void)
|
|
||||||
{
|
|
||||||
QueryPerformanceFrequency((LARGE_INTEGER*) &_glfw.timer.win32.frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
|
||||||
{
|
|
||||||
uint64_t value;
|
|
||||||
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
|
||||||
{
|
|
||||||
return _glfw.timer.win32.frequency;
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +0,0 @@
|
|||||||
set -e
|
|
||||||
|
|
||||||
dir=$(go list -f '{{.Dir}}' github.com/go-gl/glfw/v3.3/glfw)/glfw
|
|
||||||
ls ./deps/mingw | xargs -I '{}' cp $dir/deps/mingw/'{}' ./deps/mingw/'{}'
|
|
||||||
ls ./include/GLFW | xargs -I '{}' cp $dir/include/GLFW/'{}' ./include/GLFW/'{}'
|
|
||||||
ls ./src | xargs -I '{}' cp $dir/src/'{}' ./src/'{}'
|
|
||||||
echo 'Apply the change based on README.md later.'
|
|
@ -15,428 +15,368 @@
|
|||||||
package glfw
|
package glfw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
"math/bits"
|
|
||||||
"reflect"
|
"github.com/hajimehoshi/ebiten/v2/internal/glfwwin"
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type glfwImage struct {
|
type Cursor glfwwin.Cursor
|
||||||
width int32
|
|
||||||
height int32
|
|
||||||
pixels uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
type glfwWindows map[uintptr]*Window
|
|
||||||
|
|
||||||
var (
|
|
||||||
theGLFWWindows = glfwWindows{}
|
|
||||||
glfwWindowsM sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func (w glfwWindows) add(win uintptr) *Window {
|
|
||||||
if win == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ww := &Window{w: win}
|
|
||||||
glfwWindowsM.Lock()
|
|
||||||
w[win] = ww
|
|
||||||
glfwWindowsM.Unlock()
|
|
||||||
return ww
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w glfwWindows) remove(win uintptr) {
|
|
||||||
glfwWindowsM.Lock()
|
|
||||||
delete(w, win)
|
|
||||||
glfwWindowsM.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w glfwWindows) get(win uintptr) *Window {
|
|
||||||
if win == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
glfwWindowsM.Lock()
|
|
||||||
ww := w[win]
|
|
||||||
glfwWindowsM.Unlock()
|
|
||||||
return ww
|
|
||||||
}
|
|
||||||
|
|
||||||
type Cursor struct {
|
|
||||||
c uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateStandardCursor(shape StandardCursor) *Cursor {
|
func CreateStandardCursor(shape StandardCursor) *Cursor {
|
||||||
c := glfwDLL.call("glfwCreateStandardCursor", uintptr(shape))
|
c, err := glfwwin.CreateStandardCursor(glfwwin.StandardCursor(shape))
|
||||||
panicError()
|
if err != nil {
|
||||||
return &Cursor{c: c}
|
panic(err)
|
||||||
|
}
|
||||||
|
return (*Cursor)(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Monitor struct {
|
type Monitor glfwwin.Monitor
|
||||||
m uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Monitor) GetContentScale() (float32, float32) {
|
func (m *Monitor) GetContentScale() (float32, float32) {
|
||||||
var sx, sy float32
|
sx, sy, err := (*glfwwin.Monitor)(m).GetContentScale()
|
||||||
glfwDLL.call("glfwGetMonitorContentScale", m.m, uintptr(unsafe.Pointer(&sx)), uintptr(unsafe.Pointer(&sy)))
|
if err != nil {
|
||||||
panicError()
|
panic(err)
|
||||||
|
}
|
||||||
return sx, sy
|
return sx, sy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Monitor) GetPos() (int, int) {
|
func (m *Monitor) GetPos() (int, int) {
|
||||||
var x, y int32
|
x, y, err := (*glfwwin.Monitor)(m).GetPos()
|
||||||
glfwDLL.call("glfwGetMonitorPos", m.m, uintptr(unsafe.Pointer(&x)), uintptr(unsafe.Pointer(&y)))
|
if err != nil {
|
||||||
panicError()
|
panic(err)
|
||||||
return int(x), int(y)
|
}
|
||||||
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Monitor) GetVideoMode() *VidMode {
|
func (m *Monitor) GetVideoMode() *VidMode {
|
||||||
v := glfwDLL.call("glfwGetVideoMode", m.m)
|
v, err := (*glfwwin.Monitor)(m).GetVideoMode()
|
||||||
panicError()
|
if err != nil {
|
||||||
var vals []int32
|
panic(err)
|
||||||
h := (*reflect.SliceHeader)(unsafe.Pointer(&vals))
|
|
||||||
h.Data = v
|
|
||||||
h.Len = 6
|
|
||||||
h.Cap = 6
|
|
||||||
return &VidMode{
|
|
||||||
Width: int(vals[0]),
|
|
||||||
Height: int(vals[1]),
|
|
||||||
RedBits: int(vals[2]),
|
|
||||||
GreenBits: int(vals[3]),
|
|
||||||
BlueBits: int(vals[4]),
|
|
||||||
RefreshRate: int(vals[5]),
|
|
||||||
}
|
}
|
||||||
|
return (*VidMode)(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Window struct {
|
type Window glfwwin.Window
|
||||||
w uintptr
|
|
||||||
|
|
||||||
prevSizeCallback SizeCallback
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) Destroy() {
|
func (w *Window) Destroy() {
|
||||||
glfwDLL.call("glfwDestroyWindow", w.w)
|
if err := (*glfwwin.Window)(w).Destroy(); err != nil {
|
||||||
panicError()
|
|
||||||
theGLFWWindows.remove(w.w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetAttrib(attrib Hint) int {
|
|
||||||
r := glfwDLL.call("glfwGetWindowAttrib", w.w, uintptr(attrib))
|
|
||||||
panicError()
|
|
||||||
return int(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetAttrib(attrib Hint, value int) {
|
|
||||||
glfwDLL.call("glfwSetWindowAttrib", w.w, uintptr(attrib), uintptr(value))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetCursorPos() (x, y float64) {
|
|
||||||
glfwDLL.call("glfwGetCursorPos", w.w, uintptr(unsafe.Pointer(&x)), uintptr(unsafe.Pointer(&y)))
|
|
||||||
panicError()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetInputMode(mode InputMode) int {
|
|
||||||
r := glfwDLL.call("glfwGetInputMode", w.w, uintptr(mode))
|
|
||||||
panicError()
|
|
||||||
return int(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetKey(key Key) Action {
|
|
||||||
r := glfwDLL.call("glfwGetKey", w.w, uintptr(key))
|
|
||||||
panicError()
|
|
||||||
return Action(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetMonitor() *Monitor {
|
|
||||||
m := glfwDLL.call("glfwGetWindowMonitor", w.w)
|
|
||||||
panicError()
|
|
||||||
if m == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &Monitor{m}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetMouseButton(button MouseButton) Action {
|
|
||||||
r := glfwDLL.call("glfwGetMouseButton", w.w, uintptr(button))
|
|
||||||
panicError()
|
|
||||||
return Action(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetPos() (int, int) {
|
|
||||||
var x, y int32
|
|
||||||
glfwDLL.call("glfwGetWindowPos", w.w, uintptr(unsafe.Pointer(&x)), uintptr(unsafe.Pointer(&y)))
|
|
||||||
panicError()
|
|
||||||
return int(x), int(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) GetSize() (int, int) {
|
|
||||||
var width, height int32
|
|
||||||
glfwDLL.call("glfwGetWindowSize", w.w, uintptr(unsafe.Pointer(&width)), uintptr(unsafe.Pointer(&height)))
|
|
||||||
panicError()
|
|
||||||
return int(width), int(height)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) Hide() {
|
|
||||||
glfwDLL.call("glfwHideWindow", w.w)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) Iconify() {
|
|
||||||
glfwDLL.call("glfwIconifyWindow", w.w)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) MakeContextCurrent() {
|
|
||||||
glfwDLL.call("glfwMakeContextCurrent", w.w)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) Maximize() {
|
|
||||||
glfwDLL.call("glfwMaximizeWindow", w.w)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) Restore() {
|
|
||||||
glfwDLL.call("glfwRestoreWindow", w.w)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) {
|
|
||||||
glfwDLL.call("glfwSetCharModsCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
|
|
||||||
panicError()
|
|
||||||
return ToCharModsCallback(nil) // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
|
|
||||||
glfwDLL.call("glfwSetWindowCloseCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
|
|
||||||
panicError()
|
|
||||||
return ToCloseCallback(nil) // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetCursor(cursor *Cursor) {
|
|
||||||
var c uintptr
|
|
||||||
if cursor != nil {
|
|
||||||
c = cursor.c
|
|
||||||
}
|
|
||||||
glfwDLL.call("glfwSetCursor", w.w, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
|
|
||||||
glfwDLL.call("glfwSetFramebufferSizeCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
|
|
||||||
panicError()
|
|
||||||
return ToFramebufferSizeCallback(nil) // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
|
|
||||||
glfwDLL.call("glfwSetScrollCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
|
|
||||||
panicError()
|
|
||||||
return ToScrollCallback(nil) // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetShouldClose(value bool) {
|
|
||||||
var v uintptr = False
|
|
||||||
if value {
|
|
||||||
v = True
|
|
||||||
}
|
|
||||||
glfwDLL.call("glfwSetWindowShouldClose", w.w, v)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
|
|
||||||
glfwDLL.call("glfwSetWindowSizeCallback", w.w, uniquePtrToCallback[uniquePtr(cbfun)])
|
|
||||||
panicError()
|
|
||||||
prev := w.prevSizeCallback
|
|
||||||
w.prevSizeCallback = cbfun
|
|
||||||
return prev
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetSizeLimits(minw, minh, maxw, maxh int) {
|
|
||||||
glfwDLL.call("glfwSetWindowSizeLimits", w.w, uintptr(minw), uintptr(minh), uintptr(maxw), uintptr(maxh))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetAspectRatio(numer, denom int) {
|
|
||||||
glfwDLL.call("glfwSetWindowAspectRatio", w.w, uintptr(numer), uintptr(denom))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetIcon(images []image.Image) {
|
|
||||||
gimgs := make([]glfwImage, len(images))
|
|
||||||
defer runtime.KeepAlive(gimgs)
|
|
||||||
|
|
||||||
for i, img := range images {
|
|
||||||
b := img.Bounds()
|
|
||||||
m := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
|
||||||
draw.Draw(m, m.Bounds(), img, b.Min, draw.Src)
|
|
||||||
gimgs[i].width = int32(b.Dx())
|
|
||||||
gimgs[i].height = int32(b.Dy())
|
|
||||||
gimgs[i].pixels = uintptr(unsafe.Pointer(&m.Pix[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwDLL.call("glfwSetWindowIcon", w.w, uintptr(len(gimgs)), uintptr(unsafe.Pointer(&gimgs[0])))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetInputMode(mode InputMode, value int) {
|
|
||||||
glfwDLL.call("glfwSetInputMode", w.w, uintptr(mode), uintptr(value))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetMonitor(monitor *Monitor, xpos, ypos, width, height, refreshRate int) {
|
|
||||||
var m uintptr
|
|
||||||
if monitor != nil {
|
|
||||||
m = monitor.m
|
|
||||||
}
|
|
||||||
glfwDLL.call("glfwSetWindowMonitor", w.w, m, uintptr(xpos), uintptr(ypos), uintptr(width), uintptr(height), uintptr(refreshRate))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetPos(xpos, ypos int) {
|
|
||||||
glfwDLL.call("glfwSetWindowPos", w.w, uintptr(xpos), uintptr(ypos))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetSize(width, height int) {
|
|
||||||
glfwDLL.call("glfwSetWindowSize", w.w, uintptr(width), uintptr(height))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SetTitle(title string) {
|
|
||||||
s := []byte(title)
|
|
||||||
s = append(s, 0)
|
|
||||||
defer runtime.KeepAlive(s)
|
|
||||||
glfwDLL.call("glfwSetWindowTitle", w.w, uintptr(unsafe.Pointer(&s[0])))
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) ShouldClose() bool {
|
|
||||||
r := glfwDLL.call("glfwWindowShouldClose", w.w)
|
|
||||||
panicError()
|
|
||||||
return byte(r) == True
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) Show() {
|
|
||||||
glfwDLL.call("glfwShowWindow", w.w)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) SwapBuffers() {
|
|
||||||
glfwDLL.call("glfwSwapBuffers", w.w)
|
|
||||||
panicError()
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateWindow(width, height int, title string, monitor *Monitor, share *Window) (*Window, error) {
|
|
||||||
s := []byte(title)
|
|
||||||
s = append(s, 0)
|
|
||||||
defer runtime.KeepAlive(s)
|
|
||||||
|
|
||||||
var gm uintptr
|
|
||||||
if monitor != nil {
|
|
||||||
gm = monitor.m
|
|
||||||
}
|
|
||||||
var gw uintptr
|
|
||||||
if share != nil {
|
|
||||||
gw = share.w
|
|
||||||
}
|
|
||||||
|
|
||||||
w := glfwDLL.call("glfwCreateWindow", uintptr(width), uintptr(height), uintptr(unsafe.Pointer(&s[0])), gm, gw)
|
|
||||||
if w == 0 {
|
|
||||||
return nil, acceptError(APIUnavailable, VersionUnavailable)
|
|
||||||
}
|
|
||||||
return theGLFWWindows.add(w), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMonitors() []*Monitor {
|
|
||||||
var l int32
|
|
||||||
ptr := glfwDLL.call("glfwGetMonitors", uintptr(unsafe.Pointer(&l)))
|
|
||||||
panicError()
|
|
||||||
ms := make([]*Monitor, l)
|
|
||||||
for i := int32(0); i < l; i++ {
|
|
||||||
m := *(*unsafe.Pointer)(unsafe.Pointer(ptr))
|
|
||||||
if m != nil {
|
|
||||||
ms[i] = &Monitor{uintptr(m)}
|
|
||||||
}
|
|
||||||
ptr += bits.UintSize / 8
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPrimaryMonitor() *Monitor {
|
|
||||||
m := glfwDLL.call("glfwGetPrimaryMonitor")
|
|
||||||
panicError()
|
|
||||||
if m == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &Monitor{m}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Init() error {
|
|
||||||
glfwDLL.call("glfwInit")
|
|
||||||
// InvalidValue can happen when specific joysticks are used. This issue
|
|
||||||
// will be fixed in GLFW 3.3.5. As a temporary fix, ignore this error.
|
|
||||||
// See go-gl/glfw#292, go-gl/glfw#324, and glfw/glfw#1763
|
|
||||||
// (#1229).
|
|
||||||
err := acceptError(APIUnavailable, InvalidValue)
|
|
||||||
if e, ok := err.(*glfwError); ok && e.code == InvalidValue {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func panicErrorExceptForInvalidValue() {
|
|
||||||
// InvalidValue can happen when specific joysticks are used. This issue
|
|
||||||
// will be fixed in GLFW 3.3.5. As a temporary fix, ignore this error.
|
|
||||||
// See go-gl/glfw#292, go-gl/glfw#324, and glfw/glfw#1763
|
|
||||||
// (#1229).
|
|
||||||
err := acceptError(InvalidValue)
|
|
||||||
if e, ok := err.(*glfwError); ok && e.code == InvalidValue {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetAttrib(attrib Hint) int {
|
||||||
|
r, err := (*glfwwin.Window)(w).GetAttrib(glfwwin.Hint(attrib))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetAttrib(attrib Hint, value int) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetAttrib(glfwwin.Hint(attrib), value); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetCursorPos() (x, y float64) {
|
||||||
|
x, y, err := (*glfwwin.Window)(w).GetCursorPos()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetInputMode(mode InputMode) int {
|
||||||
|
r, err := (*glfwwin.Window)(w).GetInputMode(glfwwin.InputMode(mode))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetKey(key Key) Action {
|
||||||
|
r, err := (*glfwwin.Window)(w).GetKey(glfwwin.Key(key))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return Action(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetMonitor() *Monitor {
|
||||||
|
m, err := (*glfwwin.Window)(w).GetMonitor()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return (*Monitor)(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetMouseButton(button MouseButton) Action {
|
||||||
|
r, err := (*glfwwin.Window)(w).GetMouseButton(glfwwin.MouseButton(button))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return Action(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetPos() (int, int) {
|
||||||
|
x, y, err := (*glfwwin.Window)(w).GetPos()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) GetSize() (int, int) {
|
||||||
|
width, height, err := (*glfwwin.Window)(w).GetSize()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return width, height
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) Hide() {
|
||||||
|
if err := (*glfwwin.Window)(w).Hide(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) Iconify() {
|
||||||
|
if err := (*glfwwin.Window)(w).Iconify(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) MakeContextCurrent() {
|
||||||
|
if err := (*glfwwin.Window)(w).MakeContextCurrent(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) Maximize() {
|
||||||
|
if err := (*glfwwin.Window)(w).Maximize(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) Restore() {
|
||||||
|
if err := (*glfwwin.Window)(w).Restore(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) {
|
||||||
|
f, err := (*glfwwin.Window)(w).SetCharModsCallback(cbfun)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
|
||||||
|
f, err := (*glfwwin.Window)(w).SetCloseCallback(cbfun)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetCursor(cursor *Cursor) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetCursor((*glfwwin.Cursor)(cursor)); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
|
||||||
|
f, err := (*glfwwin.Window)(w).SetFramebufferSizeCallback(cbfun)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
|
||||||
|
f, err := (*glfwwin.Window)(w).SetScrollCallback(cbfun)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetShouldClose(value bool) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetShouldClose(value); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
|
||||||
|
f, err := (*glfwwin.Window)(w).SetSizeCallback(cbfun)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetSizeLimits(minw, minh, maxw, maxh int) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetSizeLimits(minw, minh, maxw, maxh); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetAspectRatio(numer, denom int) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetAspectRatio(numer, denom); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetIcon(images []image.Image) {
|
||||||
|
gimgs := make([]*glfwwin.Image, len(images))
|
||||||
|
for i, img := range images {
|
||||||
|
b := img.Bounds()
|
||||||
|
m := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
||||||
|
draw.Draw(m, m.Bounds(), img, b.Min, draw.Src)
|
||||||
|
gimgs[i] = &glfwwin.Image{
|
||||||
|
Width: b.Dx(),
|
||||||
|
Height: b.Dy(),
|
||||||
|
Pixels: m.Pix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := (*glfwwin.Window)(w).SetIcon(gimgs); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetInputMode(mode InputMode, value int) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetInputMode(glfwwin.InputMode(mode), value); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetMonitor(monitor *Monitor, xpos, ypos, width, height, refreshRate int) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetMonitor((*glfwwin.Monitor)(monitor), xpos, ypos, width, height, refreshRate); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetPos(xpos, ypos int) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetPos(xpos, ypos); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetSize(width, height int) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetSize(width, height); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SetTitle(title string) {
|
||||||
|
if err := (*glfwwin.Window)(w).SetTitle(title); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) ShouldClose() bool {
|
||||||
|
r, err := (*glfwwin.Window)(w).ShouldClose()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) Show() {
|
||||||
|
if err := (*glfwwin.Window)(w).Show(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Window) SwapBuffers() {
|
||||||
|
if err := (*glfwwin.Window)(w).SwapBuffers(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateWindow(width, height int, title string, monitor *Monitor, share *Window) (*Window, error) {
|
||||||
|
w, err := glfwwin.CreateWindow(width, height, title, (*glfwwin.Monitor)(monitor), (*glfwwin.Window)(share))
|
||||||
|
// TODO: acceptError(APIUnavailable, VersionUnavailable)?
|
||||||
|
return (*Window)(w), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMonitors() []*Monitor {
|
||||||
|
ms, err := glfwwin.GetMonitors()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
result := make([]*Monitor, 0, len(ms))
|
||||||
|
for _, m := range ms {
|
||||||
|
result = append(result, (*Monitor)(m))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPrimaryMonitor() *Monitor {
|
||||||
|
m, err := glfwwin.GetPrimaryMonitor()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return (*Monitor)(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init() error {
|
||||||
|
// InvalidValue can happen when specific joysticks are used. This issue
|
||||||
|
// will be fixed in GLFW 3.3.5. As a temporary fix, ignore this error.
|
||||||
|
// See go-gl/glfw#292, go-gl/glfw#324, and glfw/glfw#1763
|
||||||
|
// (#1229).
|
||||||
|
// TODO: acceptError(APIUnavailable, InvalidValue)?
|
||||||
|
err := glfwwin.Init()
|
||||||
|
if err != nil && !errors.Is(err, glfwwin.InvalidValue) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func PollEvents() {
|
func PollEvents() {
|
||||||
glfwDLL.call("glfwPollEvents")
|
if err := glfwwin.PollEvents(); err != nil && !errors.Is(err, glfwwin.InvalidValue) {
|
||||||
// This should be used for WaitEvents and WaitEventsTimeout if needed.
|
panic(err)
|
||||||
panicErrorExceptForInvalidValue()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostEmptyEvent() {
|
func PostEmptyEvent() {
|
||||||
glfwDLL.call("glfwPostEmptyEvent")
|
if err := glfwwin.PostEmptyEvent(); err != nil {
|
||||||
panicError()
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback {
|
func SetMonitorCallback(cbfun MonitorCallback) MonitorCallback {
|
||||||
glfwDLL.call("glfwSetMonitorCallback", uniquePtrToCallback[uniquePtr(cbfun)])
|
f, err := glfwwin.SetMonitorCallback(cbfun)
|
||||||
panicError()
|
if err != nil {
|
||||||
return ToMonitorCallback(nil) // TODO
|
panic(err)
|
||||||
|
}
|
||||||
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func SwapInterval(interval int) {
|
func SwapInterval(interval int) {
|
||||||
glfwDLL.call("glfwSwapInterval", uintptr(interval))
|
if err := glfwwin.SwapInterval(interval); err != nil {
|
||||||
panicError()
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Terminate() {
|
func Terminate() {
|
||||||
flushErrors()
|
if err := glfwwin.Terminate(); err != nil {
|
||||||
glfwDLL.call("glfwTerminate")
|
|
||||||
if err := glfwDLL.unload(); err != nil {
|
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WaitEvents() {
|
func WaitEvents() {
|
||||||
glfwDLL.call("glfwWaitEvents")
|
if err := glfwwin.WaitEvents(); err != nil {
|
||||||
panicError()
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WindowHint(target Hint, hint int) {
|
func WindowHint(target Hint, hint int) {
|
||||||
glfwDLL.call("glfwWindowHint", uintptr(target), uintptr(hint))
|
if err := glfwwin.WindowHint(glfwwin.Hint(target), hint); err != nil {
|
||||||
panicError()
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,8 +0,0 @@
|
|||||||
// Code generated by gen.go. DO NOT EDIT.
|
|
||||||
|
|
||||||
//go:build !ebitenexternaldll
|
|
||||||
// +build !ebitenexternaldll
|
|
||||||
|
|
||||||
package glfw
|
|
||||||
|
|
||||||
const glfwDLLHash = "ad5f2451f6d4fe11bccda498dad4e6ba1522a84c51d78e9003e99b4cff3807ea"
|
|
@ -1,8 +0,0 @@
|
|||||||
// Code generated by gen.go. DO NOT EDIT.
|
|
||||||
|
|
||||||
//go:build !ebitenexternaldll
|
|
||||||
// +build !ebitenexternaldll
|
|
||||||
|
|
||||||
package glfw
|
|
||||||
|
|
||||||
const glfwDLLHash = "6dd83fa958939315d474392aebac5fd1708d6cfb6b3d5cc6d9e43f35a3243f58"
|
|
@ -1,137 +0,0 @@
|
|||||||
// Copyright 2018 The Ebiten Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package glfw
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
type dll struct {
|
|
||||||
d *windows.LazyDLL
|
|
||||||
procs map[string]*windows.LazyProc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *dll) call(name string, args ...uintptr) uintptr {
|
|
||||||
if d.procs == nil {
|
|
||||||
d.procs = map[string]*windows.LazyProc{}
|
|
||||||
}
|
|
||||||
if _, ok := d.procs[name]; !ok {
|
|
||||||
d.procs[name] = d.d.NewProc(name)
|
|
||||||
}
|
|
||||||
// It looks like there is no way to handle Windows errors correctly.
|
|
||||||
r, _, _ := d.procs[name].Call(args...)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *dll) unload() error {
|
|
||||||
if err := windows.FreeLibrary(windows.Handle(d.d.Handle())); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bytePtrToString(ptr *byte) string {
|
|
||||||
var bs []byte
|
|
||||||
for i := uintptr(0); ; i++ {
|
|
||||||
b := *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + i))
|
|
||||||
if b == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
bs = append(bs, b)
|
|
||||||
}
|
|
||||||
return string(bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
type glfwError struct {
|
|
||||||
code ErrorCode
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *glfwError) Error() string {
|
|
||||||
return fmt.Sprintf("glfw: %s: %s", e.code.String(), e.desc)
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastErr = make(chan *glfwError, 1)
|
|
||||||
|
|
||||||
func fetchError() *glfwError {
|
|
||||||
select {
|
|
||||||
case err := <-lastErr:
|
|
||||||
return err
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func panicError() {
|
|
||||||
if err := acceptError(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func flushErrors() {
|
|
||||||
if err := fetchError(); err != nil {
|
|
||||||
panic(fmt.Sprintf("glfw: uncaught error: %s", err.Error()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func acceptError(codes ...ErrorCode) error {
|
|
||||||
err := fetchError()
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for _, c := range codes {
|
|
||||||
if err.code == c {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch err.code {
|
|
||||||
case PlatformError:
|
|
||||||
// TODO: Should we log this?
|
|
||||||
return nil
|
|
||||||
case NotInitialized, NoCurrentContext, InvalidEnum, InvalidValue, OutOfMemory:
|
|
||||||
panic(err)
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("glfw: uncaught error: %s", err.Error()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func goGLFWErrorCallback(code uintptr, desc *byte) uintptr {
|
|
||||||
flushErrors()
|
|
||||||
err := &glfwError{
|
|
||||||
code: ErrorCode(code),
|
|
||||||
desc: bytePtrToString(desc),
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case lastErr <- err:
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("glfw: uncaught error: %s", err.Error()))
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var glfwDLL *dll
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
dll, err := loadDLL()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
glfwDLL = dll
|
|
||||||
|
|
||||||
glfwDLL.call("glfwSetErrorCallback", windows.NewCallbackCDecl(goGLFWErrorCallback))
|
|
||||||
}
|
|
@ -14,8 +14,14 @@
|
|||||||
|
|
||||||
package glfw
|
package glfw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/glfwwin"
|
||||||
|
)
|
||||||
|
|
||||||
func (w *Window) GetWin32Window() uintptr {
|
func (w *Window) GetWin32Window() uintptr {
|
||||||
r := glfwDLL.call("glfwGetWin32Window", w.w)
|
r, err := (*glfwwin.Window)(w).GetWin32Window()
|
||||||
panicError()
|
if err != nil {
|
||||||
return r
|
panic(err)
|
||||||
|
}
|
||||||
|
return uintptr(r)
|
||||||
}
|
}
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
// Copyright 2021 The Ebiten Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
//go:build !ebitenexternaldll
|
|
||||||
// +build !ebitenexternaldll
|
|
||||||
|
|
||||||
package glfw
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"compress/gzip"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/gofrs/flock"
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
func writeDLLFile(name string) error {
|
|
||||||
f, err := gzip.NewReader(bytes.NewReader(glfwDLLCompressed))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
out, err := os.Create(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
if _, err := io.Copy(out, f); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadDLL() (*dll, error) {
|
|
||||||
cachedir, err := os.UserCacheDir()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dir := filepath.Join(cachedir, "ebiten")
|
|
||||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the file operation atomic among multiple processes.
|
|
||||||
fl := flock.New(filepath.Join(dir, glfwDLLHash+".lock"))
|
|
||||||
fl.Lock()
|
|
||||||
defer fl.Unlock()
|
|
||||||
|
|
||||||
fn := filepath.Join(dir, glfwDLLHash+".dll")
|
|
||||||
if _, err := os.Stat(fn); err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a DLL as a temporary file and then rename it later.
|
|
||||||
// Without the temporary file, writing a DLL might fail in the process of writing and Ebiten cannot
|
|
||||||
// notice that the DLL file is incomplete.
|
|
||||||
if err := writeDLLFile(fn + ".tmp"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.Rename(fn+".tmp", fn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dll{
|
|
||||||
d: windows.NewLazyDLL(fn),
|
|
||||||
}, nil
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2021 The Ebiten Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
//go:build tools
|
|
||||||
// +build tools
|
|
||||||
|
|
||||||
package glfw
|
|
||||||
|
|
||||||
import (
|
|
||||||
// Used in gen.go
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
|
@ -12,27 +12,19 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//go:build !js
|
|
||||||
// +build !js
|
|
||||||
|
|
||||||
package glfw
|
package glfw
|
||||||
|
|
||||||
type uniquePtr *byte
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/glfwwin"
|
||||||
type (
|
|
||||||
CharModsCallback uniquePtr
|
|
||||||
CloseCallback uniquePtr
|
|
||||||
FramebufferSizeCallback uniquePtr
|
|
||||||
MonitorCallback uniquePtr
|
|
||||||
ScrollCallback uniquePtr
|
|
||||||
SizeCallback uniquePtr
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type VidMode struct {
|
type (
|
||||||
Width int
|
CharModsCallback = glfwwin.CharModsCallback
|
||||||
Height int
|
CloseCallback = glfwwin.CloseCallback
|
||||||
RedBits int
|
FramebufferSizeCallback = glfwwin.FramebufferSizeCallback
|
||||||
GreenBits int
|
MonitorCallback = glfwwin.MonitorCallback
|
||||||
BlueBits int
|
ScrollCallback = glfwwin.ScrollCallback
|
||||||
RefreshRate int
|
SizeCallback = glfwwin.SizeCallback
|
||||||
}
|
)
|
||||||
|
|
||||||
|
type VidMode glfwwin.VidMode
|
||||||
|
@ -334,7 +334,8 @@ func platformTerminate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Restore previous foreground lock timeout system setting
|
// Restore previous foreground lock timeout system setting
|
||||||
if err := _SystemParametersInfoW(_SPI_SETFOREGROUNDLOCKTIMEOUT, 0, uintptr(_glfw.win32.foregroundLockTimeout), _SPIF_SENDCHANGE); err != nil {
|
if err := _SystemParametersInfoW(_SPI_SETFOREGROUNDLOCKTIMEOUT, 0, uintptr(_glfw.win32.foregroundLockTimeout), _SPIF_SENDCHANGE); err != nil && !errors.Is(err, windows.ERROR_ACCESS_DENIED) {
|
||||||
|
// Access-denied can happen on WSL.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,7 +1034,10 @@ func (u *userInterfaceImpl) update() (float64, float64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) loop() error {
|
func (u *userInterfaceImpl) loop() error {
|
||||||
defer u.t.Call(glfw.Terminate)
|
defer u.t.Call(func() {
|
||||||
|
u.window.Destroy()
|
||||||
|
glfw.Terminate()
|
||||||
|
})
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var unfocused bool
|
var unfocused bool
|
||||||
|
Loading…
Reference in New Issue
Block a user