mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=575469; implement CreateOffscreen and context sharing in GLContexts; r=bas
This commit is contained in:
parent
dbd5cb620b
commit
e5aa4fb514
@ -170,7 +170,9 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
format.depth = 16;
|
||||
format.minDepth = 1;
|
||||
|
||||
gl = gl::GLContextProvider::CreatePBuffer(gfxIntSize(width, height), format);
|
||||
gl = gl::GLContextProvider::CreatePBuffer(gfxIntSize(width, height),
|
||||
gl::GLContextProvider::GetGlobalContext(),
|
||||
format);
|
||||
|
||||
#ifdef USE_GLES2
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
@ -184,7 +186,9 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
#endif
|
||||
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = gl::GLContextProviderOSMesa::CreatePBuffer(gfxIntSize(width, height), format);
|
||||
gl = gl::GLContextProviderOSMesa::CreatePBuffer(gfxIntSize(width, height),
|
||||
nsnull,
|
||||
format);
|
||||
if (!InitAndValidateGL()) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -76,15 +76,40 @@ LayerManagerOGL::LayerManagerOGL(nsIWidget *aWidget)
|
||||
|
||||
LayerManagerOGL::~LayerManagerOGL()
|
||||
{
|
||||
if (mGLContext)
|
||||
mGLContext->MakeCurrent();
|
||||
mRoot = nsnull;
|
||||
CleanupResources();
|
||||
}
|
||||
|
||||
mRoot = NULL;
|
||||
void
|
||||
LayerManagerOGL::CleanupResources()
|
||||
{
|
||||
if (!mGLContext)
|
||||
return;
|
||||
|
||||
mGLContext->MakeCurrent();
|
||||
|
||||
for (unsigned int i = 0; i < mPrograms.Length(); ++i)
|
||||
delete mPrograms[i];
|
||||
|
||||
mPrograms.Clear();
|
||||
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
|
||||
|
||||
if (mBackBufferFBO) {
|
||||
mGLContext->fDeleteFramebuffers(1, &mBackBufferFBO);
|
||||
mBackBufferFBO = 0;
|
||||
}
|
||||
|
||||
if (mBackBufferTexture) {
|
||||
mGLContext->fDeleteTextures(1, &mBackBufferTexture);
|
||||
mBackBufferTexture = 0;
|
||||
}
|
||||
|
||||
if (mQuadVBO) {
|
||||
mGLContext->fDeleteBuffers(1, &mQuadVBO);
|
||||
mQuadVBO = 0;
|
||||
}
|
||||
|
||||
mGLContext = nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -93,6 +118,8 @@ LayerManagerOGL::Initialize(GLContext *aExistingContext)
|
||||
if (aExistingContext) {
|
||||
mGLContext = aExistingContext;
|
||||
} else {
|
||||
if (mGLContext)
|
||||
CleanupResources();
|
||||
mGLContext = gl::GLContextProvider::CreateForWindow(mWidget);
|
||||
|
||||
if (!mGLContext) {
|
||||
|
@ -80,7 +80,9 @@ class THEBES_API LayerManagerOGL : public LayerManager {
|
||||
public:
|
||||
LayerManagerOGL(nsIWidget *aWidget);
|
||||
virtual ~LayerManagerOGL();
|
||||
|
||||
|
||||
void CleanupResources();
|
||||
|
||||
/**
|
||||
* Initializes the layer manager, this is when the layer manager will
|
||||
* actually access the device and attempt to create the swap chain used
|
||||
|
@ -120,7 +120,10 @@ public:
|
||||
: mGL(aGL), mProgram(0)
|
||||
{ }
|
||||
|
||||
virtual ~LayerManagerOGLProgram() { }
|
||||
virtual ~LayerManagerOGLProgram() {
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteProgram(mProgram);
|
||||
}
|
||||
|
||||
void Activate() {
|
||||
NS_ASSERTION(mProgram != 0, "Attempting to activate a program that's not in use!");
|
||||
@ -199,11 +202,9 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
GLContext *mGL;
|
||||
nsRefPtr<GLContext> mGL;
|
||||
|
||||
GLuint mProgram;
|
||||
GLuint mFragmentShader;
|
||||
GLuint mVertexShader;
|
||||
|
||||
nsTArray<UniformValue> mUniformValues;
|
||||
|
||||
@ -254,15 +255,15 @@ protected:
|
||||
bool CreateProgram(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
mVertexShader = CreateShader(LOCAL_GL_VERTEX_SHADER, aVertexShaderString);
|
||||
mFragmentShader = CreateShader(LOCAL_GL_FRAGMENT_SHADER, aFragmentShaderString);
|
||||
GLuint vertexShader = CreateShader(LOCAL_GL_VERTEX_SHADER, aVertexShaderString);
|
||||
GLuint fragmentShader = CreateShader(LOCAL_GL_FRAGMENT_SHADER, aFragmentShaderString);
|
||||
|
||||
if (!mVertexShader || !mFragmentShader)
|
||||
if (!vertexShader || !fragmentShader)
|
||||
return false;
|
||||
|
||||
mProgram = mGL->fCreateProgram();
|
||||
mGL->fAttachShader(mProgram, mVertexShader);
|
||||
mGL->fAttachShader(mProgram, mFragmentShader);
|
||||
mGL->fAttachShader(mProgram, vertexShader);
|
||||
mGL->fAttachShader(mProgram, fragmentShader);
|
||||
|
||||
// bind common attribs to consistent indices
|
||||
mGL->fBindAttribLocation(mProgram, VertexAttrib, "aVertexCoord");
|
||||
@ -296,10 +297,13 @@ protected:
|
||||
fprintf (stderr, "=== Log:\n%s\n", nsPromiseFlatCString(log).get());
|
||||
fprintf (stderr, "============\n");
|
||||
|
||||
// We can mark the shaders for deletion; they're attached to the program
|
||||
// and will remain attached.
|
||||
mGL->fDeleteShader(vertexShader);
|
||||
mGL->fDeleteShader(fragmentShader);
|
||||
|
||||
if (!success) {
|
||||
mGL->fDeleteProgram(mProgram);
|
||||
mGL->fDeleteShader(mVertexShader);
|
||||
mGL->fDeleteShader(mFragmentShader);
|
||||
|
||||
mProgram = 0;
|
||||
|
||||
|
@ -111,6 +111,7 @@ LibrarySymbolLoader::LoadSymbols(PRLibrary *lib,
|
||||
const char *prefix)
|
||||
{
|
||||
char sbuf[MAX_SYMBOL_LENGTH * 2];
|
||||
int failCount = 0;
|
||||
|
||||
SymLoadStruct *ss = firstStruct;
|
||||
while (ss->symPointer) {
|
||||
@ -136,13 +137,13 @@ LibrarySymbolLoader::LoadSymbols(PRLibrary *lib,
|
||||
|
||||
if (*ss->symPointer == 0) {
|
||||
fprintf (stderr, "Can't find symbol '%s'\n", ss->symNames[0]);
|
||||
return PR_FALSE;
|
||||
failCount++;
|
||||
}
|
||||
|
||||
ss++;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
return failCount == 0 ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -179,13 +180,7 @@ GLContext::InitWithPrefix(const char *prefix, PRBool trygl)
|
||||
#endif
|
||||
{ (PRFuncPtr*) &fClearStencil, { "ClearStencil", NULL } },
|
||||
{ (PRFuncPtr*) &fColorMask, { "ColorMask", NULL } },
|
||||
{ (PRFuncPtr*) &fCreateProgram, { "CreateProgram", "CreateProgramARB", NULL } },
|
||||
{ (PRFuncPtr*) &fCreateShader, { "CreateShader", "CreateShaderARB", NULL } },
|
||||
{ (PRFuncPtr*) &fCullFace, { "CullFace", NULL } },
|
||||
{ (PRFuncPtr*) &fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", NULL } },
|
||||
{ (PRFuncPtr*) &fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", NULL } },
|
||||
{ (PRFuncPtr*) &fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", NULL } },
|
||||
{ (PRFuncPtr*) &fDeleteShader, { "DeleteShader", "DeleteShaderARB", NULL } },
|
||||
{ (PRFuncPtr*) &fDetachShader, { "DetachShader", "DetachShaderARB", NULL } },
|
||||
{ (PRFuncPtr*) &fDepthFunc, { "DepthFunc", NULL } },
|
||||
{ (PRFuncPtr*) &fDepthMask, { "DepthMask", NULL } },
|
||||
@ -217,8 +212,6 @@ GLContext::InitWithPrefix(const char *prefix, PRBool trygl)
|
||||
{ (PRFuncPtr*) &fGetFloatv, { "GetFloatv", NULL } },
|
||||
{ (PRFuncPtr*) &fGetBooleanv, { "GetBooleanv", NULL } },
|
||||
{ (PRFuncPtr*) &fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", NULL } },
|
||||
{ (PRFuncPtr*) &fGenBuffers, { "GenBuffers", "GenBuffersARB", NULL } },
|
||||
{ (PRFuncPtr*) &fGenTextures, { "GenTextures", NULL } },
|
||||
{ (PRFuncPtr*) &fGetError, { "GetError", NULL } },
|
||||
{ (PRFuncPtr*) &fGetProgramiv, { "GetProgramiv", "GetProgramivARB", NULL } },
|
||||
{ (PRFuncPtr*) &fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", NULL } },
|
||||
@ -307,22 +300,28 @@ GLContext::InitWithPrefix(const char *prefix, PRBool trygl)
|
||||
{ (PRFuncPtr*) &fBindFramebuffer, { "BindFramebuffer", "BindFramebufferEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fBindRenderbuffer, { "BindRenderbuffer", "BindRenderbufferEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fCheckFramebufferStatus, { "CheckFramebufferStatus", "CheckFramebufferStatusEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fFramebufferRenderbuffer, { "FramebufferRenderbuffer", "FramebufferRenderbufferEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fFramebufferTexture2D, { "FramebufferTexture2D", "FramebufferTexture2DEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fGenerateMipmap, { "GenerateMipmap", "GenerateMipmapEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fGetFramebufferAttachmentParameteriv, { "GetFramebufferAttachmentParameteriv", "GetFramebufferAttachmentParameterivEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fGetRenderbufferParameteriv, { "GetRenderbufferParameteriv", "GetRenderbufferParameterivEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", NULL } },
|
||||
{ (PRFuncPtr*) &fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", NULL } },
|
||||
#if 0
|
||||
{ (PRFuncPtr*) &fMapBuffer, { "MapBuffer", NULL } },
|
||||
{ (PRFuncPtr*) &fUnmapBuffer, { "UnmapBuffer", NULL } },
|
||||
#endif
|
||||
|
||||
{ (PRFuncPtr*) &priv_fGenBuffers, { "GenBuffers", "GenBuffersARB", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fGenTextures, { "GenTextures", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fCreateProgram, { "CreateProgram", "CreateProgramARB", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fCreateShader, { "CreateShader", "CreateShaderARB", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", NULL } },
|
||||
|
||||
{ (PRFuncPtr*) &priv_fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fDeleteShader, { "DeleteShader", "DeleteShaderARB", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", NULL } },
|
||||
{ (PRFuncPtr*) &priv_fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", NULL } },
|
||||
|
||||
{ NULL, { NULL } },
|
||||
|
||||
@ -472,5 +471,361 @@ BasicTextureImage::EndUpdate()
|
||||
return PR_TRUE; // mTexture is bound
|
||||
}
|
||||
|
||||
PRBool
|
||||
GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
bool alpha = mCreationFormat.alpha > 0;
|
||||
int depth = mCreationFormat.depth;
|
||||
int stencil = mCreationFormat.stencil;
|
||||
|
||||
#ifdef USE_GLES2
|
||||
const bool isMobile = true;
|
||||
#else
|
||||
const bool isMobile = false;
|
||||
#endif
|
||||
|
||||
bool firstTime = (mOffscreenFBO == 0);
|
||||
|
||||
GLuint curBoundTexture = 0;
|
||||
GLuint curBoundRenderbuffer = 0;
|
||||
GLuint curBoundFramebuffer = 0;
|
||||
|
||||
GLint viewport[4];
|
||||
|
||||
// save a few things for later restoring
|
||||
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
|
||||
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*) &curBoundFramebuffer);
|
||||
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, (GLint*) &curBoundRenderbuffer);
|
||||
fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
|
||||
|
||||
// If this is the first time we're going through this, we need
|
||||
// to create the objects we'll use. Otherwise, just bind them.
|
||||
if (firstTime) {
|
||||
fGenTextures(1, &mOffscreenTexture);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, mOffscreenTexture);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
|
||||
fGenFramebuffers(1, &mOffscreenFBO);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mOffscreenFBO);
|
||||
|
||||
if (depth) {
|
||||
fGenRenderbuffers(1, &mOffscreenDepthRB);
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
fGenRenderbuffers(1, &mOffscreenStencilRB);
|
||||
}
|
||||
} else {
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, mOffscreenTexture);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mOffscreenFBO);
|
||||
}
|
||||
|
||||
// resize the FBO components
|
||||
if (alpha) {
|
||||
fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
} else {
|
||||
fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGB,
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGB,
|
||||
isMobile ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
|
||||
: LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
if (depth) {
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
LOCAL_GL_DEPTH_COMPONENT16,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenStencilRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
LOCAL_GL_STENCIL_INDEX8,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
|
||||
// Now assemble the FBO, if we're creating one
|
||||
// for the first time.
|
||||
if (firstTime) {
|
||||
fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
mOffscreenTexture,
|
||||
0);
|
||||
if (depth) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
mOffscreenDepthRB);
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
mOffscreenStencilRB);
|
||||
}
|
||||
}
|
||||
|
||||
// We should be all resized. Check for framebuffer completeness.
|
||||
GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
NS_WARNING("Error resizing offscreen framebuffer -- framebuffer not complete");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mOffscreenSize = aSize;
|
||||
mOffscreenActualSize = aSize;
|
||||
|
||||
if (firstTime) {
|
||||
UpdateActualFormat();
|
||||
}
|
||||
|
||||
// We're good, and the framebuffer is already attached, so let's
|
||||
// clear out our new framebuffer; otherwise we'll end up displaying
|
||||
// random memory. We saved all of these things earlier so that we
|
||||
// can restore them.
|
||||
fViewport(0, 0, aSize.width, aSize.height);
|
||||
|
||||
// Ok, now restore the GL state back to what it was before the resize took place.
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, curBoundFramebuffer);
|
||||
|
||||
// -don't- restore the viewport the first time through this, since
|
||||
// the previous one isn't valid.
|
||||
if (!firstTime)
|
||||
fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
|
||||
ClearSafely();
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeleteOffscreenFBO()
|
||||
{
|
||||
fDeleteFramebuffers(1, &mOffscreenFBO);
|
||||
fDeleteTextures(1, &mOffscreenTexture);
|
||||
fDeleteRenderbuffers(1, &mOffscreenDepthRB);
|
||||
fDeleteRenderbuffers(1, &mOffscreenStencilRB);
|
||||
|
||||
mOffscreenFBO = 0;
|
||||
mOffscreenTexture = 0;
|
||||
mOffscreenDepthRB = 0;
|
||||
mOffscreenStencilRB = 0;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::ClearSafely()
|
||||
{
|
||||
GLfloat clearColor[4];
|
||||
GLfloat clearDepth;
|
||||
GLint clearStencil;
|
||||
|
||||
fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, clearColor);
|
||||
fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &clearDepth);
|
||||
fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &clearStencil);
|
||||
|
||||
fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
fClearStencil(0);
|
||||
#ifdef USE_GLES2
|
||||
fClearDepthf(1.0f);
|
||||
#else
|
||||
fClearDepth(1.0);
|
||||
#endif
|
||||
|
||||
fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
fClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
||||
fClearStencil(clearStencil);
|
||||
#ifdef USE_GLES2
|
||||
fClearDepthf(clearDepth);
|
||||
#else
|
||||
fClearDepth(clearDepth);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::UpdateActualFormat()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
GLContext::CreatedProgram(GLContext *aOrigin, GLuint aName)
|
||||
{
|
||||
mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::CreatedShader(GLContext *aOrigin, GLuint aName)
|
||||
{
|
||||
mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
for (GLsizei i = 0; i < aCount; ++i) {
|
||||
mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
for (GLsizei i = 0; i < aCount; ++i) {
|
||||
mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
for (GLsizei i = 0; i < aCount; ++i) {
|
||||
mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
for (GLsizei i = 0; i < aCount; ++i) {
|
||||
mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveNamesFromArray(GLContext *aOrigin, GLsizei aCount, GLuint *aNames, nsTArray<GLContext::NamedResource>& aArray)
|
||||
{
|
||||
for (GLsizei j = 0; j < aCount; ++j) {
|
||||
GLuint name = aNames[j];
|
||||
PRBool found = PR_FALSE;
|
||||
for (PRUint32 i = 0; i < aArray.Length(); ++i) {
|
||||
if (aArray[i].name == name) {
|
||||
aArray.RemoveElementAt(i);
|
||||
found = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
printf_stderr("GL Context %p deleting resource %d, which doesn't exist!", aOrigin, name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeletedProgram(GLContext *aOrigin, GLuint aName)
|
||||
{
|
||||
RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeletedShader(GLContext *aOrigin, GLuint aName)
|
||||
{
|
||||
RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeletedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeletedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
|
||||
{
|
||||
RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
|
||||
}
|
||||
|
||||
static void
|
||||
MarkContextDestroyedInArray(GLContext *aContext, nsTArray<GLContext::NamedResource>& aArray)
|
||||
{
|
||||
for (PRUint32 i = 0; i < aArray.Length(); ++i) {
|
||||
if (aArray[i].origin == aContext)
|
||||
aArray[i].originDeleted = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::SharedContextDestroyed(GLContext *aChild)
|
||||
{
|
||||
MarkContextDestroyedInArray(aChild, mTrackedPrograms);
|
||||
MarkContextDestroyedInArray(aChild, mTrackedShaders);
|
||||
MarkContextDestroyedInArray(aChild, mTrackedTextures);
|
||||
MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
|
||||
MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
|
||||
MarkContextDestroyedInArray(aChild, mTrackedBuffers);
|
||||
}
|
||||
|
||||
static void
|
||||
ReportArrayContents(const nsTArray<GLContext::NamedResource>& aArray)
|
||||
{
|
||||
nsTArray<GLContext::NamedResource> copy(aArray);
|
||||
copy.Sort();
|
||||
|
||||
GLContext *lastContext = NULL;
|
||||
for (PRUint32 i = 0; i < copy.Length(); ++i) {
|
||||
if (lastContext != copy[i].origin) {
|
||||
if (lastContext)
|
||||
printf_stderr("\n");
|
||||
printf_stderr(" [%p - %s] ", copy[i].origin, copy[i].originDeleted ? "deleted" : "live");
|
||||
lastContext = copy[i].origin;
|
||||
}
|
||||
printf_stderr("%d ", copy[i].name);
|
||||
}
|
||||
printf_stderr("\n");
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::ReportOutstandingNames()
|
||||
{
|
||||
printf_stderr("== GLContext %p ==\n", this);
|
||||
printf_stderr("Outstanding Textures:\n");
|
||||
ReportArrayContents(mTrackedTextures);
|
||||
printf_stderr("Outstanding Buffers:\n");
|
||||
ReportArrayContents(mTrackedBuffers);
|
||||
printf_stderr("Outstanding Programs:\n");
|
||||
ReportArrayContents(mTrackedPrograms);
|
||||
printf_stderr("Outstanding Shaders:\n");
|
||||
ReportArrayContents(mTrackedShaders);
|
||||
printf_stderr("Outstanding Framebuffers:\n");
|
||||
ReportArrayContents(mTrackedFramebuffers);
|
||||
printf_stderr("Outstanding Renderbuffers:\n");
|
||||
ReportArrayContents(mTrackedRenderbuffers);
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#ifndef GLAPIENTRY
|
||||
#ifdef XP_WIN
|
||||
@ -249,19 +250,110 @@ protected:
|
||||
nsIntRect mUpdateRect;
|
||||
};
|
||||
|
||||
struct THEBES_API ContextFormat {
|
||||
static const ContextFormat BasicRGBA32Format;
|
||||
|
||||
enum StandardContextFormat {
|
||||
Empty,
|
||||
BasicRGBA32,
|
||||
StrictBasicRGBA32,
|
||||
BasicRGB24,
|
||||
StrictBasicRGB24,
|
||||
BasicRGB16_565,
|
||||
StrictBasicRGB16_565
|
||||
};
|
||||
|
||||
ContextFormat() {
|
||||
memset(this, 0, sizeof(ContextFormat));
|
||||
}
|
||||
|
||||
ContextFormat(const StandardContextFormat cf) {
|
||||
memset(this, 0, sizeof(ContextFormat));
|
||||
|
||||
switch (cf) {
|
||||
case BasicRGBA32:
|
||||
red = green = blue = alpha = 8;
|
||||
minRed = minGreen = minBlue = minAlpha = 1;
|
||||
break;
|
||||
|
||||
case StrictBasicRGBA32:
|
||||
red = green = blue = alpha = 8;
|
||||
minRed = minGreen = minBlue = minAlpha = 8;
|
||||
break;
|
||||
|
||||
case BasicRGB24:
|
||||
red = green = blue = 8;
|
||||
minRed = minGreen = minBlue = 1;
|
||||
break;
|
||||
|
||||
case StrictBasicRGB24:
|
||||
red = green = blue = 8;
|
||||
minRed = minGreen = minBlue = 8;
|
||||
break;
|
||||
|
||||
case StrictBasicRGB16_565:
|
||||
red = minRed = 5;
|
||||
green = minGreen = 6;
|
||||
blue = minBlue = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int depth, minDepth;
|
||||
int stencil, minStencil;
|
||||
int red, minRed;
|
||||
int green, minGreen;
|
||||
int blue, minBlue;
|
||||
int alpha, minAlpha;
|
||||
|
||||
int colorBits() const { return red + green + blue; }
|
||||
};
|
||||
|
||||
class GLContext
|
||||
: public LibrarySymbolLoader
|
||||
{
|
||||
THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(GLContext)
|
||||
public:
|
||||
GLContext()
|
||||
: mInitialized(PR_FALSE)
|
||||
GLContext(const ContextFormat& aFormat,
|
||||
PRBool aIsOffscreen = PR_FALSE,
|
||||
GLContext *aSharedContext = nsnull)
|
||||
: mInitialized(PR_FALSE),
|
||||
mCreationFormat(aFormat),
|
||||
mIsOffscreen(aIsOffscreen),
|
||||
mSharedContext(aSharedContext),
|
||||
mOffscreenTexture(0),
|
||||
mOffscreenFBO(0),
|
||||
mOffscreenDepthRB(0),
|
||||
mOffscreenStencilRB(0)
|
||||
{
|
||||
mUserData.Init();
|
||||
}
|
||||
|
||||
virtual ~GLContext() { }
|
||||
virtual ~GLContext() {
|
||||
#ifdef DEBUG
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->SharedContextDestroyed(this);
|
||||
tip->ReportOutstandingNames();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
enum GLContextType {
|
||||
ContextTypeUnknown,
|
||||
ContextTypeWGL,
|
||||
ContextTypeCGL,
|
||||
ContextTypeGLX,
|
||||
ContextTypeEGL,
|
||||
ContextTypeOSMesa
|
||||
};
|
||||
|
||||
virtual GLContextType GetContextType() { return ContextTypeUnknown; }
|
||||
virtual PRBool MakeCurrent() = 0;
|
||||
virtual PRBool SetupLookupFunction() = 0;
|
||||
|
||||
@ -279,23 +371,22 @@ public:
|
||||
|
||||
enum NativeDataType {
|
||||
NativeGLContext,
|
||||
NativeCGLContext,
|
||||
NativePBuffer,
|
||||
NativeImageSurface,
|
||||
NativeThebesSurface,
|
||||
NativeDataTypeMax
|
||||
};
|
||||
|
||||
virtual void *GetNativeData(NativeDataType aType) { return NULL; }
|
||||
GLContext *GetSharedContext() { return mSharedContext; }
|
||||
|
||||
/* If this is a PBuffer context, resize the pbufer to the given dimensions,
|
||||
* keping the same format and attributes. If the resize succeeds, return
|
||||
* PR_TRUE. Otherwise, or if this is not a pbuffer, return PR_FALSE.
|
||||
*
|
||||
* On a successful resize, the previous contents of the pbuffer are cleared,
|
||||
* and the new contents are undefined.
|
||||
const ContextFormat& CreationFormat() { return mCreationFormat; }
|
||||
const ContextFormat& ActualFormat() { return mActualFormat; }
|
||||
|
||||
/**
|
||||
* If this context is double-buffered, returns TRUE.
|
||||
*/
|
||||
virtual PRBool Resize(const gfxIntSize& aNewSize) { return PR_FALSE; }
|
||||
|
||||
virtual PRBool IsDoubleBuffered() { return PR_FALSE; }
|
||||
|
||||
/**
|
||||
* If this context wraps a double-buffered target, swap the back
|
||||
* and front buffers. It should be assumed that after a swap, the
|
||||
@ -326,6 +417,99 @@ public:
|
||||
fDeleteTextures(1, &tex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Offscreen support API
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bind aOffscreen's color buffer as a texture to the TEXTURE_2D
|
||||
* target. Returns TRUE on success, otherwise FALSE. If
|
||||
* aOffscreen is not an offscreen context, returns FALSE. If
|
||||
* BindOffscreenNeedsTexture() returns TRUE, then you should have
|
||||
* a 2D texture name bound whose image will be replaced by the
|
||||
* contents of the offscreen context. If it returns FALSE,
|
||||
* the current 2D texture binding will be replaced.
|
||||
*
|
||||
* After a successul call to BindTex2DOffscreen, UnbindTex2DOffscreen
|
||||
* *must* be called once rendering is complete.
|
||||
*
|
||||
* The same texture unit must be active for Bind/Unbind of a given
|
||||
* context.
|
||||
*/
|
||||
virtual PRBool BindOffscreenNeedsTexture(GLContext *aOffscreen) {
|
||||
return aOffscreen->mOffscreenTexture == 0;
|
||||
}
|
||||
|
||||
virtual PRBool BindTex2DOffscreen(GLContext *aOffscreen) {
|
||||
if (aOffscreen->GetContextType() != GetContextType()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!aOffscreen->mOffscreenFBO) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!aOffscreen->mSharedContext ||
|
||||
aOffscreen->mSharedContext != mSharedContext)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, aOffscreen->mOffscreenTexture);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
virtual void UnbindTex2DOffscreen(GLContext *aOffscreen) { }
|
||||
|
||||
PRBool IsOffscreen() {
|
||||
return mIsOffscreen;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the methods below are only valid if IsOffscreen() returns
|
||||
* true.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Resize the current offscreen buffer. Returns true on success.
|
||||
* If it returns false, the context should be treated as unusable
|
||||
* and should be recreated. After the resize, the viewport is not
|
||||
* changed; glViewport should be called as appropriate.
|
||||
*/
|
||||
virtual PRBool ResizeOffscreen(const gfxIntSize& aNewSize) {
|
||||
if (mOffscreenFBO)
|
||||
return ResizeOffscreenFBO(aNewSize);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return size of this offscreen context.
|
||||
*/
|
||||
gfxIntSize OffscreenSize() {
|
||||
return mOffscreenSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* In some cases, we have to allocate a bigger offscreen buffer
|
||||
* than what's requested. This is the bigger size.
|
||||
*/
|
||||
gfxIntSize OffscreenActualSize() {
|
||||
return mOffscreenActualSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this context is FBO-backed, return the FBO or the color
|
||||
* buffer texture. If the context is not FBO-backed, 0 is
|
||||
* returned (which is also a valid FBO binding).
|
||||
*/
|
||||
GLuint GetOffscreenFBO() {
|
||||
return mOffscreenFBO;
|
||||
}
|
||||
GLuint GetOffscreenTexture() {
|
||||
return mOffscreenTexture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a valid, allocated TextureImage of |aSize| with
|
||||
* |aContentType|. The TextureImage's texture is configured to
|
||||
@ -346,8 +530,31 @@ public:
|
||||
PRBool aUseNearestFilter=PR_FALSE);
|
||||
|
||||
protected:
|
||||
PRPackedBool mInitialized;
|
||||
ContextFormat mCreationFormat;
|
||||
PRPackedBool mIsOffscreen;
|
||||
nsRefPtr<GLContext> mSharedContext;
|
||||
|
||||
void UpdateActualFormat();
|
||||
ContextFormat mActualFormat;
|
||||
|
||||
gfxIntSize mOffscreenSize;
|
||||
gfxIntSize mOffscreenActualSize;
|
||||
GLuint mOffscreenTexture;
|
||||
|
||||
// helper to create/resize an offscreen FBO,
|
||||
// for offscreen implementations that use FBOs.
|
||||
PRBool ResizeOffscreenFBO(const gfxIntSize& aSize);
|
||||
void DeleteOffscreenFBO();
|
||||
GLuint mOffscreenFBO;
|
||||
GLuint mOffscreenDepthRB;
|
||||
GLuint mOffscreenStencilRB;
|
||||
|
||||
// Clear to transparent black, with 0 depth and stencil,
|
||||
// while preserving current ClearColor etc. values.
|
||||
// Useful for resizing offscreen buffers.
|
||||
void ClearSafely();
|
||||
|
||||
PRBool mInitialized;
|
||||
nsDataHashtable<nsVoidPtrHashKey, void*> mUserData;
|
||||
|
||||
PRBool InitWithPrefix(const char *prefix, PRBool trygl);
|
||||
@ -408,20 +615,8 @@ public:
|
||||
PFNGLCLEARSTENCILPROC fClearStencil;
|
||||
typedef void (GLAPIENTRY * PFNGLCOLORMASKPROC) (realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha);
|
||||
PFNGLCOLORMASKPROC fColorMask;
|
||||
typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void);
|
||||
PFNGLCREATEPROGRAMPROC fCreateProgram;
|
||||
typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type);
|
||||
PFNGLCREATESHADERPROC fCreateShader;
|
||||
typedef void (GLAPIENTRY * PFNGLCULLFACEPROC) (GLenum mode);
|
||||
PFNGLCULLFACEPROC fCullFace;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
|
||||
PFNGLDELETEBUFFERSPROC fDeleteBuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint* textures);
|
||||
PFNGLDELETETEXTURESPROC fDeleteTextures;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
PFNGLDELETEPROGRAMPROC fDeleteProgram;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
PFNGLDELETESHADERPROC fDeleteShader;
|
||||
typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
PFNGLDETACHSHADERPROC fDetachShader;
|
||||
typedef void (GLAPIENTRY * PFNGLDEPTHFUNCPROC) (GLenum);
|
||||
@ -473,10 +668,6 @@ public:
|
||||
PFNGLGETBOOLEANBPROC fGetBooleanv;
|
||||
typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
|
||||
PFNGLGETBUFFERPARAMETERIVPROC fGetBufferParameteriv;
|
||||
typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
|
||||
PFNGLGENBUFFERSPROC fGenBuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
PFNGLGENTEXTURESPROC fGenTextures;
|
||||
typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target);
|
||||
PFNGLGENERATEMIPMAPPROC fGenerateMipmap;
|
||||
typedef GLenum (GLAPIENTRY * PFNGLGETERRORPROC) (void);
|
||||
@ -523,12 +714,6 @@ public:
|
||||
PFNGLLINEWIDTHPROC fLineWidth;
|
||||
typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
PFNGLLINKPROGRAMPROC fLinkProgram;
|
||||
#if 0
|
||||
typedef void * (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
|
||||
PFNGLMAPBUFFERPROC fMapBuffer;
|
||||
typedef realGLboolean (GLAPIENTRY * PFNGLUNAMPBUFFERPROC) (GLenum target);
|
||||
PFNGLUNAMPBUFFERPROC fUnmapBuffer;
|
||||
#endif
|
||||
typedef void (GLAPIENTRY * PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
PFNGLPIXELSTOREIPROC fPixelStorei;
|
||||
typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat bias);
|
||||
@ -650,10 +835,6 @@ public:
|
||||
PFNGLBINDRENDERBUFFER fBindRenderbuffer;
|
||||
typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUS) (GLenum target);
|
||||
PFNGLCHECKFRAMEBUFFERSTATUS fCheckFramebufferStatus;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERS) (GLsizei n, const GLuint* ids);
|
||||
PFNGLDELETEFRAMEBUFFERS fDeleteFramebuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERS) (GLsizei n, const GLuint* ids);
|
||||
PFNGLDELETERENDERBUFFERS fDeleteRenderbuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFER) (GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbuffer);
|
||||
PFNGLFRAMEBUFFERRENDERBUFFER fFramebufferRenderbuffer;
|
||||
typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2D) (GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint texture, GLint level);
|
||||
@ -662,10 +843,6 @@ public:
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV fGetFramebufferAttachmentParameteriv;
|
||||
typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIV) (GLenum target, GLenum pname, GLint* value);
|
||||
PFNGLGETRENDERBUFFERPARAMETERIV fGetRenderbufferParameteriv;
|
||||
typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERS) (GLsizei n, GLuint* ids);
|
||||
PFNGLGENFRAMEBUFFERS fGenFramebuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERS) (GLsizei n, GLuint* ids);
|
||||
PFNGLGENRENDERBUFFERS fGenRenderbuffers;
|
||||
typedef realGLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFER) (GLuint framebuffer);
|
||||
PFNGLISFRAMEBUFFER fIsFramebuffer;
|
||||
typedef realGLboolean (GLAPIENTRY * PFNGLISRENDERBUFFER) (GLuint renderbuffer);
|
||||
@ -673,6 +850,264 @@ public:
|
||||
typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
|
||||
PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage;
|
||||
|
||||
protected:
|
||||
/* These are special -- they create or delete GL resources that can live
|
||||
* in a shared namespace. In DEBUG, we wrap these calls so that we can
|
||||
* check when we have something that failed to do cleanup at the time the
|
||||
* final context is destroyed.
|
||||
*/
|
||||
|
||||
typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void);
|
||||
PFNGLCREATEPROGRAMPROC priv_fCreateProgram;
|
||||
typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type);
|
||||
PFNGLCREATESHADERPROC priv_fCreateShader;
|
||||
typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
|
||||
PFNGLGENBUFFERSPROC priv_fGenBuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
PFNGLGENTEXTURESPROC priv_fGenTextures;
|
||||
typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERS) (GLsizei n, GLuint* ids);
|
||||
PFNGLGENFRAMEBUFFERS priv_fGenFramebuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERS) (GLsizei n, GLuint* ids);
|
||||
PFNGLGENRENDERBUFFERS priv_fGenRenderbuffers;
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
PFNGLDELETEPROGRAMPROC priv_fDeleteProgram;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
PFNGLDELETESHADERPROC priv_fDeleteShader;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
|
||||
PFNGLDELETEBUFFERSPROC priv_fDeleteBuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint* textures);
|
||||
PFNGLDELETETEXTURESPROC priv_fDeleteTextures;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERS) (GLsizei n, const GLuint* ids);
|
||||
PFNGLDELETEFRAMEBUFFERS priv_fDeleteFramebuffers;
|
||||
typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERS) (GLsizei n, const GLuint* ids);
|
||||
PFNGLDELETERENDERBUFFERS priv_fDeleteRenderbuffers;
|
||||
|
||||
public:
|
||||
#ifndef DEBUG
|
||||
GLuint GLAPIENTRY fCreateProgram() {
|
||||
return priv_fCreateProgram();
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY fCreateShader(GLenum t) {
|
||||
return priv_fCreateShader(t);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenBuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenBuffers(n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenTextures(GLsizei n, GLuint* names) {
|
||||
priv_fGenTextures(n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenFramebuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenFramebuffers(n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenRenderbuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenRenderbuffers(n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteProgram(GLuint program) {
|
||||
priv_fDeleteProgram(program);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteShader(GLuint shader) {
|
||||
priv_fDeleteShader(shader);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteBuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteBuffers(n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteTextures(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteTextures(n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteFramebuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteFramebuffers(n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteRenderbuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteRenderbuffers(n, names);
|
||||
}
|
||||
#else
|
||||
GLuint GLAPIENTRY fCreateProgram() {
|
||||
GLuint ret = priv_fCreateProgram();
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedProgram(this, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY fCreateShader(GLenum t) {
|
||||
GLuint ret = priv_fCreateShader(t);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedShader(this, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenBuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenBuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedBuffers(this, n, names);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenTextures(GLsizei n, GLuint* names) {
|
||||
priv_fGenTextures(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedTextures(this, n, names);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenFramebuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenFramebuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedFramebuffers(this, n, names);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenRenderbuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenRenderbuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedRenderbuffers(this, n, names);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteProgram(GLuint program) {
|
||||
priv_fDeleteProgram(program);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedProgram(this, program);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteShader(GLuint shader) {
|
||||
priv_fDeleteShader(shader);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedShader(this, shader);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteBuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteBuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedBuffers(this, n, names);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteTextures(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteTextures(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedTextures(this, n, names);
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteFramebuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteFramebuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedFramebuffers(this, n, names);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteRenderbuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteRenderbuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedRenderbuffers(this, n, names);
|
||||
}
|
||||
}
|
||||
|
||||
void CreatedProgram(GLContext *aOrigin, GLuint aName);
|
||||
void CreatedShader(GLContext *aOrigin, GLuint aName);
|
||||
void CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
void CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
void CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
void CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
void DeletedProgram(GLContext *aOrigin, GLuint aName);
|
||||
void DeletedShader(GLContext *aOrigin, GLuint aName);
|
||||
void DeletedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
void DeletedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
void DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
void DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
||||
|
||||
void SharedContextDestroyed(GLContext *aChild);
|
||||
void ReportOutstandingNames();
|
||||
|
||||
struct NamedResource {
|
||||
NamedResource()
|
||||
: origin(nsnull), name(0), originDeleted(PR_FALSE)
|
||||
{ }
|
||||
|
||||
NamedResource(GLContext *aOrigin, GLuint aName)
|
||||
: origin(aOrigin), name(aName), originDeleted(PR_FALSE)
|
||||
{ }
|
||||
|
||||
GLContext *origin;
|
||||
GLuint name;
|
||||
PRBool originDeleted;
|
||||
|
||||
// for sorting
|
||||
bool operator<(const NamedResource& aOther) const {
|
||||
if (intptr_t(origin) < intptr_t(aOther.origin))
|
||||
return true;
|
||||
if (name < aOther.name)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool operator==(const NamedResource& aOther) const {
|
||||
return origin == aOther.origin &&
|
||||
name == aOther.name &&
|
||||
originDeleted == aOther.originDeleted;
|
||||
}
|
||||
};
|
||||
|
||||
nsTArray<NamedResource> mTrackedPrograms;
|
||||
nsTArray<NamedResource> mTrackedShaders;
|
||||
nsTArray<NamedResource> mTrackedTextures;
|
||||
nsTArray<NamedResource> mTrackedFramebuffers;
|
||||
nsTArray<NamedResource> mTrackedRenderbuffers;
|
||||
nsTArray<NamedResource> mTrackedBuffers;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
inline void
|
||||
|
@ -48,56 +48,6 @@ class gfxASurface;
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
struct THEBES_API ContextFormat {
|
||||
static const ContextFormat BasicRGBA32Format;
|
||||
|
||||
enum StandardContextFormat {
|
||||
Empty,
|
||||
BasicRGBA32,
|
||||
StrictBasicRGBA32,
|
||||
BasicRGBX32,
|
||||
StrictBasicRGBX32
|
||||
};
|
||||
|
||||
ContextFormat(const StandardContextFormat cf) {
|
||||
memset(this, 0, sizeof(ContextFormat));
|
||||
|
||||
switch (cf) {
|
||||
case BasicRGBA32:
|
||||
red = green = blue = alpha = 8;
|
||||
minRed = minGreen = minBlue = minAlpha = 1;
|
||||
break;
|
||||
|
||||
case StrictBasicRGBA32:
|
||||
red = green = blue = alpha = 8;
|
||||
minRed = minGreen = minBlue = minAlpha = 8;
|
||||
break;
|
||||
|
||||
case BasicRGBX32:
|
||||
red = green = blue = 8;
|
||||
minRed = minGreen = minBlue = 1;
|
||||
break;
|
||||
|
||||
case StrictBasicRGBX32:
|
||||
red = green = blue = alpha = 8;
|
||||
minRed = minGreen = minBlue = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int depth, minDepth;
|
||||
int stencil, minStencil;
|
||||
int red, minRed;
|
||||
int green, minGreen;
|
||||
int blue, minBlue;
|
||||
int alpha, minAlpha;
|
||||
|
||||
int colorBits() const { return red + green + blue; }
|
||||
};
|
||||
|
||||
#define IN_GL_CONTEXT_PROVIDER_H
|
||||
|
||||
// Null and OSMesa are always there
|
||||
|
@ -50,7 +50,11 @@ namespace gl {
|
||||
class CGLLibrary
|
||||
{
|
||||
public:
|
||||
CGLLibrary() : mInitialized(PR_FALSE), mOGLLibrary(nsnull) {}
|
||||
CGLLibrary()
|
||||
: mInitialized(PR_FALSE),
|
||||
mOGLLibrary(nsnull),
|
||||
mPixelFormat(nsnull)
|
||||
{ }
|
||||
|
||||
PRBool EnsureInitialized()
|
||||
{
|
||||
@ -69,34 +73,68 @@ public:
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NSOpenGLPixelFormat *PixelFormat()
|
||||
{
|
||||
if (mPixelFormat == nsnull) {
|
||||
NSOpenGLPixelFormatAttribute attribs[] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
(NSOpenGLPixelFormatAttribute)nil
|
||||
};
|
||||
|
||||
mPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||
}
|
||||
|
||||
return mPixelFormat;
|
||||
}
|
||||
private:
|
||||
PRBool mInitialized;
|
||||
PRLibrary *mOGLLibrary;
|
||||
NSOpenGLPixelFormat *mPixelFormat;
|
||||
};
|
||||
|
||||
CGLLibrary sCGLLibrary;
|
||||
|
||||
class GLContextCGL : public GLContext
|
||||
{
|
||||
friend class GLContextProviderCGL;
|
||||
|
||||
public:
|
||||
GLContextCGL(NSOpenGLContext *aContext)
|
||||
: mContext(aContext), mCGLContext(nsnull), mPBuffer(nsnull)
|
||||
GLContextCGL(const ContextFormat& aFormat,
|
||||
GLContext *aShareContext,
|
||||
NSOpenGLContext *aContext,
|
||||
PRBool aIsOffscreen = PR_FALSE)
|
||||
: GLContext(aFormat, aIsOffscreen, aShareContext),
|
||||
mContext(aContext),
|
||||
mPBuffer(nsnull),
|
||||
mTempTextureName(0)
|
||||
{ }
|
||||
|
||||
GLContextCGL(CGLContextObj aContext, CGLPBufferObj aPBuffer)
|
||||
: mContext(nsnull), mCGLContext(aContext), mPBuffer(aPBuffer)
|
||||
GLContextCGL(const ContextFormat& aFormat,
|
||||
GLContext *aShareContext,
|
||||
NSOpenGLContext *aContext,
|
||||
NSOpenGLPixelBuffer *aPixelBuffer)
|
||||
: GLContext(aFormat, PR_TRUE, aShareContext),
|
||||
mContext(aContext),
|
||||
mPBuffer(aPixelBuffer),
|
||||
mTempTextureName(0)
|
||||
{ }
|
||||
|
||||
~GLContextCGL()
|
||||
{
|
||||
if (mOffscreenFBO) {
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
}
|
||||
|
||||
if (mContext)
|
||||
[mContext release];
|
||||
|
||||
if (mCGLContext)
|
||||
CGLDestroyContext(mCGLContext);
|
||||
|
||||
if (mPBuffer)
|
||||
CGLDestroyPBuffer(mPBuffer);
|
||||
[mPBuffer release];
|
||||
}
|
||||
|
||||
GLContextType GetContextType() {
|
||||
return ContextTypeCGL;
|
||||
}
|
||||
|
||||
PRBool Init()
|
||||
@ -111,12 +149,6 @@ public:
|
||||
case NativeGLContext:
|
||||
return mContext;
|
||||
|
||||
case NativeCGLContext:
|
||||
return mCGLContext ? mCGLContext : [mContext CGLContextObj];
|
||||
|
||||
case NativePBuffer:
|
||||
return mPBuffer;
|
||||
|
||||
default:
|
||||
return nsnull;
|
||||
}
|
||||
@ -126,8 +158,6 @@ public:
|
||||
{
|
||||
if (mContext) {
|
||||
[mContext makeCurrentContext];
|
||||
} else if (mCGLContext) {
|
||||
CGLSetCurrentContext(mCGLContext);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -137,18 +167,104 @@ public:
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool BindTex2DOffscreen(GLContext *aOffscreen);
|
||||
void UnbindTex2DOffscreen(GLContext *aOffscreen);
|
||||
PRBool ResizeOffscreen(const gfxIntSize& aNewSize);
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
CreateBasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
GLContext* aContext);
|
||||
|
||||
private:
|
||||
NSOpenGLContext *mContext;
|
||||
CGLContextObj mCGLContext;
|
||||
CGLPBufferObj mPBuffer;
|
||||
NSOpenGLPixelBuffer *mPBuffer;
|
||||
GLuint mTempTextureName;
|
||||
};
|
||||
|
||||
PRBool
|
||||
GLContextCGL::BindTex2DOffscreen(GLContext *aOffscreen)
|
||||
{
|
||||
if (aOffscreen->GetContextType() != ContextTypeCGL) {
|
||||
NS_WARNING("non-CGL context");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!aOffscreen->IsOffscreen()) {
|
||||
NS_WARNING("non-offscreen context");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
GLContextCGL *offs = static_cast<GLContextCGL*>(aOffscreen);
|
||||
|
||||
if (offs->mPBuffer) {
|
||||
fGenTextures(1, &mTempTextureName);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, mTempTextureName);
|
||||
|
||||
[mContext
|
||||
setTextureImageToPixelBuffer:offs->mPBuffer
|
||||
colorBuffer:LOCAL_GL_FRONT];
|
||||
} else if (offs->mOffscreenTexture) {
|
||||
if (offs->GetSharedContext() != GLContextProviderCGL::GetGlobalContext())
|
||||
{
|
||||
NS_WARNING("offscreen FBO context can only be bound with context sharing!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, offs->mOffscreenTexture);
|
||||
} else {
|
||||
NS_WARNING("don't know how to bind this!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
GLContextCGL::UnbindTex2DOffscreen(GLContext *aOffscreen)
|
||||
{
|
||||
NS_ASSERTION(aOffscreen->GetContextType() == ContextTypeCGL, "wrong type");
|
||||
|
||||
GLContextCGL *offs = static_cast<GLContextCGL*>(aOffscreen);
|
||||
if (offs->mPBuffer) {
|
||||
NS_ASSERTION(mTempTextureName, "We didn't have an offscreen texture name?");
|
||||
fDeleteTextures(1, &mTempTextureName);
|
||||
mTempTextureName = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
GLContextCGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
||||
{
|
||||
if (mPBuffer) {
|
||||
NSOpenGLPixelBuffer *pb = [[NSOpenGLPixelBuffer alloc]
|
||||
initWithTextureTarget:LOCAL_GL_TEXTURE_2D
|
||||
textureInternalFormat:(mCreationFormat.alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB)
|
||||
textureMaxMipMapLevel:0
|
||||
pixelsWide:aNewSize.width
|
||||
pixelsHigh:aNewSize.height];
|
||||
if (!pb) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
[mPBuffer release];
|
||||
mPBuffer = pb;
|
||||
|
||||
mOffscreenSize = aNewSize;
|
||||
mOffscreenActualSize = aNewSize;
|
||||
|
||||
[mContext setPixelBuffer:pb cubeMapFace:0 mipMapLevel:0
|
||||
currentVirtualScreen:[mContext currentVirtualScreen]];
|
||||
|
||||
MakeCurrent();
|
||||
ClearSafely();
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return ResizeOffscreenFBO(aNewSize);
|
||||
}
|
||||
|
||||
class TextureImageCGL : public BasicTextureImage
|
||||
{
|
||||
friend already_AddRefed<TextureImage>
|
||||
@ -204,112 +320,176 @@ GLContextCGL::CreateBasicTextureImage(GLuint aTexture,
|
||||
return teximage.forget();
|
||||
}
|
||||
|
||||
static GLContextCGL *
|
||||
GetGlobalContextCGL()
|
||||
{
|
||||
return static_cast<GLContextCGL*>(GLContextProviderCGL::GetGlobalContext());
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateForWindow(nsIWidget *aWidget)
|
||||
{
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
NSOpenGLPixelFormatAttribute attributes [] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
(NSOpenGLPixelFormatAttribute)nil
|
||||
};
|
||||
|
||||
NSOpenGLPixelFormat *pixelFormat = [[(NSOpenGLPixelFormat *)[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes:attributes]
|
||||
autorelease];
|
||||
NSOpenGLContext *context = [[NSOpenGLContext alloc]
|
||||
initWithFormat:pixelFormat
|
||||
shareContext:NULL];
|
||||
|
||||
if (context == nil) {
|
||||
GLContextCGL *shareContext = GetGlobalContextCGL();
|
||||
|
||||
NSOpenGLContext *context = [[NSOpenGLContext alloc]
|
||||
initWithFormat:sCGLLibrary.PixelFormat()
|
||||
shareContext:(shareContext ? shareContext->mContext : NULL)];
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextCGL> glContext = new GLContextCGL(context);
|
||||
NSView *childView = (NSView *)aWidget->GetNativeData(NS_NATIVE_WIDGET);
|
||||
[context setView:childView];
|
||||
|
||||
nsRefPtr<GLContextCGL> glContext = new GLContextCGL(ContextFormat(ContextFormat::BasicRGB24),
|
||||
shareContext,
|
||||
context);
|
||||
if (!glContext->Init()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NSView *childView = (NSView *)aWidget->GetNativeData(NS_NATIVE_WIDGET);
|
||||
if ([context view] != childView) {
|
||||
[context setView:childView];
|
||||
}
|
||||
}
|
||||
|
||||
return glContext.forget().get();
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreatePBuffer(const gfxIntSize &aSize,
|
||||
const ContextFormat &aFormat)
|
||||
static already_AddRefed<GLContextCGL>
|
||||
CreateOffscreenPBufferContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat,
|
||||
PRBool aShare = PR_FALSE)
|
||||
{
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsTArray<CGLPixelFormatAttribute> attribs;
|
||||
|
||||
#define A1_(_x) do { \
|
||||
attribs.AppendElement((CGLPixelFormatAttribute) _x); \
|
||||
} while(0)
|
||||
#define A2_(_x,_y) do { \
|
||||
attribs.AppendElement((CGLPixelFormatAttribute) _x); \
|
||||
attribs.AppendElement((CGLPixelFormatAttribute) _y); \
|
||||
} while(0)
|
||||
|
||||
A1_(kCGLPFAAccelerated);
|
||||
A1_(kCGLPFAMinimumPolicy);
|
||||
A1_(kCGLPFAPBuffer);
|
||||
|
||||
A2_(kCGLPFAColorSize, aFormat.colorBits());
|
||||
A2_(kCGLPFAAlphaSize, aFormat.alpha);
|
||||
A2_(kCGLPFADepthSize, aFormat.depth);
|
||||
|
||||
A1_(0);
|
||||
|
||||
CGLError err;
|
||||
|
||||
GLint nFormats;
|
||||
CGLPixelFormatObj pixelFormat;
|
||||
CGLContextObj context;
|
||||
CGLPBufferObj pbuffer;
|
||||
GLint screen;
|
||||
|
||||
err = CGLChoosePixelFormat(attribs.Elements(), &pixelFormat, &nFormats);
|
||||
if (err) {
|
||||
GLContextCGL *shareContext = aShare ? GetGlobalContextCGL() : nsnull;
|
||||
if (aShare && !shareContext) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
err = CGLCreateContext(pixelFormat, NULL, &context);
|
||||
if (err) {
|
||||
nsTArray<NSOpenGLPixelFormatAttribute> attribs;
|
||||
|
||||
#define A_(_x) attribs.AppendElement(NSOpenGLPixelFormatAttribute(_x))
|
||||
A_(NSOpenGLPFAAccelerated);
|
||||
A_(NSOpenGLPFAPixelBuffer);
|
||||
A_(NSOpenGLPFAMinimumPolicy);
|
||||
|
||||
A_(NSOpenGLPFAColorSize);
|
||||
A_(aFormat.colorBits());
|
||||
|
||||
A_(NSOpenGLPFAAlphaSize);
|
||||
A_(aFormat.alpha);
|
||||
|
||||
A_(NSOpenGLPFADepthSize);
|
||||
A_(aFormat.depth);
|
||||
|
||||
A_(NSOpenGLPFAStencilSize);
|
||||
A_(aFormat.stencil);
|
||||
|
||||
A_(0);
|
||||
#undef A_
|
||||
|
||||
printf_stderr("colorbits: %d alpha: %d depth: %d stencil: %d\n", aFormat.colorBits(), aFormat.alpha, aFormat.depth, aFormat.stencil);
|
||||
|
||||
NSOpenGLPixelFormat *pbFormat = [[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes:attribs.Elements()];
|
||||
if (!pbFormat) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
err = CGLCreatePBuffer(aSize.width, aSize.height, LOCAL_GL_TEXTURE_2D,
|
||||
LOCAL_GL_RGBA,
|
||||
0, &pbuffer);
|
||||
if (err) {
|
||||
NSOpenGLPixelBuffer *pb = [[NSOpenGLPixelBuffer alloc]
|
||||
initWithTextureTarget:LOCAL_GL_TEXTURE_2D
|
||||
textureInternalFormat:(aFormat.alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB)
|
||||
textureMaxMipMapLevel:0
|
||||
pixelsWide:aSize.width
|
||||
pixelsHigh:aSize.height];
|
||||
if (!pb) {
|
||||
[pbFormat release];
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
err = CGLGetVirtualScreen(context, &screen);
|
||||
if (err) {
|
||||
NSOpenGLContext *context = [[NSOpenGLContext alloc]
|
||||
initWithFormat:pbFormat
|
||||
shareContext:shareContext ? shareContext->mContext : NULL];
|
||||
if (!context) {
|
||||
[pbFormat release];
|
||||
[pb release];
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
err = CGLSetPBuffer(context, pbuffer, 0, 0, screen);
|
||||
if (err) {
|
||||
[context
|
||||
setPixelBuffer:pb
|
||||
cubeMapFace:0
|
||||
mipMapLevel:0
|
||||
currentVirtualScreen:[context currentVirtualScreen]];
|
||||
|
||||
{
|
||||
GLint l;
|
||||
[pbFormat getValues:&l forAttribute:NSOpenGLPFADepthSize forVirtualScreen:[context currentVirtualScreen]];
|
||||
printf_stderr("*** depth: %d (req: %d)\n", l, aFormat.depth);
|
||||
}
|
||||
|
||||
[pbFormat release];
|
||||
|
||||
nsRefPtr<GLContextCGL> glContext = new GLContextCGL(aFormat, shareContext, context, pb);
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContextCGL>
|
||||
CreateOffscreenFBOContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat,
|
||||
PRBool aShare = PR_TRUE)
|
||||
{
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
CGLDestroyPixelFormat(pixelFormat);
|
||||
|
||||
nsRefPtr<GLContextCGL> glContext = new GLContextCGL(context, pbuffer);
|
||||
if (!glContext->Init()) {
|
||||
GLContextCGL *shareContext = aShare ? GetGlobalContextCGL() : nsnull;
|
||||
if (aShare && !shareContext) {
|
||||
// if there is no share context, then we can't use FBOs.
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget().get();
|
||||
NSOpenGLContext *context = [[NSOpenGLContext alloc]
|
||||
initWithFormat:sCGLLibrary.PixelFormat()
|
||||
shareContext:shareContext ? shareContext->mContext : NULL];
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextCGL> glContext = new GLContextCGL(aFormat, shareContext, context, PR_TRUE);
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
nsRefPtr<GLContextCGL> glContext;
|
||||
|
||||
glContext = CreateOffscreenPBufferContext(aSize, aFormat);
|
||||
if (glContext &&
|
||||
glContext->Init())
|
||||
{
|
||||
glContext->mOffscreenSize = aSize;
|
||||
glContext->mOffscreenActualSize = aSize;
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
// try a FBO as second choice
|
||||
glContext = CreateOffscreenFBOContext(aSize, aFormat);
|
||||
if (glContext &&
|
||||
glContext->Init() &&
|
||||
glContext->ResizeOffscreenFBO(aSize))
|
||||
{
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
// everything failed
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
@ -318,5 +498,27 @@ GLContextProviderCGL::CreateForNativePixmapSurface(gfxASurface *aSurface)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static nsRefPtr<GLContext> gGlobalContext;
|
||||
|
||||
GLContext *
|
||||
GLContextProviderCGL::GetGlobalContext()
|
||||
{
|
||||
if (!sCGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!gGlobalContext) {
|
||||
// There are bugs in some older drivers with pbuffers less
|
||||
// than 16x16 in size; also 16x16 is POT so that we can do
|
||||
// a FBO with it on older video cards. A FBO context for
|
||||
// sharing is preferred since it has no associated target.
|
||||
gGlobalContext = CreateOffscreenFBOContext(gfxIntSize(16, 16),
|
||||
ContextFormat(ContextFormat::BasicRGB24),
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
}
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,7 +53,7 @@
|
||||
#include "nsDebug.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "GLXLibrary.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxXlibSurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxPlatform.h"
|
||||
@ -61,6 +61,10 @@
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
static PRBool gIsATI = PR_FALSE;
|
||||
static PRBool gIsChromium = PR_FALSE;
|
||||
static int gGLXVersion = 0;
|
||||
|
||||
PRBool
|
||||
GLXLibrary::EnsureInitialized()
|
||||
{
|
||||
@ -90,6 +94,10 @@ GLXLibrary::EnsureInitialized()
|
||||
{ (PRFuncPtr*) &xGetFBConfigAttrib, { "glXGetFBConfigAttrib", NULL } },
|
||||
{ (PRFuncPtr*) &xSwapBuffers, { "glXSwapBuffers", NULL } },
|
||||
{ (PRFuncPtr*) &xQueryServerString, { "glXQueryServerString", NULL } },
|
||||
{ (PRFuncPtr*) &xCreatePixmap, { "glXCreatePixmap", NULL } },
|
||||
{ (PRFuncPtr*) &xDestroyPixmap, { "glXDestroyPixmap", NULL } },
|
||||
{ (PRFuncPtr*) &xGetClientString, { "glXGetClientString", NULL } },
|
||||
{ (PRFuncPtr*) &xCreateContext, { "glXCreateContext", NULL } },
|
||||
{ NULL, { NULL } }
|
||||
};
|
||||
|
||||
@ -98,6 +106,40 @@ GLXLibrary::EnsureInitialized()
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
const char *vendor = xQueryServerString(DefaultXDisplay(),
|
||||
DefaultScreen(DefaultXDisplay()),
|
||||
GLX_VENDOR);
|
||||
const char *serverVersionStr = xQueryServerString(DefaultXDisplay(),
|
||||
DefaultScreen(DefaultXDisplay()),
|
||||
GLX_VERSION);
|
||||
const char *clientVersionStr = xGetClientString(DefaultXDisplay(),
|
||||
GLX_VERSION);
|
||||
|
||||
|
||||
int serverVersion = 0, clientVersion = 0;
|
||||
if (serverVersionStr &&
|
||||
strlen(serverVersionStr) > 3 &&
|
||||
serverVersionStr[1] == '.')
|
||||
{
|
||||
serverVersion = (serverVersionStr[0] - '0') << 8 | (serverVersionStr[2] - '0');
|
||||
}
|
||||
|
||||
if (clientVersion &&
|
||||
strlen(clientVersionStr) > 3 &&
|
||||
clientVersionStr[1] == '.')
|
||||
{
|
||||
clientVersion = (clientVersionStr[0] - '0') << 8 | (clientVersionStr[2] - '0');
|
||||
}
|
||||
|
||||
gGLXVersion = PR_MIN(clientVersion, serverVersion);
|
||||
|
||||
if (gGLXVersion < 0x0103)
|
||||
return PR_FALSE;
|
||||
|
||||
gIsATI = vendor && strstr(vendor, "ATI");
|
||||
gIsChromium = (vendor && strstr(vendor, "Chromium")) ||
|
||||
(serverVersion && strstr(serverVersionStr, "Chromium"));
|
||||
|
||||
mInitialized = PR_TRUE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -116,7 +158,14 @@ class GLContextGLX : public GLContext
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<GLContextGLX>
|
||||
CreateGLContext(Display *display, GLXDrawable drawable, GLXFBConfig cfg, PRBool pbuffer)
|
||||
CreateGLContext(const ContextFormat& format,
|
||||
Display *display,
|
||||
GLXDrawable drawable,
|
||||
GLXFBConfig cfg,
|
||||
XVisualInfo *vinfo,
|
||||
GLContextGLX *shareContext,
|
||||
PRBool deleteDrawable,
|
||||
gfxXlibSurface *pixmap = nsnull)
|
||||
{
|
||||
int db = 0, err;
|
||||
err = sGLXLibrary.xGetFBConfigAttrib(display, cfg,
|
||||
@ -128,27 +177,45 @@ public:
|
||||
}
|
||||
|
||||
ctxErrorOccurred = false;
|
||||
int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&ctxErrorHandler);
|
||||
int (*oldHandler)(Display *, XErrorEvent *);
|
||||
GLXContext context;
|
||||
|
||||
GLXContext context = sGLXLibrary.xCreateNewContext(display,
|
||||
cfg,
|
||||
GLX_RGBA_TYPE,
|
||||
NULL,
|
||||
True);
|
||||
TRY_AGAIN_NO_SHARING:
|
||||
oldHandler = XSetErrorHandler(&ctxErrorHandler);
|
||||
|
||||
if (gGLXVersion >= 0x0103) {
|
||||
context = sGLXLibrary.xCreateNewContext(display,
|
||||
cfg,
|
||||
GLX_RGBA_TYPE,
|
||||
shareContext ? shareContext->mContext : NULL,
|
||||
True);
|
||||
} else {
|
||||
context = sGLXLibrary.xCreateContext(display,
|
||||
vinfo,
|
||||
shareContext ? shareContext->mContext : NULL,
|
||||
True);
|
||||
}
|
||||
|
||||
XSync(display, False);
|
||||
XSetErrorHandler(oldHandler);
|
||||
|
||||
if (!context || ctxErrorOccurred) {
|
||||
if (shareContext) {
|
||||
shareContext = nsnull;
|
||||
goto TRY_AGAIN_NO_SHARING;
|
||||
}
|
||||
NS_WARNING("Failed to create GLXContext!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext(new GLContextGLX(display,
|
||||
nsRefPtr<GLContextGLX> glContext(new GLContextGLX(format,
|
||||
shareContext,
|
||||
display,
|
||||
drawable,
|
||||
context,
|
||||
pbuffer,
|
||||
db));
|
||||
deleteDrawable,
|
||||
db,
|
||||
pixmap));
|
||||
if (!glContext->Init()) {
|
||||
return nsnull;
|
||||
}
|
||||
@ -158,11 +225,15 @@ public:
|
||||
|
||||
~GLContextGLX()
|
||||
{
|
||||
if (mPBuffer) {
|
||||
sGLXLibrary.xDestroyPbuffer(mDisplay, mWindow);
|
||||
}
|
||||
|
||||
sGLXLibrary.xDeleteContext(mDisplay, mContext);
|
||||
|
||||
if (mDeleteDrawable) {
|
||||
sGLXLibrary.xDestroyPixmap(mDisplay, mDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
GLContextType GetContextType() {
|
||||
return ContextTypeGLX;
|
||||
}
|
||||
|
||||
PRBool Init()
|
||||
@ -178,7 +249,7 @@ public:
|
||||
|
||||
PRBool MakeCurrent()
|
||||
{
|
||||
Bool succeeded = sGLXLibrary.xMakeCurrent(mDisplay, mWindow, mContext);
|
||||
Bool succeeded = sGLXLibrary.xMakeCurrent(mDisplay, mDrawable, mContext);
|
||||
NS_ASSERTION(succeeded, "Failed to make GL context current!");
|
||||
return succeeded;
|
||||
}
|
||||
@ -195,22 +266,24 @@ public:
|
||||
case NativeGLContext:
|
||||
return mContext;
|
||||
|
||||
case NativePBuffer:
|
||||
if (mPBuffer) {
|
||||
return (void *)mWindow;
|
||||
}
|
||||
// fall through
|
||||
case NativeThebesSurface:
|
||||
return mPixmap;
|
||||
|
||||
default:
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
virtual PRBool SwapBuffers()
|
||||
PRBool IsDoubleBuffered()
|
||||
{
|
||||
if (mPBuffer || !mDoubleBuffered)
|
||||
return mDoubleBuffered;
|
||||
}
|
||||
|
||||
PRBool SwapBuffers()
|
||||
{
|
||||
if (!mDoubleBuffered)
|
||||
return PR_FALSE;
|
||||
sGLXLibrary.xSwapBuffers(mDisplay, mWindow);
|
||||
sGLXLibrary.xSwapBuffers(mDisplay, mDrawable);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -249,19 +322,33 @@ public:
|
||||
GLContext* aContext);
|
||||
|
||||
private:
|
||||
GLContextGLX(Display *aDisplay, GLXDrawable aWindow, GLXContext aContext, PRBool aPBuffer = PR_FALSE, PRBool aDoubleBuffered=PR_FALSE)
|
||||
: mContext(aContext),
|
||||
mDisplay(aDisplay),
|
||||
mWindow(aWindow),
|
||||
mPBuffer(aPBuffer),
|
||||
mDoubleBuffered(aDoubleBuffered) {}
|
||||
friend class GLContextProviderGLX;
|
||||
|
||||
GLContextGLX(const ContextFormat& aFormat,
|
||||
GLContext *aShareContext,
|
||||
Display *aDisplay,
|
||||
GLXDrawable aDrawable,
|
||||
GLXContext aContext,
|
||||
PRBool aDeleteDrawable,
|
||||
PRBool aDoubleBuffered,
|
||||
gfxXlibSurface *aPixmap)
|
||||
: GLContext(aFormat, aDeleteDrawable ? PR_TRUE : PR_FALSE, aShareContext),
|
||||
mContext(aContext),
|
||||
mDisplay(aDisplay),
|
||||
mDrawable(aDrawable),
|
||||
mDeleteDrawable(aDeleteDrawable),
|
||||
mDoubleBuffered(aDoubleBuffered),
|
||||
mPixmap(aPixmap)
|
||||
{ }
|
||||
|
||||
GLXContext mContext;
|
||||
Display *mDisplay;
|
||||
GLXDrawable mWindow;
|
||||
PRBool mPBuffer;
|
||||
PRBool mDoubleBuffered;
|
||||
GLXDrawable mDrawable;
|
||||
PRPackedBool mDeleteDrawable;
|
||||
PRPackedBool mDoubleBuffered;
|
||||
|
||||
nsTArray<GLuint> textures;
|
||||
nsRefPtr<gfxXlibSurface> mPixmap;
|
||||
};
|
||||
|
||||
// FIXME/bug 575505: this is a (very slow!) placeholder
|
||||
@ -321,7 +408,14 @@ GLContextGLX::CreateBasicTextureImage(GLuint aTexture,
|
||||
return teximage.forget();
|
||||
}
|
||||
|
||||
static PRBool AreCompatibleVisuals(XVisualInfo *one, XVisualInfo *two)
|
||||
static GLContextGLX *
|
||||
GetGlobalContextGLX()
|
||||
{
|
||||
return static_cast<GLContextGLX*>(GLContextProviderGLX::GetGlobalContext());
|
||||
}
|
||||
|
||||
static PRBool
|
||||
AreCompatibleVisuals(XVisualInfo *one, XVisualInfo *two)
|
||||
{
|
||||
if (one->c_class != two->c_class) {
|
||||
return PR_FALSE;
|
||||
@ -362,11 +456,9 @@ GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
|
||||
int xscreen = DefaultScreen(display);
|
||||
Window window = GET_NATIVE_WINDOW(aWidget);
|
||||
|
||||
const char *vendor = sGLXLibrary.xQueryServerString(display, xscreen, GLX_VENDOR);
|
||||
PRBool isATI = vendor && strstr(vendor, "ATI");
|
||||
int numConfigs;
|
||||
ScopedXFree<GLXFBConfig> cfgs;
|
||||
if (isATI) {
|
||||
if (gIsATI) {
|
||||
const int attribs[] = {
|
||||
GLX_DOUBLEBUFFER, False,
|
||||
0
|
||||
@ -402,7 +494,7 @@ GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
|
||||
#endif
|
||||
|
||||
ScopedXFree<XVisualInfo> vi;
|
||||
if (isATI) {
|
||||
if (gIsATI) {
|
||||
XVisualInfo vinfo_template;
|
||||
int nvisuals;
|
||||
vinfo_template.visual = widgetAttrs.visual;
|
||||
@ -415,18 +507,20 @@ GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
|
||||
}
|
||||
|
||||
int matchIndex = -1;
|
||||
ScopedXFree<XVisualInfo> vinfo;
|
||||
|
||||
for (int i = 0; i < numConfigs; i++) {
|
||||
ScopedXFree<XVisualInfo> info(sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]));
|
||||
if (!info) {
|
||||
vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]);
|
||||
if (!vinfo) {
|
||||
continue;
|
||||
}
|
||||
if (isATI) {
|
||||
if (AreCompatibleVisuals(vi, info)) {
|
||||
if (gIsATI) {
|
||||
if (AreCompatibleVisuals(vi, vinfo)) {
|
||||
matchIndex = i;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (widgetVisualID == info->visualid) {
|
||||
if (widgetVisualID == vinfo->visualid) {
|
||||
matchIndex = i;
|
||||
break;
|
||||
}
|
||||
@ -438,21 +532,155 @@ GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(display,
|
||||
GLContextGLX *shareContext = GetGlobalContextGLX();
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24),
|
||||
display,
|
||||
window,
|
||||
cfgs[matchIndex],
|
||||
vinfo,
|
||||
shareContext,
|
||||
PR_FALSE);
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderGLX::CreatePBuffer(const gfxIntSize &aSize, const ContextFormat& aFormat)
|
||||
static already_AddRefed<GLContextGLX>
|
||||
CreateOffscreenPixmapContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat,
|
||||
PRBool aShare)
|
||||
{
|
||||
if (!sGLXLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsTArray<int> attribs;
|
||||
Display *display = DefaultXDisplay();
|
||||
int xscreen = DefaultScreen(display);
|
||||
|
||||
int attribs[] = {
|
||||
GLX_DOUBLEBUFFER, False,
|
||||
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
||||
GLX_X_RENDERABLE, True,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_ALPHA_SIZE, 0,
|
||||
GLX_DEPTH_SIZE, 0,
|
||||
0
|
||||
};
|
||||
int numConfigs = 0;
|
||||
|
||||
ScopedXFree<GLXFBConfig> cfgs;
|
||||
cfgs = sGLXLibrary.xChooseFBConfig(display,
|
||||
xscreen,
|
||||
attribs,
|
||||
&numConfigs);
|
||||
if (!cfgs) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_ASSERTION(numConfigs > 0,
|
||||
"glXChooseFBConfig() failed to match our requested format and violated its spec (!)");
|
||||
|
||||
ScopedXFree<XVisualInfo> vinfo;
|
||||
int chosenIndex;
|
||||
|
||||
for (int i = 0; i < numConfigs; ++i) {
|
||||
int dtype, visid;
|
||||
|
||||
if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_DRAWABLE_TYPE, &dtype) != Success
|
||||
|| !(dtype & GLX_PIXMAP_BIT))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &visid) != Success
|
||||
|| visid == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]);
|
||||
|
||||
if (vinfo) {
|
||||
chosenIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vinfo) {
|
||||
NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
|
||||
vinfo->visual,
|
||||
gfxIntSize(16, 16));
|
||||
if (xsurface->CairoStatus() != 0) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
GLXPixmap glxpixmap = sGLXLibrary.xCreatePixmap(display,
|
||||
cfgs[chosenIndex],
|
||||
xsurface->XDrawable(),
|
||||
NULL);
|
||||
if (glxpixmap == 0) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
GLContextGLX *shareContext = aShare ? GetGlobalContextGLX() : nsnull;
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(aFormat,
|
||||
display,
|
||||
glxpixmap,
|
||||
cfgs[chosenIndex],
|
||||
vinfo,
|
||||
shareContext,
|
||||
PR_TRUE,
|
||||
xsurface);
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext =
|
||||
CreateOffscreenPixmapContext(aSize, aFormat, PR_TRUE);
|
||||
|
||||
if (!glContext) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!glContext->GetSharedContext()) {
|
||||
// no point in returning anything if sharing failed, we can't
|
||||
// render from this
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!glContext->ResizeOffscreenFBO(aSize)) {
|
||||
// we weren't able to create the initial
|
||||
// offscreen FBO, so this is dead
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderGLX::CreateForNativePixmapSurface(gfxASurface *aSurface)
|
||||
{
|
||||
if (!sGLXLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() != gfxASurface::SurfaceTypeXlib) {
|
||||
NS_WARNING("GLContextProviderGLX::CreateForNativePixmapSurface called with non-Xlib surface");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsAutoTArray<int, 20> attribs;
|
||||
|
||||
#define A1_(_x) do { attribs.AppendElement(_x); } while(0)
|
||||
#define A2_(_x,_y) do { \
|
||||
@ -460,20 +688,14 @@ GLContextProviderGLX::CreatePBuffer(const gfxIntSize &aSize, const ContextFormat
|
||||
attribs.AppendElement(_y); \
|
||||
} while(0)
|
||||
|
||||
A2_(GLX_DOUBLEBUFFER, False);
|
||||
A2_(GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT);
|
||||
A1_(0);
|
||||
|
||||
int numFormats;
|
||||
Display *display = DefaultXDisplay();
|
||||
int xscreen = DefaultScreen(display);
|
||||
|
||||
A2_(GLX_DOUBLEBUFFER, False);
|
||||
A2_(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
|
||||
|
||||
A2_(GLX_RED_SIZE, aFormat.red);
|
||||
A2_(GLX_GREEN_SIZE, aFormat.green);
|
||||
A2_(GLX_BLUE_SIZE, aFormat.blue);
|
||||
A2_(GLX_ALPHA_SIZE, aFormat.alpha);
|
||||
A2_(GLX_DEPTH_SIZE, aFormat.depth);
|
||||
A1_(0);
|
||||
|
||||
ScopedXFree<GLXFBConfig> cfg(sGLXLibrary.xChooseFBConfig(display,
|
||||
xscreen,
|
||||
attribs.Elements(),
|
||||
@ -483,35 +705,44 @@ GLContextProviderGLX::CreatePBuffer(const gfxIntSize &aSize, const ContextFormat
|
||||
}
|
||||
NS_ASSERTION(numFormats > 0,
|
||||
"glXChooseFBConfig() failed to match our requested format and violated its spec (!)");
|
||||
|
||||
nsTArray<int> pbattribs;
|
||||
pbattribs.AppendElement(GLX_PBUFFER_WIDTH);
|
||||
pbattribs.AppendElement(aSize.width);
|
||||
pbattribs.AppendElement(GLX_PBUFFER_HEIGHT);
|
||||
pbattribs.AppendElement(aSize.height);
|
||||
pbattribs.AppendElement(GLX_PRESERVED_CONTENTS);
|
||||
pbattribs.AppendElement(True);
|
||||
pbattribs.AppendElement(0);
|
||||
|
||||
GLXPbuffer pbuffer = sGLXLibrary.xCreatePbuffer(display,
|
||||
gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface);
|
||||
|
||||
GLXPixmap glxpixmap = sGLXLibrary.xCreatePixmap(display,
|
||||
cfg[0],
|
||||
pbattribs.Elements());
|
||||
xs->XDrawable(),
|
||||
NULL);
|
||||
|
||||
if (pbuffer == 0) {
|
||||
nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24),
|
||||
display,
|
||||
glxpixmap,
|
||||
cfg[0],
|
||||
NULL,
|
||||
NULL,
|
||||
PR_FALSE,
|
||||
xs);
|
||||
|
||||
if (!glContext->Init()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(display,
|
||||
pbuffer,
|
||||
cfg[0],
|
||||
PR_TRUE);
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderGLX::CreateForNativePixmapSurface(gfxASurface *aSurface)
|
||||
static nsRefPtr<GLContext> gGlobalContext;
|
||||
|
||||
GLContext *
|
||||
GLContextProviderGLX::GetGlobalContext()
|
||||
{
|
||||
return nsnull;
|
||||
static bool triedToCreateContext = false;
|
||||
if (!triedToCreateContext && !gGlobalContext) {
|
||||
triedToCreateContext = true;
|
||||
gGlobalContext = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
|
||||
ContextFormat(ContextFormat::BasicRGB24),
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
}
|
||||
|
||||
} /* namespace gl */
|
||||
|
@ -47,33 +47,65 @@ class THEBES_API GL_CONTEXT_PROVIDER_NAME
|
||||
public:
|
||||
/**
|
||||
* Create a context that renders to the surface of the widget that is
|
||||
* passed in.
|
||||
* passed in. The context is always created with an RGB pixel format,
|
||||
* with no alpha, depth or stencil. If any of those features are needed,
|
||||
* either use a framebuffer, or use CreateOffscreen.
|
||||
*
|
||||
* @param Widget whose surface to create a context for
|
||||
* @return Context to use for this window
|
||||
* This context will attempt to share resources with all other window
|
||||
* contexts. As such, it's critical that resources allocated that are not
|
||||
* needed by other contexts be deleted before the context is destroyed.
|
||||
*
|
||||
* The GetSharedContext() method will return non-null if sharing
|
||||
* was successful.
|
||||
*
|
||||
* Note: a context created for a widget /must not/ hold a strong
|
||||
* reference to the widget; otherwise a cycle can be created through
|
||||
* a GL layer manager.
|
||||
*
|
||||
* @param aWidget Widget whose surface to create a context for
|
||||
*
|
||||
* @return Context to use for the window
|
||||
*/
|
||||
static already_AddRefed<GLContext>
|
||||
CreateForWindow(nsIWidget *aWidget);
|
||||
|
||||
/**
|
||||
* Creates a PBuffer.
|
||||
* Create a context for offscreen rendering. The target of this
|
||||
* context should be treated as opaque -- it might be a FBO, or a
|
||||
* pbuffer, or some other construct. Users of this GLContext
|
||||
* should not bind framebuffer 0 directly, and instead should bind
|
||||
* the framebuffer returned by GetOffscreenFBO().
|
||||
*
|
||||
* @param aSize Size of the pbuffer to create
|
||||
* @param aFormat A ContextFormat describing the desired context attributes. Defaults to a basic RGBA32 context.
|
||||
* The offscreen context returned by this method will always have
|
||||
* the ability to be rendered into a context created by a window.
|
||||
* It might or might not share resources with the global context;
|
||||
* query GetSharedContext() for a non-null result to check. If
|
||||
* resource sharing can be avoided on the target platform, it will
|
||||
* be, in order to isolate the offscreen context.
|
||||
*
|
||||
* @return Context to use for this Pbuffer
|
||||
* @param aSize The initial size of this offscreen context.
|
||||
* @param aFormat The ContextFormat for this offscreen context.
|
||||
*
|
||||
* @return Context to use for offscreen rendering
|
||||
*/
|
||||
static already_AddRefed<GLContext>
|
||||
CreatePBuffer(const gfxIntSize &aSize,
|
||||
const ContextFormat& aFormat = ContextFormat::BasicRGBA32Format);
|
||||
CreateOffscreen(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat = ContextFormat::BasicRGBA32Format);
|
||||
|
||||
/**
|
||||
* Try to create a GL context from native surface for arbitrary gfxASurface
|
||||
* If surface not compatible this will return NULL
|
||||
*
|
||||
* @param aSurface surface to create a context for
|
||||
*
|
||||
* @return Context to use for this surface
|
||||
*/
|
||||
static already_AddRefed<GLContext>
|
||||
CreateForNativePixmapSurface(gfxASurface *aSurface);
|
||||
|
||||
/**
|
||||
* Get a pointer to the global context, creating it if it doesn't exist.
|
||||
*/
|
||||
static GLContext *
|
||||
GetGlobalContext();
|
||||
};
|
||||
|
@ -45,13 +45,20 @@ GLContextProviderNull::CreateForWindow(nsIWidget*)
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderNull::CreateForNativePixmapSurface(gfxASurface *aSurface)
|
||||
GLContextProviderNull::CreateOffscreen(const gfxIntSize&,
|
||||
const ContextFormat&)
|
||||
{
|
||||
return 0;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderNull::CreatePBuffer(const gfxIntSize &, const ContextFormat &)
|
||||
GLContextProviderNull::CreateForNativePixmapSurface(gfxASurface *)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
GLContext *
|
||||
GLContextProviderNull::GetGlobalContext()
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -153,8 +153,9 @@ OSMesaLibrary::EnsureInitialized()
|
||||
class GLContextOSMesa : public GLContext
|
||||
{
|
||||
public:
|
||||
GLContextOSMesa()
|
||||
: mThebesSurface(nsnull),
|
||||
GLContextOSMesa(const ContextFormat& aFormat)
|
||||
: GLContext(aFormat, PR_TRUE, nsnull),
|
||||
mThebesSurface(nsnull),
|
||||
mContext(nsnull)
|
||||
{
|
||||
}
|
||||
@ -165,25 +166,34 @@ public:
|
||||
sOSMesaLibrary.fDestroyContext(mContext);
|
||||
}
|
||||
|
||||
PRBool Init(const gfxIntSize &aSize, const ContextFormat& aFormat)
|
||||
GLContextType GetContextType() {
|
||||
return ContextTypeOSMesa;
|
||||
}
|
||||
|
||||
PRBool Init(const gfxIntSize &aSize)
|
||||
{
|
||||
int osmesa_format = -1;
|
||||
int gfxasurface_imageformat = -1;
|
||||
PRBool format_accepted = PR_FALSE;
|
||||
|
||||
if (aFormat.red == 8 && aFormat.green == 8 && aFormat.blue == 8) {
|
||||
if (aFormat.alpha == 8) {
|
||||
osmesa_format = OSMESA_BGRA;
|
||||
gfxasurface_imageformat = gfxASurface::ImageFormatARGB32;
|
||||
format_accepted = PR_TRUE;
|
||||
}
|
||||
else if (aFormat.alpha == 0) {
|
||||
if (mCreationFormat.red > 0 &&
|
||||
mCreationFormat.green > 0 &&
|
||||
mCreationFormat.blue > 0 &&
|
||||
mCreationFormat.red <= 8 &&
|
||||
mCreationFormat.green <= 8 &&
|
||||
mCreationFormat.blue <= 8)
|
||||
{
|
||||
if (mCreationFormat.alpha == 0) {
|
||||
// we can't use OSMESA_BGR because it is packed 24 bits per pixel.
|
||||
// So we use OSMESA_BGRA and have to use ImageFormatRGB24
|
||||
// to make sure that the dummy alpha channel is ignored.
|
||||
osmesa_format = OSMESA_BGRA;
|
||||
gfxasurface_imageformat = gfxASurface::ImageFormatRGB24;
|
||||
format_accepted = PR_TRUE;
|
||||
} else if (mCreationFormat.alpha <= 8) {
|
||||
osmesa_format = OSMESA_BGRA;
|
||||
gfxasurface_imageformat = gfxASurface::ImageFormatARGB32;
|
||||
format_accepted = PR_TRUE;
|
||||
}
|
||||
}
|
||||
if (!format_accepted) {
|
||||
@ -197,7 +207,7 @@ public:
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mContext = sOSMesaLibrary.fCreateContextExt(osmesa_format, aFormat.depth, aFormat.stencil, 0, NULL);
|
||||
mContext = sOSMesaLibrary.fCreateContextExt(osmesa_format, mCreationFormat.depth, mCreationFormat.stencil, 0, NULL);
|
||||
if (!mContext) {
|
||||
NS_WARNING("OSMesaCreateContextExt failed!");
|
||||
return PR_FALSE;
|
||||
@ -215,10 +225,10 @@ public:
|
||||
PRBool MakeCurrent()
|
||||
{
|
||||
PRBool succeeded
|
||||
= sOSMesaLibrary.fMakeCurrent (mContext, mThebesSurface->Data(),
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mThebesSurface->Width(),
|
||||
mThebesSurface->Height());
|
||||
= sOSMesaLibrary.fMakeCurrent(mContext, mThebesSurface->Data(),
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mThebesSurface->Width(),
|
||||
mThebesSurface->Height());
|
||||
NS_ASSERTION(succeeded, "Failed to make OSMesa context current!");
|
||||
|
||||
return succeeded;
|
||||
@ -252,25 +262,27 @@ GLContextProviderOSMesa::CreateForWindow(nsIWidget *aWidget)
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderOSMesa::CreateForNativePixmapSurface(gfxASurface *aSurface)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderOSMesa::CreatePBuffer(const gfxIntSize &aSize, const ContextFormat& aFormat)
|
||||
GLContextProviderOSMesa::CreateOffscreen(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
if (!sOSMesaLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextOSMesa> glContext = new GLContextOSMesa;
|
||||
nsRefPtr<GLContextOSMesa> glContext = new GLContextOSMesa(aFormat);
|
||||
|
||||
if (!glContext->Init(aSize, aFormat)) {
|
||||
if (!glContext->Init(aSize))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget().get();
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
GLContext *
|
||||
GLContextProviderOSMesa::GetGlobalContext()
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
} /* namespace gl */
|
||||
|
@ -49,9 +49,62 @@ namespace gl {
|
||||
|
||||
WGLLibrary sWGLLibrary;
|
||||
|
||||
static HWND gDummyWindow = 0;
|
||||
static HDC gDummyWindowDC = 0;
|
||||
static HANDLE gDummyWindowGLContext = 0;
|
||||
static HWND gSharedWindow = 0;
|
||||
static HDC gSharedWindowDC = 0;
|
||||
static HGLRC gSharedWindowGLContext = 0;
|
||||
static int gSharedWindowPixelFormat = 0;
|
||||
|
||||
static HWND
|
||||
CreateDummyWindow(HDC *aWindowDC = nsnull)
|
||||
{
|
||||
WNDCLASSW wc;
|
||||
if (!GetClassInfoW(GetModuleHandle(NULL), L"GLContextWGLClass", &wc)) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASSW));
|
||||
wc.style = CS_OWNDC;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = L"GLContextWGLClass";
|
||||
if (!RegisterClassW(&wc)) {
|
||||
NS_WARNING("Failed to register GLContextWGLClass?!");
|
||||
// er. failed to register our class?
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HWND win = CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0,
|
||||
0, 0, 16, 16,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
NS_ENSURE_TRUE(win, NULL);
|
||||
|
||||
HDC dc = GetDC(win);
|
||||
NS_ENSURE_TRUE(dc, NULL);
|
||||
|
||||
if (gSharedWindowPixelFormat == 0) {
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
pfd.cDepthBits = 0;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
gSharedWindowPixelFormat = ChoosePixelFormat(dc, &pfd);
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(dc, gSharedWindowPixelFormat, NULL)) {
|
||||
NS_WARNING("SetPixelFormat failed!");
|
||||
DestroyWindow(win);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (aWindowDC) {
|
||||
*aWindowDC = dc;
|
||||
}
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
PRBool
|
||||
WGLLibrary::EnsureInitialized()
|
||||
@ -74,6 +127,7 @@ WGLLibrary::EnsureInitialized()
|
||||
{ (PRFuncPtr*) &fDeleteContext, { "wglDeleteContext", NULL } },
|
||||
{ (PRFuncPtr*) &fGetCurrentContext, { "wglGetCurrentContext", NULL } },
|
||||
{ (PRFuncPtr*) &fGetCurrentDC, { "wglGetCurrentDC", NULL } },
|
||||
{ (PRFuncPtr*) &fShareLists, { "wglShareLists", NULL } },
|
||||
{ NULL, { NULL } }
|
||||
};
|
||||
|
||||
@ -82,61 +136,19 @@ WGLLibrary::EnsureInitialized()
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// This is ridiculous -- we have to actually create a context to get the OpenGL
|
||||
// ICD to load.
|
||||
|
||||
WNDCLASSW wc;
|
||||
if (!GetClassInfoW(GetModuleHandle(NULL), L"DummyGLWindowClass", &wc)) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASSW));
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = L"DummyGLWindowClass";
|
||||
if (!RegisterClassW(&wc)) {
|
||||
NS_WARNING("Failed to register DummyGLWindowClass?!");
|
||||
// er. failed to register our class?
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gDummyWindow = CreateWindowW(L"DummyGLWindowClass", L"DummyGLWindow", 0,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
if (!gDummyWindow) {
|
||||
NS_WARNING("CreateWindow DummyGLWindow failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
gDummyWindowDC = GetDC(gDummyWindow);
|
||||
if (!gDummyWindowDC) {
|
||||
NS_WARNING("GetDC gDummyWindow failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// find default pixel format
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
int pixelformat = ChoosePixelFormat(gDummyWindowDC, &pfd);
|
||||
|
||||
// set the pixel format for the dc
|
||||
if (!SetPixelFormat(gDummyWindowDC, pixelformat, &pfd)) {
|
||||
NS_WARNING("SetPixelFormat failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
// This is ridiculous -- we have to actually create a context to
|
||||
// get the OpenGL ICD to load.
|
||||
gSharedWindow = CreateDummyWindow(&gSharedWindowDC);
|
||||
NS_ENSURE_TRUE(gSharedWindow, PR_FALSE);
|
||||
|
||||
// create rendering context
|
||||
gDummyWindowGLContext = fCreateContext(gDummyWindowDC);
|
||||
if (!gDummyWindowGLContext) {
|
||||
NS_WARNING("wglCreateContext failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
gSharedWindowGLContext = fCreateContext(gSharedWindowDC);
|
||||
NS_ENSURE_TRUE(gSharedWindowGLContext, PR_FALSE);
|
||||
|
||||
HGLRC curCtx = fGetCurrentContext();
|
||||
HDC curDC = fGetCurrentDC();
|
||||
|
||||
if (!fMakeCurrent((HDC)gDummyWindowDC, (HGLRC)gDummyWindowGLContext)) {
|
||||
if (!fMakeCurrent((HDC)gSharedWindowDC, (HGLRC)gSharedWindowGLContext)) {
|
||||
NS_WARNING("wglMakeCurrent failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -177,33 +189,75 @@ WGLLibrary::EnsureInitialized()
|
||||
fMakeCurrent(curDC, curCtx);
|
||||
|
||||
mInitialized = PR_TRUE;
|
||||
|
||||
// Call this to create the global GLContext instance,
|
||||
// and to check for errors. Note that this must happen /after/
|
||||
// setting mInitialized to TRUE, or an infinite loop results.
|
||||
if (GLContextProviderWGL::GetGlobalContext() == nsnull) {
|
||||
mInitialized = PR_FALSE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
class GLContextWGL : public GLContext
|
||||
{
|
||||
public:
|
||||
GLContextWGL(HDC aDC, HGLRC aContext)
|
||||
: mContext(aContext), mDC(aDC), mPBuffer(nsnull), mPixelFormat(-1)
|
||||
{ }
|
||||
GLContextWGL(const ContextFormat& aFormat,
|
||||
GLContext *aSharedContext,
|
||||
HDC aDC,
|
||||
HGLRC aContext,
|
||||
HWND aWindow = nsnull,
|
||||
PRBool aIsOffscreen = PR_FALSE)
|
||||
: GLContext(aFormat, aIsOffscreen, aSharedContext),
|
||||
mDC(aDC),
|
||||
mContext(aContext),
|
||||
mWnd(aWindow),
|
||||
mPBuffer(NULL),
|
||||
mPixelFormat(0)
|
||||
{
|
||||
}
|
||||
|
||||
GLContextWGL(HANDLE aPBuffer, int aPixelFormat) {
|
||||
mPBuffer = aPBuffer;
|
||||
mPixelFormat = aPixelFormat;
|
||||
mDC = sWGLLibrary.fGetPbufferDC(mPBuffer);
|
||||
mContext = sWGLLibrary.fCreateContext(mDC);
|
||||
GLContextWGL(const ContextFormat& aFormat,
|
||||
GLContext *aSharedContext,
|
||||
HANDLE aPbuffer,
|
||||
HDC aDC,
|
||||
HGLRC aContext,
|
||||
int aPixelFormat)
|
||||
: GLContext(aFormat, PR_TRUE, aSharedContext),
|
||||
mDC(aDC),
|
||||
mContext(aContext),
|
||||
mWnd(NULL),
|
||||
mPBuffer(aPbuffer),
|
||||
mPixelFormat(aPixelFormat)
|
||||
{
|
||||
}
|
||||
|
||||
~GLContextWGL()
|
||||
{
|
||||
if (mOffscreenFBO) {
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
}
|
||||
|
||||
sWGLLibrary.fDeleteContext(mContext);
|
||||
|
||||
if (mPBuffer)
|
||||
sWGLLibrary.fDestroyPbuffer(mPBuffer);
|
||||
if (mWnd)
|
||||
DestroyWindow(mWnd);
|
||||
}
|
||||
|
||||
GLContextType GetContextType() {
|
||||
return ContextTypeWGL;
|
||||
}
|
||||
|
||||
PRBool Init()
|
||||
{
|
||||
if (!mDC || !mContext)
|
||||
return PR_FALSE;
|
||||
|
||||
MakeCurrent();
|
||||
SetupLookupFunction();
|
||||
return InitWithPrefix("gl", PR_TRUE);
|
||||
@ -237,34 +291,100 @@ public:
|
||||
case NativeGLContext:
|
||||
return mContext;
|
||||
|
||||
case NativePBuffer:
|
||||
return mPBuffer;
|
||||
|
||||
default:
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool Resize(const gfxIntSize& aNewSize) {
|
||||
if (!mPBuffer)
|
||||
PRBool BindTex2DOffscreen(GLContext *aOffscreen);
|
||||
void UnbindTex2DOffscreen(GLContext *aOffscreen);
|
||||
PRBool ResizeOffscreen(const gfxIntSize& aNewSize);
|
||||
|
||||
HGLRC Context() { return mContext; }
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
CreateBasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
GLContext* aContext);
|
||||
|
||||
protected:
|
||||
friend class GLContextProviderWGL;
|
||||
|
||||
HDC mDC;
|
||||
HGLRC mContext;
|
||||
HWND mWnd;
|
||||
HANDLE mPBuffer;
|
||||
int mPixelFormat;
|
||||
};
|
||||
|
||||
PRBool
|
||||
GLContextWGL::BindTex2DOffscreen(GLContext *aOffscreen)
|
||||
{
|
||||
if (aOffscreen->GetContextType() != ContextTypeWGL) {
|
||||
NS_WARNING("non-WGL context");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!aOffscreen->IsOffscreen()) {
|
||||
NS_WARNING("non-offscreen context");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
GLContextWGL *offs = static_cast<GLContextWGL*>(aOffscreen);
|
||||
|
||||
if (offs->mPBuffer) {
|
||||
BOOL ok = sWGLLibrary.fBindTexImage(offs->mPBuffer,
|
||||
LOCAL_WGL_FRONT_LEFT_ARB);
|
||||
if (!ok) {
|
||||
NS_WARNING("CanvasLayerOGL::Updated wglBindTexImageARB failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
} else if (offs->mOffscreenTexture) {
|
||||
if (offs->GetSharedContext() != GLContextProviderWGL::GetGlobalContext())
|
||||
{
|
||||
NS_WARNING("offscreen FBO context can only be bound with context sharing!");
|
||||
return PR_FALSE;
|
||||
|
||||
nsTArray<int> pbattribs;
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_FORMAT_ARB);
|
||||
// XXX fixme after bug 571092 lands and we have the format available
|
||||
if (true /*aFormat.alpha > 0*/) {
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_RGBA_ARB);
|
||||
} else {
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_RGB_ARB);
|
||||
}
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_TARGET_ARB);
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_2D_ARB);
|
||||
|
||||
pbattribs.AppendElement(0);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, offs->mOffscreenTexture);
|
||||
} else {
|
||||
NS_WARNING("don't know how to bind this!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
HANDLE newbuf = sWGLLibrary.fCreatePbuffer(gDummyWindowDC, mPixelFormat,
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
GLContextWGL::UnbindTex2DOffscreen(GLContext *aOffscreen)
|
||||
{
|
||||
NS_ASSERTION(aOffscreen->GetContextType() == ContextTypeWGL, "wrong type");
|
||||
|
||||
GLContextWGL *offs = static_cast<GLContextWGL*>(aOffscreen);
|
||||
if (offs->mPBuffer) {
|
||||
// XXX so, according to the extension, ReleaseTexImage is not required to
|
||||
// preserve color buffer contents. This sucks, but everywhere that I've
|
||||
// tried it the color buffer is preserved. So let's cross our fingers..
|
||||
sWGLLibrary.fReleaseTexImage(offs->mPBuffer, LOCAL_WGL_FRONT_LEFT_ARB);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
GLContextWGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
||||
{
|
||||
if (mPBuffer) {
|
||||
int pbattrs[] = {
|
||||
LOCAL_WGL_TEXTURE_FORMAT_ARB,
|
||||
mCreationFormat.alpha > 0 ? LOCAL_WGL_TEXTURE_RGBA_ARB
|
||||
: LOCAL_WGL_TEXTURE_RGB_ARB,
|
||||
LOCAL_WGL_TEXTURE_TARGET_ARB, LOCAL_WGL_TEXTURE_2D_ARB,
|
||||
0
|
||||
};
|
||||
|
||||
HANDLE newbuf = sWGLLibrary.fCreatePbuffer(gSharedWindowDC, mPixelFormat,
|
||||
aNewSize.width, aNewSize.height,
|
||||
pbattribs.Elements());
|
||||
pbattrs);
|
||||
if (!newbuf)
|
||||
return PR_FALSE;
|
||||
|
||||
@ -274,30 +394,28 @@ public:
|
||||
isCurrent = true;
|
||||
}
|
||||
|
||||
// hey, it worked!
|
||||
sWGLLibrary.fDestroyPbuffer(mPBuffer);
|
||||
|
||||
mPBuffer = newbuf;
|
||||
mDC = sWGLLibrary.fGetPbufferDC(mPBuffer);
|
||||
|
||||
if (isCurrent)
|
||||
MakeCurrent();
|
||||
mOffscreenSize = aNewSize;
|
||||
mOffscreenActualSize = aNewSize;
|
||||
|
||||
MakeCurrent();
|
||||
ClearSafely();
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
CreateBasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
GLContext* aContext);
|
||||
return ResizeOffscreenFBO(aNewSize);
|
||||
}
|
||||
|
||||
private:
|
||||
HGLRC mContext;
|
||||
HDC mDC;
|
||||
HANDLE mPBuffer;
|
||||
int mPixelFormat;
|
||||
};
|
||||
static GLContextWGL *
|
||||
GetGlobalContextWGL()
|
||||
{
|
||||
return static_cast<GLContextWGL*>(GLContextProviderWGL::GetGlobalContext());
|
||||
}
|
||||
|
||||
class TextureImageWGL : public BasicTextureImage
|
||||
{
|
||||
@ -351,6 +469,7 @@ GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget)
|
||||
if (!sWGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to make sure we call SetPixelFormat -after- calling
|
||||
* EnsureInitialized, otherwise it can load/unload the dll and
|
||||
@ -359,75 +478,77 @@ GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget)
|
||||
|
||||
HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC);
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
ZeroMemory(&pfd, sizeof(pfd));
|
||||
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cDepthBits = 0;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
int iFormat = ChoosePixelFormat(dc, &pfd);
|
||||
|
||||
SetPixelFormat(dc, iFormat, &pfd);
|
||||
SetPixelFormat(dc, gSharedWindowPixelFormat, NULL);
|
||||
HGLRC context = sWGLLibrary.fCreateContext(dc);
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextWGL> glContext = new GLContextWGL(dc, context);
|
||||
glContext->Init();
|
||||
GLContextWGL *shareContext = GetGlobalContextWGL();
|
||||
if (shareContext &&
|
||||
!sWGLLibrary.fShareLists(shareContext->Context(), context))
|
||||
{
|
||||
shareContext = nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget().get();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderWGL::CreatePBuffer(const gfxIntSize& aSize, const ContextFormat& aFormat)
|
||||
{
|
||||
if (!sWGLLibrary.EnsureInitialized()) {
|
||||
nsRefPtr<GLContextWGL> glContext = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24),
|
||||
shareContext, dc, context);
|
||||
if (!glContext->Init()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsTArray<int> attribs;
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
#define A1_(_x) do { attribs.AppendElement(_x); } while(0)
|
||||
#define A2_(_x,_y) do { \
|
||||
attribs.AppendElement(_x); \
|
||||
attribs.AppendElement(_y); \
|
||||
} while(0)
|
||||
static already_AddRefed<GLContextWGL>
|
||||
CreatePBufferOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
#define A1(_a,_x) do { _a.AppendElement(_x); } while(0)
|
||||
#define A2(_a,_x,_y) do { _a.AppendElement(_x); _a.AppendElement(_y); } while(0)
|
||||
|
||||
A2_(LOCAL_WGL_SUPPORT_OPENGL_ARB, LOCAL_GL_TRUE);
|
||||
A2_(LOCAL_WGL_DRAW_TO_PBUFFER_ARB, LOCAL_GL_TRUE);
|
||||
A2_(LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE);
|
||||
nsTArray<int> attrs;
|
||||
|
||||
A2_(LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB);
|
||||
A2(attrs, LOCAL_WGL_SUPPORT_OPENGL_ARB, LOCAL_GL_TRUE);
|
||||
A2(attrs, LOCAL_WGL_DRAW_TO_PBUFFER_ARB, LOCAL_GL_TRUE);
|
||||
A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE);
|
||||
|
||||
A2_(LOCAL_WGL_COLOR_BITS_ARB, aFormat.colorBits());
|
||||
A2_(LOCAL_WGL_RED_BITS_ARB, aFormat.red);
|
||||
A2_(LOCAL_WGL_GREEN_BITS_ARB, aFormat.green);
|
||||
A2_(LOCAL_WGL_BLUE_BITS_ARB, aFormat.blue);
|
||||
A2_(LOCAL_WGL_ALPHA_BITS_ARB, aFormat.alpha);
|
||||
A2(attrs, LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB);
|
||||
|
||||
A2_(LOCAL_WGL_DEPTH_BITS_ARB, aFormat.depth);
|
||||
A2(attrs, LOCAL_WGL_COLOR_BITS_ARB, aFormat.colorBits());
|
||||
A2(attrs, LOCAL_WGL_RED_BITS_ARB, aFormat.red);
|
||||
A2(attrs, LOCAL_WGL_GREEN_BITS_ARB, aFormat.green);
|
||||
A2(attrs, LOCAL_WGL_BLUE_BITS_ARB, aFormat.blue);
|
||||
A2(attrs, LOCAL_WGL_ALPHA_BITS_ARB, aFormat.alpha);
|
||||
|
||||
if (aFormat.alpha > 0)
|
||||
A2_(LOCAL_WGL_BIND_TO_TEXTURE_RGBA_ARB, LOCAL_GL_TRUE);
|
||||
else
|
||||
A2_(LOCAL_WGL_BIND_TO_TEXTURE_RGB_ARB, LOCAL_GL_TRUE);
|
||||
A2(attrs, LOCAL_WGL_DEPTH_BITS_ARB, aFormat.depth);
|
||||
|
||||
A2_(LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE);
|
||||
A2_(LOCAL_WGL_STEREO_ARB, LOCAL_GL_FALSE);
|
||||
if (aFormat.alpha > 0) {
|
||||
A2(attrs, LOCAL_WGL_BIND_TO_TEXTURE_RGBA_ARB, LOCAL_GL_TRUE);
|
||||
} else {
|
||||
A2(attrs, LOCAL_WGL_BIND_TO_TEXTURE_RGB_ARB, LOCAL_GL_TRUE);
|
||||
}
|
||||
|
||||
A1_(0);
|
||||
A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE);
|
||||
A2(attrs, LOCAL_WGL_STEREO_ARB, LOCAL_GL_FALSE);
|
||||
|
||||
#define MAX_NUM_FORMATS 256
|
||||
UINT numFormats = MAX_NUM_FORMATS;
|
||||
int formats[MAX_NUM_FORMATS];
|
||||
A1(attrs, 0);
|
||||
|
||||
if (!sWGLLibrary.fChoosePixelFormat(gDummyWindowDC,
|
||||
attribs.Elements(), NULL,
|
||||
nsTArray<int> pbattrs;
|
||||
A2(pbattrs, LOCAL_WGL_TEXTURE_TARGET_ARB, LOCAL_WGL_TEXTURE_2D_ARB);
|
||||
|
||||
if (aFormat.alpha > 0) {
|
||||
A2(pbattrs, LOCAL_WGL_TEXTURE_FORMAT_ARB, LOCAL_WGL_TEXTURE_RGBA_ARB);
|
||||
} else {
|
||||
A2(pbattrs, LOCAL_WGL_TEXTURE_FORMAT_ARB, LOCAL_WGL_TEXTURE_RGB_ARB);
|
||||
}
|
||||
A1(pbattrs, 0);
|
||||
|
||||
UINT numFormats = 256;
|
||||
int formats[256];
|
||||
|
||||
if (!sWGLLibrary.fChoosePixelFormat(gSharedWindowDC,
|
||||
attrs.Elements(), NULL,
|
||||
numFormats, formats, &numFormats)
|
||||
|| numFormats == 0)
|
||||
{
|
||||
@ -437,33 +558,106 @@ GLContextProviderWGL::CreatePBuffer(const gfxIntSize& aSize, const ContextFormat
|
||||
// XXX add back the priority choosing code here
|
||||
int chosenFormat = formats[0];
|
||||
|
||||
nsTArray<int> pbattribs;
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_FORMAT_ARB);
|
||||
if (aFormat.alpha > 0) {
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_RGBA_ARB);
|
||||
} else {
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_RGB_ARB);
|
||||
}
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_TARGET_ARB);
|
||||
pbattribs.AppendElement(LOCAL_WGL_TEXTURE_2D_ARB);
|
||||
|
||||
// hmm, do we need mipmaps?
|
||||
//pbattribs.AppendElement(LOCAL_WGL_MIPMAP_TEXTURE_ARB);
|
||||
//pbattribs.AppendElement(LOCAL_GL_TRUE);
|
||||
|
||||
pbattribs.AppendElement(0);
|
||||
|
||||
HANDLE pbuffer = sWGLLibrary.fCreatePbuffer(gDummyWindowDC, chosenFormat,
|
||||
HANDLE pbuffer = sWGLLibrary.fCreatePbuffer(gSharedWindowDC, chosenFormat,
|
||||
aSize.width, aSize.height,
|
||||
pbattribs.Elements());
|
||||
pbattrs.Elements());
|
||||
if (!pbuffer) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextWGL> glContext = new GLContextWGL(pbuffer, chosenFormat);
|
||||
glContext->Init();
|
||||
HDC pbdc = sWGLLibrary.fGetPbufferDC(pbuffer);
|
||||
NS_ASSERTION(pbdc, "expected a dc");
|
||||
|
||||
return glContext.forget().get();
|
||||
HGLRC context = sWGLLibrary.fCreateContext(pbdc);
|
||||
if (!context) {
|
||||
sWGLLibrary.fDestroyPbuffer(pbuffer);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextWGL> glContext = new GLContextWGL(aFormat,
|
||||
nsnull,
|
||||
pbuffer,
|
||||
pbdc,
|
||||
context,
|
||||
chosenFormat);
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContextWGL>
|
||||
CreateWindowOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
// CreateWindowOffscreenContext must return a global-shared context
|
||||
GLContextWGL *shareContext = GetGlobalContextWGL();
|
||||
if (!shareContext) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
HDC dc;
|
||||
HWND win = CreateDummyWindow(&dc);
|
||||
if (!win) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
HGLRC context = sWGLLibrary.fCreateContext(dc);
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!sWGLLibrary.fShareLists(shareContext->Context(), context)) {
|
||||
NS_WARNING("wglShareLists failed!");
|
||||
|
||||
sWGLLibrary.fDeleteContext(context);
|
||||
DestroyWindow(win);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextWGL> glContext = new GLContextWGL(aFormat, shareContext,
|
||||
dc, context, win, PR_TRUE);
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
if (!sWGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextWGL> glContext;
|
||||
|
||||
// Always try to create a pbuffer context first, because we
|
||||
// want the context isolation.
|
||||
if (sWGLLibrary.fCreatePbuffer &&
|
||||
sWGLLibrary.fChoosePixelFormat)
|
||||
{
|
||||
glContext = CreatePBufferOffscreenContext(aSize, aFormat);
|
||||
}
|
||||
|
||||
// If it failed, then create a window context and use a FBO.
|
||||
if (!glContext) {
|
||||
glContext = CreateWindowOffscreenContext(aSize, aFormat);
|
||||
}
|
||||
|
||||
if (!glContext ||
|
||||
!glContext->Init())
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
glContext->mOffscreenSize = aSize;
|
||||
glContext->mOffscreenActualSize = aSize;
|
||||
|
||||
if (!glContext->mPBuffer &&
|
||||
!glContext->ResizeOffscreenFBO(aSize))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
@ -472,5 +666,32 @@ GLContextProviderWGL::CreateForNativePixmapSurface(gfxASurface *aSurface)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static nsRefPtr<GLContextWGL> gGlobalContext;
|
||||
|
||||
GLContext *
|
||||
GLContextProviderWGL::GetGlobalContext()
|
||||
{
|
||||
if (!sWGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static bool triedToCreateContext = false;
|
||||
|
||||
if (!triedToCreateContext && !gGlobalContext) {
|
||||
triedToCreateContext = true;
|
||||
|
||||
// conveniently, we already have what we need...
|
||||
gGlobalContext = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24), nsnull,
|
||||
gSharedWindowDC, gSharedWindowGLContext);
|
||||
if (!gGlobalContext->Init()) {
|
||||
NS_WARNING("Global context GLContext initialization failed?");
|
||||
gGlobalContext = nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<GLContext*>(gGlobalContext);
|
||||
}
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
@ -100,6 +100,23 @@ public:
|
||||
int);
|
||||
PFNGLXQUERYSERVERSTRING xQueryServerString;
|
||||
|
||||
typedef GLXPixmap (GLAPIENTRY * PFNGLXCREATEPIXMAP) (Display *,
|
||||
GLXFBConfig,
|
||||
Pixmap,
|
||||
const int *);
|
||||
PFNGLXCREATEPIXMAP xCreatePixmap;
|
||||
typedef void (GLAPIENTRY * PFNGLXDESTROYPIXMAP) (Display *,
|
||||
GLXPixmap);
|
||||
PFNGLXDESTROYPIXMAP xDestroyPixmap;
|
||||
typedef const char * (GLAPIENTRY * PFNGLXGETCLIENTSTRING) (Display *,
|
||||
int);
|
||||
PFNGLXGETCLIENTSTRING xGetClientString;
|
||||
typedef GLXContext (GLAPIENTRY * PFNGLXCREATECONTEXT) (Display *,
|
||||
XVisualInfo *,
|
||||
GLXContext,
|
||||
Bool);
|
||||
PFNGLXCREATECONTEXT xCreateContext;
|
||||
|
||||
PRBool EnsureInitialized();
|
||||
|
||||
private:
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
PFNWGLGETCURRENTCONTEXT fGetCurrentContext;
|
||||
typedef HDC (GLAPIENTRY * PFNWGLGETCURRENTDC) (void);
|
||||
PFNWGLGETCURRENTDC fGetCurrentDC;
|
||||
typedef BOOL (GLAPIENTRY * PFNWGLSHARELISTS) (HGLRC oldContext, HGLRC newContext);
|
||||
PFNWGLSHARELISTS fShareLists;
|
||||
|
||||
typedef HANDLE (WINAPI * PFNWGLCREATEPBUFFERPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
|
||||
PFNWGLCREATEPBUFFERPROC fCreatePbuffer;
|
||||
|
Loading…
Reference in New Issue
Block a user