Add support for ANGLE (D3D) on Skia port

Anyway we've disable the GPU support temporally (related to #960)
This commit is contained in:
David Capello 2016-02-09 23:12:59 -03:00
parent d244af8fc1
commit fc58daa814
10 changed files with 279 additions and 102 deletions

View File

@ -85,12 +85,11 @@ if(USE_SKIA_BACKEND)
find_library(SKIA_GPU_LIBRARY skia_skgpu PATH "${SKIA_BUILD_OUT_DIR}")
find_library(SKIA_UTILS_LIBRARY skia_utils PATH "${SKIA_BUILD_OUT_DIR}")
set(SKIA_LIBEGL_LIBRARY "")
if(WIN32)
find_library(SKIA_ETC1_LIBRARY libetc1 PATH "${SKIA_BUILD_OUT_DIR}/obj/gyp")
find_library(SKIA_LIBSKKTX_LIBRARY libSkKTX PATH "${SKIA_BUILD_OUT_DIR}/obj/gyp")
find_library(SKIA_OPENGL_LIBRARY opengl32)
find_library(SKIA_LIBEGL_LIBRARY libEGL.dll.lib PATH "${SKIA_BUILD_OUT_DIR}")
find_library(SKIA_LIBEGL_LIBRARY libEGL.dll PATH "${SKIA_BUILD_OUT_DIR}")
if(SKIA_LIBEGL_LIBRARY)
add_definitions(-DSK_ANGLE=1)
endif()
@ -98,6 +97,7 @@ if(USE_SKIA_BACKEND)
find_library(SKIA_ETC1_LIBRARY etc1 PATH "${SKIA_BUILD_OUT_DIR}")
find_library(SKIA_LIBSKKTX_LIBRARY SkKTX PATH "${SKIA_BUILD_OUT_DIR}")
find_library(SKIA_OPENGL_LIBRARY opengl)
set(SKIA_LIBEGL_LIBRARY "")
endif()
find_path(SKIA_CONFIG_INCLUDE_DIR SkUserConfig.h HINTS "${SKIA_DIR}/include/config")

View File

@ -1,5 +1,5 @@
// SHE library
// Copyright (C) 2015 David Capello
// Copyright (C) 2015, 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -17,6 +17,7 @@ public:
virtual void destroyGLContext() = 0;
virtual int getStencilBits() = 0;
virtual int getSampleCount() = 0;
virtual void swapBuffers() { }
};
} // namespace she

View File

@ -1,5 +1,5 @@
// SHE library
// Copyright (C) 2015 David Capello
// Copyright (C) 2015, 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -17,9 +17,7 @@ namespace she {
class GLContextCGL : public GLContext {
public:
typedef void* NativeHandle;
GLContextCGL(NativeHandle window)
GLContextCGL()
: m_glctx(nullptr)
, m_stencilBits(0)
, m_sampleCount(0) {

165
src/she/gl/gl_context_egl.h Normal file
View File

@ -0,0 +1,165 @@
// SHE library
// Copyright (C) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef SHE_GL_CONTEXT_EGL_INCLUDED
#define SHE_GL_CONTEXT_EGL_INCLUDED
#pragma once
#include "she/gl/gl_context.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
namespace she {
class GLContextEGL : public GLContext {
public:
GLContextEGL(void* nativeDisplay)
: m_nativeDisplay(nativeDisplay)
, m_context(EGL_NO_CONTEXT)
, m_display(EGL_NO_DISPLAY)
, m_surface(EGL_NO_SURFACE)
{
}
~GLContextEGL() {
destroyGLContext();
}
bool createGLContext() override {
m_display = getD3DEGLDisplay((HDC)GetDC((HWND)m_nativeDisplay));
if (m_display == EGL_NO_DISPLAY) {
LOG("Cannot create EGL display");
return false;
}
EGLint majorVersion;
EGLint minorVersion;
if (!eglInitialize(m_display, &majorVersion, &minorVersion))
return false;
static const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
EGLConfig surfaceConfig;
EGLint numConfigs;
if (!eglChooseConfig(m_display, configAttribs, &surfaceConfig, 1, &numConfigs))
return false;
static const EGLint surfaceAttribs[] = {
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE
};
m_surface = eglCreateWindowSurface(
m_display,
surfaceConfig,
(EGLNativeWindowType)m_nativeDisplay,
surfaceAttribs);
if (m_surface == EGL_NO_SURFACE)
return false;
static const EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
m_context = eglCreateContext(m_display, surfaceConfig,
EGL_NO_CONTEXT,
contextAttribs);
if (m_context == EGL_NO_CONTEXT)
return false;
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
return false;
eglGetConfigAttrib(m_display, surfaceConfig, EGL_STENCIL_SIZE, &m_stencilBits);
eglGetConfigAttrib(m_display, surfaceConfig, EGL_SAMPLES, &m_sampleCount);
return true;
}
void destroyGLContext() override {
if (m_display != EGL_NO_DISPLAY) {
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_surface != EGL_NO_SURFACE) {
eglDestroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE;
}
if (m_context != EGL_NO_CONTEXT) {
eglDestroyContext(m_display, m_context);
m_context = EGL_NO_CONTEXT;
}
eglTerminate(m_display);
m_display = EGL_NO_DISPLAY;
}
}
int getStencilBits() override {
return m_stencilBits;
}
int getSampleCount() override {
return m_sampleCount;
}
void swapBuffers() override {
eglSwapBuffers(m_display, m_surface);
}
private:
static void* getD3DEGLDisplay(void* nativeDisplay) {
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
eglGetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
if (!eglGetPlatformDisplayEXT)
return eglGetDisplay(static_cast<EGLNativeDisplayType>(nativeDisplay));
EGLint attribs[3][3] = {
{
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_NONE
},
{
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
EGL_NONE
},
{
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
EGL_NONE
}
};
EGLDisplay display = EGL_NO_DISPLAY;
for (int i=0; i<3 && display == EGL_NO_DISPLAY; ++i) {
display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
nativeDisplay, attribs[i]);
}
return display;
}
void* m_nativeDisplay;
void* m_context;
void* m_display;
void* m_surface;
EGLint m_stencilBits;
EGLint m_sampleCount;
};
} // namespace she
#endif

View File

@ -1,5 +1,5 @@
// SHE library
// Copyright (C) 2015 David Capello
// Copyright (C) 2015-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -16,8 +16,6 @@ namespace she {
class GLContextWGL : public GLContext {
public:
typedef HWND NativeHandle;
GLContextWGL(HWND hwnd)
: m_hwnd(hwnd)
, m_glrc(nullptr) {

View File

@ -1,55 +0,0 @@
// SHE library
// Copyright (C) 2012-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef SHE_SKIA_GL_CONTEXT_INCLUDED
#define SHE_SKIA_GL_CONTEXT_INCLUDED
#pragma once
#ifndef SK_SUPPORT_GPU
#error Skia was compiled without GPU support
#endif
#include "gl/GrGLInterface.h"
#include <stdexcept>
namespace she {
template<typename Base>
class GLContextSkia : public Base {
public:
GLContextSkia(typename Base::NativeHandle nativeHandle) : Base(nativeHandle) {
Base::createGLContext();
if (!createSkiaInterfaces()) {
Base::destroyGLContext();
throw std::runtime_error("Cannot create OpenGL context");
}
}
~GLContextSkia() {
m_gl.reset(nullptr);
}
const GrGLInterface* gl() const {
return m_gl.get();
}
private:
bool createSkiaInterfaces() {
SkAutoTUnref<const GrGLInterface> gl(GrGLCreateNativeInterface());
if (!gl || !gl->validate())
return false;
m_gl.reset(gl.detach());
return true;
}
SkAutoTUnref<const GrGLInterface> m_gl;
};
} // namespace she
#endif

View File

@ -1,5 +1,5 @@
// SHE library
// Copyright (C) 2012-2015 David Capello
// Copyright (C) 2012-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -48,10 +48,8 @@ public:
int(Capabilities::MultipleDisplays) |
int(Capabilities::CanResizeDisplay) |
int(Capabilities::DisplayScale)
#ifdef _WIN32
// GPU acceleration is available on Windows at this moment
| int(Capabilities::GpuAccelerationSwitch)
#endif
// GPU acceleration is disabled at this moment
//| int(Capabilities::GpuAccelerationSwitch)
);
}

View File

@ -1,5 +1,5 @@
// SHE library
// Copyright (C) 2012-2015 David Capello
// Copyright (C) 2012-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -23,8 +23,8 @@
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "gl/GrGLInterface.h"
#include "she/gl/gl_context_cgl.h"
#include "she/skia/gl_context_skia.h"
#include "she/skia/skia_surface.h"
#endif
@ -39,6 +39,7 @@ public:
, m_backend(Backend::NONE)
#if SK_SUPPORT_GPU
, m_nsGL(nil)
, m_skSurface(nullptr)
#endif
{
m_closing = false;
@ -123,7 +124,7 @@ public:
bool gpu = she::instance()->gpuAcceleration();
(void)gpu;
// Disable GPU acceleration because it isn't ready yet.
// Disable GPU acceleration.
gpu = false;
#if SK_SUPPORT_GPU
@ -183,19 +184,29 @@ private:
bool attachGL() {
if (!m_glCtx) {
try {
auto ctx = new GLContextSkia<GLContextCGL>(nullptr);
SkAutoTDelete<GLContext> ctx(new GLContextCGL);
if (!ctx->createGLContext())
throw std::runtime_error("Cannot create CGL context");
m_glInterfaces.reset(GrGLCreateNativeInterface());
if (!m_glInterfaces || !m_glInterfaces->validate()) {
LOG("Cannot create GL interfaces\n");
detachGL();
return false;
}
m_glCtx.reset(ctx);
m_grCtx.reset(GrContext::Create(kOpenGL_GrBackend,
(GrBackendContext)m_glCtx->gl()));
(GrBackendContext)m_glInterfaces.get()));
m_nsGL = [[NSOpenGLContext alloc]
initWithCGLContextObj:m_glCtx->cglContext()];
initWithCGLContextObj:static_cast<GLContextCGL*>(m_glCtx.get())->cglContext()];
[m_nsGL setView:m_window.contentView];
LOG("Using CGL backend\n");
}
catch (const std::exception& ex) {
//LOG("Cannot create GL context: %s\n", ex.what());
LOG("Cannot create GL context: %s\n", ex.what());
detachGL();
return false;
}
@ -206,6 +217,11 @@ private:
void detachGL() {
if (m_nsGL)
m_nsGL = nil;
setSurface(nullptr);
m_skSurfaceDirect.reset(nullptr);
m_grRenderTarget.reset(nullptr);
m_grCtx.reset(nullptr);
m_glCtx.reset(nullptr);
}
@ -222,14 +238,16 @@ private:
desc.fStencilBits = m_glCtx->getStencilBits();
desc.fRenderTargetHandle = 0; // direct frame buffer
m_grRenderTarget.reset(m_grCtx->textureProvider()->wrapBackendRenderTarget(desc));
setSurface(nullptr); // set m_skSurface comparing with the old m_skSurfaceDirect
m_skSurfaceDirect.reset(
SkSurface::NewRenderTargetDirect(m_grRenderTarget));
if (scale == 1) {
m_skSurface.reset(m_skSurfaceDirect);
setSurface(m_skSurfaceDirect);
}
else {
m_skSurface.reset(
setSurface(
SkSurface::NewRenderTarget(
m_grCtx,
SkSurface::kYes_Budgeted,
@ -239,13 +257,20 @@ private:
}
if (!m_skSurface)
throw std::runtime_error("Error creating OpenGL surface for main display");
throw std::runtime_error("Error creating surface for main display");
m_display->setSkiaSurface(new SkiaSurface(m_skSurface));
if (m_nsGL)
[m_nsGL update];
}
void setSurface(SkSurface* surface) {
if (m_skSurface && m_skSurface != m_skSurfaceDirect)
delete m_skSurface;
m_skSurface = surface;
}
#endif
void paintGC(const gfx::Rect& rect) {
@ -281,12 +306,13 @@ private:
bool m_closing;
OSXWindow* m_window;
#if SK_SUPPORT_GPU
base::UniquePtr<GLContextSkia<GLContextCGL> > m_glCtx;
base::UniquePtr<GLContext> m_glCtx;
SkAutoTUnref<const GrGLInterface> m_glInterfaces;
NSOpenGLContext* m_nsGL;
SkAutoTUnref<GrContext> m_grCtx;
SkAutoTUnref<GrRenderTarget> m_grRenderTarget;
SkAutoTDelete<SkSurface> m_skSurfaceDirect;
SkAutoTDelete<SkSurface> m_skSurface;
SkSurface* m_skSurface;
gfx::Size m_lastSize;
#endif
};

View File

@ -19,13 +19,16 @@
#include "GrContext.h"
#include "she/gl/gl_context_wgl.h"
#if SK_ANGLE
#include "she/gl/gl_context_egl.h"
#endif
#endif
#ifdef _WIN32
#include <windows.h>
#include "she/win/window_dde.h" // Include this one time to
#include "she/win/window_dde.h"
#endif
@ -117,7 +120,8 @@ void SkiaWindow::paintImpl(HDC hdc)
}
// Flush GL context
m_glCtx->gl()->fFunctions.fFlush();
m_glInterfaces->fFunctions.fFlush();
m_glCtx->swapBuffers();
break;
#endif // SK_SUPPORT_GPU
@ -154,20 +158,32 @@ void SkiaWindow::paintHDC(HDC hdc)
#if SK_SUPPORT_GPU
bool SkiaWindow::attachGL()
#if SK_ANGLE
bool SkiaWindow::attachANGLE()
{
if (!m_glCtx) {
try {
auto ctx = new GLContextSkia<GLContextWGL>(handle());
SkAutoTDelete<GLContext> ctx(new GLContextEGL(handle()));
if (!ctx->createGLContext())
throw std::runtime_error("Cannot create EGL context");
m_glInterfaces.reset(GrGLCreateANGLEInterface());
if (!m_glInterfaces || !m_glInterfaces->validate())
throw std::runtime_error("Cannot create EGL interfaces\n");
m_stencilBits = ctx->getStencilBits();
m_sampleCount = ctx->getSampleCount();
m_glCtx.reset(ctx);
m_grCtx.reset(GrContext::Create(kOpenGL_GrBackend,
(GrBackendContext)m_glCtx->gl()));
m_glCtx.reset(ctx.detach());
m_grCtx.reset(
GrContext::Create(kOpenGL_GrBackend,
(GrBackendContext)m_glInterfaces.get()));
LOG("Using EGL backend\n");
}
catch (const std::exception& ex) {
LOG("Cannot create GL context: %s\n", ex.what());
LOG("Error initializing EGL backend: %s\n", ex.what());
detachGL();
}
}
@ -178,15 +194,41 @@ bool SkiaWindow::attachGL()
return false;
}
#if SK_ANGLE
bool SkiaWindow::attachANGLE()
{
return false; // TODO
}
#endif // SK_ANGLE
bool SkiaWindow::attachGL()
{
if (!m_glCtx) {
try {
SkAutoTDelete<GLContext> ctx(new GLContextWGL(handle()));
if (!ctx->createGLContext())
throw std::runtime_error("Cannot create WGL context\n");
m_glInterfaces.reset(GrGLCreateNativeInterface());
if (!m_glInterfaces || !m_glInterfaces->validate())
throw std::runtime_error("Cannot create WGL interfaces\n");
m_stencilBits = ctx->getStencilBits();
m_sampleCount = ctx->getSampleCount();
m_glCtx.reset(ctx.detach());
m_grCtx.reset(GrContext::Create(kOpenGL_GrBackend,
(GrBackendContext)m_glInterfaces.get()));
LOG("Using WGL backend\n");
}
catch (const std::exception& ex) {
LOG("Error initializing WGL backend: %s\n", ex.what());
detachGL();
}
}
if (m_glCtx)
return true;
else
return false;
}
void SkiaWindow::detachGL()
{
if (m_glCtx && m_display)
@ -232,7 +274,7 @@ void SkiaWindow::createRenderTarget(const gfx::Size& size)
}
if (!m_skSurface)
throw std::runtime_error("Error creating OpenGL surface for main display");
throw std::runtime_error("Error creating surface for main display");
m_display->setSkiaSurface(new SkiaSurface(m_skSurface));
}
@ -251,6 +293,9 @@ void SkiaWindow::resizeImpl(const gfx::Size& size)
bool gpu = instance()->gpuAcceleration();
(void)gpu;
// Disable GPU acceleration.
gpu = false;
#if SK_SUPPORT_GPU
#if SK_ANGLE
if (gpu && attachANGLE()) {

View File

@ -14,8 +14,8 @@
#include "she/win/window.h"
#if SK_SUPPORT_GPU
#include "she/gl/gl_context_wgl.h"
#include "she/skia/gl_context_skia.h"
#include "gl/GrGLInterface.h"
#include "she/gl/gl_context.h"
#endif
namespace she {
@ -39,10 +39,10 @@ private:
void paintHDC(HDC dc);
#if SK_SUPPORT_GPU
bool attachGL();
#if SK_ANGLE
bool attachANGLE();
#endif // SK_ANGLE
bool attachGL();
void detachGL();
void createRenderTarget(const gfx::Size& size);
void setSurface(SkSurface* surface);
@ -52,7 +52,8 @@ private:
SkiaDisplay* m_display;
Backend m_backend;
#if SK_SUPPORT_GPU
base::UniquePtr<GLContextSkia<GLContextWGL> > m_glCtx;
base::UniquePtr<GLContext> m_glCtx;
SkAutoTUnref<const GrGLInterface> m_glInterfaces;
SkAutoTUnref<GrContext> m_grCtx;
SkAutoTUnref<GrRenderTarget> m_grRenderTarget;
SkAutoTDelete<SkSurface> m_skSurfaceDirect;