b=574481; fix layers lifetime issues; part 2 - add some utils to GLContext; r=bas

This commit is contained in:
Vladimir Vukicevic 2010-08-06 22:09:18 -07:00
parent 956826cf56
commit 781c3188c7
7 changed files with 216 additions and 116 deletions

View File

@ -668,6 +668,143 @@ GLContext::UpdateActualFormat()
// TODO
}
void
GLContext::MarkDestroyed()
{
MakeCurrent();
DeleteOffscreenFBO();
memset(&mFunctionListStartSentinel, 0, &mFunctionListEndSentinel - &mFunctionListStartSentinel);
}
already_AddRefed<gfxImageSurface>
GLContext::ReadTextureImage(GLuint aTexture,
const gfxIntSize& aSize,
GLenum aTextureFormat)
{
MakeCurrent();
nsRefPtr<gfxImageSurface> isurf;
GLint oldrb, oldfb, oldprog, oldvp[4], oldPackAlignment;
GLint success;
GLuint rb = 0, fb = 0;
GLuint vs = 0, fs = 0, prog = 0;
const char *vShader =
"attribute vec4 aVertex;\n"
"attribute vec2 aTexCoord;\n"
"varying vec2 vTexCoord;\n"
"void main() { gl_Position = aVertex; vTexCoord = aTexCoord; }";
const char *fShader =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec2 vTexCoord;\n"
"uniform sampler2D uTexture;\n"
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
float verts[4*4] = {
-1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f
};
float texcoords[2*4] = {
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
};
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
fGetIntegerv(LOCAL_GL_VIEWPORT, oldvp);
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &oldPackAlignment);
fGenRenderbuffers(1, &rb);
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, LOCAL_GL_RGBA,
aSize.width, aSize.height);
fGenFramebuffers(1, &fb);
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
LOCAL_GL_RENDERBUFFER, rb);
if (fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) !=
LOCAL_GL_FRAMEBUFFER_COMPLETE)
{
goto cleanup;
}
vs = fCreateShader(LOCAL_GL_VERTEX_SHADER);
fs = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
fShaderSource(vs, 1, (const GLchar**) &vShader, NULL);
fShaderSource(fs, 1, (const GLchar**) &fShader, NULL);
prog = fCreateProgram();
fAttachShader(prog, vs);
fAttachShader(prog, fs);
fBindAttribLocation(prog, 0, "aVertex");
fBindAttribLocation(prog, 1, "aTexCoord");
fLinkProgram(prog);
fGetProgramiv(prog, LOCAL_GL_LINK_STATUS, &success);
if (!success) {
goto cleanup;
}
fUseProgram(prog);
fEnableVertexAttribArray(0);
fEnableVertexAttribArray(1);
fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, verts);
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, texcoords);
fActiveTexture(LOCAL_GL_TEXTURE0);
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
fUniform1i(fGetUniformLocation(prog, "uTexture"), 0);
fViewport(0, 0, aSize.width, aSize.height);
fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
fDisableVertexAttribArray(1);
fDisableVertexAttribArray(0);
isurf = new gfxImageSurface(aSize, gfxASurface::ImageFormatARGB32);
if (!isurf || isurf->CairoStatus()) {
isurf = nsnull;
goto cleanup;
}
if (oldPackAlignment != 4)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
fReadPixels(0, 0, aSize.width, aSize.height,
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
isurf->Data());
if (oldPackAlignment != 4)
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, oldPackAlignment);
cleanup:
// note that deleting 0 has no effect in any of these calls
fDeleteRenderbuffers(1, &rb);
fDeleteFramebuffers(1, &fb);
fDeleteShader(vs);
fDeleteShader(fs);
fDeleteProgram(prog);
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
fUseProgram(oldprog);
fViewport(oldvp[0], oldvp[1], oldvp[2], oldvp[3]);
return isurf.forget();
}
#ifdef DEBUG
void

View File

@ -385,6 +385,10 @@ public:
mUserData.Put(aKey, aValue);
}
// Mark this context as destroyed. This will NULL out all
// the GL function pointers!
void MarkDestroyed();
enum NativeDataType {
NativeGLContext,
NativeImageSurface,
@ -395,6 +399,9 @@ public:
virtual void *GetNativeData(NativeDataType aType) { return NULL; }
GLContext *GetSharedContext() { return mSharedContext; }
PRBool IsGlobalSharedContext() { return mIsGlobalSharedContext; }
void SetIsGlobalSharedContext(PRBool aIsOne) { mIsGlobalSharedContext = aIsOne; }
const ContextFormat& CreationFormat() { return mCreationFormat; }
const ContextFormat& ActualFormat() { return mActualFormat; }
@ -428,20 +435,6 @@ public:
*/
virtual PRBool ReleaseTexImage() { return PR_FALSE; }
virtual GLuint CreateTexture()
{
GLuint tex;
MakeCurrent();
fGenTextures(1, &tex);
return tex;
}
virtual void DestroyTexture(GLuint tex)
{
MakeCurrent();
fDeleteTextures(1, &tex);
}
/*
* Offscreen support API
*/
@ -554,10 +547,26 @@ public:
GLint aWrapMode,
PRBool aUseNearestFilter=PR_FALSE);
/**
* Read the image data contained in aTexture, and return it as an ImageSurface.
* If GL_RGBA is given as the format, a ImageFormatARGB32 surface is returned.
* Not implemented yet:
* If GL_RGB is given as the format, a ImageFormatRGB24 surface is returned.
* If GL_LUMINANCE is given as the format, a ImageFormatA8 surface is returned.
*
* THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
* if you absolutely positively must, and never in any performance
* critical path.
*/
already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTexture,
const gfxIntSize& aSize,
GLenum aTextureFormat);
protected:
PRPackedBool mInitialized;
PRPackedBool mIsOffscreen;
PRPackedBool mIsGLES2;
PRPackedBool mIsGlobalSharedContext;
ContextFormat mCreationFormat;
nsRefPtr<GLContext> mSharedContext;
@ -607,6 +616,9 @@ public:
* perl-or-python-or-js script somewhere and would be
* autogenerated; one would be wrong.
*/
// Keep this at the start of the function pointers
void *mFunctionListStartSentinel;
typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
PFNGLACTIVETEXTUREPROC fActiveTexture;
typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
@ -851,6 +863,9 @@ public:
typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage;
// keep this at the end of the function pointers
void *mFunctionListEndSentinel;
void fDepthRange(GLclampf a, GLclampf b) {
if (mIsGLES2) {
priv_fDepthRangef(a, b);
@ -963,127 +978,73 @@ public:
priv_fDeleteRenderbuffers(n, names);
}
#else
GLContext *TrackingContext() {
GLContext *tip = this;
while (tip->mSharedContext)
tip = tip->mSharedContext;
return tip;
}
GLuint GLAPIENTRY fCreateProgram() {
GLuint ret = priv_fCreateProgram();
if (mSharedContext) {
GLContext *tip = mSharedContext;
while (tip->mSharedContext)
tip = tip->mSharedContext;
tip->CreatedProgram(this, ret);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->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);
}
TrackingContext()->DeletedRenderbuffers(this, n, names);
}
void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);

View File

@ -520,6 +520,8 @@ GLContextProviderCGL::GetGlobalContext()
gGlobalContext = nsnull;
return nsnull;
}
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
}
return gGlobalContext;

View File

@ -410,6 +410,11 @@ public:
~GLContextEGL()
{
if (mOffscreenFBO) {
MakeCurrent();
DeleteOffscreenFBO();
}
// If mGLWidget is non-null, then we've been given it by the GL context provider,
// and it's managed by the widget implementation. In this case, We can't destroy
// our contexts.
@ -1291,6 +1296,8 @@ GLContextProviderEGL::GetGlobalContext()
if (!triedToCreateContext && !gGlobalContext) {
triedToCreateContext = true;
gGlobalContext = CreateOffscreen(gfxIntSize(16, 16));
if (gGlobalContext)
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
}
return gGlobalContext;

View File

@ -225,6 +225,11 @@ TRY_AGAIN_NO_SHARING:
~GLContextGLX()
{
if (mOffscreenFBO) {
MakeCurrent();
DeleteOffscreenFBO();
}
sGLXLibrary.xDeleteContext(mDisplay, mContext);
if (mDeleteDrawable) {
@ -287,34 +292,6 @@ TRY_AGAIN_NO_SHARING:
return PR_TRUE;
}
void WindowDestroyed()
{
for (unsigned int i=0; i<textures.Length(); i++) {
GLContext::DestroyTexture(textures.ElementAt(i));
}
textures.Clear();
}
// NB: we could set a flag upon WindowDestroyed() to dictate an
// early-return from CreateTexture(), but then we would need the
// same check before all GL calls, and that heads down a rabbit
// hole.
virtual GLuint CreateTexture()
{
GLuint tex = GLContext::CreateTexture();
NS_ASSERTION(!textures.Contains(tex), "");
textures.AppendElement(tex);
return tex;
}
virtual void DestroyTexture(GLuint texture)
{
if (textures.Contains(texture)) {
textures.RemoveElement(texture);
GLContext::DestroyTexture(texture);
}
}
virtual already_AddRefed<TextureImage>
CreateBasicTextureImage(GLuint aTexture,
const nsIntSize& aSize,
@ -347,7 +324,6 @@ private:
PRPackedBool mDeleteDrawable;
PRPackedBool mDoubleBuffered;
nsTArray<GLuint> textures;
nsRefPtr<gfxXlibSurface> mPixmap;
};
@ -740,6 +716,8 @@ GLContextProviderGLX::GetGlobalContext()
gGlobalContext = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
ContextFormat(ContextFormat::BasicRGB24),
PR_FALSE);
if (gGlobalContext)
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
}
return gGlobalContext;

View File

@ -87,6 +87,10 @@ CreateDummyWindow(HDC *aWindowDC = nsnull)
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cRedBits = 8;
pfd.cGreenBits = 8;
pfd.cBlueBits = 8;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
@ -688,6 +692,8 @@ GLContextProviderWGL::GetGlobalContext()
gGlobalContext = nsnull;
return PR_FALSE;
}
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
}
return static_cast<GLContext*>(gGlobalContext);

View File

@ -116,6 +116,15 @@ public:
GLXContext,
Bool);
PFNGLXCREATECONTEXT xCreateContext;
typedef int (GLAPIENTRY * PFNGLXGETCONFIG) (Display *,
XVisualInfo *,
int,
int *);
PFNGLXGETCONFIG xGetConfig;
typedef GLXPixmap (GLAPIENTRY * PFNGLXCREATEGLXPIXMAP) (Display *,
XVisualInfo *,
Pixmap);
PFNGLXCREATEGLXPIXMAP xCreateGLXPixmap;
PRBool EnsureInitialized();