mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=583838; add ANGLE/D3D WebGL support - part 2 - build EGL on windows and try to use it; r=bjacob
This commit is contained in:
parent
30c2b7b82c
commit
c44e0d0074
@ -56,6 +56,8 @@
|
||||
|
||||
#include "GLContextProvider.h"
|
||||
|
||||
#include "prenv.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
@ -275,29 +277,77 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
format.depth = 16;
|
||||
format.minDepth = 1;
|
||||
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// On Windows, we may have a choice of backends, including straight
|
||||
// OpenGL, D3D through ANGLE via EGL, or straight EGL/GLES2.
|
||||
// We don't differentiate the latter two yet, but we allow for
|
||||
// a env var to try EGL first, instead of last.
|
||||
bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL") != nsnull;
|
||||
|
||||
// if we want EGL, try it first
|
||||
if (!gl && preferEGL) {
|
||||
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// if it failed, then try the default provider, whatever that is
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// if that failed, and we weren't already preferring EGL, try it now.
|
||||
if (!gl && !preferEGL) {
|
||||
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// other platforms just use whatever the default is
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// last chance, try OSMesa
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl) {
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
} else {
|
||||
// make sure we notify always in this case, because it's likely going to be
|
||||
// painfully slow
|
||||
LogMessage("WebGL: Using software rendering via OSMesa");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gl) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
printf_stderr ("--- WebGL context created: %p\n", gl.get());
|
||||
|
||||
#ifdef USE_GLES2
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
#else
|
||||
// Check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
if (gl->IsGLES2()) {
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
} else {
|
||||
// Otherwise, check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
#endif
|
||||
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (!InitAndValidateGL()) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LogMessage("WebGL: Using software rendering via OSMesa");
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
|
@ -701,15 +701,9 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
|
||||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use mUpdatedRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
if (mGLContext->IsGLES2()) {
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data());
|
||||
} else {
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
isurf->Data());
|
||||
}
|
||||
mGLContext->ReadPixelsIntoImageSurface(0, 0,
|
||||
mBounds.width, mBounds.height,
|
||||
isurf);
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
|
@ -111,9 +111,15 @@ CanvasLayerD3D9::Updated(const nsIntRect& aRect)
|
||||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use aRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
destination);
|
||||
nsRefPtr<gfxImageSurface> tmpSurface =
|
||||
new gfxImageSurface(destination,
|
||||
gfxIntSize(mBounds.width, mBounds.height),
|
||||
mBounds.width * 4,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
mGLContext->ReadPixelsIntoImageSurface(0, 0,
|
||||
mBounds.width, mBounds.height,
|
||||
tmpSurface);
|
||||
tmpSurface = nsnull;
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
|
@ -309,9 +309,63 @@ GLContext::InitWithPrefix(const char *prefix, PRBool trygl)
|
||||
};
|
||||
|
||||
mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
|
||||
|
||||
if (mInitialized) {
|
||||
InitExtensions();
|
||||
}
|
||||
|
||||
return mInitialized;
|
||||
}
|
||||
|
||||
// should match the order of GLExtensions
|
||||
static const char *sExtensionNames[] = {
|
||||
"GL_EXT_framebuffer_object",
|
||||
"GL_ARB_framebuffer_object",
|
||||
"GL_EXT_bgra",
|
||||
"GL_EXT_texture_format_BGRA8888",
|
||||
"GL_OES_depth24",
|
||||
"GL_OES_depth32",
|
||||
"GL_OES_stencil8",
|
||||
"GL_OES_texture_npot",
|
||||
"GL_OES_depth_texture",
|
||||
"GL_OES_packed_depth_stencil",
|
||||
"GL_IMG_read_format",
|
||||
"GL_EXT_read_format_bgra",
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
GLContext::InitExtensions()
|
||||
{
|
||||
MakeCurrent();
|
||||
const GLubyte *extensions = fGetString(LOCAL_GL_EXTENSIONS);
|
||||
char *exts = strdup((char *)extensions);
|
||||
|
||||
printf_stderr("GL extensions: %s\n", exts);
|
||||
|
||||
char *s = exts;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
char *space = strchr(s, ' ');
|
||||
if (space) {
|
||||
*space = '\0';
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
|
||||
for (int i = 0; sExtensionNames[i]; ++i) {
|
||||
if (strcmp(s, sExtensionNames[i]) == 0) {
|
||||
printf_stderr("Found extension %s\n", s);
|
||||
mAvailableExtensions[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
s = space+1;
|
||||
}
|
||||
|
||||
free(exts);
|
||||
}
|
||||
|
||||
PRBool
|
||||
GLContext::IsExtensionSupported(const char *extension)
|
||||
{
|
||||
@ -479,6 +533,9 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
|
||||
GLint viewport[4];
|
||||
|
||||
bool useDepthStencil =
|
||||
!mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
|
||||
|
||||
// save a few things for later restoring
|
||||
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
|
||||
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*) &curBoundFramebuffer);
|
||||
@ -496,7 +553,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
fGenFramebuffers(1, &mOffscreenFBO);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mOffscreenFBO);
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fGenRenderbuffers(1, &mOffscreenDepthRB);
|
||||
} else {
|
||||
if (depth) {
|
||||
@ -529,18 +586,35 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGB,
|
||||
#ifdef XP_WIN
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
#else
|
||||
mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
|
||||
: LOCAL_GL_UNSIGNED_BYTE,
|
||||
#endif
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
LOCAL_GL_DEPTH24_STENCIL8,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
if (depth) {
|
||||
GLenum depthType;
|
||||
if (mIsGLES2) {
|
||||
if (IsExtensionSupported(OES_depth32)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT32;
|
||||
} else if (IsExtensionSupported(OES_depth24)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
}
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
mIsGLES2 ? LOCAL_GL_DEPTH_COMPONENT16
|
||||
@ -565,7 +639,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
mOffscreenTexture,
|
||||
0);
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
@ -603,6 +677,10 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
|
||||
if (firstTime) {
|
||||
UpdateActualFormat();
|
||||
|
||||
printf_stderr("Created offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d\n",
|
||||
mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
|
||||
mActualFormat.depth, mActualFormat.stencil);
|
||||
}
|
||||
|
||||
// We're good, and the framebuffer is already attached, so let's
|
||||
@ -665,7 +743,16 @@ GLContext::ClearSafely()
|
||||
void
|
||||
GLContext::UpdateActualFormat()
|
||||
{
|
||||
// TODO
|
||||
ContextFormat nf;
|
||||
|
||||
fGetIntegerv(LOCAL_GL_RED_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_GREEN_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_BLUE_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_ALPHA_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_DEPTH_BITS, (GLint*) &nf.depth);
|
||||
fGetIntegerv(LOCAL_GL_STENCIL_BITS, (GLint*) &nf.depth);
|
||||
|
||||
mActualFormat = nf;
|
||||
}
|
||||
|
||||
void
|
||||
@ -805,6 +892,69 @@ GLContext::ReadTextureImage(GLuint aTexture,
|
||||
return isurf.forget();
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::ReadPixelsIntoImageSurface(GLint aX, GLint aY,
|
||||
GLsizei aWidth, GLsizei aHeight,
|
||||
gfxImageSurface *aDest)
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
if (aDest->Format() != gfxASurface::ImageFormatARGB32 &&
|
||||
aDest->Format() != gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
NS_WARNING("ReadPixelsIntoImageSurface called with invalid image format");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDest->Width() != aWidth ||
|
||||
aDest->Height() != aHeight ||
|
||||
aDest->Stride() != aWidth * 4)
|
||||
{
|
||||
NS_WARNING("ReadPixelsIntoImageSurface called with wrong size or stride surface");
|
||||
return;
|
||||
}
|
||||
|
||||
GLint currentPackAlignment = 0;
|
||||
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, ¤tPackAlignment);
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
// defaults for desktop
|
||||
GLenum format = LOCAL_GL_BGRA;
|
||||
GLenum datatype = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
bool swap = false;
|
||||
|
||||
if (IsGLES2()) {
|
||||
datatype = LOCAL_GL_UNSIGNED_BYTE;
|
||||
|
||||
if (IsExtensionSupported(gl::GLContext::EXT_read_format_bgra) ||
|
||||
IsExtensionSupported(gl::GLContext::IMG_read_format) ||
|
||||
IsExtensionSupported(gl::GLContext::EXT_bgra))
|
||||
{
|
||||
format = LOCAL_GL_BGRA;
|
||||
} else {
|
||||
format = LOCAL_GL_RGBA;
|
||||
swap = true;
|
||||
}
|
||||
}
|
||||
|
||||
fReadPixels(0, 0, aWidth, aHeight,
|
||||
format, datatype,
|
||||
aDest->Data());
|
||||
|
||||
if (swap) {
|
||||
// swap B and R bytes
|
||||
for (int j = 0; j < aHeight; ++j) {
|
||||
PRUint32 *row = (PRUint32*) (aDest->Data() + aDest->Stride() * j);
|
||||
for (int i = 0; i < aWidth; ++i) {
|
||||
*row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
|
@ -562,6 +562,40 @@ public:
|
||||
const gfxIntSize& aSize,
|
||||
GLenum aTextureFormat);
|
||||
|
||||
/**
|
||||
* Call ReadPixels into an existing gfxImageSurface for the given bounds.
|
||||
* The image surface must be using image format RGBA32 or RGB24.
|
||||
*/
|
||||
void ReadPixelsIntoImageSurface(GLint aX, GLint aY, GLsizei aWidth, GLsizei aHeight,
|
||||
gfxImageSurface *aDest);
|
||||
|
||||
/**
|
||||
* Known GL extensions that can be queried by
|
||||
* IsExtensionSupported. The results of this are cached, and as
|
||||
* such it's safe to use this even in performance critical code.
|
||||
* If you add to this array, remember to add to the string names
|
||||
* in GLContext.cpp.
|
||||
*/
|
||||
enum GLExtensions {
|
||||
EXT_framebuffer_object,
|
||||
ARB_framebuffer_object,
|
||||
EXT_bgra,
|
||||
EXT_texture_format_BGRA8888,
|
||||
OES_depth24,
|
||||
OES_depth32,
|
||||
OES_stencil8,
|
||||
OES_texture_npot,
|
||||
OES_depth_texture,
|
||||
OES_packed_depth_stencil,
|
||||
IMG_read_format,
|
||||
EXT_read_format_bgra,
|
||||
Extensions_Max
|
||||
};
|
||||
|
||||
PRBool IsExtensionSupported(GLExtensions aKnownExtension) {
|
||||
return mAvailableExtensions[aKnownExtension];
|
||||
}
|
||||
|
||||
protected:
|
||||
PRPackedBool mInitialized;
|
||||
PRPackedBool mIsOffscreen;
|
||||
@ -585,6 +619,25 @@ protected:
|
||||
GLuint mOffscreenDepthRB;
|
||||
GLuint mOffscreenStencilRB;
|
||||
|
||||
// this should just be a std::bitset, but that ended up breaking
|
||||
// MacOS X builds; see bug 584919. We can replace this with one
|
||||
// later on.
|
||||
template<size_t setlen>
|
||||
struct ExtensionBitset {
|
||||
ExtensionBitset() {
|
||||
for (int i = 0; i < setlen; ++i)
|
||||
values[i] = false;
|
||||
}
|
||||
|
||||
bool& operator[](const int index) {
|
||||
NS_ASSERTION(index >= 0 && index < setlen, "out of range");
|
||||
return values[index];
|
||||
}
|
||||
|
||||
bool values[setlen];
|
||||
};
|
||||
ExtensionBitset<Extensions_Max> mAvailableExtensions;
|
||||
|
||||
// Clear to transparent black, with 0 depth and stencil,
|
||||
// while preserving current ClearColor etc. values.
|
||||
// Useful for resizing offscreen buffers.
|
||||
@ -599,6 +652,7 @@ protected:
|
||||
|
||||
PRBool InitWithPrefix(const char *prefix, PRBool trygl);
|
||||
|
||||
void InitExtensions();
|
||||
PRBool IsExtensionSupported(const char *extension);
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
|
@ -74,12 +74,15 @@ namespace gl {
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO)
|
||||
#if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) || defined(XP_WIN)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
|
||||
#ifndef GL_CONTEXT_PROVIDER_DEFAULT
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// X11, but only if we didn't use EGL above
|
||||
#if defined(MOZ_X11) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
|
||||
|
@ -76,6 +76,58 @@ typedef void *EGLNativeWindowType;
|
||||
#define EGL_LIB "/system/lib/libEGL.so"
|
||||
#define GLES2_LIB "/system/lib/libGLESv2.so"
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HBITMAP EGLNativePixmapType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
|
||||
#define EGL_LIB "libEGL.dll"
|
||||
#define GLES2_LIB "libGLESv2.dll"
|
||||
|
||||
// a little helper
|
||||
class AutoDestroyHWND {
|
||||
public:
|
||||
AutoDestroyHWND(HWND aWnd = NULL)
|
||||
: mWnd(aWnd)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoDestroyHWND() {
|
||||
if (mWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
}
|
||||
|
||||
operator HWND() {
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND forget() {
|
||||
HWND w = mWnd;
|
||||
mWnd = NULL;
|
||||
return w;
|
||||
}
|
||||
|
||||
HWND operator=(HWND aWnd) {
|
||||
if (mWnd && mWnd != aWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
mWnd = aWnd;
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND mWnd;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#error "Platform not recognized"
|
||||
@ -147,58 +199,58 @@ public:
|
||||
mHave_EGL_KHR_gl_texture_2D_image = PR_FALSE;
|
||||
}
|
||||
|
||||
typedef EGLDisplay (*pfnGetDisplay)(void *display_id);
|
||||
typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id);
|
||||
pfnGetDisplay fGetDisplay;
|
||||
typedef EGLContext (*pfnGetCurrentContext)(void);
|
||||
typedef EGLContext (GLAPIENTRY * pfnGetCurrentContext)(void);
|
||||
pfnGetCurrentContext fGetCurrentContext;
|
||||
typedef EGLBoolean (*pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
pfnMakeCurrent fMakeCurrent;
|
||||
typedef EGLBoolean (*pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
pfnDestroyContext fDestroyContext;
|
||||
typedef EGLContext (*pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
typedef EGLContext (GLAPIENTRY * pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
pfnCreateContext fCreateContext;
|
||||
typedef EGLBoolean (*pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
pfnDestroySurface fDestroySurface;
|
||||
typedef EGLSurface (*pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
pfnCreateWindowSurface fCreateWindowSurface;
|
||||
typedef EGLSurface (*pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
pfnCreatePbufferSurface fCreatePbufferSurface;
|
||||
typedef EGLSurface (*pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
|
||||
pfnCreatePixmapSurface fCreatePixmapSurface;
|
||||
typedef EGLBoolean (*pfnBindAPI)(EGLenum api);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnBindAPI)(EGLenum api);
|
||||
pfnBindAPI fBindAPI;
|
||||
typedef EGLBoolean (*pfnInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
pfnInitialize fInitialize;
|
||||
typedef EGLBoolean (*pfnChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
pfnChooseConfig fChooseConfig;
|
||||
typedef EGLint (*pfnGetError)(void);
|
||||
typedef EGLint (GLAPIENTRY * pfnGetError)(void);
|
||||
pfnGetError fGetError;
|
||||
typedef EGLBoolean (*pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
pfnGetConfigAttrib fGetConfigAttrib;
|
||||
typedef EGLBoolean (*pfnGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
pfnGetConfigs fGetConfigs;
|
||||
typedef EGLBoolean (*pfnWaitNative)(EGLint engine);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnWaitNative)(EGLint engine);
|
||||
pfnWaitNative fWaitNative;
|
||||
typedef EGLCastToRelevantPtr (*pfnGetProcAddress)(const char *procname);
|
||||
typedef EGLCastToRelevantPtr (GLAPIENTRY * pfnGetProcAddress)(const char *procname);
|
||||
pfnGetProcAddress fGetProcAddress;
|
||||
typedef EGLBoolean (*pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
pfnSwapBuffers fSwapBuffers;
|
||||
typedef EGLBoolean (*pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
pfnCopyBuffers fCopyBuffers;
|
||||
typedef const GLubyte* (*pfnQueryString)(EGLDisplay, EGLint name);
|
||||
typedef const GLubyte* (GLAPIENTRY * pfnQueryString)(EGLDisplay, EGLint name);
|
||||
pfnQueryString fQueryString;
|
||||
typedef EGLBoolean (*pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
pfnBindTexImage fBindTexImage;
|
||||
typedef EGLBoolean (*pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
pfnReleaseTexImage fReleaseTexImage;
|
||||
typedef EGLImageKHR (*pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
typedef EGLImageKHR (GLAPIENTRY * pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
pfnCreateImageKHR fCreateImageKHR;
|
||||
typedef EGLBoolean (*pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
|
||||
pfnDestroyImageKHR fDestroyImageKHR;
|
||||
// This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES"
|
||||
// Lets keep it here for now.
|
||||
typedef void (*pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image);
|
||||
typedef void (GLAPIENTRY * pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image);
|
||||
pfnImageTargetTexture2DOES fImageTargetTexture2DOES;
|
||||
|
||||
PRBool EnsureInitialized()
|
||||
@ -253,6 +305,11 @@ public:
|
||||
return PR_FALSE;
|
||||
|
||||
const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
|
||||
if (!extensions)
|
||||
extensions = "";
|
||||
|
||||
printf_stderr("Extensions: %s 0x%02x\n", extensions, extensions[0]);
|
||||
printf_stderr("Extensions length: %d\n", strlen(extensions));
|
||||
|
||||
// note the extra space -- this ugliness tries to match
|
||||
// EGL_KHR_image in the middle of the string, or right at the
|
||||
@ -406,7 +463,13 @@ public:
|
||||
, mThebesSurface(nsnull)
|
||||
, mBound(PR_FALSE)
|
||||
, mIsPBuffer(PR_FALSE)
|
||||
{}
|
||||
#ifdef XP_WIN
|
||||
, mWnd(0)
|
||||
#endif
|
||||
{
|
||||
// any EGL contexts will always be GLESv2
|
||||
SetIsGLES2(PR_TRUE);
|
||||
}
|
||||
|
||||
~GLContextEGL()
|
||||
{
|
||||
@ -564,6 +627,15 @@ 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)
|
||||
{
|
||||
@ -582,6 +654,10 @@ protected:
|
||||
PRBool mBound;
|
||||
|
||||
PRPackedBool mIsPBuffer;
|
||||
|
||||
#ifdef XP_WIN
|
||||
AutoDestroyHWND mWnd;
|
||||
#endif
|
||||
};
|
||||
|
||||
PRBool
|
||||
@ -1172,6 +1248,95 @@ 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
|
||||
@ -1188,6 +1353,8 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
||||
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
|
||||
|
@ -414,6 +414,11 @@ else
|
||||
CPPSRCS += GLContextProvider$(GL_PROVIDER).cpp
|
||||
endif
|
||||
|
||||
# Win32 is a special snowflake, for ANGLE
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
CPPSRCS += GLContextProviderEGL.cpp
|
||||
endif
|
||||
|
||||
DEFINES += -DIMPL_THEBES -DWOFF_MOZILLA_CLIENT
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
Loading…
Reference in New Issue
Block a user