Add ANGLE support to Viewer on Windows

Change-Id: I97a844b2f289d2518f60a64f94d60551c4530dd4
Reviewed-on: https://skia-review.googlesource.com/35742
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Salomon 2017-08-17 14:37:06 -04:00 committed by Skia Commit-Bot
parent 1dc8ecbf5f
commit 194db176c9
13 changed files with 280 additions and 76 deletions

View File

@ -1579,6 +1579,9 @@ if (skia_enable_tools) {
"tools/viewer/sk_app/win/Window_win.cpp",
"tools/viewer/sk_app/win/main_win.cpp",
]
if (skia_use_angle) {
sources += [ "tools/viewer/sk_app/win/ANGLEWindowContext_win.cpp" ]
}
} else if (is_mac) {
sources += [
"tools/viewer/sk_app/mac/GLWindowContext_mac.cpp",
@ -1618,6 +1621,9 @@ if (skia_enable_tools) {
} else if (is_mac) {
deps += [ "//third_party/libsdl" ]
}
if (skia_use_angle) {
deps += [ "//third_party/angle2" ]
}
}
}

View File

@ -165,8 +165,11 @@ DEFINE_pathrenderer_flag;
DEFINE_bool(instancedRendering, false, "Enable instanced rendering on GPU backends.");
DECLARE_int32(threads)
const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
const char* kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
"OpenGL",
#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
"ANGLE",
#endif
#ifdef SK_VULKAN
"Vulkan",
#endif
@ -178,6 +181,11 @@ static sk_app::Window::BackendType get_backend_type(const char* str) {
if (0 == strcmp(str, "vk")) {
return sk_app::Window::kVulkan_BackendType;
} else
#endif
#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
if (0 == strcmp(str, "angle")) {
return sk_app::Window::kANGLE_BackendType;
} else
#endif
if (0 == strcmp(str, "gl")) {
return sk_app::Window::kNativeGL_BackendType;
@ -366,26 +374,17 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fWindow->inval();
});
fCommands.addCommand('d', "Modes", "Change rendering backend", [this]() {
sk_app::Window::BackendType newBackend = fBackendType;
#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
if (sk_app::Window::kRaster_BackendType == fBackendType) {
newBackend = sk_app::Window::kNativeGL_BackendType;
#ifdef SK_VULKAN
} else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
newBackend = sk_app::Window::kVulkan_BackendType;
#endif
} else {
newBackend = sk_app::Window::kRaster_BackendType;
}
#elif defined(SK_BUILD_FOR_UNIX)
sk_app::Window::BackendType newBackend = (sk_app::Window::BackendType)(
(fBackendType + 1) % sk_app::Window::kBackendTypeCount);
// Switching to and from Vulkan is problematic on Linux so disabled for now
if (sk_app::Window::kRaster_BackendType == fBackendType) {
newBackend = sk_app::Window::kNativeGL_BackendType;
} else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
newBackend = sk_app::Window::kRaster_BackendType;
#if defined(SK_BUILD_FOR_UNIX) && defined(SK_VULKAN)
if (newBackend == sk_app::Window::kVulkan_BackendType) {
newBackend = (sk_app::Window::BackendType)((newBackend + 1) %
sk_app::Window::kBackendTypeCount);
} else if (fBackendType == sk_app::Window::kVulkan_BackendType) {
newBackend = sk_app::Window::kVulkan_BackendType;
}
#endif
this->setBackend(newBackend);
});
@ -706,10 +705,14 @@ void Viewer::setBackend(sk_app::Window::BackendType backendType) {
fWindow->detach();
#if defined(SK_BUILD_FOR_WIN) && defined(SK_VULKAN)
// Switching from OpenGL to Vulkan (or vice-versa on some systems) in the same window is
// problematic at this point on Windows, so we just delete the window and recreate it.
// Switching between OpenGL, Vulkan, and ANGLE in the same window is problematic at this point
// on Windows, so we just delete the window and recreate it.
if (sk_app::Window::kVulkan_BackendType == fBackendType ||
sk_app::Window::kNativeGL_BackendType == fBackendType) {
sk_app::Window::kNativeGL_BackendType == fBackendType
#if SK_ANGLE
|| sk_app::Window::kANGLE_BackendType == fBackendType
#endif
) {
DisplayParams params = fWindow->getRequestedDisplayParams();
delete fWindow;
fWindow = Window::CreateNativeWindow(nullptr);
@ -1048,6 +1051,10 @@ void Viewer::drawImGui(SkCanvas* canvas) {
ImGui::RadioButton("Raster", &newBackend, sk_app::Window::kRaster_BackendType);
ImGui::SameLine();
ImGui::RadioButton("OpenGL", &newBackend, sk_app::Window::kNativeGL_BackendType);
#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
ImGui::SameLine();
ImGui::RadioButton("ANGLE", &newBackend, sk_app::Window::kANGLE_BackendType);
#endif
#if defined(SK_VULKAN)
ImGui::SameLine();
ImGui::RadioButton("Vulkan", &newBackend, sk_app::Window::kVulkan_BackendType);

View File

@ -30,10 +30,9 @@ GLWindowContext::GLWindowContext(const DisplayParams& params)
}
void GLWindowContext::initializeContext() {
this->onInitializeContext();
SkASSERT(!fContext);
fBackendContext.reset(GrGLCreateNativeInterface());
fBackendContext = this->onInitializeContext();
fContext = GrContext::MakeGL(fBackendContext.get(), fDisplayParams.fGrContextOptions);
if (!fContext && fDisplayParams.fMSAASampleCount) {
fDisplayParams.fMSAASampleCount /= 2;

View File

@ -40,7 +40,7 @@ protected:
// This should be called by subclass constructor. It is also called when window/display
// parameters change. This will in turn call onInitializeContext().
void initializeContext();
virtual void onInitializeContext() = 0;
virtual sk_sp<const GrGLInterface> onInitializeContext() = 0;
// This should be called by subclass destructor. It is also called when window/display
// parameters change prior to initializing a new GL context. This will in turn call

View File

@ -41,6 +41,9 @@ public:
enum BackendType {
kNativeGL_BackendType,
#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
kANGLE_BackendType,
#endif
#ifdef SK_VULKAN
kVulkan_BackendType,
#endif

View File

@ -6,11 +6,11 @@
* found in the LICENSE file.
*/
#include <GLES/gl.h>
#include "WindowContextFactory_android.h"
#include "../GLWindowContext.h"
#include <EGL/egl.h>
#include <GLES/gl.h>
#include "../GLWindowContext.h"
#include "WindowContextFactory_android.h"
#include "gl/GrGLInterface.h"
using sk_app::GLWindowContext;
using sk_app::DisplayParams;
@ -25,7 +25,7 @@ public:
void onSwapBuffers() override;
void onInitializeContext() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
@ -57,7 +57,7 @@ GLWindowContext_android::~GLWindowContext_android() {
this->destroyContext();
}
void GLWindowContext_android::onInitializeContext() {
sk_sp<const GrGLInterface> GLWindowContext_android::onInitializeContext() {
fWidth = ANativeWindow_getWidth(fNativeWindow);
fHeight = ANativeWindow_getHeight(fNativeWindow);
@ -131,6 +131,8 @@ void GLWindowContext_android::onInitializeContext() {
eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits);
eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount);
return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
}
void GLWindowContext_android::onDestroyContext() {

View File

@ -6,12 +6,11 @@
* found in the LICENSE file.
*/
#include "../GLWindowContext.h"
#include "WindowContextFactory_mac.h"
#include "SDL.h"
#include <OpenGL/gl.h>
#include "../GLWindowContext.h"
#include "SDL.h"
#include "WindowContextFactory_mac.h"
#include "gl/GrGLInterface.h"
using sk_app::DisplayParams;
using sk_app::window_context_factory::MacWindowInfo;
@ -26,8 +25,8 @@ public:
~GLWindowContext_mac() override;
void onSwapBuffers() override;
void onInitializeContext() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
@ -51,13 +50,13 @@ GLWindowContext_mac::~GLWindowContext_mac() {
this->destroyContext();
}
void GLWindowContext_mac::onInitializeContext() {
sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() {
SkASSERT(fWindow);
fGLContext = SDL_GL_CreateContext(fWindow);
if (!fGLContext) {
SkDebugf("%s\n", SDL_GetError());
return;
return nullptr;
}
if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
@ -74,6 +73,7 @@ void GLWindowContext_mac::onInitializeContext() {
} else {
SkDebugf("MakeCurrent failed: %s\n", SDL_GetError());
}
return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
}
void GLWindowContext_mac::onDestroyContext() {

View File

@ -6,15 +6,14 @@
* found in the LICENSE file.
*/
#include <OpenGL/gl.h>
#include "../GLWindowContext.h"
#include "SDL.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "sk_tool_utils.h"
#include "WindowContextFactory_mac.h"
#include "SDL.h"
#include <OpenGL/gl.h>
#include "gl/GrGLInterface.h"
#include "sk_tool_utils.h"
using sk_app::DisplayParams;
using sk_app::window_context_factory::MacWindowInfo;
@ -37,7 +36,7 @@ public:
void onSwapBuffers() override;
void onInitializeContext() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
@ -63,13 +62,13 @@ RasterWindowContext_mac::~RasterWindowContext_mac() {
this->destroyContext();
}
void RasterWindowContext_mac::onInitializeContext() {
sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
SkASSERT(fWindow);
fGLContext = SDL_GL_CreateContext(fWindow);
if (!fGLContext) {
SkDebugf("%s\n", SDL_GetError());
return;
return nullptr;
}
if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
@ -91,6 +90,7 @@ void RasterWindowContext_mac::onInitializeContext() {
SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType,
kPremul_SkAlphaType, fDisplayParams.fColorSpace);
fBackbufferSurface = SkSurface::MakeRaster(info);
return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
}
void RasterWindowContext_mac::onDestroyContext() {

View File

@ -6,10 +6,10 @@
* found in the LICENSE file.
*/
#include <GL/gl.h>
#include "../GLWindowContext.h"
#include "WindowContextFactory_unix.h"
#include <GL/gl.h>
#include "gl/GrGLInterface.h"
using sk_app::window_context_factory::XlibWindowInfo;
using sk_app::DisplayParams;
@ -27,7 +27,7 @@ public:
void onDestroyContext() override;
protected:
void onInitializeContext() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
private:
GLWindowContext_xlib(void*, const DisplayParams&);
@ -55,7 +55,7 @@ GLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const
using CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*);
void GLWindowContext_xlib::onInitializeContext() {
sk_sp<const GrGLInterface> GLWindowContext_xlib::onInitializeContext() {
SkASSERT(fDisplay);
SkASSERT(!fGLContext);
// We attempt to use glXCreateContextAttribsARB as RenderDoc requires that the context be
@ -86,25 +86,28 @@ void GLWindowContext_xlib::onInitializeContext() {
fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
}
if (!fGLContext) {
return;
return nullptr;
}
if (glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
glClearStencil(0);
glClearColor(0, 0, 0, 0);
glStencilMask(0xffffffff);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
XWindow root;
int x, y;
unsigned int border_width, depth;
XGetGeometry(fDisplay, fWindow, &root, &x, &y,
(unsigned int*)&fWidth, (unsigned int*)&fHeight, &border_width, &depth);
glViewport(0, 0, fWidth, fHeight);
if (!glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
return nullptr;
}
glClearStencil(0);
glClearColor(0, 0, 0, 0);
glStencilMask(0xffffffff);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
XWindow root;
int x, y;
unsigned int border_width, depth;
XGetGeometry(fDisplay, fWindow, &root, &x, &y, (unsigned int*)&fWidth, (unsigned int*)&fHeight,
&border_width, &depth);
glViewport(0, 0, fWidth, fHeight);
return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
}
GLWindowContext_xlib::~GLWindowContext_xlib() {

View File

@ -0,0 +1,177 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "../GLWindowContext.h"
#include "WindowContextFactory_win.h"
#include "gl/GrGLAssembleInterface.h"
#include "gl/GrGLDefines.h"
using sk_app::GLWindowContext;
using sk_app::DisplayParams;
namespace {
EGLDisplay get_angle_egl_display(HDC hdc) {
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
eglGetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
// We expect ANGLE to support this extension
if (!eglGetPlatformDisplayEXT) {
return EGL_NO_DISPLAY;
}
// We currently only support D3D11 ANGLE.
static constexpr EGLint kType = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
static constexpr EGLint attribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, kType, EGL_NONE};
return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, hdc, attribs);
}
class ANGLEGLWindowContext_win : public GLWindowContext {
public:
ANGLEGLWindowContext_win(HWND, const DisplayParams&);
~ANGLEGLWindowContext_win() override;
protected:
void onSwapBuffers() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
HWND fHWND;
EGLDisplay fDisplay = EGL_NO_DISPLAY;
EGLContext fContext = EGL_NO_CONTEXT;
EGLSurface fSurface = EGL_NO_SURFACE;
typedef GLWindowContext INHERITED;
};
ANGLEGLWindowContext_win::ANGLEGLWindowContext_win(HWND wnd, const DisplayParams& params)
: INHERITED(params), fHWND(wnd) {
this->initializeContext();
}
ANGLEGLWindowContext_win::~ANGLEGLWindowContext_win() { this->destroyContext(); }
sk_sp<const GrGLInterface> ANGLEGLWindowContext_win::onInitializeContext() {
HDC dc = GetDC(fHWND);
fDisplay = get_angle_egl_display(dc);
if (EGL_NO_DISPLAY == fDisplay) {
return nullptr;
}
EGLint majorVersion;
EGLint minorVersion;
if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
SkDebugf("Could not initialize display!\n");
return nullptr;
}
EGLint numConfigs;
fSampleCount = this->getDisplayParams().fMSAASampleCount;
const int sampleBuffers = fSampleCount > 0 ? 1 : 0;
const EGLint configAttribs[] = {EGL_RENDERABLE_TYPE,
// We currently only support ES3.
EGL_OPENGL_ES3_BIT,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_SAMPLE_BUFFERS,
sampleBuffers,
EGL_SAMPLES,
fSampleCount,
EGL_NONE};
EGLConfig surfaceConfig;
if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
SkDebugf("Could not create choose config!\n");
return nullptr;
}
// We currently only support ES3.
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
fContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
if (EGL_NO_CONTEXT == fContext) {
SkDebugf("Could not create context!\n");
return nullptr;
}
fSurface = eglCreateWindowSurface(fDisplay, surfaceConfig, fHWND, nullptr);
if (EGL_NO_SURFACE == fSurface) {
SkDebugf("Could not create surface!\n");
return nullptr;
}
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Could not make contxt current!\n");
return nullptr;
}
sk_sp<const GrGLInterface> interface(GrGLAssembleInterface(
nullptr,
[](void* ctx, const char name[]) -> GrGLFuncPtr { return eglGetProcAddress(name); }));
if (interface) {
interface->fFunctions.fClearStencil(0);
interface->fFunctions.fClearColor(0, 0, 0, 0);
interface->fFunctions.fStencilMask(0xffffffff);
interface->fFunctions.fClear(GR_GL_STENCIL_BUFFER_BIT | GR_GL_COLOR_BUFFER_BIT);
// use DescribePixelFormat to get the stencil depth.
int pixelFormat = GetPixelFormat(dc);
PIXELFORMATDESCRIPTOR pfd;
DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
fStencilBits = pfd.cStencilBits;
RECT rect;
GetClientRect(fHWND, &rect);
fWidth = rect.right - rect.left;
fHeight = rect.bottom - rect.top;
interface->fFunctions.fViewport(0, 0, fWidth, fHeight);
}
return interface;
}
void ANGLEGLWindowContext_win::onDestroyContext() {
eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (EGL_NO_CONTEXT != fContext) {
eglDestroyContext(fDisplay, fContext);
}
if (EGL_NO_SURFACE != fSurface) {
eglDestroySurface(fDisplay, fSurface);
}
if (EGL_NO_DISPLAY != fDisplay) {
eglTerminate(fDisplay);
}
}
void ANGLEGLWindowContext_win::onSwapBuffers() {
if (!eglSwapBuffers(fDisplay, fSurface)) {
SkDebugf("Could not complete eglSwapBuffers.\n");
}
}
} // anonymous namespace
namespace sk_app {
namespace window_context_factory {
WindowContext* NewANGLEForWin(HWND wnd, const DisplayParams& params) {
ANGLEGLWindowContext_win* ctx = new ANGLEGLWindowContext_win(wnd, params);
if (!ctx->isValid()) {
delete ctx;
return nullptr;
}
return ctx;
}
} // namespace window_context_factory
} // namespace sk_app

View File

@ -6,13 +6,12 @@
* found in the LICENSE file.
*/
#include "WindowContextFactory_win.h"
#include <Windows.h>
#include <GL/gl.h>
// windows stuff
#include "win/SkWGL.h"
#include "../GLWindowContext.h"
#include "GrGLInterface.h"
#include "WindowContextFactory_win.h"
#include "win/SkWGL.h"
using sk_app::GLWindowContext;
using sk_app::DisplayParams;
@ -27,7 +26,7 @@ public:
protected:
void onSwapBuffers() override;
void onInitializeContext() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
@ -51,13 +50,13 @@ GLWindowContext_win::~GLWindowContext_win() {
this->destroyContext();
}
void GLWindowContext_win::onInitializeContext() {
sk_sp<const GrGLInterface> GLWindowContext_win::onInitializeContext() {
HDC dc = GetDC(fHWND);
fHGLRC = SkCreateWGLContext(dc, fDisplayParams.fMSAASampleCount, false /* deepColor */,
kGLPreferCompatibilityProfile_SkWGLContextRequest);
if (NULL == fHGLRC) {
return;
return nullptr;
}
// Look to see if RenderDoc is attached. If so, re-create the context with a core profile
@ -70,7 +69,7 @@ void GLWindowContext_win::onInitializeContext() {
fHGLRC = SkCreateWGLContext(dc, fDisplayParams.fMSAASampleCount, false /* deepColor */,
kGLPreferCoreProfile_SkWGLContextRequest);
if (NULL == fHGLRC) {
return;
return nullptr;
}
}
}
@ -107,6 +106,7 @@ void GLWindowContext_win::onInitializeContext() {
fHeight = rect.bottom - rect.top;
glViewport(0, 0, fWidth, fHeight);
}
return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
}

View File

@ -22,6 +22,8 @@ WindowContext* NewVulkanForWin(HWND, const DisplayParams&);
WindowContext* NewGLForWin(HWND, const DisplayParams&);
WindowContext* NewANGLEForWin(HWND, const DisplayParams&);
WindowContext* NewRasterForWin(HWND, const DisplayParams&);
} // namespace window_context_factory

View File

@ -349,6 +349,11 @@ bool Window_win::attach(BackendType attachType) {
case kNativeGL_BackendType:
fWindowContext = window_context_factory::NewGLForWin(fHWnd, fRequestedDisplayParams);
break;
#if SK_ANGLE
case kANGLE_BackendType:
fWindowContext = window_context_factory::NewANGLEForWin(fHWnd, fRequestedDisplayParams);
break;
#endif
case kRaster_BackendType:
fWindowContext = window_context_factory::NewRasterForWin(fHWnd,
fRequestedDisplayParams);