Bug 627656 - Rather than creating a new texture for the resizer every draw and then deleting it once we're done, create a texture once on our first draw, then hold on to it until our widget is deleted. r=jrmuizel,mattwoodrow a=jrmuizel
authorJoe Drew <joe@drew.ca>
Sat, 19 Feb 2011 17:23:02 -0500
changeset 62871 3e52c6d7f7283cc0921d19a74bf4867fdd8777d0
parent 62870 c22790bab37ac767d7bb098974443c9ed5c905a3
child 62872 61ab16f6fa0b35e9bd2008f6f883067b8a1603d2
push id18923
push usermwoodrow@mozilla.com
push dateSat, 19 Feb 2011 22:42:01 +0000
treeherdermozilla-central@3e52c6d7f728 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, mattwoodrow, jrmuizel
bugs627656
milestone2.0b12pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 627656 - Rather than creating a new texture for the resizer every draw and then deleting it once we're done, create a texture once on our first draw, then hold on to it until our widget is deleted. r=jrmuizel,mattwoodrow a=jrmuizel
widget/src/cocoa/nsChildView.h
widget/src/cocoa/nsChildView.mm
--- a/widget/src/cocoa/nsChildView.h
+++ b/widget/src/cocoa/nsChildView.h
@@ -66,16 +66,22 @@
 #import <Cocoa/Cocoa.h>
 #import <AppKit/NSOpenGL.h>
 
 class gfxASurface;
 class nsChildView;
 class nsCocoaWindow;
 union nsPluginPort;
 
+namespace mozilla {
+namespace gl {
+class TextureImage;
+}
+}
+
 #ifndef NP_NO_CARBON
 enum {
   // Currently focused ChildView (while this TSM document is active).
   // Transient (only set while TSMProcessRawKeyEvent() is processing a key
   // event), and the ChildView will be retained and released around the call
   // to TSMProcessRawKeyEvent() -- so it can be weak.
   kFocusedChildViewTSMDocPropertyTag  = 'GKFV', // type ChildView* [WEAK]
 };
@@ -455,16 +461,17 @@ protected:
 
 #ifdef ACCESSIBILITY
   // weak ref to this childview's associated mozAccessible for speed reasons 
   // (we get queried for it *a lot* but don't want to own it)
   nsWeakPtr             mAccessible;
 #endif
 
   nsRefPtr<gfxASurface> mTempThebesSurface;
+  nsRefPtr<mozilla::gl::TextureImage> mResizerImage;
 
   PRPackedBool          mVisible;
   PRPackedBool          mDrawing;
   PRPackedBool          mPluginDrawing;
   PRPackedBool          mIsDispatchPaint; // Is a paint event being dispatched
 
   NP_CGContext          mPluginCGContext;
 #ifndef NP_NO_QUICKDRAW
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -513,16 +513,18 @@ nsChildView::~nsChildView()
   for (nsIWidget* kid = mLastChild; kid;) {
     nsChildView* childView = static_cast<nsChildView*>(kid);
     kid = kid->GetPrevSibling();
     childView->ResetParent();
   }
 
   NS_WARN_IF_FALSE(mOnDestroyCalled, "nsChildView object destroyed without calling Destroy()");
 
+  mResizerImage = nsnull;
+
   // An nsChildView object that was in use can be destroyed without Destroy()
   // ever being called on it.  So we also need to do a quick, safe cleanup
   // here (it's too late to just call Destroy(), which can cause crashes).
   // It's particularly important to make sure widgetDestroyed is called on our
   // mView -- this method NULLs mView's mGeckoChild, and NULL checks on
   // mGeckoChild are used throughout the ChildView class to tell if it's safe
   // to use a ChildView object.
   [mView widgetDestroyed]; // Safe if mView is nil.
@@ -2091,87 +2093,108 @@ nsChildView::GetThebesSurface()
 {
   if (!mTempThebesSurface) {
     mTempThebesSurface = new gfxQuartzSurface(gfxSize(1, 1), gfxASurface::ImageFormatARGB32);
   }
 
   return mTempThebesSurface;
 }
 
+static void
+DrawResizer(CGContextRef aCtx)
+{
+  CGContextSetShouldAntialias(aCtx, false);
+  CGPoint points[6];
+  points[0] = CGPointMake(13.0f, 4.0f);
+  points[1] = CGPointMake(3.0f, 14.0f);
+  points[2] = CGPointMake(13.0f, 8.0f);
+  points[3] = CGPointMake(7.0f, 14.0f);
+  points[4] = CGPointMake(13.0f, 12.0f);
+  points[5] = CGPointMake(11.0f, 14.0f);
+  CGContextSetRGBStrokeColor(aCtx, 0.00f, 0.00f, 0.00f, 0.15f);
+  CGContextStrokeLineSegments(aCtx, points, 6);
+
+  points[0] = CGPointMake(13.0f, 5.0f);
+  points[1] = CGPointMake(4.0f, 14.0f);
+  points[2] = CGPointMake(13.0f, 9.0f);
+  points[3] = CGPointMake(8.0f, 14.0f);
+  points[4] = CGPointMake(13.0f, 13.0f);
+  points[5] = CGPointMake(12.0f, 14.0f);
+  CGContextSetRGBStrokeColor(aCtx, 0.13f, 0.13f, 0.13f, 0.54f);
+  CGContextStrokeLineSegments(aCtx, points, 6);
+
+  points[0] = CGPointMake(13.0f, 6.0f);
+  points[1] = CGPointMake(5.0f, 14.0f);
+  points[2] = CGPointMake(13.0f, 10.0f);
+  points[3] = CGPointMake(9.0f, 14.0f);
+  points[5] = CGPointMake(13.0f, 13.9f);
+  points[4] = CGPointMake(13.0f, 14.0f);
+  CGContextSetRGBStrokeColor(aCtx, 0.84f, 0.84f, 0.84f, 0.55f);
+  CGContextStrokeLineSegments(aCtx, points, 6);
+}
+
 void
 nsChildView::DrawOver(LayerManager* aManager, nsIntRect aRect)
 {
   if (!ShowsResizeIndicator(nsnull)) {
     return;
   }
 
   nsRefPtr<LayerManagerOGL> manager(static_cast<LayerManagerOGL*>(aManager));
   if (!manager) {
     return;
   }
 
+  if (!mResizerImage) {
+    mResizerImage = manager->gl()->CreateTextureImage(nsIntSize(15, 15),
+                                                      gfxASurface::CONTENT_COLOR_ALPHA,
+                                                      LOCAL_GL_CLAMP_TO_EDGE,
+                                                      /* aUseNearestFilter = */ PR_TRUE);
+
+    // Creation of texture images can fail.
+    if (!mResizerImage)
+      return;
+
+    nsIntRegion update(nsIntRect(0, 0, 15, 15));
+    gfxASurface *asurf = mResizerImage->BeginUpdate(update);
+    if (!asurf) {
+      mResizerImage = nsnull;
+      return;
+    }
+
+    NS_ABORT_IF_FALSE(asurf->GetType() == gfxASurface::SurfaceTypeQuartz,
+                  "BeginUpdate must return a Quartz surface!");
+
+    nsRefPtr<gfxQuartzSurface> image = static_cast<gfxQuartzSurface*>(asurf);
+    DrawResizer(image->GetCGContext());
+
+    mResizerImage->EndUpdate();
+  }
+
+  NS_ABORT_IF_FALSE(mResizerImage, "Must have a texture allocated by now!");
+
   float bottomX = aRect.x + aRect.width;
   float bottomY = aRect.y + aRect.height;
 
-  nsRefPtr<gfxQuartzSurface> image =
-    new gfxQuartzSurface(gfxIntSize(15, 15), gfxASurface::ImageFormatARGB32);
-  CGContextRef ctx = image->GetCGContext();
-
-  CGContextSetShouldAntialias(ctx, false);
-  CGPoint points[6];
-  points[0] = CGPointMake(13.0f, 4.0f);
-  points[1] = CGPointMake(3.0f, 14.0f);
-  points[2] = CGPointMake(13.0f, 8.0f);
-  points[3] = CGPointMake(7.0f, 14.0f);
-  points[4] = CGPointMake(13.0f, 12.0f);
-  points[5] = CGPointMake(11.0f, 14.0f);
-  CGContextSetRGBStrokeColor(ctx, 0.00f, 0.00f, 0.00f, 0.15f);
-  CGContextStrokeLineSegments(ctx, points, 6);
-
-  points[0] = CGPointMake(13.0f, 5.0f);
-  points[1] = CGPointMake(4.0f, 14.0f);
-  points[2] = CGPointMake(13.0f, 9.0f);
-  points[3] = CGPointMake(8.0f, 14.0f);
-  points[4] = CGPointMake(13.0f, 13.0f);
-  points[5] = CGPointMake(12.0f, 14.0f);
-  CGContextSetRGBStrokeColor(ctx, 0.13f, 0.13f, 0.13f, 0.54f);
-  CGContextStrokeLineSegments(ctx, points, 6);
-
-  points[0] = CGPointMake(13.0f, 6.0f);
-  points[1] = CGPointMake(5.0f, 14.0f);
-  points[2] = CGPointMake(13.0f, 10.0f);
-  points[3] = CGPointMake(9.0f, 14.0f);
-  points[5] = CGPointMake(13.0f, 13.9f);
-  points[4] = CGPointMake(13.0f, 14.0f);
-  CGContextSetRGBStrokeColor(ctx, 0.84f, 0.84f, 0.84f, 0.55f);
-  CGContextStrokeLineSegments(ctx, points, 6);
-
-  GLuint tex = 0;
-
-  ShaderProgramType shader =
-#ifdef MOZ_ENABLE_LIBXUL
-    manager->gl()->UploadSurfaceToTexture(image, nsIntRect(0, 0, 15, 15), tex);
-#else
-    manager->gl()->UploadSurfaceToTextureExternal(image, nsIntRect(0, 0, 15, 15), tex);
-#endif
+  manager->gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+  manager->gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mResizerImage->Texture());
 
   ColorTextureLayerProgram *program =
-    manager->GetColorTextureLayerProgram(shader);
+    manager->GetColorTextureLayerProgram(mResizerImage->GetShaderProgramType());
   program->Activate();
   program->SetLayerQuadRect(nsIntRect(bottomX - 15,
                                       bottomY - 15,
                                       15,
                                       15));
   program->SetLayerTransform(gfx3DMatrix());
   program->SetLayerOpacity(1.0);
   program->SetRenderOffset(nsIntPoint(0,0));
   program->SetTextureUnit(0);
 
   manager->BindAndDrawQuad(program);
-  manager->gl()->fDeleteTextures(1, &tex);
 }
 
 void
 nsChildView::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
 {
   NSWindow* win = [mView window];
   if (!win || ![win isKindOfClass:[ToolbarWindow class]])
     return;