mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
b=574481; fix layers lifetime issues; part 2 - add some utils to GLContext; r=bas
This commit is contained in:
parent
956826cf56
commit
781c3188c7
@ -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
|
||||
|
@ -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);
|
||||
|
@ -520,6 +520,8 @@ GLContextProviderCGL::GetGlobalContext()
|
||||
gGlobalContext = nsnull;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user