mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 13:07:26 +01:00
b359985e97
Many of the structs found in internal.h (internal_windows.go) contain defines such as GLFW_WIN32_WINDOW_STATE which gets replaced with a struct defined in win32platform_windows.go (win32_platform.h). Originally, these structs where directly placed inside of internal_windows.go. However, to make it easier to add macOS and Linux these cannot be in this file. This commit separates the windows specific structs into the respective windows file and updates the field to be named state. Updates #2546
573 lines
16 KiB
Go
573 lines
16 KiB
Go
// SPDX-License-Identifier: Zlib
|
|
// SPDX-FileCopyrightText: 2002-2006 Marcus Geelnard
|
|
// SPDX-FileCopyrightText: 2006-2019 Camilla Löwy
|
|
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
|
|
|
|
package goglfw
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/windows"
|
|
|
|
"github.com/hajimehoshi/ebiten/v2/internal/microsoftgdk"
|
|
)
|
|
|
|
func findPixelFormatAttribValue(attribs []int32, values []int32, attrib int32) int32 {
|
|
for i := range attribs {
|
|
if attribs[i] == attrib {
|
|
return values[i]
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (w *Window) choosePixelFormat(ctxconfig *ctxconfig, fbconfig_ *fbconfig) (int, error) {
|
|
var nativeCount int32
|
|
var attribs []int32
|
|
|
|
if _glfw.platformContext.ARB_pixel_format {
|
|
var attrib int32 = _WGL_NUMBER_PIXEL_FORMATS_ARB
|
|
if err := wglGetPixelFormatAttribivARB(w.context.platform.dc, 1, 0, 1, &attrib, &nativeCount); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
attribs = append(attribs,
|
|
_WGL_SUPPORT_OPENGL_ARB,
|
|
_WGL_DRAW_TO_WINDOW_ARB,
|
|
_WGL_PIXEL_TYPE_ARB,
|
|
_WGL_ACCELERATION_ARB,
|
|
_WGL_RED_BITS_ARB,
|
|
_WGL_RED_SHIFT_ARB,
|
|
_WGL_GREEN_BITS_ARB,
|
|
_WGL_GREEN_SHIFT_ARB,
|
|
_WGL_BLUE_BITS_ARB,
|
|
_WGL_BLUE_SHIFT_ARB,
|
|
_WGL_ALPHA_BITS_ARB,
|
|
_WGL_ALPHA_SHIFT_ARB,
|
|
_WGL_DEPTH_BITS_ARB,
|
|
_WGL_STENCIL_BITS_ARB,
|
|
_WGL_ACCUM_BITS_ARB,
|
|
_WGL_ACCUM_RED_BITS_ARB,
|
|
_WGL_ACCUM_GREEN_BITS_ARB,
|
|
_WGL_ACCUM_BLUE_BITS_ARB,
|
|
_WGL_ACCUM_ALPHA_BITS_ARB,
|
|
_WGL_AUX_BUFFERS_ARB,
|
|
_WGL_STEREO_ARB,
|
|
_WGL_DOUBLE_BUFFER_ARB)
|
|
|
|
if _glfw.platformContext.ARB_multisample {
|
|
attribs = append(attribs, _WGL_SAMPLES_ARB)
|
|
}
|
|
|
|
if ctxconfig.client == OpenGLAPI {
|
|
if _glfw.platformContext.ARB_framebuffer_sRGB || _glfw.platformContext.EXT_framebuffer_sRGB {
|
|
attribs = append(attribs, _WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB)
|
|
}
|
|
} else {
|
|
if _glfw.platformContext.EXT_colorspace {
|
|
attribs = append(attribs, _WGL_COLORSPACE_EXT)
|
|
}
|
|
}
|
|
} else {
|
|
c, err := _DescribePixelFormat(w.context.platform.dc, 1, uint32(unsafe.Sizeof(_PIXELFORMATDESCRIPTOR{})), nil)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
nativeCount = c
|
|
}
|
|
|
|
usableConfigs := make([]*fbconfig, 0, nativeCount)
|
|
for i := int32(0); i < nativeCount; i++ {
|
|
var u fbconfig
|
|
pixelFormat := uintptr(i) + 1
|
|
|
|
if _glfw.platformContext.ARB_pixel_format {
|
|
// Get pixel format attributes through "modern" extension
|
|
values := make([]int32, len(attribs))
|
|
if err := wglGetPixelFormatAttribivARB(w.context.platform.dc, int32(pixelFormat), 0, uint32(len(attribs)), &attribs[0], &values[0]); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
findAttribValue := func(attrib int32) int32 {
|
|
return findPixelFormatAttribValue(attribs, values, attrib)
|
|
}
|
|
|
|
if findAttribValue(_WGL_SUPPORT_OPENGL_ARB) == 0 || findAttribValue(_WGL_DRAW_TO_WINDOW_ARB) == 0 {
|
|
continue
|
|
}
|
|
|
|
if findAttribValue(_WGL_PIXEL_TYPE_ARB) != _WGL_TYPE_RGBA_ARB {
|
|
continue
|
|
}
|
|
|
|
if findAttribValue(_WGL_ACCELERATION_ARB) == _WGL_NO_ACCELERATION_ARB {
|
|
continue
|
|
}
|
|
|
|
if (findAttribValue(_WGL_DOUBLE_BUFFER_ARB) != 0) != fbconfig_.doublebuffer {
|
|
continue
|
|
}
|
|
|
|
u.redBits = int(findAttribValue(_WGL_RED_BITS_ARB))
|
|
u.greenBits = int(findAttribValue(_WGL_GREEN_BITS_ARB))
|
|
u.blueBits = int(findAttribValue(_WGL_BLUE_BITS_ARB))
|
|
u.alphaBits = int(findAttribValue(_WGL_ALPHA_BITS_ARB))
|
|
|
|
u.depthBits = int(findAttribValue(_WGL_DEPTH_BITS_ARB))
|
|
u.stencilBits = int(findAttribValue(_WGL_STENCIL_BITS_ARB))
|
|
|
|
u.accumRedBits = int(findAttribValue(_WGL_ACCUM_RED_BITS_ARB))
|
|
u.accumGreenBits = int(findAttribValue(_WGL_ACCUM_GREEN_BITS_ARB))
|
|
u.accumBlueBits = int(findAttribValue(_WGL_ACCUM_BLUE_BITS_ARB))
|
|
u.accumAlphaBits = int(findAttribValue(_WGL_ACCUM_ALPHA_BITS_ARB))
|
|
|
|
u.auxBuffers = int(findAttribValue(_WGL_AUX_BUFFERS_ARB))
|
|
|
|
if findAttribValue(_WGL_STEREO_ARB) != 0 {
|
|
u.stereo = true
|
|
}
|
|
|
|
if _glfw.platformContext.ARB_multisample {
|
|
u.samples = int(findAttribValue(_WGL_SAMPLES_ARB))
|
|
}
|
|
|
|
if ctxconfig.client == OpenGLAPI {
|
|
if _glfw.platformContext.ARB_framebuffer_sRGB || _glfw.platformContext.EXT_framebuffer_sRGB {
|
|
if findAttribValue(_WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB) != 0 {
|
|
u.sRGB = true
|
|
}
|
|
}
|
|
} else {
|
|
if _glfw.platformContext.EXT_colorspace {
|
|
if findAttribValue(_WGL_COLORSPACE_EXT) == _WGL_COLORSPACE_SRGB_EXT {
|
|
u.sRGB = true
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Get pixel format attributes through legacy PFDs
|
|
|
|
var pfd _PIXELFORMATDESCRIPTOR
|
|
if _, err := _DescribePixelFormat(w.context.platform.dc, int32(pixelFormat), uint32(unsafe.Sizeof(pfd)), &pfd); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if pfd.dwFlags&_PFD_DRAW_TO_WINDOW == 0 || pfd.dwFlags&_PFD_SUPPORT_OPENGL == 0 {
|
|
continue
|
|
}
|
|
|
|
if pfd.dwFlags&_PFD_GENERIC_ACCELERATED == 0 && pfd.dwFlags&_PFD_GENERIC_FORMAT != 0 {
|
|
continue
|
|
}
|
|
|
|
if pfd.iPixelType != _PFD_TYPE_RGBA {
|
|
continue
|
|
}
|
|
|
|
if (pfd.dwFlags&_PFD_DOUBLEBUFFER != 0) != fbconfig_.doublebuffer {
|
|
continue
|
|
}
|
|
|
|
u.redBits = int(pfd.cRedBits)
|
|
u.greenBits = int(pfd.cGreenBits)
|
|
u.blueBits = int(pfd.cBlueBits)
|
|
u.alphaBits = int(pfd.cAlphaBits)
|
|
|
|
u.depthBits = int(pfd.cDepthBits)
|
|
u.stencilBits = int(pfd.cStencilBits)
|
|
|
|
u.accumRedBits = int(pfd.cAccumRedBits)
|
|
u.accumGreenBits = int(pfd.cAccumGreenBits)
|
|
u.accumBlueBits = int(pfd.cAccumBlueBits)
|
|
u.accumAlphaBits = int(pfd.cAccumAlphaBits)
|
|
|
|
u.auxBuffers = int(pfd.cAuxBuffers)
|
|
|
|
if pfd.dwFlags&_PFD_STEREO != 0 {
|
|
u.stereo = true
|
|
}
|
|
}
|
|
|
|
u.handle = pixelFormat
|
|
usableConfigs = append(usableConfigs, &u)
|
|
}
|
|
|
|
if len(usableConfigs) == 0 {
|
|
return 0, fmt.Errorf("goglfw: the driver does not appear to support OpenGL")
|
|
}
|
|
|
|
closest := chooseFBConfig(fbconfig_, usableConfigs)
|
|
if closest == nil {
|
|
return 0, fmt.Errorf("goglfw: failed to find a suitable pixel format")
|
|
}
|
|
|
|
return int(closest.handle), nil
|
|
}
|
|
|
|
func makeContextCurrentWGL(window *Window) error {
|
|
if window != nil {
|
|
if err := wglMakeCurrent(window.context.platform.dc, window.context.platform.handle); err != nil {
|
|
_ = _glfw.contextSlot.set(0)
|
|
return err
|
|
}
|
|
if err := _glfw.contextSlot.set(uintptr(unsafe.Pointer(window))); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if err := wglMakeCurrent(0, 0); err != nil {
|
|
_ = _glfw.contextSlot.set(0)
|
|
return err
|
|
}
|
|
if err := _glfw.contextSlot.set(0); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func swapBuffersWGL(window *Window) error {
|
|
if window.monitor == nil && _IsWindowsVistaOrGreater() {
|
|
// DWM Composition is always enabled on Win8+
|
|
enabled := _IsWindows8OrGreater()
|
|
|
|
if !enabled {
|
|
var err error
|
|
enabled, err = _DwmIsCompositionEnabled()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// HACK: Use DwmFlush when desktop composition is enabled
|
|
if enabled {
|
|
for i := 0; i < window.context.platform.interval; i++ {
|
|
// Ignore an error from DWM functions as they might not be implemented e.g. on Proton (#2113).
|
|
_ = _DwmFlush()
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := _SwapBuffers(window.context.platform.dc); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func swapIntervalWGL(interval int) error {
|
|
ptr, err := _glfw.contextSlot.get()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
window := (*Window)(unsafe.Pointer(ptr))
|
|
|
|
window.context.platform.interval = interval
|
|
|
|
if window.monitor == nil && _IsWindowsVistaOrGreater() {
|
|
// DWM Composition is always enabled on Win8+
|
|
enabled := _IsWindows8OrGreater()
|
|
|
|
if !enabled {
|
|
e, err := _DwmIsCompositionEnabled()
|
|
// Ignore an error from DWM functions as they might not be implemented e.g. on Proton (#2113).
|
|
if err == nil {
|
|
enabled = e
|
|
}
|
|
}
|
|
|
|
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
|
// avoid interfering with DWM vsync
|
|
if enabled {
|
|
interval = 0
|
|
}
|
|
}
|
|
|
|
if _glfw.platformContext.EXT_swap_control {
|
|
if err := wglSwapIntervalEXT(int32(interval)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func extensionSupportedWGL(extension string) bool {
|
|
var extensions string
|
|
|
|
if wglGetExtensionsStringARB_Available() {
|
|
extensions = wglGetExtensionsStringARB(wglGetCurrentDC())
|
|
} else if wglGetExtensionsStringEXT_Available() {
|
|
extensions = wglGetExtensionsStringEXT()
|
|
}
|
|
|
|
if len(extensions) == 0 {
|
|
return false
|
|
}
|
|
|
|
for _, str := range strings.Split(extensions, " ") {
|
|
if extension == str {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func getProcAddressWGL(procname string) uintptr {
|
|
proc := wglGetProcAddress(procname)
|
|
if proc != 0 {
|
|
return proc
|
|
}
|
|
return opengl32.NewProc(procname).Addr()
|
|
}
|
|
|
|
func destroyContextWGL(window *Window) error {
|
|
if window.context.platform.handle != 0 {
|
|
// Ignore ERROR_BUSY. This happens when the thread is different from the context thread (#2518).
|
|
// This is a known issue of GLFW (glfw/glfw#2239).
|
|
// TODO: Delete the context on an appropriate thread.
|
|
if err := wglDeleteContext(window.context.platform.handle); err != nil && !errors.Is(err, windows.ERROR_BUSY) {
|
|
return err
|
|
}
|
|
window.context.platform.handle = 0
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func initWGL() error {
|
|
if microsoftgdk.IsXbox() {
|
|
return fmt.Errorf("goglfw: WGL is not available in Xbox")
|
|
}
|
|
|
|
if _glfw.platformContext.inited {
|
|
return nil
|
|
}
|
|
|
|
// opengl32.dll must be loaded first. The loading state might affect Windows APIs.
|
|
// This is needed at least before SetPixelFormat.
|
|
if err := opengl32.Load(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// NOTE: A dummy context has to be created for opengl32.dll to load the
|
|
// OpenGL ICD, from which we can then query WGL extensions
|
|
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
|
// creation failure occurs during manual pixel format enumeration
|
|
|
|
dc, err := _GetDC(_glfw.platformWindow.helperWindowHandle)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pfd := _PIXELFORMATDESCRIPTOR{
|
|
nVersion: 1,
|
|
dwFlags: _PFD_DRAW_TO_WINDOW | _PFD_SUPPORT_OPENGL | _PFD_DOUBLEBUFFER,
|
|
iPixelType: _PFD_TYPE_RGBA,
|
|
cColorBits: 24,
|
|
}
|
|
pfd.nSize = uint16(unsafe.Sizeof(pfd))
|
|
|
|
format, err := _ChoosePixelFormat(dc, &pfd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := _SetPixelFormat(dc, format, &pfd); err != nil {
|
|
return err
|
|
}
|
|
|
|
rc, err := wglCreateContext(dc)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
pdc := wglGetCurrentDC()
|
|
prc := wglGetCurrentContext()
|
|
|
|
if err := wglMakeCurrent(dc, rc); err != nil {
|
|
_ = wglMakeCurrent(pdc, prc)
|
|
_ = wglDeleteContext(rc)
|
|
return err
|
|
}
|
|
|
|
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
|
// extension string that tells us whether the functions are supported
|
|
//
|
|
// Interestingly, wglGetProcAddress might return 0 after extensionSupportedWGL is called.
|
|
initWGLExtensionFunctions()
|
|
|
|
// NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
|
|
// checked below as we are already using them
|
|
_glfw.platformContext.ARB_multisample = extensionSupportedWGL("WGL_ARB_multisample")
|
|
_glfw.platformContext.ARB_framebuffer_sRGB = extensionSupportedWGL("WGL_ARB_framebuffer_sRGB")
|
|
_glfw.platformContext.EXT_framebuffer_sRGB = extensionSupportedWGL("WGL_EXT_framebuffer_sRGB")
|
|
_glfw.platformContext.ARB_create_context = extensionSupportedWGL("WGL_ARB_create_context")
|
|
_glfw.platformContext.ARB_create_context_profile = extensionSupportedWGL("WGL_ARB_create_context_profile")
|
|
_glfw.platformContext.EXT_create_context_es2_profile = extensionSupportedWGL("WGL_EXT_create_context_es2_profile")
|
|
_glfw.platformContext.ARB_create_context_robustness = extensionSupportedWGL("WGL_ARB_create_context_robustness")
|
|
_glfw.platformContext.ARB_create_context_no_error = extensionSupportedWGL("WGL_ARB_create_context_no_error")
|
|
_glfw.platformContext.EXT_swap_control = extensionSupportedWGL("WGL_EXT_swap_control")
|
|
_glfw.platformContext.EXT_colorspace = extensionSupportedWGL("WGL_EXT_colorspace")
|
|
_glfw.platformContext.ARB_pixel_format = extensionSupportedWGL("WGL_ARB_pixel_format")
|
|
_glfw.platformContext.ARB_context_flush_control = extensionSupportedWGL("WGL_ARB_context_flush_control")
|
|
|
|
if err := wglMakeCurrent(pdc, prc); err != nil {
|
|
return err
|
|
}
|
|
if err := wglDeleteContext(rc); err != nil {
|
|
return err
|
|
}
|
|
_glfw.platformContext.inited = true
|
|
return nil
|
|
}
|
|
|
|
func terminateWGL() {
|
|
}
|
|
|
|
func (w *Window) createContextWGL(ctxconfig *ctxconfig, fbconfig *fbconfig) error {
|
|
var share _HGLRC
|
|
if ctxconfig.share != nil {
|
|
share = ctxconfig.share.context.platform.handle
|
|
}
|
|
|
|
dc, err := _GetDC(w.platform.handle)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
w.context.platform.dc = dc
|
|
|
|
pixelFormat, err := w.choosePixelFormat(ctxconfig, fbconfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var pfd _PIXELFORMATDESCRIPTOR
|
|
if _, err := _DescribePixelFormat(w.context.platform.dc, int32(pixelFormat), uint32(unsafe.Sizeof(pfd)), &pfd); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := _SetPixelFormat(w.context.platform.dc, int32(pixelFormat), &pfd); err != nil {
|
|
return err
|
|
}
|
|
|
|
if ctxconfig.client == OpenGLAPI {
|
|
if ctxconfig.forward && !_glfw.platformContext.ARB_create_context {
|
|
return fmt.Errorf("goglfw: a forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable: %w", VersionUnavailable)
|
|
}
|
|
|
|
if ctxconfig.profile != 0 && !_glfw.platformContext.ARB_create_context_profile {
|
|
return fmt.Errorf("goglfw: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable: %w", VersionUnavailable)
|
|
}
|
|
} else {
|
|
if !_glfw.platformContext.ARB_create_context || !_glfw.platformContext.ARB_create_context_profile || !_glfw.platformContext.EXT_create_context_es2_profile {
|
|
return fmt.Errorf("goglfw: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable: %w", ApiUnavailable)
|
|
}
|
|
}
|
|
|
|
if _glfw.platformContext.ARB_create_context {
|
|
var flags int32
|
|
var mask int32
|
|
if ctxconfig.client == OpenGLAPI {
|
|
if ctxconfig.forward {
|
|
flags |= _WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
|
|
}
|
|
|
|
if ctxconfig.profile == OpenGLCoreProfile {
|
|
mask |= _WGL_CONTEXT_CORE_PROFILE_BIT_ARB
|
|
} else if ctxconfig.profile == OpenGLCompatProfile {
|
|
mask |= _WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
|
|
}
|
|
} else {
|
|
mask |= _WGL_CONTEXT_ES2_PROFILE_BIT_EXT
|
|
}
|
|
|
|
if ctxconfig.debug {
|
|
flags |= _WGL_CONTEXT_DEBUG_BIT_ARB
|
|
}
|
|
|
|
var attribs []int32
|
|
if ctxconfig.robustness != 0 {
|
|
if _glfw.platformContext.ARB_create_context_robustness {
|
|
if ctxconfig.robustness == NoResetNotification {
|
|
attribs = append(attribs, _WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, _WGL_NO_RESET_NOTIFICATION_ARB)
|
|
} else if ctxconfig.robustness == LoseContextOnReset {
|
|
attribs = append(attribs, _WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, _WGL_LOSE_CONTEXT_ON_RESET_ARB)
|
|
}
|
|
flags |= _WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB
|
|
}
|
|
}
|
|
|
|
if ctxconfig.release != 0 {
|
|
if _glfw.platformContext.ARB_context_flush_control {
|
|
if ctxconfig.release == ReleaseBehaviorNone {
|
|
attribs = append(attribs, _WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, _WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB)
|
|
} else if ctxconfig.release == ReleaseBehaviorFlush {
|
|
attribs = append(attribs, _WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, _WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB)
|
|
}
|
|
}
|
|
}
|
|
|
|
if ctxconfig.noerror {
|
|
if _glfw.platformContext.ARB_create_context_no_error {
|
|
attribs = append(attribs, _WGL_CONTEXT_OPENGL_NO_ERROR_ARB, 1)
|
|
}
|
|
}
|
|
|
|
// 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 {
|
|
attribs = append(attribs, _WGL_CONTEXT_MAJOR_VERSION_ARB, int32(ctxconfig.major))
|
|
attribs = append(attribs, _WGL_CONTEXT_MINOR_VERSION_ARB, int32(ctxconfig.minor))
|
|
}
|
|
|
|
if flags != 0 {
|
|
attribs = append(attribs, _WGL_CONTEXT_FLAGS_ARB, flags)
|
|
}
|
|
|
|
if mask != 0 {
|
|
attribs = append(attribs, _WGL_CONTEXT_PROFILE_MASK_ARB, mask)
|
|
}
|
|
|
|
attribs = append(attribs, 0, 0)
|
|
|
|
var err error
|
|
w.context.platform.handle, err = wglCreateContextAttribsARB(w.context.platform.dc, share, &attribs[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
var err error
|
|
w.context.platform.handle, err = wglCreateContext(w.context.platform.dc)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if share != 0 {
|
|
if err := wglShareLists(share, w.context.platform.handle); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
w.context.makeCurrent = makeContextCurrentWGL
|
|
w.context.swapBuffers = swapBuffersWGL
|
|
w.context.swapInterval = swapIntervalWGL
|
|
w.context.extensionSupported = extensionSupportedWGL
|
|
w.context.getProcAddress = getProcAddressWGL
|
|
w.context.destroy = destroyContextWGL
|
|
|
|
return nil
|
|
}
|
|
|
|
func getWGLContext(handle *Window) _HGLRC {
|
|
window := handle
|
|
if !_glfw.initialized {
|
|
panic(NotInitialized)
|
|
}
|
|
if window.context.source != NativeContextAPI {
|
|
// TODO: Should this return an error?
|
|
return 0
|
|
}
|
|
return window.context.platform.handle
|
|
}
|