shiny/driver/gldriver: try multiple ANGLE platforms

On Windows mobile/gl uses ANGLE for EGL. ANGLE has multiple backends
and for some graphics cards one of these may work better than other.

Automatically try to choose the next platform when initialization fails:
1. Default
2. Direct3D 11
3. Direct3D 9
4. Direct3D 11 with WARP

Change-Id: Ief0911574afaf4ded3f578a1cd7b9639828f3486
Reviewed-on: https://go-review.googlesource.com/30754
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
Egon Elbre 2016-10-10 12:35:17 +03:00 коммит произвёл Alex Brainman
Родитель 42596718c7
Коммит 807d650904
2 изменённых файлов: 73 добавлений и 17 удалений

Просмотреть файл

@ -30,13 +30,25 @@ const (
_EGL_CONFIG_CAVEAT = 0x3027
_EGL_NONE = 0x3038
_EGL_CONTEXT_CLIENT_VERSION = 0x3098
)
// ANGLE specific options found in eglext.h
const (
_EGL_PLATFORM_ANGLE_ANGLE = 0x3202
_EGL_PLATFORM_ANGLE_TYPE_ANGLE = 0x3203
_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204
_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205
_EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206
_EGL_CONTEXT_CLIENT_VERSION = 0x3098
_EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207
_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208
_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209
_EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A
_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE = 0x320B
_EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE = 0x320D
_EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE = 0x320E
)
const (

Просмотреть файл

@ -222,28 +222,72 @@ func eglErr() error {
}
func createEGLSurface(hwnd syscall.Handle, w *windowImpl) error {
displayAttrib := [...]eglInt{
_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
_EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE,
_EGL_NONE,
var displayAttribPlatforms = [][]eglInt{
// Default
[]eglInt{
_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
_EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE,
_EGL_NONE,
},
// Direct3D 11
[]eglInt{
_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE,
_EGL_NONE,
},
// Direct3D 9
[]eglInt{
_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
_EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE,
_EGL_NONE,
},
// Direct3D 11 with WARP
// https://msdn.microsoft.com/en-us/library/windows/desktop/gg615082.aspx
[]eglInt{
_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE,
_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE,
_EGL_NONE,
},
}
dc, err := win32.GetDC(hwnd)
if err != nil {
return fmt.Errorf("win32.GetDC failed: %v", err)
}
display, _, _ := eglGetPlatformDisplayEXT.Call(
_EGL_PLATFORM_ANGLE_ANGLE,
uintptr(dc),
uintptr(unsafe.Pointer(&displayAttrib)),
)
if display == _EGL_NO_DISPLAY {
return fmt.Errorf("eglGetPlatformDisplayEXT failed: %v", eglErr())
}
if ret, _, _ := eglInitialize.Call(display, 0, 0); ret == 0 {
return fmt.Errorf("eglInitialize failed: %v", eglErr())
var display uintptr = _EGL_NO_DISPLAY
for i, displayAttrib := range displayAttribPlatforms {
lastTry := i == len(displayAttribPlatforms)-1
display, _, _ = eglGetPlatformDisplayEXT.Call(
_EGL_PLATFORM_ANGLE_ANGLE,
uintptr(dc),
uintptr(unsafe.Pointer(&displayAttrib[0])),
)
if display == _EGL_NO_DISPLAY {
if !lastTry {
continue
}
return fmt.Errorf("eglGetPlatformDisplayEXT failed: %v", eglErr())
}
if ret, _, _ := eglInitialize.Call(display, 0, 0); ret == 0 {
if !lastTry {
continue
}
return fmt.Errorf("eglInitialize failed: %v", eglErr())
}
}
eglBindAPI.Call(_EGL_OPENGL_ES_API)