зеркало из https://github.com/mozilla/gecko-dev.git
b=618892; [webgl] use ANGLE pbuffers to speed up webgl with d3d10 layers; r=bas
This commit is contained in:
Родитель
9765b7449a
Коммит
1f95129bca
|
@ -76,23 +76,34 @@ CanvasLayerD3D10::Initialize(const Data& aData)
|
|||
void *data = mSurface->GetData(&gKeyD3D10Texture);
|
||||
if (data) {
|
||||
mTexture = static_cast<ID3D10Texture2D*>(data);
|
||||
mIsD2DTexture = true;
|
||||
mIsD2DTexture = PR_TRUE;
|
||||
device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mIsD2DTexture = false;
|
||||
mIsD2DTexture = PR_FALSE;
|
||||
mUsingSharedTexture = PR_FALSE;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create texture for CanvasLayer!");
|
||||
return;
|
||||
HANDLE shareHandle = mGLContext ? mGLContext->GetD3DShareHandle() : nsnull;
|
||||
if (shareHandle) {
|
||||
HRESULT hr = device()->OpenSharedResource(shareHandle, __uuidof(ID3D10Texture2D), getter_AddRefs(mTexture));
|
||||
if (SUCCEEDED(hr))
|
||||
mUsingSharedTexture = PR_TRUE;
|
||||
}
|
||||
|
||||
if (!mUsingSharedTexture) {
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create texture for CanvasLayer!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
}
|
||||
|
||||
|
@ -104,6 +115,15 @@ CanvasLayerD3D10::Updated(const nsIntRect& aRect)
|
|||
return;
|
||||
}
|
||||
|
||||
if (mUsingSharedTexture) {
|
||||
// need to sync on the d3d9 device
|
||||
if (mGLContext) {
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fFinish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGLContext) {
|
||||
// WebGL reads entire surface.
|
||||
D3D10_MAPPED_TEXTURE2D map;
|
||||
|
|
|
@ -82,6 +82,7 @@ private:
|
|||
PRPackedBool mDataIsPremultiplied;
|
||||
PRPackedBool mNeedsYFlip;
|
||||
PRPackedBool mIsD2DTexture;
|
||||
PRPackedBool mUsingSharedTexture;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
|
|
@ -92,13 +92,11 @@ LayerManagerD3D10::Initialize()
|
|||
{
|
||||
HRESULT hr;
|
||||
|
||||
cairo_device_t *device = gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
|
||||
if (!device) {
|
||||
return false;
|
||||
mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
if (!mDevice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDevice = cairo_d2d_device_get_device(device);
|
||||
|
||||
UINT size = sizeof(ID3D10Effect*);
|
||||
if (FAILED(mDevice->GetPrivateData(sEffect, &size, mEffect.StartAssignment()))) {
|
||||
D3D10CreateEffectFromMemoryFunc createEffect = (D3D10CreateEffectFromMemoryFunc)
|
||||
|
|
|
@ -495,6 +495,11 @@ public:
|
|||
const ContextFormat& CreationFormat() { return mCreationFormat; }
|
||||
const ContextFormat& ActualFormat() { return mActualFormat; }
|
||||
|
||||
/**
|
||||
* If this GL context has a D3D texture share handle, returns non-null.
|
||||
*/
|
||||
virtual void *GetD3DShareHandle() { return nsnull; }
|
||||
|
||||
/**
|
||||
* If this context is double-buffered, returns TRUE.
|
||||
*/
|
||||
|
|
|
@ -209,10 +209,12 @@ public:
|
|||
: mInitialized(PR_FALSE),
|
||||
mEGLLibrary(nsnull)
|
||||
{
|
||||
mIsANGLE = PR_FALSE;
|
||||
mHave_EGL_KHR_image_base = PR_FALSE;
|
||||
mHave_EGL_KHR_image_pixmap = PR_FALSE;
|
||||
mHave_EGL_KHR_gl_texture_2D_image = PR_FALSE;
|
||||
mHave_EGL_KHR_lock_surface = PR_FALSE;
|
||||
mHave_EGL_ANGLE_surface_d3d_share_handle = PR_FALSE;
|
||||
}
|
||||
|
||||
typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id);
|
||||
|
@ -276,6 +278,9 @@ public:
|
|||
typedef EGLBoolean (GLAPIENTRY * pfnQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
|
||||
pfnQuerySurface fQuerySurface;
|
||||
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnQuerySurfacePointerANGLE)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
|
||||
pfnQuerySurfacePointerANGLE fQuerySurfacePointerANGLE;
|
||||
|
||||
// This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES"
|
||||
// Lets keep it here for now.
|
||||
typedef void (GLAPIENTRY * pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image);
|
||||
|
@ -372,6 +377,11 @@ public:
|
|||
mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (!fInitialize(mEGLDisplay, NULL, NULL))
|
||||
return PR_FALSE;
|
||||
|
||||
const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
|
||||
if (vendor && strstr(vendor, "TransGaming") != 0) {
|
||||
mIsANGLE = PR_TRUE;
|
||||
}
|
||||
|
||||
const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
|
||||
if (!extensions)
|
||||
|
@ -448,6 +458,19 @@ public:
|
|||
mHave_EGL_KHR_gl_texture_2D_image = PR_FALSE;
|
||||
}
|
||||
|
||||
if (strstr(extensions, "EGL_ANGLE_surface_d3d_share_handle")) {
|
||||
LibrarySymbolLoader::SymLoadStruct d3dSymbols[] = {
|
||||
{ (PRFuncPtr*) &fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", NULL } },
|
||||
{ NULL, { NULL } }
|
||||
};
|
||||
|
||||
LibrarySymbolLoader::LoadSymbols(mEGLLibrary, &d3dSymbols[0],
|
||||
(LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress);
|
||||
if (fQuerySurfacePointerANGLE) {
|
||||
mHave_EGL_ANGLE_surface_d3d_share_handle = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
mInitialized = PR_TRUE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -456,6 +479,10 @@ public:
|
|||
return mEGLDisplay;
|
||||
}
|
||||
|
||||
PRBool IsANGLE() {
|
||||
return mIsANGLE;
|
||||
}
|
||||
|
||||
PRBool HasKHRImageBase() {
|
||||
return mHave_EGL_KHR_image_base;
|
||||
}
|
||||
|
@ -472,6 +499,10 @@ public:
|
|||
return mHave_EGL_KHR_lock_surface;
|
||||
}
|
||||
|
||||
PRBool HasANGLESurfaceD3DShareHandle() {
|
||||
return mHave_EGL_ANGLE_surface_d3d_share_handle;
|
||||
}
|
||||
|
||||
void
|
||||
DumpEGLConfig(EGLConfig cfg)
|
||||
{
|
||||
|
@ -531,10 +562,13 @@ private:
|
|||
PRLibrary *mEGLLibrary;
|
||||
EGLDisplay mEGLDisplay;
|
||||
|
||||
PRPackedBool mIsANGLE;
|
||||
|
||||
PRPackedBool mHave_EGL_KHR_image_base;
|
||||
PRPackedBool mHave_EGL_KHR_image_pixmap;
|
||||
PRPackedBool mHave_EGL_KHR_gl_texture_2D_image;
|
||||
PRPackedBool mHave_EGL_KHR_lock_surface;
|
||||
PRPackedBool mHave_EGL_ANGLE_surface_d3d_share_handle;
|
||||
} sEGLLibrary;
|
||||
|
||||
class GLContextEGL : public GLContext
|
||||
|
@ -556,9 +590,6 @@ public:
|
|||
, mBound(PR_FALSE)
|
||||
, mIsPBuffer(PR_FALSE)
|
||||
, mIsDoubleBuffered(PR_FALSE)
|
||||
#ifdef XP_WIN
|
||||
, mWnd(0)
|
||||
#endif
|
||||
{
|
||||
// any EGL contexts will always be GLESv2
|
||||
SetIsGLES2(PR_TRUE);
|
||||
|
@ -757,15 +788,6 @@ public:
|
|||
CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
|
||||
#ifdef XP_WIN
|
||||
static already_AddRefed<GLContextEGL>
|
||||
CreateEGLWin32OffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
|
||||
void HoldWin32Window(HWND aWnd) { mWnd = aWnd; }
|
||||
HWND GetWin32Window() { return mWnd; }
|
||||
#endif
|
||||
|
||||
void SetOffscreenSize(const gfxIntSize &aRequestedSize,
|
||||
const gfxIntSize &aActualSize)
|
||||
{
|
||||
|
@ -773,6 +795,26 @@ public:
|
|||
mOffscreenActualSize = aActualSize;
|
||||
}
|
||||
|
||||
void *GetD3DShareHandle() {
|
||||
if (!sEGLLibrary.HasANGLESurfaceD3DShareHandle()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void *h = nsnull;
|
||||
|
||||
#ifndef EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE
|
||||
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
|
||||
#endif
|
||||
|
||||
if (!sEGLLibrary.fQuerySurfacePointerANGLE(EGL_DISPLAY(), mSurface,
|
||||
EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, (void**) &h))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class GLContextProviderEGL;
|
||||
|
||||
|
@ -785,10 +827,6 @@ protected:
|
|||
|
||||
PRPackedBool mIsPBuffer;
|
||||
PRPackedBool mIsDoubleBuffered;
|
||||
|
||||
#ifdef XP_WIN
|
||||
AutoDestroyHWND mWnd;
|
||||
#endif
|
||||
};
|
||||
|
||||
PRBool
|
||||
|
@ -1659,6 +1697,7 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
|||
LOCAL_EGL_DEPTH_SIZE, aFormat.minDepth,
|
||||
LOCAL_EGL_STENCIL_SIZE, aFormat.minStencil,
|
||||
|
||||
// these get overwritten below; if you add anything above
|
||||
aFormat.minAlpha ?
|
||||
LOCAL_EGL_BIND_TO_TEXTURE_RGBA :
|
||||
LOCAL_EGL_BIND_TO_TEXTURE_RGB,
|
||||
|
@ -1667,6 +1706,14 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
|||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
// if we're running under ANGLE, we can't set
|
||||
// BIND_TO_TEXTURE since we're probably doing d3d interop
|
||||
if (sEGLLibrary.IsANGLE()) {
|
||||
int k = sizeof(attribs)/sizeof(EGLint) - 3;
|
||||
attribs[k] = LOCAL_EGL_NONE;
|
||||
attribs[k+1] = LOCAL_EGL_NONE;
|
||||
}
|
||||
|
||||
EGLConfig configs[64];
|
||||
int numConfigs = 64;
|
||||
|
||||
|
@ -1694,7 +1741,6 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
|||
LOCAL_EGL_HEIGHT, 0,
|
||||
|
||||
LOCAL_EGL_TEXTURE_TARGET, LOCAL_EGL_TEXTURE_2D,
|
||||
|
||||
LOCAL_EGL_TEXTURE_FORMAT,
|
||||
aFormat.minAlpha ?
|
||||
LOCAL_EGL_TEXTURE_RGBA :
|
||||
|
@ -1703,6 +1749,14 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
|||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
// if under ANGLE, then TEXTURE_TARGET/TEXTURE_FORMAT
|
||||
// need to be stripped out (we don't support bind-to-texture,
|
||||
// and just do d3d interop)
|
||||
if (sEGLLibrary.IsANGLE()) {
|
||||
pbattrs[4] = LOCAL_EGL_NONE;
|
||||
pbattrs[5] = LOCAL_EGL_NONE;
|
||||
}
|
||||
|
||||
TRY_AGAIN_POWER_OF_TWO:
|
||||
pbattrs[1] = pbsize.width;
|
||||
pbattrs[3] = pbsize.height;
|
||||
|
@ -1902,95 +1956,6 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize,
|
|||
return glContext.forget();
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLWin32OffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
if (!sEGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
WNDCLASSW wc;
|
||||
if (!GetClassInfoW(GetModuleHandle(NULL), L"ANGLEContextClass", &wc)) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASSW));
|
||||
wc.style = CS_OWNDC;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = L"ANGLEContextClass";
|
||||
if (!RegisterClassW(&wc)) {
|
||||
NS_WARNING("Failed to register ANGLEContextClass?!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AutoDestroyHWND wnd = CreateWindowW(L"ANGLEContextClass", L"ANGLEContext", 0,
|
||||
0, 0, 16, 16,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
NS_ENSURE_TRUE(HWND(wnd), NULL);
|
||||
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
|
||||
// We don't really care, we're going to use a FBO anyway
|
||||
EGLint attribs[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
EGLint ncfg = 1;
|
||||
if (!sEGLLibrary.fChooseConfig(sEGLLibrary.Display(), attribs, &config, ncfg, &ncfg) ||
|
||||
ncfg < 1)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
surface = sEGLLibrary.fCreateWindowSurface(sEGLLibrary.Display(),
|
||||
config,
|
||||
HWND(wnd),
|
||||
0);
|
||||
if (!surface) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API)) {
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
EGLint cxattribs[] = {
|
||||
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
context = sEGLLibrary.fCreateContext(sEGLLibrary.Display(),
|
||||
config,
|
||||
EGL_NO_CONTEXT,
|
||||
cxattribs);
|
||||
if (!context) {
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextEGL> glContext = new GLContextEGL(aFormat, nsnull,
|
||||
config, surface, context,
|
||||
PR_TRUE);
|
||||
|
||||
// hold this even before we initialize, because we need to make
|
||||
// sure it gets destroyed after the surface etc. in case of error.
|
||||
glContext->HoldWin32Window(wnd.forget());
|
||||
|
||||
if (!glContext->Init() ||
|
||||
!glContext->ResizeOffscreenFBO(aSize))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Under EGL, if we're under X11, then we have to create a Pixmap
|
||||
// because Maemo's EGL implementation doesn't support pbuffers at all
|
||||
// for some reason. On Android, pbuffers are supported fine, though
|
||||
|
@ -2003,12 +1968,10 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
#if defined(ANDROID)
|
||||
#if defined(ANDROID) || defined(XP_WIN)
|
||||
return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat);
|
||||
#elif defined(MOZ_X11)
|
||||
return GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat);
|
||||
#elif defined(XP_WIN)
|
||||
return GLContextEGL::CreateEGLWin32OffscreenContext(aSize, aFormat);
|
||||
#else
|
||||
return nsnull;
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче