Bug 573929: Prevent GLX textures from being released after the window supplying the GLContext from which they were allocated dies. r=vlad

This commit is contained in:
Matt Woodrow 2010-06-23 18:37:00 -05:00
Родитель 8ff0a90b04
Коммит e196cc7eda
4 изменённых файлов: 65 добавлений и 10 удалений

Просмотреть файл

@ -60,8 +60,7 @@ public:
}
NS_IMETHOD Run() {
if (mTexture) {
mContext->MakeCurrent();
mContext->fDeleteTextures(1, &mTexture);
mContext->DestroyTexture(mTexture);
}
// Ensure context is released on the main thread
mContext = nsnull;
@ -80,8 +79,7 @@ GLTexture::Allocate(GLContext *aContext)
Release();
mContext = aContext;
mContext->MakeCurrent();
mContext->fGenTextures(1, &mTexture);
mTexture = mContext->CreateTexture();
}
void
@ -104,8 +102,7 @@ GLTexture::Release()
if (NS_IsMainThread()) {
if (mTexture) {
mContext->MakeCurrent();
mContext->fDeleteTextures(1, &mTexture);
mContext->DestroyTexture(mTexture);
mTexture = 0;
}
mContext = nsnull;

Просмотреть файл

@ -129,6 +129,8 @@ public:
virtual PRBool MakeCurrent() = 0;
virtual PRBool SetupLookupFunction() = 0;
virtual void WindowDestroyed() {}
void *GetUserData(void *aKey) {
void *result = nsnull;
mUserData.Get(aKey, &result);
@ -173,6 +175,20 @@ public:
* Releases a color buffer that is being used as a texture
*/
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);
}
protected:
PRBool mInitialized;

Просмотреть файл

@ -213,6 +213,34 @@ public:
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);
}
}
private:
GLContextGLX(Display *aDisplay, GLXDrawable aWindow, GLXContext aContext, PRBool aPBuffer = PR_FALSE, PRBool aDoubleBuffered=PR_FALSE)
: mContext(aContext),
@ -226,6 +254,7 @@ private:
GLXDrawable mWindow;
PRBool mPBuffer;
PRBool mDoubleBuffered;
nsTArray<GLuint> textures;
};
static PRBool AreCompatibleVisuals(XVisualInfo *one, XVisualInfo *two)

Просмотреть файл

@ -149,6 +149,9 @@ D_DEBUG_DOMAIN( ns_Window, "nsWindow", "nsWindow" );
#define GDK_WINDOW_XWINDOW(_win) _win
#endif
using mozilla::gl::GLContext;
using mozilla::layers::LayerManagerOGL;
// Don't put more than this many rects in the dirty region, just fluff
// out to the bounding-box if there are more
#define MAX_RECTS_IN_REGION 100
@ -718,13 +721,20 @@ nsWindow::Destroy(void)
if (mIsDestroyed || !mCreated)
return NS_OK;
/** Need to clean our LayerManager up while still alive */
mLayerManager = NULL;
LOG(("nsWindow::Destroy [%p]\n", (void *)this));
mIsDestroyed = PR_TRUE;
mCreated = PR_FALSE;
nsRefPtr<GLContext> gl;
if (GetLayerManager()->GetBackendType() == LayerManager::LAYERS_OPENGL)
{
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(GetLayerManager());
gl = manager->gl();
}
/** Need to clean our LayerManager up while still alive */
mLayerManager = NULL;
if (gUseBufferPixmap &&
gBufferPixmapUsageCount &&
--gBufferPixmapUsageCount == 0)
@ -812,6 +822,9 @@ nsWindow::Destroy(void)
gdk_window_set_user_data(mGdkWindow, NULL);
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", NULL);
if (gl) {
gl->WindowDestroyed();
}
gdk_window_destroy(mGdkWindow);
mGdkWindow = nsnull;
}
@ -2362,7 +2375,7 @@ nsWindow::OnExposeEvent(GtkWidget *aWidget, GdkEventExpose *aEvent)
if (GetLayerManager()->GetBackendType() == LayerManager::LAYERS_OPENGL)
{
mozilla::layers::LayerManagerOGL *manager = static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager());
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(GetLayerManager());
manager->SetClippingRegion(event.region);
nsEventStatus status;