mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
glfw: Add DLL build results
This also adds fixes for 32bit machines.
This commit is contained in:
parent
90f82de5ef
commit
ad285c2235
1
go.mod
1
go.mod
@ -14,6 +14,7 @@ require (
|
|||||||
github.com/theckman/go-flock v0.6.0
|
github.com/theckman/go-flock v0.6.0
|
||||||
golang.org/x/image v0.0.0-20180926015637-991ec62608f3
|
golang.org/x/image v0.0.0-20180926015637-991ec62608f3
|
||||||
golang.org/x/mobile v0.0.0-20180907224111-0ff817254b04
|
golang.org/x/mobile v0.0.0-20180907224111-0ff817254b04
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
|
||||||
golang.org/x/sys v0.0.0-20180814072032-4e1fef560951
|
golang.org/x/sys v0.0.0-20180814072032-4e1fef560951
|
||||||
golang.org/x/tools v0.0.0-20181023010539-40a48ad93fbe // indirect
|
golang.org/x/tools v0.0.0-20181023010539-40a48ad93fbe // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -43,6 +43,8 @@ golang.org/x/image v0.0.0-20180926015637-991ec62608f3/go.mod h1:ux5Hcp/YLpHSI86h
|
|||||||
golang.org/x/mobile v0.0.0-20180806140643-507816974b79/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20180806140643-507816974b79/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20180907224111-0ff817254b04 h1:quPNpjsj/QWqlvWw4OdGlA+ct0TPbmdJXYofkRod1Xo=
|
golang.org/x/mobile v0.0.0-20180907224111-0ff817254b04 h1:quPNpjsj/QWqlvWw4OdGlA+ct0TPbmdJXYofkRod1Xo=
|
||||||
golang.org/x/mobile v0.0.0-20180907224111-0ff817254b04/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20180907224111-0ff817254b04/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180806082429-34b17bdb4300/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180806082429-34b17bdb4300/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180814072032-4e1fef560951 h1:VfGaXvV9wRnTJreeGDE0FWEDiQP1WWUDmutCjCThDz8=
|
golang.org/x/sys v0.0.0-20180814072032-4e1fef560951 h1:VfGaXvV9wRnTJreeGDE0FWEDiQP1WWUDmutCjCThDz8=
|
||||||
golang.org/x/sys v0.0.0-20180814072032-4e1fef560951/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180814072032-4e1fef560951/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
154
internal/glfw/gen.go
Normal file
154
internal/glfw/gen.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
var srcs = []string{
|
||||||
|
"glfw/src/context.c",
|
||||||
|
"glfw/src/init.c",
|
||||||
|
"glfw/src/input.c",
|
||||||
|
"glfw/src/monitor.c",
|
||||||
|
"glfw/src/vulkan.c",
|
||||||
|
"glfw/src/window.c",
|
||||||
|
"glfw/src/win32_init.c",
|
||||||
|
"glfw/src/win32_joystick.c",
|
||||||
|
"glfw/src/win32_monitor.c",
|
||||||
|
"glfw/src/win32_time.c",
|
||||||
|
"glfw/src/win32_tls.c",
|
||||||
|
"glfw/src/win32_window.c",
|
||||||
|
"glfw/src/wgl_context.c",
|
||||||
|
"glfw/src/egl_context.c",
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{
|
||||||
|
"-input",
|
||||||
|
dll,
|
||||||
|
"-output",
|
||||||
|
fmt.Sprintf("glfwdll_windows_%s.go", arch),
|
||||||
|
"-package",
|
||||||
|
"glfw",
|
||||||
|
"-var",
|
||||||
|
"glfwDLLCompressed",
|
||||||
|
"-compress",
|
||||||
|
}
|
||||||
|
if err := execCommand("file2byteslice", args...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range objs {
|
||||||
|
if err := os.Remove(o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := os.Remove(dll); 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)
|
||||||
|
}
|
||||||
|
}
|
17
internal/glfw/generate.go
Normal file
17
internal/glfw/generate.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// 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:generate go run gen.go
|
||||||
|
|
||||||
|
package glfw
|
22
internal/glfw/glfw/COPYING.txt
Normal file
22
internal/glfw/glfw/COPYING.txt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
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.
|
||||||
|
|
117
internal/glfw/glfw/deps/mingw/_mingw_dxhelper.h
Normal file
117
internal/glfw/glfw/deps/mingw/_mingw_dxhelper.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* 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 */
|
||||||
|
|
2467
internal/glfw/glfw/deps/mingw/dinput.h
Normal file
2467
internal/glfw/glfw/deps/mingw/dinput.h
Normal file
File diff suppressed because it is too large
Load Diff
239
internal/glfw/glfw/deps/mingw/xinput.h
Normal file
239
internal/glfw/glfw/deps/mingw/xinput.h
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* 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 */
|
4248
internal/glfw/glfw/include/GLFW/glfw3.h
Normal file
4248
internal/glfw/glfw/include/GLFW/glfw3.h
Normal file
File diff suppressed because it is too large
Load Diff
456
internal/glfw/glfw/include/GLFW/glfw3native.h
Normal file
456
internal/glfw/glfw/include/GLFW/glfw3native.h
Normal file
@ -0,0 +1,456 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
* GLFW 3.2 - www.glfw.org
|
||||||
|
* A library for OpenGL, window and input
|
||||||
|
*------------------------------------------------------------------------
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#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
|
||||||
|
*
|
||||||
|
* **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 exactly one
|
||||||
|
* 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`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_MIR`
|
||||||
|
*
|
||||||
|
* The available context API macros are:
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_WGL`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_NSGL`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_GLX`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_EGL`
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||||
|
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||||
|
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||||
|
#undef APIENTRY
|
||||||
|
#include <windows.h>
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
#if defined(__OBJC__)
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#else
|
||||||
|
typedef void* id;
|
||||||
|
#endif
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_X11)
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_MIR)
|
||||||
|
#include <mir_toolkit/mir_client_library.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
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
#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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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_MIR)
|
||||||
|
/*! @brief Returns the `MirConnection*` used by GLFW.
|
||||||
|
*
|
||||||
|
* @return The `MirConnection*` used by GLFW, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.2.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI MirConnection* glfwGetMirDisplay(void);
|
||||||
|
|
||||||
|
/*! @brief Returns the Mir output ID of the specified monitor.
|
||||||
|
*
|
||||||
|
* @return The Mir output ID of the specified monitor, or zero if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.2.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @brief Returns the `MirSurface*` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `MirSurface*` of the specified window, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.2.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI MirSurface* glfwGetMirWindow(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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _glfw3_native_h_ */
|
||||||
|
|
720
internal/glfw/glfw/src/context.c
Normal file
720
internal/glfw/glfw/src/context.c
Normal file
@ -0,0 +1,720 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||||
|
{
|
||||||
|
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
|
||||||
|
ctxconfig->source != GLFW_EGL_CONTEXT_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid context creation API %i",
|
||||||
|
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 %i",
|
||||||
|
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 %i",
|
||||||
|
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 %i",
|
||||||
|
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 %i",
|
||||||
|
ctxconfig->release);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->doublebuffer != current->doublebuffer)
|
||||||
|
{
|
||||||
|
// Double buffering 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
_GLFWwindow* window;
|
||||||
|
const char* version;
|
||||||
|
const char* prefixes[] =
|
||||||
|
{
|
||||||
|
"OpenGL ES-CM ",
|
||||||
|
"OpenGL ES-CL ",
|
||||||
|
"OpenGL ES ",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
window->context.source = ctxconfig->source;
|
||||||
|
window->context.client = GLFW_OPENGL_API;
|
||||||
|
|
||||||
|
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");
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
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);
|
||||||
|
window->context.swapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (window && window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
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 (GLFWwindow*) _glfwPlatformGetCurrentContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
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, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.swapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSwapInterval(int interval)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
window = _glfwPlatformGetCurrentContext();
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.swapInterval(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
assert(extension != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
window = _glfwPlatformGetCurrentContext();
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*extension == '\0')
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Extension name is 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 = _glfwPlatformGetCurrentContext();
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.getProcAddress(procname);
|
||||||
|
}
|
||||||
|
|
746
internal/glfw/glfw/src/egl_context.c
Normal file
746
internal/glfw/glfw/src/egl_context.c
Normal file
@ -0,0 +1,746 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 EGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#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)
|
||||||
|
// Only consider EGLConfigs with associated Visuals
|
||||||
|
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||||
|
continue;
|
||||||
|
#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 = GLFW_TRUE;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetCurrentContext(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersEGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window != _glfwPlatformGetCurrentContext())
|
||||||
|
{
|
||||||
|
_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 = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
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_WIN32)
|
||||||
|
"libEGL.dll",
|
||||||
|
"EGL.dll",
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
"libEGL.dylib",
|
||||||
|
#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 = (PFNEGLGETCONFIGATTRIBPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
|
||||||
|
_glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
|
||||||
|
_glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
|
||||||
|
_glfw.egl.GetError = (PFNEGLGETERRORPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
|
||||||
|
_glfw.egl.Initialize = (PFNEGLINITIALIZEPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
|
||||||
|
_glfw.egl.Terminate = (PFNEGLTERMINATEPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
|
||||||
|
_glfw.egl.BindAPI = (PFNEGLBINDAPIPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
|
||||||
|
_glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
|
||||||
|
_glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
|
||||||
|
_glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
|
||||||
|
_glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
|
||||||
|
_glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
|
||||||
|
_glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
|
||||||
|
_glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
|
||||||
|
_glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
|
||||||
|
_glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC)
|
||||||
|
_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");
|
||||||
|
|
||||||
|
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 setEGLattrib(attribName, attribValue) \
|
||||||
|
{ \
|
||||||
|
attribs[index++] = attribName; \
|
||||||
|
attribs[index++] = attribValue; \
|
||||||
|
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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 index = 0, 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 (_glfw.egl.KHR_create_context_no_error)
|
||||||
|
{
|
||||||
|
if (ctxconfig->noerror)
|
||||||
|
flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->debug)
|
||||||
|
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||||
|
|
||||||
|
if (ctxconfig->robustness)
|
||||||
|
{
|
||||||
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
|
{
|
||||||
|
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
|
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
|
{
|
||||||
|
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
|
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
|
{
|
||||||
|
setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||||
|
setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||||
|
|
||||||
|
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||||
|
|
||||||
|
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||||
|
// supported on EGL but are not a hard constraint, so ignore and continue
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
if (fbconfig->sRGB)
|
||||||
|
{
|
||||||
|
if (_glfw.egl.KHR_gl_colorspace)
|
||||||
|
{
|
||||||
|
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setEGLattrib(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
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char** sonames;
|
||||||
|
const char* es1sonames[] =
|
||||||
|
{
|
||||||
|
#if 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_WIN32)
|
||||||
|
"GLESv2.dll",
|
||||||
|
"libGLESv2.dll",
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
"libGLESv2.dylib",
|
||||||
|
#else
|
||||||
|
"libGLESv2.so.2",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
const char* glsonames[] =
|
||||||
|
{
|
||||||
|
#if 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 setEGLattrib
|
||||||
|
|
||||||
|
// Returns the Visual and depth of the chosen EGLConfig
|
||||||
|
//
|
||||||
|
#if defined(_GLFW_X11)
|
||||||
|
GLFWbool _glfwChooseVisualEGL(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.client == GLFW_NO_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.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.egl.surface;
|
||||||
|
}
|
||||||
|
|
213
internal/glfw/glfw/src/egl_context.h
Normal file
213
internal/glfw/glfw/src/egl_context.h
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 EGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#ifndef _glfw3_egl_context_h_
|
||||||
|
#define _glfw3_egl_context_h_
|
||||||
|
|
||||||
|
#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_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;
|
||||||
|
#elif defined(_GLFW_MIR)
|
||||||
|
#define EGLAPIENTRY
|
||||||
|
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
|
||||||
|
typedef MirEGLNativeWindowType 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_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
|
||||||
|
|
||||||
|
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 * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||||
|
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
|
||||||
|
typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);
|
||||||
|
typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);
|
||||||
|
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);
|
||||||
|
typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);
|
||||||
|
typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(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;
|
||||||
|
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;
|
||||||
|
PFNEGLGETCONFIGSPROC GetConfigs;
|
||||||
|
PFNEGLGETDISPLAYPROC GetDisplay;
|
||||||
|
PFNEGLGETERRORPROC GetError;
|
||||||
|
PFNEGLINITIALIZEPROC Initialize;
|
||||||
|
PFNEGLTERMINATEPROC Terminate;
|
||||||
|
PFNEGLBINDAPIPROC BindAPI;
|
||||||
|
PFNEGLCREATECONTEXTPROC CreateContext;
|
||||||
|
PFNEGLDESTROYSURFACEPROC DestroySurface;
|
||||||
|
PFNEGLDESTROYCONTEXTPROC DestroyContext;
|
||||||
|
PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;
|
||||||
|
PFNEGLMAKECURRENTPROC MakeCurrent;
|
||||||
|
PFNEGLSWAPBUFFERSPROC SwapBuffers;
|
||||||
|
PFNEGLSWAPINTERVALPROC SwapInterval;
|
||||||
|
PFNEGLQUERYSTRINGPROC QueryString;
|
||||||
|
PFNEGLGETPROCADDRESSPROC 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 _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig,
|
||||||
|
Visual** visual, int* depth);
|
||||||
|
#endif /*_GLFW_X11*/
|
||||||
|
|
||||||
|
#endif // _glfw3_egl_context_h_
|
200
internal/glfw/glfw/src/init.c
Normal file
200
internal/glfw/glfw/src/init.c
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
// The three global variables below comprise all global data in GLFW.
|
||||||
|
// Any other global variable is a bug.
|
||||||
|
|
||||||
|
// Global state shared between compilation units of GLFW
|
||||||
|
// These are documented in internal.h
|
||||||
|
//
|
||||||
|
GLFWbool _glfwInitialized = GLFW_FALSE;
|
||||||
|
_GLFWlibrary _glfw;
|
||||||
|
|
||||||
|
// This is outside of _glfw so it can be initialized and usable before
|
||||||
|
// glfwInit is called, which lets that function report errors
|
||||||
|
//
|
||||||
|
static GLFWerrorfun _glfwErrorCallback = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a generic string representation of the specified error
|
||||||
|
//
|
||||||
|
static const char* getErrorString(int error)
|
||||||
|
{
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case GLFW_NOT_INITIALIZED:
|
||||||
|
return "The GLFW library is not initialized";
|
||||||
|
case GLFW_NO_CURRENT_CONTEXT:
|
||||||
|
return "There is no current context";
|
||||||
|
case GLFW_INVALID_ENUM:
|
||||||
|
return "Invalid argument for enum parameter";
|
||||||
|
case GLFW_INVALID_VALUE:
|
||||||
|
return "Invalid value for parameter";
|
||||||
|
case GLFW_OUT_OF_MEMORY:
|
||||||
|
return "Out of memory";
|
||||||
|
case GLFW_API_UNAVAILABLE:
|
||||||
|
return "The requested API is unavailable";
|
||||||
|
case GLFW_VERSION_UNAVAILABLE:
|
||||||
|
return "The requested API version is unavailable";
|
||||||
|
case GLFW_PLATFORM_ERROR:
|
||||||
|
return "A platform-specific error occurred";
|
||||||
|
case GLFW_FORMAT_UNAVAILABLE:
|
||||||
|
return "The requested format is unavailable";
|
||||||
|
case GLFW_NO_WINDOW_CONTEXT:
|
||||||
|
return "The specified window has no context";
|
||||||
|
default:
|
||||||
|
return "ERROR: UNKNOWN GLFW ERROR";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW event API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwInputError(int error, const char* format, ...)
|
||||||
|
{
|
||||||
|
if (_glfwErrorCallback)
|
||||||
|
{
|
||||||
|
char buffer[8192];
|
||||||
|
const char* description;
|
||||||
|
|
||||||
|
if (format)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
va_list vl;
|
||||||
|
|
||||||
|
va_start(vl, format);
|
||||||
|
count = vsnprintf(buffer, sizeof(buffer), format, vl);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
if (count < 0)
|
||||||
|
buffer[sizeof(buffer) - 1] = '\0';
|
||||||
|
|
||||||
|
description = buffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
description = getErrorString(error);
|
||||||
|
|
||||||
|
_glfwErrorCallback(error, description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI int glfwInit(void)
|
||||||
|
{
|
||||||
|
if (_glfwInitialized)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
|
|
||||||
|
if (!_glfwPlatformInit())
|
||||||
|
{
|
||||||
|
_glfwPlatformTerminate();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||||
|
_glfwInitialized = GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfw.timerOffset = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
|
// Not all window hints have zero as their default value
|
||||||
|
glfwDefaultWindowHints();
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwTerminate(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!_glfwInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwTerminateVulkan();
|
||||||
|
|
||||||
|
_glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
|
||||||
|
_glfw.monitors = NULL;
|
||||||
|
_glfw.monitorCount = 0;
|
||||||
|
|
||||||
|
_glfwPlatformTerminate();
|
||||||
|
|
||||||
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
|
_glfwInitialized = GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
659
internal/glfw/glfw/src/input.c
Normal file
659
internal/glfw/glfw/src/input.c
Normal file
@ -0,0 +1,659 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// Internal key state used for sticky keys
|
||||||
|
#define _GLFW_STICK 3
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW event API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
|
{
|
||||||
|
if (key >= 0 && key <= GLFW_KEY_LAST)
|
||||||
|
{
|
||||||
|
GLFWbool repeated = GLFW_FALSE;
|
||||||
|
|
||||||
|
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
|
||||||
|
repeated = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (action == GLFW_RELEASE && window->stickyKeys)
|
||||||
|
window->keys[key] = _GLFW_STICK;
|
||||||
|
else
|
||||||
|
window->keys[key] = (char) action;
|
||||||
|
|
||||||
|
if (repeated)
|
||||||
|
action = GLFW_REPEAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->callbacks.key)
|
||||||
|
window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
|
||||||
|
{
|
||||||
|
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (window->callbacks.charmods)
|
||||||
|
window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
|
||||||
|
|
||||||
|
if (plain)
|
||||||
|
{
|
||||||
|
if (window->callbacks.character)
|
||||||
|
window->callbacks.character((GLFWwindow*) window, codepoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
||||||
|
{
|
||||||
|
if (window->callbacks.scroll)
|
||||||
|
window->callbacks.scroll((GLFWwindow*) window, &xoffset, &yoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
||||||
|
{
|
||||||
|
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Register mouse button action
|
||||||
|
if (action == GLFW_RELEASE && window->stickyMouseButtons)
|
||||||
|
window->mouseButtons[button] = _GLFW_STICK;
|
||||||
|
else
|
||||||
|
window->mouseButtons[button] = (char) action;
|
||||||
|
|
||||||
|
if (window->callbacks.mouseButton)
|
||||||
|
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||||
|
{
|
||||||
|
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window->virtualCursorPosX = xpos;
|
||||||
|
window->virtualCursorPosY = ypos;
|
||||||
|
|
||||||
|
if (window->callbacks.cursorPos)
|
||||||
|
window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
||||||
|
{
|
||||||
|
if (window->callbacks.cursorEnter)
|
||||||
|
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
||||||
|
{
|
||||||
|
if (window->callbacks.drop)
|
||||||
|
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputJoystickChange(int joy, int event)
|
||||||
|
{
|
||||||
|
if (_glfw.callbacks.joystick)
|
||||||
|
_glfw.callbacks.joystick(joy, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwIsPrintable(int key)
|
||||||
|
{
|
||||||
|
return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||
|
||||||
|
(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||
|
||||||
|
key == GLFW_KEY_KP_EQUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case GLFW_CURSOR:
|
||||||
|
return window->cursorMode;
|
||||||
|
case GLFW_STICKY_KEYS:
|
||||||
|
return window->stickyKeys;
|
||||||
|
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||||
|
return window->stickyMouseButtons;
|
||||||
|
default:
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case GLFW_CURSOR:
|
||||||
|
{
|
||||||
|
if (value != GLFW_CURSOR_NORMAL &&
|
||||||
|
value != GLFW_CURSOR_HIDDEN &&
|
||||||
|
value != GLFW_CURSOR_DISABLED)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid cursor mode %i",
|
||||||
|
value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->cursorMode == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window->cursorMode = value;
|
||||||
|
|
||||||
|
_glfwPlatformGetCursorPos(window,
|
||||||
|
&window->virtualCursorPosX,
|
||||||
|
&window->virtualCursorPosY);
|
||||||
|
|
||||||
|
if (_glfwPlatformWindowFocused(window))
|
||||||
|
_glfwPlatformSetCursorMode(window, value);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLFW_STICKY_KEYS:
|
||||||
|
{
|
||||||
|
if (window->stickyKeys == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Release all sticky keys
|
||||||
|
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||||
|
{
|
||||||
|
if (window->keys[i] == _GLFW_STICK)
|
||||||
|
window->keys[i] = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||||
|
{
|
||||||
|
if (window->stickyMouseButtons == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Release all sticky mouse buttons
|
||||||
|
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||||
|
{
|
||||||
|
if (window->mouseButtons[i] == _GLFW_STICK)
|
||||||
|
window->mouseButtons[i] = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return _glfwPlatformGetKeyName(key, scancode);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
|
||||||
|
|
||||||
|
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
|
||||||
|
return GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->keys[key] == _GLFW_STICK)
|
||||||
|
{
|
||||||
|
// Sticky mode: release key now
|
||||||
|
window->keys[key] = GLFW_RELEASE;
|
||||||
|
return GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) window->keys[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
|
||||||
|
|
||||||
|
if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
|
||||||
|
return GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->mouseButtons[button] == _GLFW_STICK)
|
||||||
|
{
|
||||||
|
// Sticky mode: release mouse button now
|
||||||
|
window->mouseButtons[button] = GLFW_RELEASE;
|
||||||
|
return GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) window->mouseButtons[button];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = 0;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
|
{
|
||||||
|
if (xpos)
|
||||||
|
*xpos = window->virtualCursorPosX;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = window->virtualCursorPosY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_glfwPlatformGetCursorPos(window, xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
|
||||||
|
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid cursor position %f %f",
|
||||||
|
xpos, ypos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfwPlatformWindowFocused(window))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
|
{
|
||||||
|
// Only update the accumulated position if the cursor is disabled
|
||||||
|
window->virtualCursorPosX = xpos;
|
||||||
|
window->virtualCursorPosY = ypos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Update system cursor position
|
||||||
|
_glfwPlatformSetCursorPos(window, xpos, ypos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
|
||||||
|
{
|
||||||
|
_GLFWcursor* cursor;
|
||||||
|
|
||||||
|
assert(image != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
cursor = calloc(1, sizeof(_GLFWcursor));
|
||||||
|
cursor->next = _glfw.cursorListHead;
|
||||||
|
_glfw.cursorListHead = cursor;
|
||||||
|
|
||||||
|
if (!_glfwPlatformCreateCursor(cursor, image, xhot, yhot))
|
||||||
|
{
|
||||||
|
glfwDestroyCursor((GLFWcursor*) cursor);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (GLFWcursor*) cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
|
||||||
|
{
|
||||||
|
_GLFWcursor* cursor;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (shape != GLFW_ARROW_CURSOR &&
|
||||||
|
shape != GLFW_IBEAM_CURSOR &&
|
||||||
|
shape != GLFW_CROSSHAIR_CURSOR &&
|
||||||
|
shape != GLFW_HAND_CURSOR &&
|
||||||
|
shape != GLFW_HRESIZE_CURSOR &&
|
||||||
|
shape != GLFW_VRESIZE_CURSOR)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = calloc(1, sizeof(_GLFWcursor));
|
||||||
|
cursor->next = _glfw.cursorListHead;
|
||||||
|
_glfw.cursorListHead = cursor;
|
||||||
|
|
||||||
|
if (!_glfwPlatformCreateStandardCursor(cursor, shape))
|
||||||
|
{
|
||||||
|
glfwDestroyCursor((GLFWcursor*) cursor);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (GLFWcursor*) cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
|
||||||
|
{
|
||||||
|
_GLFWcursor* cursor = (_GLFWcursor*) handle;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (cursor == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make sure the cursor is not being used by any window
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
{
|
||||||
|
if (window->cursor == cursor)
|
||||||
|
glfwSetCursor((GLFWwindow*) window, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformDestroyCursor(cursor);
|
||||||
|
|
||||||
|
// Unlink cursor from global linked list
|
||||||
|
{
|
||||||
|
_GLFWcursor** prev = &_glfw.cursorListHead;
|
||||||
|
|
||||||
|
while (*prev != cursor)
|
||||||
|
prev = &((*prev)->next);
|
||||||
|
|
||||||
|
*prev = cursor->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) windowHandle;
|
||||||
|
_GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
window->cursor = cursor;
|
||||||
|
|
||||||
|
_glfwPlatformSetCursor(window, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.key, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.character, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
|
||||||
|
GLFWmousebuttonfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
|
||||||
|
GLFWcursorposfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
|
||||||
|
GLFWcursorenterfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
|
||||||
|
GLFWscrollfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwJoystickPresent(int joy)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
|
||||||
|
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformJoystickPresent(joy);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
|
||||||
|
{
|
||||||
|
assert(count != NULL);
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformGetJoystickAxes(joy, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count)
|
||||||
|
{
|
||||||
|
assert(count != NULL);
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformGetJoystickButtons(joy, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetJoystickName(int joy)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformGetJoystickName(joy);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
assert(string != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformSetClipboardString(window, string);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return _glfwPlatformGetClipboardString(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI double glfwGetTime(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
||||||
|
return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
|
||||||
|
_glfwPlatformGetTimerFrequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetTime(double time)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (time != time || time < 0.0 || time > 18446744073.0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.timerOffset = _glfwPlatformGetTimerValue() -
|
||||||
|
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI uint64_t glfwGetTimerValue(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
return _glfwPlatformGetTimerValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI uint64_t glfwGetTimerFrequency(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
return _glfwPlatformGetTimerFrequency();
|
||||||
|
}
|
||||||
|
|
1055
internal/glfw/glfw/src/internal.h
Normal file
1055
internal/glfw/glfw/src/internal.h
Normal file
File diff suppressed because it is too large
Load Diff
477
internal/glfw/glfw/src/monitor.c
Normal file
477
internal/glfw/glfw/src/monitor.c
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
// 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 //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwInputMonitorChange(void)
|
||||||
|
{
|
||||||
|
int i, j, monitorCount = _glfw.monitorCount;
|
||||||
|
_GLFWmonitor** monitors = _glfw.monitors;
|
||||||
|
|
||||||
|
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||||
|
|
||||||
|
// Re-use still connected monitor objects
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < monitorCount; j++)
|
||||||
|
{
|
||||||
|
if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j]))
|
||||||
|
{
|
||||||
|
_glfwFreeMonitor(_glfw.monitors[i]);
|
||||||
|
_glfw.monitors[i] = monitors[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find and report disconnected monitors (not in the new list)
|
||||||
|
|
||||||
|
for (i = 0; i < monitorCount; i++)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
for (j = 0; j < _glfw.monitorCount; j++)
|
||||||
|
{
|
||||||
|
if (monitors[i] == _glfw.monitors[j])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j < _glfw.monitorCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
{
|
||||||
|
if (window->monitor == monitors[i])
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
|
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.callbacks.monitor)
|
||||||
|
_glfw.callbacks.monitor((GLFWmonitor*) monitors[i], GLFW_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find and report newly connected monitors (not in the old list)
|
||||||
|
// Re-used monitor objects are then removed from the old list to avoid
|
||||||
|
// having them destroyed at the end of this function
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < monitorCount; j++)
|
||||||
|
{
|
||||||
|
if (_glfw.monitors[i] == monitors[j])
|
||||||
|
{
|
||||||
|
monitors[j] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j < monitorCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (_glfw.callbacks.monitor)
|
||||||
|
_glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwFreeMonitors(monitors, monitorCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||||
|
{
|
||||||
|
monitor->window = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
||||||
|
monitor->name = strdup(name);
|
||||||
|
monitor->widthMM = widthMM;
|
||||||
|
monitor->heightMM = heightMM;
|
||||||
|
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
if (monitor == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwFreeGammaArrays(&monitor->originalRamp);
|
||||||
|
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||||
|
|
||||||
|
free(monitor->modes);
|
||||||
|
free(monitor->name);
|
||||||
|
free(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
free(ramp->red);
|
||||||
|
free(ramp->green);
|
||||||
|
free(ramp->blue);
|
||||||
|
|
||||||
|
memset(ramp, 0, sizeof(GLFWgammaramp));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
_glfwFreeMonitor(monitors[i]);
|
||||||
|
|
||||||
|
free(monitors);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
|
||||||
|
{
|
||||||
|
return compareVideoModes(fm, sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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 const char* glfwGetMonitorName(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return monitor->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned short values[256];
|
||||||
|
GLFWgammaramp ramp;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
|
||||||
|
// Calculate intensity
|
||||||
|
value = i / 255.0;
|
||||||
|
// Apply gamma curve
|
||||||
|
value = pow(value, 1.0 / gamma) * 65535.0 + 0.5;
|
||||||
|
|
||||||
|
// Clamp to value range
|
||||||
|
if (value > 65535.0)
|
||||||
|
value = 65535.0;
|
||||||
|
|
||||||
|
values[i] = (unsigned short) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ramp.red = values;
|
||||||
|
ramp.green = values;
|
||||||
|
ramp.blue = values;
|
||||||
|
ramp.size = 256;
|
||||||
|
|
||||||
|
glfwSetGammaRamp(handle, &ramp);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||||
|
_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
|
||||||
|
|
||||||
|
return &monitor->currentRamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
assert(ramp != NULL);
|
||||||
|
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)
|
||||||
|
_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
|
||||||
|
|
||||||
|
_glfwPlatformSetGammaRamp(monitor, ramp);
|
||||||
|
}
|
||||||
|
|
302
internal/glfw/glfw/src/vulkan.c
Normal file
302
internal/glfw/glfw/src/vulkan.c
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwInitVulkan(void)
|
||||||
|
{
|
||||||
|
VkResult err;
|
||||||
|
VkExtensionProperties* ep;
|
||||||
|
uint32_t i, count;
|
||||||
|
|
||||||
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
|
#if defined(_GLFW_WIN32)
|
||||||
|
const char* name = "vulkan-1.dll";
|
||||||
|
#else
|
||||||
|
const char* name = "libvulkan.so.1";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_glfw.vk.available)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfw.vk.handle = _glfw_dlopen(name);
|
||||||
|
if (!_glfw.vk.handle)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"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_PLATFORM_ERROR,
|
||||||
|
"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 (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||||
|
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
||||||
|
if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||||
|
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
||||||
|
if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
|
||||||
|
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
|
||||||
|
if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
||||||
|
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
|
||||||
|
if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
|
||||||
|
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ep);
|
||||||
|
|
||||||
|
_glfw.vk.available = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (_glfw.vk.KHR_surface)
|
||||||
|
{
|
||||||
|
_glfw.vk.extensions =
|
||||||
|
_glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwTerminateVulkan(void)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.vk.extensionCount; i++)
|
||||||
|
free(_glfw.vk.extensions[i]);
|
||||||
|
free(_glfw.vk.extensions);
|
||||||
|
|
||||||
|
if (_glfw.vk.handle)
|
||||||
|
_glfw_dlclose(_glfw.vk.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||||
|
{
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan())
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*count = _glfw.vk.extensionCount;
|
||||||
|
return (const char**) _glfw.vk.extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
||||||
|
const char* procname)
|
||||||
|
{
|
||||||
|
GLFWvkproc proc;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan())
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
||||||
|
if (!proc)
|
||||||
|
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
||||||
|
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||||
|
VkPhysicalDevice device,
|
||||||
|
uint32_t queuefamily)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan())
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfw.vk.extensions)
|
||||||
|
{
|
||||||
|
_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(window != NULL);
|
||||||
|
assert(surface != NULL);
|
||||||
|
|
||||||
|
*surface = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan())
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfw.vk.extensions)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Vulkan: Window surface creation extensions not found");
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
|
||||||
|
}
|
||||||
|
|
718
internal/glfw/glfw/src/wgl_context.c
Normal file
718
internal/glfw/glfw/src/wgl_context.c
Normal file
@ -0,0 +1,718 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 WGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the specified attribute of the specified pixel format
|
||||||
|
//
|
||||||
|
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
|
||||||
|
{
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
assert(_glfw.wgl.ARB_pixel_format);
|
||||||
|
|
||||||
|
if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
|
||||||
|
pixelFormat,
|
||||||
|
0, 1, &attrib, &value))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve pixel format attribute %i",
|
||||||
|
attrib);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a list of available and usable framebuffer configs
|
||||||
|
//
|
||||||
|
static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
|
||||||
|
{
|
||||||
|
_GLFWfbconfig* usableConfigs;
|
||||||
|
const _GLFWfbconfig* closest;
|
||||||
|
int i, pixelFormat, nativeCount, usableCount;
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_pixel_format)
|
||||||
|
{
|
||||||
|
nativeCount = getPixelFormatAttrib(window,
|
||||||
|
1,
|
||||||
|
WGL_NUMBER_PIXEL_FORMATS_ARB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nativeCount = DescribePixelFormat(window->context.wgl.dc,
|
||||||
|
1,
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
|
usableCount = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < nativeCount; i++)
|
||||||
|
{
|
||||||
|
const int n = i + 1;
|
||||||
|
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_pixel_format)
|
||||||
|
{
|
||||||
|
// Get pixel format attributes through "modern" extension
|
||||||
|
|
||||||
|
if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
|
||||||
|
!getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
|
||||||
|
WGL_TYPE_RGBA_ARB)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
|
||||||
|
WGL_NO_ACCELERATION_ARB)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
|
||||||
|
u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
|
||||||
|
u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
|
||||||
|
u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
|
||||||
|
|
||||||
|
u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
|
||||||
|
u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
|
||||||
|
|
||||||
|
u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
|
||||||
|
u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
|
||||||
|
u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
|
||||||
|
u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
|
||||||
|
|
||||||
|
u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
|
||||||
|
|
||||||
|
if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
|
||||||
|
u->stereo = GLFW_TRUE;
|
||||||
|
if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
|
||||||
|
u->doublebuffer = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_multisample)
|
||||||
|
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||||
|
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||||
|
{
|
||||||
|
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||||
|
u->sRGB = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
|
||||||
|
// Get pixel format attributes through legacy PFDs
|
||||||
|
|
||||||
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
|
n,
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
&pfd))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (pfd.dwFlags & PFD_DOUBLEBUFFER)
|
||||||
|
u->doublebuffer = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->handle = n;
|
||||||
|
usableCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usableCount)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"WGL: The driver does not appear to support OpenGL");
|
||||||
|
|
||||||
|
free(usableConfigs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
closest = _glfwChooseFBConfig(desired, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns whether desktop compositing is enabled
|
||||||
|
//
|
||||||
|
static GLFWbool isCompositionEnabled(void)
|
||||||
|
{
|
||||||
|
BOOL enabled;
|
||||||
|
|
||||||
|
if (!_glfw_DwmIsCompositionEnabled)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
||||||
|
_glfwPlatformSetCurrentContext(window);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to make context current");
|
||||||
|
_glfwPlatformSetCurrentContext(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!wglMakeCurrent(NULL, NULL))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to clear current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetCurrentContext(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersWGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
// HACK: Use DwmFlush when desktop composition is enabled
|
||||||
|
if (isCompositionEnabled() && !window->monitor)
|
||||||
|
{
|
||||||
|
int count = abs(window->context.wgl.interval);
|
||||||
|
while (count--)
|
||||||
|
_glfw_DwmFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapBuffers(window->context.wgl.dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapIntervalWGL(int interval)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
window->context.wgl.interval = interval;
|
||||||
|
|
||||||
|
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
||||||
|
// avoid interfering with DWM vsync
|
||||||
|
if (isCompositionEnabled() && !window->monitor)
|
||||||
|
interval = 0;
|
||||||
|
|
||||||
|
if (_glfw.wgl.EXT_swap_control)
|
||||||
|
_glfw.wgl.SwapIntervalEXT(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extensionSupportedWGL(const char* extension)
|
||||||
|
{
|
||||||
|
const char* extensions;
|
||||||
|
|
||||||
|
if (_glfw.wgl.GetExtensionsStringEXT)
|
||||||
|
{
|
||||||
|
extensions = _glfw.wgl.GetExtensionsStringEXT();
|
||||||
|
if (extensions)
|
||||||
|
{
|
||||||
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.wgl.GetExtensionsStringARB)
|
||||||
|
{
|
||||||
|
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
|
||||||
|
if (extensions)
|
||||||
|
{
|
||||||
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWglproc getProcAddressWGL(const char* procname)
|
||||||
|
{
|
||||||
|
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
|
||||||
|
if (proc)
|
||||||
|
return proc;
|
||||||
|
|
||||||
|
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the OpenGL context
|
||||||
|
//
|
||||||
|
static void destroyContextWGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->context.wgl.handle)
|
||||||
|
{
|
||||||
|
wglDeleteContext(window->context.wgl.handle);
|
||||||
|
window->context.wgl.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize WGL-specific extensions
|
||||||
|
//
|
||||||
|
static void loadWGLExtensions(void)
|
||||||
|
{
|
||||||
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
HGLRC rc;
|
||||||
|
HDC dc = GetDC(_glfw.win32.helperWindowHandle);;
|
||||||
|
|
||||||
|
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to set pixel format for dummy context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = wglCreateContext(dc);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to create dummy context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wglMakeCurrent(dc, rc))
|
||||||
|
{
|
||||||
|
wglDeleteContext(rc);
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to make dummy context current");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.EXT_swap_control =
|
||||||
|
extensionSupportedWGL("WGL_EXT_swap_control");
|
||||||
|
_glfw.wgl.ARB_pixel_format =
|
||||||
|
extensionSupportedWGL("WGL_ARB_pixel_format");
|
||||||
|
_glfw.wgl.ARB_context_flush_control =
|
||||||
|
extensionSupportedWGL("WGL_ARB_context_flush_control");
|
||||||
|
|
||||||
|
wglMakeCurrent(dc, NULL);
|
||||||
|
wglDeleteContext(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize WGL
|
||||||
|
//
|
||||||
|
GLFWbool _glfwInitWGL(void)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.instance)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
||||||
|
if (!_glfw.wgl.instance)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.wgl.CreateContext = (WGLCREATECONTEXT_T)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
|
||||||
|
_glfw.wgl.DeleteContext = (WGLDELETECONTEXT_T)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
|
||||||
|
_glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
|
||||||
|
_glfw.wgl.GetCurrentDC = (WGLGETCURRENTDC_T)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
|
||||||
|
_glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
|
||||||
|
_glfw.wgl.ShareLists = (WGLSHARELISTS_T)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate WGL
|
||||||
|
//
|
||||||
|
void _glfwTerminateWGL(void)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.instance)
|
||||||
|
FreeLibrary(_glfw.wgl.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define setWGLattrib(attribName, attribValue) \
|
||||||
|
{ \
|
||||||
|
attribs[index++] = attribName; \
|
||||||
|
attribs[index++] = attribValue; \
|
||||||
|
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (!_glfw.wgl.extensionsLoaded)
|
||||||
|
loadWGLExtensions();
|
||||||
|
|
||||||
|
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, fbconfig);
|
||||||
|
if (!pixelFormat)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
|
pixelFormat, sizeof(pfd), &pfd))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
||||||
|
{
|
||||||
|
_glfwInputError(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->noerror)
|
||||||
|
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
||||||
|
|
||||||
|
if (ctxconfig->robustness)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.ARB_create_context_robustness)
|
||||||
|
{
|
||||||
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
|
{
|
||||||
|
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
|
{
|
||||||
|
setWGLattrib(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)
|
||||||
|
{
|
||||||
|
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
|
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
{
|
||||||
|
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
|
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||||
|
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||||
|
|
||||||
|
setWGLattrib(0, 0);
|
||||||
|
|
||||||
|
window->context.wgl.handle =
|
||||||
|
_glfw.wgl.CreateContextAttribsARB(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 (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)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: Failed to create OpenGL context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (share)
|
||||||
|
{
|
||||||
|
if (!wglShareLists(share, window->context.wgl.handle))
|
||||||
|
{
|
||||||
|
_glfwInputError(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 setWGLattrib
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.wgl.handle;
|
||||||
|
}
|
||||||
|
|
157
internal/glfw/glfw/src/wgl_context.h
Normal file
157
internal/glfw/glfw/src/wgl_context.h
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 WGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#ifndef _glfw3_wgl_context_h_
|
||||||
|
#define _glfw3_wgl_context_h_
|
||||||
|
|
||||||
|
|
||||||
|
#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 ERROR_INVALID_VERSION_ARB 0x2095
|
||||||
|
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
||||||
|
|
||||||
|
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*);
|
||||||
|
|
||||||
|
typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC);
|
||||||
|
typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC);
|
||||||
|
typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR);
|
||||||
|
typedef HDC (WINAPI * WGLGETCURRENTDC_T)(void);
|
||||||
|
typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);
|
||||||
|
typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
|
||||||
|
|
||||||
|
// opengl32.dll function pointer typedefs
|
||||||
|
#define wglCreateContext _glfw.wgl.CreateContext
|
||||||
|
#define wglDeleteContext _glfw.wgl.DeleteContext
|
||||||
|
#define wglGetProcAddress _glfw.wgl.GetProcAddress
|
||||||
|
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
|
||||||
|
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
||||||
|
#define wglShareLists _glfw.wgl.ShareLists
|
||||||
|
|
||||||
|
#define _GLFW_RECREATION_NOT_NEEDED 0
|
||||||
|
#define _GLFW_RECREATION_REQUIRED 1
|
||||||
|
#define _GLFW_RECREATION_IMPOSSIBLE 2
|
||||||
|
|
||||||
|
#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;
|
||||||
|
WGLCREATECONTEXT_T CreateContext;
|
||||||
|
WGLDELETECONTEXT_T DeleteContext;
|
||||||
|
WGLGETPROCADDRESS_T GetProcAddress;
|
||||||
|
WGLGETCURRENTDC_T GetCurrentDC;
|
||||||
|
WGLMAKECURRENT_T MakeCurrent;
|
||||||
|
WGLSHARELISTS_T ShareLists;
|
||||||
|
|
||||||
|
GLFWbool extensionsLoaded;
|
||||||
|
|
||||||
|
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
|
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
|
||||||
|
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
||||||
|
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
||||||
|
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||||
|
GLFWbool EXT_swap_control;
|
||||||
|
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_context_flush_control;
|
||||||
|
|
||||||
|
} _GLFWlibraryWGL;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwInitWGL(void);
|
||||||
|
void _glfwTerminateWGL(void);
|
||||||
|
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
|
#endif // _glfw3_wgl_context_h_
|
473
internal/glfw/glfw/src/win32_init.c
Normal file
473
internal/glfw/glfw/src/win32_init.c
Normal file
@ -0,0 +1,473 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#include <initguid.h>
|
||||||
|
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
|
||||||
|
|
||||||
|
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||||
|
|
||||||
|
// Applications 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;
|
||||||
|
|
||||||
|
// Applications 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.winmm.instance = LoadLibraryA("winmm.dll");
|
||||||
|
if (!_glfw.win32.winmm.instance)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
|
||||||
|
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
||||||
|
|
||||||
|
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
||||||
|
if (!_glfw.win32.user32.instance)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
|
||||||
|
_glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
||||||
|
|
||||||
|
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)
|
||||||
|
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.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)
|
||||||
|
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
|
||||||
|
_glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)
|
||||||
|
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
||||||
|
if (_glfw.win32.dwmapi.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
||||||
|
_glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
||||||
|
if (_glfw.win32.shcore.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.shcore.SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T)
|
||||||
|
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
||||||
|
}
|
||||||
|
|
||||||
|
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.winmm.instance)
|
||||||
|
FreeLibrary(_glfw.win32.winmm.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create key code translation tables
|
||||||
|
//
|
||||||
|
static void createKeyTables(void)
|
||||||
|
{
|
||||||
|
int scancode;
|
||||||
|
|
||||||
|
memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys));
|
||||||
|
memset(_glfw.win32.nativeKeys, -1, sizeof(_glfw.win32.nativeKeys));
|
||||||
|
|
||||||
|
_glfw.win32.publicKeys[0x00B] = GLFW_KEY_0;
|
||||||
|
_glfw.win32.publicKeys[0x002] = GLFW_KEY_1;
|
||||||
|
_glfw.win32.publicKeys[0x003] = GLFW_KEY_2;
|
||||||
|
_glfw.win32.publicKeys[0x004] = GLFW_KEY_3;
|
||||||
|
_glfw.win32.publicKeys[0x005] = GLFW_KEY_4;
|
||||||
|
_glfw.win32.publicKeys[0x006] = GLFW_KEY_5;
|
||||||
|
_glfw.win32.publicKeys[0x007] = GLFW_KEY_6;
|
||||||
|
_glfw.win32.publicKeys[0x008] = GLFW_KEY_7;
|
||||||
|
_glfw.win32.publicKeys[0x009] = GLFW_KEY_8;
|
||||||
|
_glfw.win32.publicKeys[0x00A] = GLFW_KEY_9;
|
||||||
|
_glfw.win32.publicKeys[0x01E] = GLFW_KEY_A;
|
||||||
|
_glfw.win32.publicKeys[0x030] = GLFW_KEY_B;
|
||||||
|
_glfw.win32.publicKeys[0x02E] = GLFW_KEY_C;
|
||||||
|
_glfw.win32.publicKeys[0x020] = GLFW_KEY_D;
|
||||||
|
_glfw.win32.publicKeys[0x012] = GLFW_KEY_E;
|
||||||
|
_glfw.win32.publicKeys[0x021] = GLFW_KEY_F;
|
||||||
|
_glfw.win32.publicKeys[0x022] = GLFW_KEY_G;
|
||||||
|
_glfw.win32.publicKeys[0x023] = GLFW_KEY_H;
|
||||||
|
_glfw.win32.publicKeys[0x017] = GLFW_KEY_I;
|
||||||
|
_glfw.win32.publicKeys[0x024] = GLFW_KEY_J;
|
||||||
|
_glfw.win32.publicKeys[0x025] = GLFW_KEY_K;
|
||||||
|
_glfw.win32.publicKeys[0x026] = GLFW_KEY_L;
|
||||||
|
_glfw.win32.publicKeys[0x032] = GLFW_KEY_M;
|
||||||
|
_glfw.win32.publicKeys[0x031] = GLFW_KEY_N;
|
||||||
|
_glfw.win32.publicKeys[0x018] = GLFW_KEY_O;
|
||||||
|
_glfw.win32.publicKeys[0x019] = GLFW_KEY_P;
|
||||||
|
_glfw.win32.publicKeys[0x010] = GLFW_KEY_Q;
|
||||||
|
_glfw.win32.publicKeys[0x013] = GLFW_KEY_R;
|
||||||
|
_glfw.win32.publicKeys[0x01F] = GLFW_KEY_S;
|
||||||
|
_glfw.win32.publicKeys[0x014] = GLFW_KEY_T;
|
||||||
|
_glfw.win32.publicKeys[0x016] = GLFW_KEY_U;
|
||||||
|
_glfw.win32.publicKeys[0x02F] = GLFW_KEY_V;
|
||||||
|
_glfw.win32.publicKeys[0x011] = GLFW_KEY_W;
|
||||||
|
_glfw.win32.publicKeys[0x02D] = GLFW_KEY_X;
|
||||||
|
_glfw.win32.publicKeys[0x015] = GLFW_KEY_Y;
|
||||||
|
_glfw.win32.publicKeys[0x02C] = GLFW_KEY_Z;
|
||||||
|
|
||||||
|
_glfw.win32.publicKeys[0x028] = GLFW_KEY_APOSTROPHE;
|
||||||
|
_glfw.win32.publicKeys[0x02B] = GLFW_KEY_BACKSLASH;
|
||||||
|
_glfw.win32.publicKeys[0x033] = GLFW_KEY_COMMA;
|
||||||
|
_glfw.win32.publicKeys[0x00D] = GLFW_KEY_EQUAL;
|
||||||
|
_glfw.win32.publicKeys[0x029] = GLFW_KEY_GRAVE_ACCENT;
|
||||||
|
_glfw.win32.publicKeys[0x01A] = GLFW_KEY_LEFT_BRACKET;
|
||||||
|
_glfw.win32.publicKeys[0x00C] = GLFW_KEY_MINUS;
|
||||||
|
_glfw.win32.publicKeys[0x034] = GLFW_KEY_PERIOD;
|
||||||
|
_glfw.win32.publicKeys[0x01B] = GLFW_KEY_RIGHT_BRACKET;
|
||||||
|
_glfw.win32.publicKeys[0x027] = GLFW_KEY_SEMICOLON;
|
||||||
|
_glfw.win32.publicKeys[0x035] = GLFW_KEY_SLASH;
|
||||||
|
_glfw.win32.publicKeys[0x056] = GLFW_KEY_WORLD_2;
|
||||||
|
|
||||||
|
_glfw.win32.publicKeys[0x00E] = GLFW_KEY_BACKSPACE;
|
||||||
|
_glfw.win32.publicKeys[0x153] = GLFW_KEY_DELETE;
|
||||||
|
_glfw.win32.publicKeys[0x14F] = GLFW_KEY_END;
|
||||||
|
_glfw.win32.publicKeys[0x01C] = GLFW_KEY_ENTER;
|
||||||
|
_glfw.win32.publicKeys[0x001] = GLFW_KEY_ESCAPE;
|
||||||
|
_glfw.win32.publicKeys[0x147] = GLFW_KEY_HOME;
|
||||||
|
_glfw.win32.publicKeys[0x152] = GLFW_KEY_INSERT;
|
||||||
|
_glfw.win32.publicKeys[0x15D] = GLFW_KEY_MENU;
|
||||||
|
_glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN;
|
||||||
|
_glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP;
|
||||||
|
_glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;
|
||||||
|
_glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE;
|
||||||
|
_glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE;
|
||||||
|
_glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB;
|
||||||
|
_glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;
|
||||||
|
_glfw.win32.publicKeys[0x145] = GLFW_KEY_NUM_LOCK;
|
||||||
|
_glfw.win32.publicKeys[0x046] = GLFW_KEY_SCROLL_LOCK;
|
||||||
|
_glfw.win32.publicKeys[0x03B] = GLFW_KEY_F1;
|
||||||
|
_glfw.win32.publicKeys[0x03C] = GLFW_KEY_F2;
|
||||||
|
_glfw.win32.publicKeys[0x03D] = GLFW_KEY_F3;
|
||||||
|
_glfw.win32.publicKeys[0x03E] = GLFW_KEY_F4;
|
||||||
|
_glfw.win32.publicKeys[0x03F] = GLFW_KEY_F5;
|
||||||
|
_glfw.win32.publicKeys[0x040] = GLFW_KEY_F6;
|
||||||
|
_glfw.win32.publicKeys[0x041] = GLFW_KEY_F7;
|
||||||
|
_glfw.win32.publicKeys[0x042] = GLFW_KEY_F8;
|
||||||
|
_glfw.win32.publicKeys[0x043] = GLFW_KEY_F9;
|
||||||
|
_glfw.win32.publicKeys[0x044] = GLFW_KEY_F10;
|
||||||
|
_glfw.win32.publicKeys[0x057] = GLFW_KEY_F11;
|
||||||
|
_glfw.win32.publicKeys[0x058] = GLFW_KEY_F12;
|
||||||
|
_glfw.win32.publicKeys[0x064] = GLFW_KEY_F13;
|
||||||
|
_glfw.win32.publicKeys[0x065] = GLFW_KEY_F14;
|
||||||
|
_glfw.win32.publicKeys[0x066] = GLFW_KEY_F15;
|
||||||
|
_glfw.win32.publicKeys[0x067] = GLFW_KEY_F16;
|
||||||
|
_glfw.win32.publicKeys[0x068] = GLFW_KEY_F17;
|
||||||
|
_glfw.win32.publicKeys[0x069] = GLFW_KEY_F18;
|
||||||
|
_glfw.win32.publicKeys[0x06A] = GLFW_KEY_F19;
|
||||||
|
_glfw.win32.publicKeys[0x06B] = GLFW_KEY_F20;
|
||||||
|
_glfw.win32.publicKeys[0x06C] = GLFW_KEY_F21;
|
||||||
|
_glfw.win32.publicKeys[0x06D] = GLFW_KEY_F22;
|
||||||
|
_glfw.win32.publicKeys[0x06E] = GLFW_KEY_F23;
|
||||||
|
_glfw.win32.publicKeys[0x076] = GLFW_KEY_F24;
|
||||||
|
_glfw.win32.publicKeys[0x038] = GLFW_KEY_LEFT_ALT;
|
||||||
|
_glfw.win32.publicKeys[0x01D] = GLFW_KEY_LEFT_CONTROL;
|
||||||
|
_glfw.win32.publicKeys[0x02A] = GLFW_KEY_LEFT_SHIFT;
|
||||||
|
_glfw.win32.publicKeys[0x15B] = GLFW_KEY_LEFT_SUPER;
|
||||||
|
_glfw.win32.publicKeys[0x137] = GLFW_KEY_PRINT_SCREEN;
|
||||||
|
_glfw.win32.publicKeys[0x138] = GLFW_KEY_RIGHT_ALT;
|
||||||
|
_glfw.win32.publicKeys[0x11D] = GLFW_KEY_RIGHT_CONTROL;
|
||||||
|
_glfw.win32.publicKeys[0x036] = GLFW_KEY_RIGHT_SHIFT;
|
||||||
|
_glfw.win32.publicKeys[0x15C] = GLFW_KEY_RIGHT_SUPER;
|
||||||
|
_glfw.win32.publicKeys[0x150] = GLFW_KEY_DOWN;
|
||||||
|
_glfw.win32.publicKeys[0x14B] = GLFW_KEY_LEFT;
|
||||||
|
_glfw.win32.publicKeys[0x14D] = GLFW_KEY_RIGHT;
|
||||||
|
_glfw.win32.publicKeys[0x148] = GLFW_KEY_UP;
|
||||||
|
|
||||||
|
_glfw.win32.publicKeys[0x052] = GLFW_KEY_KP_0;
|
||||||
|
_glfw.win32.publicKeys[0x04F] = GLFW_KEY_KP_1;
|
||||||
|
_glfw.win32.publicKeys[0x050] = GLFW_KEY_KP_2;
|
||||||
|
_glfw.win32.publicKeys[0x051] = GLFW_KEY_KP_3;
|
||||||
|
_glfw.win32.publicKeys[0x04B] = GLFW_KEY_KP_4;
|
||||||
|
_glfw.win32.publicKeys[0x04C] = GLFW_KEY_KP_5;
|
||||||
|
_glfw.win32.publicKeys[0x04D] = GLFW_KEY_KP_6;
|
||||||
|
_glfw.win32.publicKeys[0x047] = GLFW_KEY_KP_7;
|
||||||
|
_glfw.win32.publicKeys[0x048] = GLFW_KEY_KP_8;
|
||||||
|
_glfw.win32.publicKeys[0x049] = GLFW_KEY_KP_9;
|
||||||
|
_glfw.win32.publicKeys[0x04E] = GLFW_KEY_KP_ADD;
|
||||||
|
_glfw.win32.publicKeys[0x053] = GLFW_KEY_KP_DECIMAL;
|
||||||
|
_glfw.win32.publicKeys[0x135] = GLFW_KEY_KP_DIVIDE;
|
||||||
|
_glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER;
|
||||||
|
_glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY;
|
||||||
|
_glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT;
|
||||||
|
|
||||||
|
for (scancode = 0; scancode < 512; scancode++)
|
||||||
|
{
|
||||||
|
if (_glfw.win32.publicKeys[scancode] > 0)
|
||||||
|
_glfw.win32.nativeKeys[_glfw.win32.publicKeys[scancode]] = scancode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a dummy window for behind-the-scenes work
|
||||||
|
//
|
||||||
|
static HWND createHelperWindow(void)
|
||||||
|
{
|
||||||
|
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||||
|
_GLFW_WNDCLASSNAME,
|
||||||
|
L"GLFW helper window",
|
||||||
|
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||||
|
0, 0, 1, 1,
|
||||||
|
HWND_MESSAGE, NULL,
|
||||||
|
GetModuleHandleW(NULL),
|
||||||
|
NULL);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to create helper window");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: The first call to ShowWindow is ignored if the parent process
|
||||||
|
// passed along a STARTUPINFO, so clear that flag with a no-op call
|
||||||
|
ShowWindow(window, 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;
|
||||||
|
|
||||||
|
RegisterDeviceNotificationW(window,
|
||||||
|
(DEV_BROADCAST_HDR*) &dbi,
|
||||||
|
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Returns a wide string version of the specified UTF-8 string
|
||||||
|
//
|
||||||
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||||
|
{
|
||||||
|
WCHAR* target;
|
||||||
|
int length;
|
||||||
|
|
||||||
|
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||||
|
if (!length)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
target = calloc(length, sizeof(WCHAR));
|
||||||
|
|
||||||
|
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
|
||||||
|
{
|
||||||
|
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 length;
|
||||||
|
|
||||||
|
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (!length)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
target = calloc(length, 1);
|
||||||
|
|
||||||
|
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
|
||||||
|
{
|
||||||
|
free(target);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformInit(void)
|
||||||
|
{
|
||||||
|
if (!_glfwInitThreadLocalStorageWin32())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
if (_glfw_SetProcessDpiAwareness)
|
||||||
|
_glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
|
else if (_glfw_SetProcessDPIAware)
|
||||||
|
_glfw_SetProcessDPIAware();
|
||||||
|
|
||||||
|
if (!_glfwRegisterWindowClassWin32())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
_glfw.win32.helperWindowHandle = createHelperWindow();
|
||||||
|
if (!_glfw.win32.helperWindowHandle)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
_glfwPlatformPollEvents();
|
||||||
|
|
||||||
|
_glfwInitTimerWin32();
|
||||||
|
_glfwInitJoysticksWin32();
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformTerminate(void)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
_glfwTerminateWGL();
|
||||||
|
_glfwTerminateEGL();
|
||||||
|
|
||||||
|
_glfwTerminateJoysticksWin32();
|
||||||
|
_glfwTerminateThreadLocalStorageWin32();
|
||||||
|
|
||||||
|
freeLibraries();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
{
|
||||||
|
return _GLFW_VERSION_NUMBER " Win32 WGL EGL"
|
||||||
|
#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
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
763
internal/glfw/glfw/src/win32_joystick.c
Normal file
763
internal/glfw/glfw/src/win32_joystick.c
Normal file
@ -0,0 +1,763 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.1 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <initguid.h>
|
||||||
|
|
||||||
|
#define _GLFW_PRESENCE_ONLY 1
|
||||||
|
#define _GLFW_UPDATE_STATE 2
|
||||||
|
|
||||||
|
#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 only the necessary GUIDs (it's bad enough that we're exporting these)
|
||||||
|
//
|
||||||
|
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
|
||||||
|
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||||
|
|
||||||
|
// 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 360 Controller";
|
||||||
|
else
|
||||||
|
return "Xbox 360 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(_GLFWjoystickWin32* js)
|
||||||
|
{
|
||||||
|
if (js->device)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Unacquire(js->device);
|
||||||
|
IDirectInputDevice8_Release(js->device);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(js->name);
|
||||||
|
free(js->axes);
|
||||||
|
free(js->buttons);
|
||||||
|
free(js->objects);
|
||||||
|
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
||||||
|
|
||||||
|
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DirectInput device object enumeration callback
|
||||||
|
// Insights gleaned from SDL2
|
||||||
|
//
|
||||||
|
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 joy = 0;
|
||||||
|
DIDEVCAPS dc;
|
||||||
|
DIPROPDWORD dipd;
|
||||||
|
IDirectInputDevice8* device;
|
||||||
|
_GLFWobjenumWin32 data;
|
||||||
|
_GLFWjoystickWin32* js;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (!_glfw.win32_js[joy].present)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joy > GLFW_JOYSTICK_LAST)
|
||||||
|
return DIENUM_STOP;
|
||||||
|
|
||||||
|
if (supportsXInput(&di->guidProduct))
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
|
if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
|
||||||
|
&di->guidInstance,
|
||||||
|
&device,
|
||||||
|
NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: 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,
|
||||||
|
"DI: 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,
|
||||||
|
"DI: 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 + dc.dwButtons + dc.dwPOVs,
|
||||||
|
sizeof(_GLFWjoyobjectWin32));
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_EnumObjects(device,
|
||||||
|
deviceObjectCallback,
|
||||||
|
&data,
|
||||||
|
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: Failed to enumerate device objects");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(data.objects, data.objectCount,
|
||||||
|
sizeof(_GLFWjoyobjectWin32),
|
||||||
|
compareJoystickObjects);
|
||||||
|
|
||||||
|
js = _glfw.win32_js + joy;
|
||||||
|
js->device = device;
|
||||||
|
js->guid = di->guidInstance;
|
||||||
|
js->axisCount = data.axisCount + data.sliderCount;
|
||||||
|
js->axes = calloc(js->axisCount, sizeof(float));
|
||||||
|
js->buttonCount += data.buttonCount + data.povCount * 4;
|
||||||
|
js->buttons = calloc(js->buttonCount, 1);
|
||||||
|
js->objects = data.objects;
|
||||||
|
js->objectCount = data.objectCount;
|
||||||
|
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
||||||
|
js->present = GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to open the specified joystick device
|
||||||
|
// TODO: Pack state arrays for non-gamepad devices
|
||||||
|
//
|
||||||
|
static GLFWbool openXinputDevice(DWORD index)
|
||||||
|
{
|
||||||
|
int joy;
|
||||||
|
XINPUT_CAPABILITIES xic;
|
||||||
|
_GLFWjoystickWin32* js;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (_glfw.win32_js[joy].present &&
|
||||||
|
_glfw.win32_js[joy].device == NULL &&
|
||||||
|
_glfw.win32_js[joy].index == index)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
if (!_glfw.win32_js[joy].present)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joy > GLFW_JOYSTICK_LAST)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
js = _glfw.win32_js + joy;
|
||||||
|
js->axisCount = 6;
|
||||||
|
js->axes = calloc(js->axisCount, sizeof(float));
|
||||||
|
js->buttonCount = 14;
|
||||||
|
js->buttons = calloc(js->buttonCount, 1);
|
||||||
|
js->present = GLFW_TRUE;
|
||||||
|
js->name = strdup(getDeviceDescription(&xic));
|
||||||
|
js->index = index;
|
||||||
|
|
||||||
|
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polls for and processes events the specified joystick
|
||||||
|
//
|
||||||
|
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
|
||||||
|
{
|
||||||
|
if (!js->present)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (js->device)
|
||||||
|
{
|
||||||
|
int i, j, ai = 0, bi = 0;
|
||||||
|
HRESULT result;
|
||||||
|
DIJOYSTATE state;
|
||||||
|
|
||||||
|
IDirectInputDevice8_Poll(js->device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
|
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Acquire(js->device);
|
||||||
|
IDirectInputDevice8_Poll(js->device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
closeJoystick(js);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == _GLFW_PRESENCE_ONLY)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
for (i = 0; i < js->objectCount; i++)
|
||||||
|
{
|
||||||
|
const void* data = (char*) &state + js->objects[i].offset;
|
||||||
|
|
||||||
|
switch (js->objects[i].type)
|
||||||
|
{
|
||||||
|
case _GLFW_TYPE_AXIS:
|
||||||
|
case _GLFW_TYPE_SLIDER:
|
||||||
|
{
|
||||||
|
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GLFW_TYPE_BUTTON:
|
||||||
|
{
|
||||||
|
if (*((BYTE*) data) & 0x80)
|
||||||
|
js->buttons[bi++] = GLFW_PRESS;
|
||||||
|
else
|
||||||
|
js->buttons[bi++] = GLFW_RELEASE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GLFW_TYPE_POV:
|
||||||
|
{
|
||||||
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||||
|
// Screams of horror are appropriate at this point
|
||||||
|
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||||
|
if (value < 0 || value > 8)
|
||||||
|
value = 8;
|
||||||
|
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
if (directions[value] & (1 << j))
|
||||||
|
js->buttons[bi++] = GLFW_PRESS;
|
||||||
|
else
|
||||||
|
js->buttons[bi++] = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DWORD result;
|
||||||
|
XINPUT_STATE xis;
|
||||||
|
const WORD buttons[14] =
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
XINPUT_GAMEPAD_DPAD_UP,
|
||||||
|
XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||||
|
XINPUT_GAMEPAD_DPAD_DOWN,
|
||||||
|
XINPUT_GAMEPAD_DPAD_LEFT
|
||||||
|
};
|
||||||
|
|
||||||
|
result = _glfw_XInputGetState(js->index, &xis);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||||
|
closeJoystick(js);
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == _GLFW_PRESENCE_ONLY)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
if (sqrt((double) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
||||||
|
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
|
||||||
|
(double) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
|
||||||
|
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
js->axes[0] = 0.f;
|
||||||
|
js->axes[1] = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sqrt((double) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
|
||||||
|
xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >
|
||||||
|
(double) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
|
||||||
|
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
js->axes[2] = 0.f;
|
||||||
|
js->axes[3] = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
|
||||||
|
else
|
||||||
|
js->axes[4] = -1.f;
|
||||||
|
|
||||||
|
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
||||||
|
else
|
||||||
|
js->axes[5] = -1.f;
|
||||||
|
|
||||||
|
for (i = 0; i < 14; i++)
|
||||||
|
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize joystick interface
|
||||||
|
//
|
||||||
|
void _glfwInitJoysticksWin32(void)
|
||||||
|
{
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
{
|
||||||
|
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
|
||||||
|
DIRECTINPUT_VERSION,
|
||||||
|
&IID_IDirectInput8W,
|
||||||
|
(void**) &_glfw.win32.dinput8.api,
|
||||||
|
NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"DI: Failed to create interface");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwDetectJoystickConnectionWin32();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close all opened joystick handles
|
||||||
|
//
|
||||||
|
void _glfwTerminateJoysticksWin32(void)
|
||||||
|
{
|
||||||
|
int joy;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
closeJoystick(_glfw.win32_js + joy);
|
||||||
|
|
||||||
|
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 i;
|
||||||
|
|
||||||
|
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
||||||
|
openXinputDevice(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 joy;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformJoystickPresent(int joy)
|
||||||
|
{
|
||||||
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
|
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
|
{
|
||||||
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = js->axisCount;
|
||||||
|
return js->axes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
|
{
|
||||||
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = js->buttonCount;
|
||||||
|
return js->buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetJoystickName(int joy)
|
||||||
|
{
|
||||||
|
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||||
|
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return js->name;
|
||||||
|
}
|
||||||
|
|
64
internal/glfw/glfw/src/win32_joystick.h
Normal file
64
internal/glfw/glfw/src/win32_joystick.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#ifndef _glfw3_win32_joystick_h_
|
||||||
|
#define _glfw3_win32_joystick_h_
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||||
|
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
|
||||||
|
|
||||||
|
// Joystick element (axis, button or slider)
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoyobjectWin32
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int type;
|
||||||
|
} _GLFWjoyobjectWin32;
|
||||||
|
|
||||||
|
// Win32-specific per-joystick data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoystickWin32
|
||||||
|
{
|
||||||
|
GLFWbool present;
|
||||||
|
float* axes;
|
||||||
|
int axisCount;
|
||||||
|
unsigned char* buttons;
|
||||||
|
int buttonCount;
|
||||||
|
_GLFWjoyobjectWin32* objects;
|
||||||
|
int objectCount;
|
||||||
|
char* name;
|
||||||
|
IDirectInputDevice8W* device;
|
||||||
|
DWORD index;
|
||||||
|
GUID guid;
|
||||||
|
} _GLFWjoystickWin32;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwInitJoysticksWin32(void);
|
||||||
|
void _glfwTerminateJoysticksWin32(void);
|
||||||
|
void _glfwDetectJoystickConnectionWin32(void);
|
||||||
|
void _glfwDetectJoystickDisconnectionWin32(void);
|
||||||
|
|
||||||
|
#endif // _glfw3_win32_joystick_h_
|
401
internal/glfw/glfw/src/win32_monitor.c
Normal file
401
internal/glfw/glfw/src/win32_monitor.c
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Create monitor from an adapter and (optionally) a display
|
||||||
|
//
|
||||||
|
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||||
|
DISPLAY_DEVICEW* display)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor;
|
||||||
|
char* name;
|
||||||
|
HDC dc;
|
||||||
|
|
||||||
|
if (display)
|
||||||
|
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
||||||
|
else
|
||||||
|
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string to UTF-8");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
||||||
|
|
||||||
|
monitor = _glfwAllocMonitor(name,
|
||||||
|
GetDeviceCaps(dc, HORZSIZE),
|
||||||
|
GetDeviceCaps(dc, VERTSIZE));
|
||||||
|
|
||||||
|
DeleteDC(dc);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Change the current video mode
|
||||||
|
//
|
||||||
|
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
|
{
|
||||||
|
GLFWvidmode current;
|
||||||
|
const GLFWvidmode* best;
|
||||||
|
DEVMODEW dm;
|
||||||
|
|
||||||
|
best = _glfwChooseVideoMode(monitor, desired);
|
||||||
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
|
dm.dmSize = sizeof(DEVMODEW);
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
|
&dm,
|
||||||
|
NULL,
|
||||||
|
CDS_FULLSCREEN,
|
||||||
|
NULL) != DISP_CHANGE_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->win32.modeChanged = GLFW_TRUE;
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||||
|
{
|
||||||
|
int found = 0;
|
||||||
|
DWORD adapterIndex, displayIndex, primaryIndex = 0;
|
||||||
|
DISPLAY_DEVICEW adapter, display;
|
||||||
|
GLFWbool hasDisplays = GLFW_FALSE;
|
||||||
|
_GLFWmonitor** monitors = NULL;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
// HACK: Check if any active adapters have connected displays
|
||||||
|
// If not, this is a headless system or a VMware guest
|
||||||
|
|
||||||
|
for (adapterIndex = 0; ; adapterIndex++)
|
||||||
|
{
|
||||||
|
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
||||||
|
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
||||||
|
display.cb = sizeof(DISPLAY_DEVICEW);
|
||||||
|
|
||||||
|
if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))
|
||||||
|
{
|
||||||
|
hasDisplays = GLFW_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (adapterIndex = 0; ; adapterIndex++)
|
||||||
|
{
|
||||||
|
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
||||||
|
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||||
|
primaryIndex = found;
|
||||||
|
|
||||||
|
if (hasDisplays)
|
||||||
|
{
|
||||||
|
for (displayIndex = 0; ; displayIndex++)
|
||||||
|
{
|
||||||
|
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
||||||
|
display.cb = sizeof(DISPLAY_DEVICEW);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
found++;
|
||||||
|
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||||
|
monitors[found - 1] = createMonitor(&adapter, &display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found++;
|
||||||
|
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||||
|
monitors[found - 1] = createMonitor(&adapter, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);
|
||||||
|
|
||||||
|
*count = found;
|
||||||
|
return monitors;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||||
|
{
|
||||||
|
if (wcslen(first->win32.displayName))
|
||||||
|
return wcscmp(first->win32.displayName, second->win32.displayName) == 0;
|
||||||
|
else
|
||||||
|
return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
DEVMODEW settings;
|
||||||
|
ZeroMemory(&settings, sizeof(DEVMODEW));
|
||||||
|
settings.dmSize = sizeof(DEVMODEW);
|
||||||
|
|
||||||
|
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
|
ENUM_CURRENT_SETTINGS,
|
||||||
|
&settings,
|
||||||
|
EDS_ROTATEDMODE);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = settings.dmPosition.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = settings.dmPosition.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(DEVMODEW));
|
||||||
|
dm.dmSize = sizeof(DEVMODEW);
|
||||||
|
|
||||||
|
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(DEVMODEW));
|
||||||
|
dm.dmSize = sizeof(DEVMODEW);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
HDC dc;
|
||||||
|
WORD values[768];
|
||||||
|
|
||||||
|
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
|
||||||
|
GetDeviceGammaRamp(dc, values);
|
||||||
|
DeleteDC(dc);
|
||||||
|
|
||||||
|
_glfwAllocGammaArrays(ramp, 256);
|
||||||
|
|
||||||
|
memcpy(ramp->red, values + 0, 256 * sizeof(unsigned short));
|
||||||
|
memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short));
|
||||||
|
memcpy(ramp->blue, values + 512, 256 * sizeof(unsigned short));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
HDC dc;
|
||||||
|
WORD values[768];
|
||||||
|
|
||||||
|
if (ramp->size != 256)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Gamma ramp size must be 256");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(values + 0, ramp->red, 256 * sizeof(unsigned short));
|
||||||
|
memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short));
|
||||||
|
memcpy(values + 512, ramp->blue, 256 * sizeof(unsigned short));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
350
internal/glfw/glfw/src/win32_platform.h
Normal file
350
internal/glfw/glfw/src/win32_platform.h
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#ifndef _glfw3_win32_platform_h_
|
||||||
|
#define _glfw3_win32_platform_h_
|
||||||
|
|
||||||
|
// 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_ARB_debug_output
|
||||||
|
// 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
|
||||||
|
|
||||||
|
#include <wctype.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#include <dinput.h>
|
||||||
|
#include <xinput.h>
|
||||||
|
#include <dbt.h>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <malloc.h>
|
||||||
|
#define strdup _strdup
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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_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
|
||||||
|
|
||||||
|
#if WINVER < 0x0601
|
||||||
|
typedef struct tagCHANGEFILTERSTRUCT
|
||||||
|
{
|
||||||
|
DWORD cbSize;
|
||||||
|
DWORD ExtStatus;
|
||||||
|
|
||||||
|
} CHANGEFILTERSTRUCT, *PCHANGEFILTERSTRUCT;
|
||||||
|
#ifndef MSGFLT_ALLOW
|
||||||
|
#define MSGFLT_ALLOW 1
|
||||||
|
#endif
|
||||||
|
#endif /*Windows 7*/
|
||||||
|
|
||||||
|
#ifndef DPI_ENUMS_DECLARED
|
||||||
|
typedef enum PROCESS_DPI_AWARENESS
|
||||||
|
{
|
||||||
|
PROCESS_DPI_UNAWARE = 0,
|
||||||
|
PROCESS_SYSTEM_DPI_AWARE = 1,
|
||||||
|
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
||||||
|
} PROCESS_DPI_AWARENESS;
|
||||||
|
#endif /*DPI_ENUMS_DECLARED*/
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// winmm.dll function pointer typedefs
|
||||||
|
typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
|
||||||
|
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
||||||
|
|
||||||
|
// xinput.dll function pointer typedefs
|
||||||
|
typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
||||||
|
typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);
|
||||||
|
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
|
||||||
|
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
|
||||||
|
|
||||||
|
// dinput8.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
||||||
|
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
|
||||||
|
|
||||||
|
// user32.dll function pointer typedefs
|
||||||
|
typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void);
|
||||||
|
typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
|
||||||
|
#define _glfw_SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware
|
||||||
|
#define _glfw_ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx
|
||||||
|
|
||||||
|
// dwmapi.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
|
||||||
|
typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
|
||||||
|
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
|
||||||
|
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
|
||||||
|
|
||||||
|
// shcore.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS);
|
||||||
|
#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||||
|
|
||||||
|
#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_TIME_STATE _GLFWtimeWin32 win32_time
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
||||||
|
|
||||||
|
|
||||||
|
// Win32-specific per-window data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwindowWin32
|
||||||
|
{
|
||||||
|
HWND handle;
|
||||||
|
HICON bigIcon;
|
||||||
|
HICON smallIcon;
|
||||||
|
|
||||||
|
GLFWbool cursorTracked;
|
||||||
|
GLFWbool iconified;
|
||||||
|
|
||||||
|
// The last received cursor position, regardless of source
|
||||||
|
int lastCursorPosX, lastCursorPosY;
|
||||||
|
|
||||||
|
} _GLFWwindowWin32;
|
||||||
|
|
||||||
|
// Win32-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryWin32
|
||||||
|
{
|
||||||
|
HWND helperWindowHandle;
|
||||||
|
DWORD foregroundLockTimeout;
|
||||||
|
char* clipboardString;
|
||||||
|
char keyName[64];
|
||||||
|
short int publicKeys[512];
|
||||||
|
short int nativeKeys[GLFW_KEY_LAST + 1];
|
||||||
|
// Where to place the cursor when re-enabled
|
||||||
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
|
// The window whose disabled cursor mode is active
|
||||||
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
TIMEGETTIME_T timeGetTime;
|
||||||
|
} winmm;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
DIRECTINPUT8CREATE_T DirectInput8Create;
|
||||||
|
IDirectInput8W* api;
|
||||||
|
} dinput8;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
XINPUTGETCAPABILITIES_T XInputGetCapabilities;
|
||||||
|
XINPUTGETSTATE_T XInputGetState;
|
||||||
|
} xinput;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
SETPROCESSDPIAWARE_T SetProcessDPIAware;
|
||||||
|
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
|
||||||
|
} user32;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
|
||||||
|
DWMFLUSH_T DwmFlush;
|
||||||
|
} dwmapi;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;
|
||||||
|
} shcore;
|
||||||
|
|
||||||
|
} _GLFWlibraryWin32;
|
||||||
|
|
||||||
|
// Win32-specific per-monitor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmonitorWin32
|
||||||
|
{
|
||||||
|
// This size matches the static size of DISPLAY_DEVICE.DeviceName
|
||||||
|
WCHAR adapterName[32];
|
||||||
|
WCHAR displayName[32];
|
||||||
|
char publicAdapterName[64];
|
||||||
|
char publicDisplayName[64];
|
||||||
|
GLFWbool modesPruned;
|
||||||
|
GLFWbool modeChanged;
|
||||||
|
|
||||||
|
} _GLFWmonitorWin32;
|
||||||
|
|
||||||
|
// Win32-specific per-cursor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcursorWin32
|
||||||
|
{
|
||||||
|
HCURSOR handle;
|
||||||
|
|
||||||
|
} _GLFWcursorWin32;
|
||||||
|
|
||||||
|
// Win32-specific global timer data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWtimeWin32
|
||||||
|
{
|
||||||
|
GLFWbool hasPC;
|
||||||
|
uint64_t frequency;
|
||||||
|
|
||||||
|
} _GLFWtimeWin32;
|
||||||
|
|
||||||
|
// Win32-specific global TLS data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWtlsWin32
|
||||||
|
{
|
||||||
|
GLFWbool allocated;
|
||||||
|
DWORD context;
|
||||||
|
|
||||||
|
} _GLFWtlsWin32;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||||
|
void _glfwUnregisterWindowClassWin32(void);
|
||||||
|
|
||||||
|
GLFWbool _glfwInitThreadLocalStorageWin32(void);
|
||||||
|
void _glfwTerminateThreadLocalStorageWin32(void);
|
||||||
|
|
||||||
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||||
|
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||||
|
|
||||||
|
void _glfwInitTimerWin32(void);
|
||||||
|
|
||||||
|
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
|
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
#endif // _glfw3_win32_platform_h_
|
74
internal/glfw/glfw/src/win32_time.c
Normal file
74
internal/glfw/glfw/src/win32_time.c
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialise timer
|
||||||
|
//
|
||||||
|
void _glfwInitTimerWin32(void)
|
||||||
|
{
|
||||||
|
uint64_t frequency;
|
||||||
|
|
||||||
|
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
||||||
|
{
|
||||||
|
_glfw.win32_time.hasPC = GLFW_TRUE;
|
||||||
|
_glfw.win32_time.frequency = frequency;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfw.win32_time.hasPC = GLFW_FALSE;
|
||||||
|
_glfw.win32_time.frequency = 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
|
{
|
||||||
|
if (_glfw.win32_time.hasPC)
|
||||||
|
{
|
||||||
|
uint64_t value;
|
||||||
|
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (uint64_t) _glfw_timeGetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
|
{
|
||||||
|
return _glfw.win32_time.frequency;
|
||||||
|
}
|
||||||
|
|
69
internal/glfw/glfw/src/win32_tls.c
Normal file
69
internal/glfw/glfw/src/win32_tls.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwInitThreadLocalStorageWin32(void)
|
||||||
|
{
|
||||||
|
_glfw.win32_tls.context = TlsAlloc();
|
||||||
|
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to allocate TLS index");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32_tls.allocated = GLFW_TRUE;
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwTerminateThreadLocalStorageWin32(void)
|
||||||
|
{
|
||||||
|
if (_glfw.win32_tls.allocated)
|
||||||
|
TlsFree(_glfw.win32_tls.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
|
||||||
|
{
|
||||||
|
TlsSetValue(_glfw.win32_tls.context, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
|
||||||
|
{
|
||||||
|
return TlsGetValue(_glfw.win32_tls.context);
|
||||||
|
}
|
||||||
|
|
1724
internal/glfw/glfw/src/win32_window.c
Normal file
1724
internal/glfw/glfw/src/win32_window.c
Normal file
File diff suppressed because it is too large
Load Diff
904
internal/glfw/glfw/src/window.c
Normal file
904
internal/glfw/glfw/src/window.c
Normal file
@ -0,0 +1,904 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.2 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||||
|
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW event API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
||||||
|
{
|
||||||
|
if (focused)
|
||||||
|
{
|
||||||
|
if (window->callbacks.focus)
|
||||||
|
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (window->callbacks.focus)
|
||||||
|
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||||
|
|
||||||
|
// Release all pressed keyboard keys
|
||||||
|
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||||
|
{
|
||||||
|
if (window->keys[i] == GLFW_PRESS)
|
||||||
|
_glfwInputKey(window, i, 0, GLFW_RELEASE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release all pressed mouse buttons
|
||||||
|
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||||
|
{
|
||||||
|
if (window->mouseButtons[i] == GLFW_PRESS)
|
||||||
|
_glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
|
||||||
|
{
|
||||||
|
if (window->callbacks.pos)
|
||||||
|
window->callbacks.pos((GLFWwindow*) window, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
if (window->callbacks.size)
|
||||||
|
window->callbacks.size((GLFWwindow*) window, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
||||||
|
{
|
||||||
|
if (window->callbacks.iconify)
|
||||||
|
window->callbacks.iconify((GLFWwindow*) window, iconified);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
if (window->callbacks.fbsize)
|
||||||
|
window->callbacks.fbsize((GLFWwindow*) window, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputWindowDamage(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->callbacks.refresh)
|
||||||
|
window->callbacks.refresh((GLFWwindow*) window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
window->closed = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (window->callbacks.close)
|
||||||
|
window->callbacks.close((GLFWwindow*) window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
window->monitor = monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||||
|
const char* title,
|
||||||
|
GLFWmonitor* monitor,
|
||||||
|
GLFWwindow* share)
|
||||||
|
{
|
||||||
|
_GLFWfbconfig fbconfig;
|
||||||
|
_GLFWctxconfig ctxconfig;
|
||||||
|
_GLFWwndconfig wndconfig;
|
||||||
|
_GLFWwindow* window;
|
||||||
|
_GLFWwindow* previous;
|
||||||
|
|
||||||
|
assert(title != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (width <= 0 || height <= 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid window size %ix%i",
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fbconfig = _glfw.hints.framebuffer;
|
||||||
|
ctxconfig = _glfw.hints.context;
|
||||||
|
wndconfig = _glfw.hints.window;
|
||||||
|
|
||||||
|
wndconfig.width = width;
|
||||||
|
wndconfig.height = height;
|
||||||
|
wndconfig.title = title;
|
||||||
|
ctxconfig.share = (_GLFWwindow*) share;
|
||||||
|
|
||||||
|
if (ctxconfig.share)
|
||||||
|
{
|
||||||
|
if (ctxconfig.client == GLFW_NO_API ||
|
||||||
|
ctxconfig.share->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfwIsValidContextConfig(&ctxconfig))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
window = calloc(1, sizeof(_GLFWwindow));
|
||||||
|
window->next = _glfw.windowListHead;
|
||||||
|
_glfw.windowListHead = window;
|
||||||
|
|
||||||
|
window->videoMode.width = width;
|
||||||
|
window->videoMode.height = height;
|
||||||
|
window->videoMode.redBits = fbconfig.redBits;
|
||||||
|
window->videoMode.greenBits = fbconfig.greenBits;
|
||||||
|
window->videoMode.blueBits = fbconfig.blueBits;
|
||||||
|
window->videoMode.refreshRate = _glfw.hints.refreshRate;
|
||||||
|
|
||||||
|
window->monitor = (_GLFWmonitor*) monitor;
|
||||||
|
window->resizable = wndconfig.resizable;
|
||||||
|
window->decorated = wndconfig.decorated;
|
||||||
|
window->autoIconify = wndconfig.autoIconify;
|
||||||
|
window->floating = wndconfig.floating;
|
||||||
|
window->cursorMode = GLFW_CURSOR_NORMAL;
|
||||||
|
|
||||||
|
window->minwidth = GLFW_DONT_CARE;
|
||||||
|
window->minheight = GLFW_DONT_CARE;
|
||||||
|
window->maxwidth = GLFW_DONT_CARE;
|
||||||
|
window->maxheight = GLFW_DONT_CARE;
|
||||||
|
window->numer = GLFW_DONT_CARE;
|
||||||
|
window->denom = GLFW_DONT_CARE;
|
||||||
|
|
||||||
|
// Save the currently current context so it can be restored later
|
||||||
|
previous = _glfwPlatformGetCurrentContext();
|
||||||
|
if (ctxconfig.client != GLFW_NO_API)
|
||||||
|
glfwMakeContextCurrent(NULL);
|
||||||
|
|
||||||
|
// Open the actual window and create its context
|
||||||
|
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
|
||||||
|
{
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
glfwDestroyWindow((GLFWwindow*) window);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig.client != GLFW_NO_API)
|
||||||
|
{
|
||||||
|
window->context.makeCurrent(window);
|
||||||
|
|
||||||
|
// Retrieve the actual (as opposed to requested) context attributes
|
||||||
|
if (!_glfwRefreshContextAttribs(&ctxconfig))
|
||||||
|
{
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
glfwDestroyWindow((GLFWwindow*) window);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the previously current context (or NULL)
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window->monitor)
|
||||||
|
{
|
||||||
|
if (wndconfig.visible)
|
||||||
|
{
|
||||||
|
_glfwPlatformShowWindow(window);
|
||||||
|
if (wndconfig.focused)
|
||||||
|
_glfwPlatformFocusWindow(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (GLFWwindow*) window;
|
||||||
|
}
|
||||||
|
|
||||||
|
void glfwDefaultWindowHints(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
|
||||||
|
|
||||||
|
// The default is OpenGL with minimum version 1.0
|
||||||
|
_glfw.hints.context.client = GLFW_OPENGL_API;
|
||||||
|
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
|
||||||
|
_glfw.hints.context.major = 1;
|
||||||
|
_glfw.hints.context.minor = 0;
|
||||||
|
|
||||||
|
// The default is a focused, visible, resizable window with decorations
|
||||||
|
_glfw.hints.window.resizable = GLFW_TRUE;
|
||||||
|
_glfw.hints.window.visible = GLFW_TRUE;
|
||||||
|
_glfw.hints.window.decorated = GLFW_TRUE;
|
||||||
|
_glfw.hints.window.focused = GLFW_TRUE;
|
||||||
|
_glfw.hints.window.autoIconify = GLFW_TRUE;
|
||||||
|
|
||||||
|
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||||
|
// double buffered
|
||||||
|
_glfw.hints.framebuffer.redBits = 8;
|
||||||
|
_glfw.hints.framebuffer.greenBits = 8;
|
||||||
|
_glfw.hints.framebuffer.blueBits = 8;
|
||||||
|
_glfw.hints.framebuffer.alphaBits = 8;
|
||||||
|
_glfw.hints.framebuffer.depthBits = 24;
|
||||||
|
_glfw.hints.framebuffer.stencilBits = 8;
|
||||||
|
_glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
|
||||||
|
|
||||||
|
// The default is to select the highest available refresh rate
|
||||||
|
_glfw.hints.refreshRate = GLFW_DONT_CARE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwWindowHint(int hint, int value)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
switch (hint)
|
||||||
|
{
|
||||||
|
case GLFW_RED_BITS:
|
||||||
|
_glfw.hints.framebuffer.redBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_GREEN_BITS:
|
||||||
|
_glfw.hints.framebuffer.greenBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_BLUE_BITS:
|
||||||
|
_glfw.hints.framebuffer.blueBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_ALPHA_BITS:
|
||||||
|
_glfw.hints.framebuffer.alphaBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_DEPTH_BITS:
|
||||||
|
_glfw.hints.framebuffer.depthBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_STENCIL_BITS:
|
||||||
|
_glfw.hints.framebuffer.stencilBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_ACCUM_RED_BITS:
|
||||||
|
_glfw.hints.framebuffer.accumRedBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_ACCUM_GREEN_BITS:
|
||||||
|
_glfw.hints.framebuffer.accumGreenBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_ACCUM_BLUE_BITS:
|
||||||
|
_glfw.hints.framebuffer.accumBlueBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_ACCUM_ALPHA_BITS:
|
||||||
|
_glfw.hints.framebuffer.accumAlphaBits = value;
|
||||||
|
break;
|
||||||
|
case GLFW_AUX_BUFFERS:
|
||||||
|
_glfw.hints.framebuffer.auxBuffers = value;
|
||||||
|
break;
|
||||||
|
case GLFW_STEREO:
|
||||||
|
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_DOUBLEBUFFER:
|
||||||
|
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_SAMPLES:
|
||||||
|
_glfw.hints.framebuffer.samples = value;
|
||||||
|
break;
|
||||||
|
case GLFW_SRGB_CAPABLE:
|
||||||
|
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_RESIZABLE:
|
||||||
|
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_DECORATED:
|
||||||
|
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_FOCUSED:
|
||||||
|
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_AUTO_ICONIFY:
|
||||||
|
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_FLOATING:
|
||||||
|
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_MAXIMIZED:
|
||||||
|
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_VISIBLE:
|
||||||
|
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_CLIENT_API:
|
||||||
|
_glfw.hints.context.client = value;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_CREATION_API:
|
||||||
|
_glfw.hints.context.source = value;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_VERSION_MAJOR:
|
||||||
|
_glfw.hints.context.major = value;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_VERSION_MINOR:
|
||||||
|
_glfw.hints.context.minor = value;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_ROBUSTNESS:
|
||||||
|
_glfw.hints.context.robustness = value;
|
||||||
|
break;
|
||||||
|
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||||
|
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||||
|
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_NO_ERROR:
|
||||||
|
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_OPENGL_PROFILE:
|
||||||
|
_glfw.hints.context.profile = value;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
||||||
|
_glfw.hints.context.release = value;
|
||||||
|
break;
|
||||||
|
case GLFW_REFRESH_RATE:
|
||||||
|
_glfw.hints.refreshRate = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
// Allow closing of NULL (to match the behavior of free)
|
||||||
|
if (window == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Clear all callbacks to avoid exposing a half torn-down window object
|
||||||
|
memset(&window->callbacks, 0, sizeof(window->callbacks));
|
||||||
|
|
||||||
|
// The window's context must not be current on another thread when the
|
||||||
|
// window is destroyed
|
||||||
|
if (window == _glfwPlatformGetCurrentContext())
|
||||||
|
glfwMakeContextCurrent(NULL);
|
||||||
|
|
||||||
|
_glfwPlatformDestroyWindow(window);
|
||||||
|
|
||||||
|
// Unlink window from global linked list
|
||||||
|
{
|
||||||
|
_GLFWwindow** prev = &_glfw.windowListHead;
|
||||||
|
|
||||||
|
while (*prev != window)
|
||||||
|
prev = &((*prev)->next);
|
||||||
|
|
||||||
|
*prev = window->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
return window->closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
window->closed = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
assert(title != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformSetWindowTitle(window, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
|
||||||
|
int count, const GLFWimage* images)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
assert(count >= 0);
|
||||||
|
assert(count == 0 || images != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformSetWindowIcon(window, count, images);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = 0;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformGetWindowPos(window, xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformSetWindowPos(window, xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = 0;
|
||||||
|
if (height)
|
||||||
|
*height = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformGetWindowSize(window, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
window->videoMode.width = width;
|
||||||
|
window->videoMode.height = height;
|
||||||
|
|
||||||
|
_glfwPlatformSetWindowSize(window, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
|
||||||
|
int minwidth, int minheight,
|
||||||
|
int maxwidth, int maxheight)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
if (minwidth < 0 || minheight < 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid window minimum size %ix%i",
|
||||||
|
minwidth, minheight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
if (maxwidth < 0 || maxheight < 0 ||
|
||||||
|
maxwidth < minwidth || maxheight < minheight)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid window maximum size %ix%i",
|
||||||
|
maxwidth, maxheight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window->minwidth = minwidth;
|
||||||
|
window->minheight = minheight;
|
||||||
|
window->maxwidth = maxwidth;
|
||||||
|
window->maxheight = maxheight;
|
||||||
|
|
||||||
|
if (window->monitor || !window->resizable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformSetWindowSizeLimits(window,
|
||||||
|
minwidth, minheight,
|
||||||
|
maxwidth, maxheight);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
if (numer <= 0 || denom <= 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid window aspect ratio %i:%i",
|
||||||
|
numer, denom);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window->numer = numer;
|
||||||
|
window->denom = denom;
|
||||||
|
|
||||||
|
if (window->monitor || !window->resizable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformSetWindowAspectRatio(window, numer, denom);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = 0;
|
||||||
|
if (height)
|
||||||
|
*height = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformGetFramebufferSize(window, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
|
||||||
|
int* left, int* top,
|
||||||
|
int* right, int* bottom)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
if (left)
|
||||||
|
*left = 0;
|
||||||
|
if (top)
|
||||||
|
*top = 0;
|
||||||
|
if (right)
|
||||||
|
*right = 0;
|
||||||
|
if (bottom)
|
||||||
|
*bottom = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformIconifyWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformRestoreWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformMaximizeWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformShowWindow(window);
|
||||||
|
_glfwPlatformFocusWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformHideWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
_glfwPlatformFocusWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
|
||||||
|
switch (attrib)
|
||||||
|
{
|
||||||
|
case GLFW_FOCUSED:
|
||||||
|
return _glfwPlatformWindowFocused(window);
|
||||||
|
case GLFW_ICONIFIED:
|
||||||
|
return _glfwPlatformWindowIconified(window);
|
||||||
|
case GLFW_VISIBLE:
|
||||||
|
return _glfwPlatformWindowVisible(window);
|
||||||
|
case GLFW_MAXIMIZED:
|
||||||
|
return _glfwPlatformWindowMaximized(window);
|
||||||
|
case GLFW_RESIZABLE:
|
||||||
|
return window->resizable;
|
||||||
|
case GLFW_DECORATED:
|
||||||
|
return window->decorated;
|
||||||
|
case GLFW_FLOATING:
|
||||||
|
return window->floating;
|
||||||
|
case GLFW_CLIENT_API:
|
||||||
|
return window->context.client;
|
||||||
|
case GLFW_CONTEXT_CREATION_API:
|
||||||
|
return window->context.source;
|
||||||
|
case GLFW_CONTEXT_VERSION_MAJOR:
|
||||||
|
return window->context.major;
|
||||||
|
case GLFW_CONTEXT_VERSION_MINOR:
|
||||||
|
return window->context.minor;
|
||||||
|
case GLFW_CONTEXT_REVISION:
|
||||||
|
return window->context.revision;
|
||||||
|
case GLFW_CONTEXT_ROBUSTNESS:
|
||||||
|
return window->context.robustness;
|
||||||
|
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||||
|
return window->context.forward;
|
||||||
|
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||||
|
return window->context.debug;
|
||||||
|
case GLFW_OPENGL_PROFILE:
|
||||||
|
return window->context.profile;
|
||||||
|
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
||||||
|
return window->context.release;
|
||||||
|
case GLFW_CONTEXT_NO_ERROR:
|
||||||
|
return window->context.noerror;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return (GLFWmonitor*) window->monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
|
||||||
|
GLFWmonitor* mh,
|
||||||
|
int xpos, int ypos,
|
||||||
|
int width, int height,
|
||||||
|
int refreshRate)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) wh;
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (width <= 0 || height <= 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid window size %ix%i",
|
||||||
|
width, height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid refresh rate %i",
|
||||||
|
refreshRate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->videoMode.width = width;
|
||||||
|
window->videoMode.height = height;
|
||||||
|
window->videoMode.refreshRate = refreshRate;
|
||||||
|
|
||||||
|
_glfwPlatformSetWindowMonitor(window, monitor,
|
||||||
|
xpos, ypos, width, height,
|
||||||
|
refreshRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
window->userPointer = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return window->userPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowposfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowsizefun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.size, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowclosefun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.close, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowrefreshfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowfocusfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowiconifyfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
|
||||||
|
GLFWframebuffersizefun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwPollEvents(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwWaitEvents(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (!_glfw.windowListHead)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformWaitEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwWaitEventsTimeout(double timeout)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformWaitEventsTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwPostEmptyEvent(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (!_glfw.windowListHead)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformPostEmptyEvent();
|
||||||
|
}
|
||||||
|
|
6
internal/glfw/glfwdll_windows_386.go
Normal file
6
internal/glfw/glfwdll_windows_386.go
Normal file
File diff suppressed because one or more lines are too long
6
internal/glfw/glfwdll_windows_amd64.go
Normal file
6
internal/glfw/glfwdll_windows_amd64.go
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user