Avoid leaking render targets in debugger
authorkkinnunen <kkinnunen@nvidia.com>
Mon, 22 Dec 2014 14:06:41 +0000 (06:06 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 22 Dec 2014 14:06:41 +0000 (06:06 -0800)
Render targets were not unreffed when QGLWidget::resizeGL was called.

Review URL: https://codereview.chromium.org/817243002

debugger/QT/SkGLWidget.cpp
debugger/QT/SkGLWidget.h

index bd24d4e..7b2a918 100644 (file)
 
 SkGLWidget::SkGLWidget(SkDebugger* debugger) : QGLWidget() {
     fDebugger = debugger;
-    fCurIntf = NULL;
-    fCurContext = NULL;
-    fGpuDevice = NULL;
-    fCanvas = NULL;
 }
 
 SkGLWidget::~SkGLWidget() {
-    SkSafeUnref(fCurIntf);
-    SkSafeUnref(fCurContext);
-    SkSafeUnref(fGpuDevice);
-    SkSafeUnref(fCanvas);
 }
 
-void SkGLWidget::setSampleCount(int sampleCount)
-{
+void SkGLWidget::setSampleCount(int sampleCount) {
     QGLFormat currentFormat = format();
     currentFormat.setSampleBuffers(sampleCount > 0);
     currentFormat.setSamples(sampleCount);
@@ -35,48 +26,59 @@ void SkGLWidget::setSampleCount(int sampleCount)
 }
 
 void SkGLWidget::initializeGL() {
-    fCurIntf = GrGLCreateNativeInterface();
+    if (!fCurIntf) {
+        fCurIntf.reset(GrGLCreateNativeInterface());
+    }
     if (!fCurIntf) {
         return;
     }
+    if (!fCurContext) {
+        fCurContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) fCurIntf.get()));
+    }
+    if (!fCurContext) {
+        return;
+    }
+
+    // The call may come multiple times, for example after setSampleCount().  The QGLContext will be
+    // different, but we do not have a mechanism to catch the destroying of QGLContext, so that
+    // proper resource cleanup could be made. Instead, we assume that the underlying GL context
+    // never actually changes. If it would, we could not destroy the resources.
+    fGpuDevice.reset(NULL);
+    fCanvas.reset(NULL);
+}
+
+void SkGLWidget::createRenderTarget() {
+    if (!fCurContext) {
+        return;
+    }
+
+    glDisable(GL_SCISSOR_TEST);
     glStencilMask(0xffffffff);
     glClearStencil(0);
     glClear(GL_STENCIL_BUFFER_BIT);
+    fCurContext->resetContext();
+
+    fGpuDevice.reset(NULL);
+    fCanvas.reset(NULL);
 
-    fCurContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) fCurIntf);
     GrBackendRenderTargetDesc desc = this->getDesc(this->width(), this->height());
     desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
-    GrRenderTarget* curRenderTarget = fCurContext->wrapBackendRenderTarget(desc);
-    fGpuDevice = SkGpuDevice::Create(curRenderTarget,
-                                     SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
-    fCanvas = new SkCanvas(fGpuDevice);
-    curRenderTarget->unref();
+    SkAutoTUnref<GrRenderTarget> curRenderTarget(fCurContext->wrapBackendRenderTarget(desc));
+    fGpuDevice.reset(SkGpuDevice::Create(curRenderTarget.get(),
+                                         SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)));
+    fCanvas.reset(new SkCanvas(fGpuDevice));
 }
 
 void SkGLWidget::resizeGL(int w, int h) {
-    if (fCurContext) {
-        glDisable(GL_SCISSOR_TEST);
-        glStencilMask(0xffffffff);
-        glClearStencil(0);
-        glClear(GL_STENCIL_BUFFER_BIT);
-        fCurContext->resetContext();
-
-        GrBackendRenderTargetDesc desc = this->getDesc(w, h);
-        desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
-        GrRenderTarget* curRenderTarget = fCurContext->wrapBackendRenderTarget(desc);
-        SkSafeUnref(fGpuDevice);
-        SkSafeUnref(fCanvas);
-        fGpuDevice = SkGpuDevice::Create(curRenderTarget,
-                                         SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
-        fCanvas = new SkCanvas(fGpuDevice);
-    }
+    SkASSERT(w == this->width() && h == this->height());
+    this->createRenderTarget();
     fDebugger->setWindowSize(w, h);
     draw();
 }
 
 void SkGLWidget::paintGL() {
     if (!this->isHidden() && fCanvas) {
-        fDebugger->draw(fCanvas);
+        fDebugger->draw(fCanvas.get());
         // TODO(chudy): Implement an optional flush button in Gui.
         fCanvas->flush();
         emit drawComplete();
index a8e4604..d78ff97 100644 (file)
@@ -45,10 +45,11 @@ protected:
 
 
 private:
-    const GrGLInterface* fCurIntf;
-    GrContext* fCurContext;
-    SkGpuDevice* fGpuDevice;
-    SkCanvas* fCanvas;
+    void createRenderTarget();
+    SkAutoTUnref<const GrGLInterface> fCurIntf;
+    SkAutoTUnref<GrContext> fCurContext;
+    SkAutoTUnref<SkGpuDevice> fGpuDevice;
+    SkAutoTUnref<SkCanvas> fCanvas;
     SkDebugger* fDebugger;
     GrBackendRenderTargetDesc getDesc(int w, int h);
 };