mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1191042 - Establish correct EGLConfig at GLContext creation. r=jrmuizel
This commit is contained in:
parent
f2f5b3c893
commit
59e904dc50
@ -571,6 +571,24 @@ CreateHeadlessANGLE(CreateContextFlags flags, const nsCOMPtr<nsIGfxInfo>& gfxInf
|
||||
{
|
||||
nsRefPtr<GLContext> gl;
|
||||
|
||||
// ANGLE doesn't really support non-alpha backbuffers.
|
||||
flags |= CreateContextFlags::SUPPORT_ALPHA;
|
||||
|
||||
// ANGLE also doesn't really support depth without stencil, and vice-versa.
|
||||
// While we could fake that we don't have one or the other, instead, we *should* just
|
||||
// fail to create a context without both. However, since the defaults are depth:true,
|
||||
// stencil:false, many demos that rely on the implicit depth allocation will fail.
|
||||
// Thus we must limp along for depth:true, stencil:false, but we shouldn't support
|
||||
// depth:false, stencil:true.
|
||||
|
||||
// That is, if there's depth, give depth+stencil, else give neither.
|
||||
if (flags & CreateContextFlags::SUPPORT_DEPTH) {
|
||||
flags |= CreateContextFlags::SUPPORT_STENCIL;
|
||||
} else {
|
||||
flags &= ~CreateContextFlags::SUPPORT_DEPTH;
|
||||
flags &= ~CreateContextFlags::SUPPORT_STENCIL;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless(flags);
|
||||
if (!gl) {
|
||||
@ -758,6 +776,16 @@ WebGLContext::CreateOffscreenGL(bool forceEnabled)
|
||||
CreateContextFlags flags = forceEnabled ? CreateContextFlags::FORCE_ENABLE_HARDWARE :
|
||||
CreateContextFlags::NONE;
|
||||
|
||||
if (mOptions.alpha)
|
||||
flags |= CreateContextFlags::SUPPORT_ALPHA;
|
||||
|
||||
if (!mOptions.antialias) {
|
||||
if (mOptions.depth)
|
||||
flags |= CreateContextFlags::SUPPORT_DEPTH;
|
||||
if (mOptions.stencil)
|
||||
flags |= CreateContextFlags::SUPPORT_STENCIL;
|
||||
}
|
||||
|
||||
gl = CreateHeadlessGL(flags, gfxInfo, this);
|
||||
|
||||
do {
|
||||
|
@ -92,15 +92,19 @@ public:
|
||||
// for the lifetime of this context.
|
||||
void HoldSurface(gfxASurface *aSurf);
|
||||
|
||||
EGLContext GetEGLContext() {
|
||||
EGLContext GetEGLContext() const {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
EGLSurface GetEGLSurface() {
|
||||
EGLConfig GetEGLConfig() const {
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
EGLSurface GetEGLSurface() const {
|
||||
return mSurface;
|
||||
}
|
||||
|
||||
EGLDisplay GetEGLDisplay() {
|
||||
EGLDisplay GetEGLDisplay() const {
|
||||
return EGL_DISPLAY();
|
||||
}
|
||||
|
||||
@ -112,7 +116,7 @@ public:
|
||||
CreateEGLPixmapOffscreenContext(const gfx::IntSize& size);
|
||||
|
||||
static already_AddRefed<GLContextEGL>
|
||||
CreateEGLPBufferOffscreenContext(const gfx::IntSize& size);
|
||||
CreateEGLPBufferOffscreenContext(CreateContextFlags flags, const gfx::IntSize& size);
|
||||
|
||||
protected:
|
||||
friend class GLContextProviderEGL;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "GLContextTypes.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "SurfaceTypes.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
#include "nsSize.h" // for gfx::IntSize (needed by GLContextProviderImpl.h below)
|
||||
|
||||
@ -18,16 +17,6 @@ class nsIWidget;
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
enum class CreateContextFlags : int8_t {
|
||||
NONE = 0,
|
||||
REQUIRE_COMPAT_PROFILE = 1 << 0,
|
||||
// Force the use of hardware backed GL, don't allow software implementations.
|
||||
FORCE_ENABLE_HARDWARE = 1 << 1,
|
||||
/* Don't force discrete GPU to be used (if applicable) */
|
||||
ALLOW_OFFLINE_RENDERER = 1 << 2,
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
|
||||
|
||||
#define IN_GL_CONTEXT_PROVIDER_H
|
||||
|
||||
// Null is always there
|
||||
|
@ -593,17 +593,6 @@ TRY_AGAIN_POWER_OF_TWO:
|
||||
return surface;
|
||||
}
|
||||
|
||||
static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
// Old versions of llvmpipe seem to need this to properly create the pbuffer (bug 981856)
|
||||
LOCAL_EGL_RED_SIZE, 8,
|
||||
LOCAL_EGL_GREEN_SIZE, 8,
|
||||
LOCAL_EGL_BLUE_SIZE, 8,
|
||||
LOCAL_EGL_ALPHA_SIZE, 0,
|
||||
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
|
||||
};
|
||||
|
||||
static const EGLint kEGLConfigAttribsRGB16[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
@ -839,18 +828,72 @@ GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
|
||||
}
|
||||
#endif // defined(ANDROID)
|
||||
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size)
|
||||
{
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
|
||||
const EGLint numConfigs = 1; // We only need one.
|
||||
EGLConfig configs[numConfigs];
|
||||
static void
|
||||
FillContextAttribs(bool alpha, bool depth, bool stencil, std::vector<EGLint>* out)
|
||||
{
|
||||
out->push_back(LOCAL_EGL_SURFACE_TYPE);
|
||||
out->push_back(LOCAL_EGL_PBUFFER_BIT);
|
||||
|
||||
out->push_back(LOCAL_EGL_RENDERABLE_TYPE);
|
||||
out->push_back(LOCAL_EGL_OPENGL_ES2_BIT);
|
||||
|
||||
out->push_back(LOCAL_EGL_RED_SIZE);
|
||||
out->push_back(8);
|
||||
|
||||
out->push_back(LOCAL_EGL_GREEN_SIZE);
|
||||
out->push_back(8);
|
||||
|
||||
out->push_back(LOCAL_EGL_BLUE_SIZE);
|
||||
out->push_back(8);
|
||||
|
||||
out->push_back(LOCAL_EGL_ALPHA_SIZE);
|
||||
out->push_back(alpha ? 8 : 0);
|
||||
|
||||
out->push_back(LOCAL_EGL_DEPTH_SIZE);
|
||||
out->push_back(depth ? 24 : 0);
|
||||
|
||||
out->push_back(LOCAL_EGL_STENCIL_SIZE);
|
||||
out->push_back(stencil ? 8 : 0);
|
||||
|
||||
// EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
|
||||
out->push_back(LOCAL_EGL_NONE);
|
||||
out->push_back(0);
|
||||
|
||||
out->push_back(0);
|
||||
out->push_back(0);
|
||||
}
|
||||
|
||||
static bool
|
||||
DoesAttribPresenceMatch(GLLibraryEGL& egl, EGLConfig config, EGLint attrib,
|
||||
bool shouldHaveBits)
|
||||
{
|
||||
EGLint bits = 0;
|
||||
egl.fGetConfigAttrib(egl.Display(), config, attrib, &bits);
|
||||
MOZ_ASSERT(egl.fGetError() == LOCAL_EGL_SUCCESS);
|
||||
|
||||
return bool(bits) == shouldHaveBits;
|
||||
}
|
||||
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
|
||||
const mozilla::gfx::IntSize& size)
|
||||
{
|
||||
const bool alpha = (flags & CreateContextFlags::SUPPORT_ALPHA);
|
||||
const bool depth = (flags & CreateContextFlags::SUPPORT_DEPTH);
|
||||
const bool stencil = (flags & CreateContextFlags::SUPPORT_STENCIL);
|
||||
|
||||
std::vector<EGLint> configAttribVec;
|
||||
FillContextAttribs(alpha, depth, stencil, &configAttribVec);
|
||||
|
||||
const EGLint* configAttribs = configAttribVec.data();
|
||||
|
||||
const EGLint kMaxConfigs = 256;
|
||||
EGLConfig configs[kMaxConfigs];
|
||||
EGLint foundConfigs = 0;
|
||||
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
|
||||
kEGLConfigAttribsOffscreenPBuffer,
|
||||
configs, numConfigs,
|
||||
configAttribs,
|
||||
configs, kMaxConfigs,
|
||||
&foundConfigs)
|
||||
|| foundConfigs == 0)
|
||||
{
|
||||
@ -858,15 +901,33 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We absolutely don't care, so just pick the first one.
|
||||
config = configs[0];
|
||||
EGLConfig config = EGL_NO_CONFIG;
|
||||
for (EGLint i = 0; i < foundConfigs; i++) {
|
||||
EGLConfig& cur = configs[i];
|
||||
|
||||
bool doesMatch = true;
|
||||
doesMatch &= DoesAttribPresenceMatch(sEGLLibrary, cur, LOCAL_EGL_ALPHA_SIZE, alpha);
|
||||
doesMatch &= DoesAttribPresenceMatch(sEGLLibrary, cur, LOCAL_EGL_DEPTH_SIZE, depth);
|
||||
doesMatch &= DoesAttribPresenceMatch(sEGLLibrary, cur, LOCAL_EGL_STENCIL_SIZE, stencil);
|
||||
|
||||
if (doesMatch) {
|
||||
config = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (config == EGL_NO_CONFIG) {
|
||||
NS_WARNING("Failed to find a compatible config.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (GLContext::ShouldSpew())
|
||||
sEGLLibrary.DumpEGLConfig(config);
|
||||
|
||||
mozilla::gfx::IntSize pbSize(size);
|
||||
surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
|
||||
LOCAL_EGL_NONE,
|
||||
pbSize);
|
||||
EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
|
||||
LOCAL_EGL_NONE,
|
||||
pbSize);
|
||||
if (!surface) {
|
||||
NS_WARNING("Failed to create PBuffer for context!");
|
||||
return nullptr;
|
||||
@ -941,7 +1002,7 @@ GLContextProviderEGL::CreateHeadless(CreateContextFlags flags)
|
||||
|
||||
mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
|
||||
nsRefPtr<GLContext> glContext;
|
||||
glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
|
||||
glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(flags, dummySize);
|
||||
if (!glContext)
|
||||
return nullptr;
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define GLCONTEXT_TYPES_H_
|
||||
|
||||
#include "GLTypes.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
@ -43,6 +44,22 @@ struct GLFormats
|
||||
GLsizei samples;
|
||||
};
|
||||
|
||||
enum class CreateContextFlags : int8_t {
|
||||
NONE = 0,
|
||||
|
||||
REQUIRE_COMPAT_PROFILE = 1 << 0,
|
||||
// Force the use of hardware backed GL, don't allow software implementations.
|
||||
FORCE_ENABLE_HARDWARE = 1 << 1,
|
||||
// Don't force discrete GPU to be used. (if applicable)
|
||||
ALLOW_OFFLINE_RENDERER = 1 << 2,
|
||||
|
||||
// Ensure that later we'll be able to attach a backbuffer with these properties:
|
||||
SUPPORT_ALPHA = 1 << 3,
|
||||
SUPPORT_DEPTH = 1 << 4,
|
||||
SUPPORT_STENCIL = 1 << 5,
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
@ -281,137 +281,6 @@ SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(layers::SurfaceDescriptor* c
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Factory
|
||||
|
||||
static void
|
||||
FillPBufferAttribs_ByBits(nsTArray<EGLint>& aAttrs,
|
||||
int redBits, int greenBits,
|
||||
int blueBits, int alphaBits,
|
||||
int depthBits, int stencilBits)
|
||||
{
|
||||
aAttrs.Clear();
|
||||
|
||||
#if defined(A1) || defined(A2)
|
||||
#error The temp-macro names we want are already defined.
|
||||
#endif
|
||||
|
||||
#define A1(_x) do { aAttrs.AppendElement(_x); } while (0)
|
||||
#define A2(_x,_y) do { A1(_x); A1(_y); } while (0)
|
||||
|
||||
A2(LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT);
|
||||
A2(LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT);
|
||||
|
||||
A2(LOCAL_EGL_RED_SIZE, redBits);
|
||||
A2(LOCAL_EGL_GREEN_SIZE, greenBits);
|
||||
A2(LOCAL_EGL_BLUE_SIZE, blueBits);
|
||||
A2(LOCAL_EGL_ALPHA_SIZE, alphaBits);
|
||||
|
||||
A2(LOCAL_EGL_DEPTH_SIZE, depthBits);
|
||||
A2(LOCAL_EGL_STENCIL_SIZE, stencilBits);
|
||||
|
||||
A1(LOCAL_EGL_NONE);
|
||||
#undef A1
|
||||
#undef A2
|
||||
}
|
||||
|
||||
static void
|
||||
FillPBufferAttribs_BySizes(nsTArray<EGLint>& attribs,
|
||||
bool bpp16, bool hasAlpha,
|
||||
int depthBits, int stencilBits)
|
||||
{
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int alpha = 0;
|
||||
|
||||
if (bpp16) {
|
||||
if (hasAlpha) {
|
||||
red = green = blue = alpha = 4;
|
||||
} else {
|
||||
red = 5;
|
||||
green = 6;
|
||||
blue = 5;
|
||||
}
|
||||
} else {
|
||||
red = green = blue = 8;
|
||||
if (hasAlpha)
|
||||
alpha = 8;
|
||||
}
|
||||
|
||||
FillPBufferAttribs_ByBits(attribs, red, green, blue, alpha, depthBits,
|
||||
stencilBits);
|
||||
}
|
||||
|
||||
static bool
|
||||
DoesAttribBitsMatchCapBool(GLLibraryEGL* egl, EGLConfig config, EGLint attrib,
|
||||
bool capBool)
|
||||
{
|
||||
EGLint bits = 0;
|
||||
egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
|
||||
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
|
||||
|
||||
bool hasBits = !!bits;
|
||||
|
||||
return hasBits == capBool;
|
||||
}
|
||||
|
||||
static EGLConfig
|
||||
ChooseConfig(GLContext* gl, GLLibraryEGL* egl, const SurfaceCaps& caps)
|
||||
{
|
||||
MOZ_ASSERT(egl);
|
||||
MOZ_ASSERT(caps.color);
|
||||
|
||||
// We might want 24-bit depth, but we're only (fairly) sure to get 16-bit.
|
||||
int depthBits = caps.depth ? 16 : 0;
|
||||
int stencilBits = caps.stencil ? 8 : 0;
|
||||
|
||||
// Ok, now we have everything.
|
||||
nsTArray<EGLint> attribs(32);
|
||||
FillPBufferAttribs_BySizes(attribs, caps.bpp16, caps.alpha, depthBits,
|
||||
stencilBits);
|
||||
|
||||
// Time to try to get this config:
|
||||
EGLConfig configs[64];
|
||||
int numConfigs = sizeof(configs)/sizeof(EGLConfig);
|
||||
int foundConfigs = 0;
|
||||
|
||||
if (!egl->fChooseConfig(egl->Display(), attribs.Elements(), configs,
|
||||
numConfigs, &foundConfigs) ||
|
||||
!foundConfigs)
|
||||
{
|
||||
NS_WARNING("No configs found for the requested formats.");
|
||||
return EGL_NO_CONFIG;
|
||||
}
|
||||
|
||||
// The requests passed to ChooseConfig are treated as minimums. If you ask
|
||||
// for 0 bits of alpha, we might still get 8 bits.
|
||||
EGLConfig config = EGL_NO_CONFIG;
|
||||
for (int i = 0; i < foundConfigs; i++) {
|
||||
EGLConfig cur = configs[i];
|
||||
if (!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_ALPHA_SIZE,
|
||||
caps.alpha) ||
|
||||
!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_DEPTH_SIZE,
|
||||
caps.depth) ||
|
||||
!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_STENCIL_SIZE,
|
||||
caps.stencil))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
config = cur;
|
||||
break;
|
||||
}
|
||||
|
||||
if (config == EGL_NO_CONFIG) {
|
||||
NS_WARNING("No acceptable EGLConfig found.");
|
||||
return EGL_NO_CONFIG;
|
||||
}
|
||||
|
||||
if (gl->DebugMode()) {
|
||||
egl->DumpEGLConfig(config);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/*static*/ UniquePtr<SurfaceFactory_ANGLEShareHandle>
|
||||
SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
|
||||
const RefPtr<layers::ISurfaceAllocator>& allocator,
|
||||
@ -449,7 +318,7 @@ SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
|
||||
*out_success = false;
|
||||
|
||||
mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext();
|
||||
mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps);
|
||||
mConfig = GLContextEGL::Cast(mProdGL)->GetEGLConfig();
|
||||
if (mConfig == EGL_NO_CONFIG)
|
||||
return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user