bug 708961 - We still use ByteBuffer.allocateDirect for large buffers r=pcwalton a=java-only
authorBrad Lassey <blassey@mozilla.com>
Tue, 13 Dec 2011 17:53:51 -0500
changeset 84169 923dab6343f90c62668aa781466095629d090982
parent 84168 b0165c0d85e1a7a15cc39c54751b2b99016fa0dd
child 84170 1f03a95b661ae74e668ed107670f0f1a72b1d60a
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspcwalton, java-only
bugs708961
milestone11.0a1
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 708961 - We still use ByteBuffer.allocateDirect for large buffers r=pcwalton a=java-only
mobile/android/base/gfx/BufferedCairoImage.java
mobile/android/base/gfx/GeckoSoftwareLayerClient.java
mobile/android/base/gfx/ScrollbarLayer.java
mobile/android/base/gfx/TextLayer.java
mobile/android/base/gfx/TileLayer.java
--- a/mobile/android/base/gfx/BufferedCairoImage.java
+++ b/mobile/android/base/gfx/BufferedCairoImage.java
@@ -32,41 +32,55 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko.gfx;
 
+import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.gfx.CairoImage;
 import org.mozilla.gecko.gfx.CairoUtils;
 import android.graphics.Bitmap;
 import java.nio.ByteBuffer;
 
 /** A Cairo image that simply saves a buffer of pixel data. */
 public class BufferedCairoImage extends CairoImage {
     private ByteBuffer mBuffer;
     private int mWidth, mHeight, mFormat;
+    private boolean mNeedToFreeBuffer = false;
 
     /** Creates a buffered Cairo image from a byte buffer. */
     public BufferedCairoImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) {
         mBuffer = inBuffer; mWidth = inWidth; mHeight = inHeight; mFormat = inFormat;
     }
 
     /** Creates a buffered Cairo image from an Android bitmap. */
     public BufferedCairoImage(Bitmap bitmap) {
         mFormat = CairoUtils.bitmapConfigToCairoFormat(bitmap.getConfig());
         mWidth = bitmap.getWidth();
         mHeight = bitmap.getHeight();
-        mBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * 4);
+        mNeedToFreeBuffer = true;
+        mBuffer = GeckoAppShell.allocateDirectBuffer(mWidth * mHeight * 4);
         bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
     }
 
-    @Override
+     protected void finalize() throws Throwable {
+        try {
+            if (mNeedToFreeBuffer && mBuffer != null)
+                GeckoAppShell.freeDirectBuffer(mBuffer);
+            mNeedToFreeBuffer = false;
+            mBuffer = null;
+        } finally {
+            super.finalize();
+        }
+    }
+
+   @Override
     public ByteBuffer getBuffer() { return mBuffer; }
     @Override
     public int getWidth() { return mWidth; }
     @Override
     public int getHeight() { return mHeight; }
     @Override
     public int getFormat() { return mFormat; }
 }
--- a/mobile/android/base/gfx/GeckoSoftwareLayerClient.java
+++ b/mobile/android/base/gfx/GeckoSoftwareLayerClient.java
@@ -98,32 +98,43 @@ public class GeckoSoftwareLayerClient ex
         mContext = context;
 
         mWidth = LayerController.TILE_WIDTH;
         mHeight = LayerController.TILE_HEIGHT;
         mFormat = CairoImage.FORMAT_RGB16_565;
 
         mScreenSize = new IntSize(1, 1);
 
-        mBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * 2);
+        mBuffer = GeckoAppShell.allocateDirectBuffer(mWidth * mHeight * 2);
 
         mCairoImage = new CairoImage() {
             @Override
             public ByteBuffer getBuffer() { return mBuffer; }
             @Override
             public int getWidth() { return mWidth; }
             @Override
             public int getHeight() { return mHeight; }
             @Override
             public int getFormat() { return mFormat; }
         };
 
         mTileLayer = new SingleTileLayer(mCairoImage);
     }
 
+
+    protected void finalize() throws Throwable {
+        try {
+            if (mBuffer != null)
+                GeckoAppShell.freeDirectBuffer(mBuffer);
+            mBuffer = null;
+        } finally {
+            super.finalize();
+        }
+    }
+
     /** Attaches the root layer to the layer controller so that Gecko appears. */
     @Override
     public void setLayerController(LayerController layerController) {
         super.setLayerController(layerController);
 
         layerController.setRoot(mTileLayer);
         if (mGeckoViewport != null) {
             layerController.setViewportMetrics(mGeckoViewport);
--- a/mobile/android/base/gfx/ScrollbarLayer.java
+++ b/mobile/android/base/gfx/ScrollbarLayer.java
@@ -46,16 +46,17 @@ import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.opengl.GLES11;
 import android.opengl.GLES11Ext;
 import android.util.Log;
 import java.nio.ByteBuffer;
 import javax.microedition.khronos.opengles.GL10;
 import org.mozilla.gecko.FloatUtils;
+import org.mozilla.gecko.GeckoAppShell;
 
 /**
  * Draws a small rect. This is scaled to become a scrollbar.
  */
 public class ScrollbarLayer extends TileLayer {
     public static final long FADE_DELAY = 500; // milliseconds before fade-out starts
     private static final float FADE_AMOUNT = 0.03f; // how much (as a percent) the scrollbar should fade per frame
 
@@ -69,31 +70,43 @@ public class ScrollbarLayer extends Tile
     private static final int[] CROPRECT_LEFTCAP = new int[] { 0, BAR_SIZE, CAP_RADIUS, -BAR_SIZE };
     private static final int[] CROPRECT_RIGHTCAP = new int[] { CAP_RADIUS, BAR_SIZE, CAP_RADIUS, -BAR_SIZE };
 
     private final boolean mVertical;
     private final ByteBuffer mBuffer;
     private final Bitmap mBitmap;
     private final Canvas mCanvas;
     private float mOpacity;
+    private boolean mFinalized = false;
 
     private ScrollbarLayer(CairoImage image, boolean vertical, ByteBuffer buffer) {
         super(false, image);
         mVertical = vertical;
         mBuffer = buffer;
 
         mBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
         mCanvas = new Canvas(mBitmap);
     }
 
+    protected void finalize() throws Throwable {
+        try {
+            if (!mFinalized && mBuffer != null)
+                GeckoAppShell.freeDirectBuffer(mBuffer);
+            mFinalized = true;
+        } finally {
+            super.finalize();
+        }
+    }
+
+
     public static ScrollbarLayer create(boolean vertical) {
         // just create an empty image for now, it will get drawn
         // on demand anyway
         int imageSize = nextPowerOfTwo(BAR_SIZE);
-        ByteBuffer buffer = ByteBuffer.allocateDirect(imageSize * imageSize * 4);
+        ByteBuffer buffer = GeckoAppShell.allocateDirectBuffer(imageSize * imageSize * 4);
         CairoImage image = new BufferedCairoImage(buffer, imageSize, imageSize, CairoImage.FORMAT_ARGB32);
         return new ScrollbarLayer(image, vertical, buffer);
     }
 
     /**
      * Decrease the opacity of the scrollbar by one frame's worth.
      * Return true if the opacity was decreased, or false if the scrollbars
      * are already fully faded out.
--- a/mobile/android/base/gfx/TextLayer.java
+++ b/mobile/android/base/gfx/TextLayer.java
@@ -32,16 +32,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko.gfx;
 
+import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.gfx.BufferedCairoImage;
 import org.mozilla.gecko.gfx.CairoImage;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.SingleTileLayer;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
@@ -51,30 +52,41 @@ import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
 
 /**
  * Draws text on a layer. This is used for the frame rate meter.
  */
 public class TextLayer extends SingleTileLayer {
     private final ByteBuffer mBuffer;
     private final IntSize mSize;
+    private boolean mFinalized = false;
 
     /*
      * This awkward pattern is necessary due to Java's restrictions on when one can call superclass
      * constructors.
      */
     private TextLayer(ByteBuffer buffer, BufferedCairoImage image, IntSize size, String text) {
         super(false, image);
         mBuffer = buffer;
         mSize = size;
         renderText(text);
     }
 
+    protected void finalize() throws Throwable {
+        try {
+            if (!mFinalized && mBuffer != null)
+                GeckoAppShell.freeDirectBuffer(mBuffer);
+            mFinalized = true;
+        } finally {
+            super.finalize();
+        }
+    }
+
     public static TextLayer create(IntSize size, String text) {
-        ByteBuffer buffer = ByteBuffer.allocateDirect(size.width * size.height * 4);
+        ByteBuffer buffer = GeckoAppShell.allocateDirectBuffer(size.width * size.height * 4);
         BufferedCairoImage image = new BufferedCairoImage(buffer, size.width, size.height,
                                                           CairoImage.FORMAT_ARGB32);
         return new TextLayer(buffer, image, size, text);
     }
 
     public void setText(String text) {
         renderText(text);
         invalidate();
--- a/mobile/android/base/gfx/TileLayer.java
+++ b/mobile/android/base/gfx/TileLayer.java
@@ -163,20 +163,10 @@ public abstract class TileLayer extends 
         gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureIDs[0]);
         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
 
         int repeatMode = mRepeat ? GL10.GL_REPEAT : GL10.GL_CLAMP_TO_EDGE;
         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, repeatMode);
         gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, repeatMode);
     }
-
-    protected static FloatBuffer createBuffer(float[] values) {
-        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(values.length * 4);
-        byteBuffer.order(ByteOrder.nativeOrder());
-
-        FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
-        floatBuffer.put(values);
-        floatBuffer.position(0);
-        return floatBuffer;
-    }
 }