зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
8ff0a90b04
Коммит
e196cc7eda
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче