OSDN Git Service

Fix deadlock.
authornicolasroard <nicolasroard@google.com>
Thu, 28 Mar 2013 05:10:01 +0000 (22:10 -0700)
committernicolasroard <nicolasroard@google.com>
Thu, 28 Mar 2013 06:28:15 +0000 (23:28 -0700)
Move the RenderScript context and Resources to CachingPipeline.

bug:8491107
Change-Id: I912555c87b060e4515cc1a4c66c8a8c9c840532d

src/com/android/gallery3d/filtershow/FilterShowActivity.java
src/com/android/gallery3d/filtershow/cache/CachingPipeline.java
src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java

index 14a5139..409f1e3 100644 (file)
@@ -50,6 +50,7 @@ import android.widget.Toast;
 
 import com.android.gallery3d.R;
 import com.android.gallery3d.data.LocalAlbum;
+import com.android.gallery3d.filtershow.cache.CachingPipeline;
 import com.android.gallery3d.filtershow.cache.FilteringPipeline;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.editors.BasicEditor;
@@ -135,8 +136,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
 
         clearGalleryBitmapPool();
 
+        CachingPipeline.createRenderscriptContext(this);
         setupMasterImage();
-        ImageFilterRS.createRenderscriptContext(this);
         setDefaultValues();
         fillEditors();
 
@@ -526,7 +527,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
         FiltersManager.getPreviewManager().freeRSFilterScripts();
         FiltersManager.getManager().freeRSFilterScripts();
         FiltersManager.reset();
-        ImageFilterRS.destroyRenderScriptContext();
+        CachingPipeline.destroyRenderScriptContext();
         super.onDestroy();
     }
 
index f2b17fc..bc1d450 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.gallery3d.filtershow.cache;
 
+import android.app.Activity;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.support.v8.renderscript.Allocation;
 import android.support.v8.renderscript.RenderScript;
@@ -33,6 +35,9 @@ public class CachingPipeline {
 
     private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
 
+    private static volatile RenderScript sRS = null;
+    private static volatile Resources sResources = null;
+
     private FiltersManager mFiltersManager = null;
     private volatile Bitmap mOriginalBitmap = null;
     private volatile Bitmap mResizedOriginalBitmap = null;
@@ -56,24 +61,60 @@ public class CachingPipeline {
         mName = name;
     }
 
-    public synchronized void reset() {
-        mOriginalBitmap = null; // just a reference to the bitmap in ImageLoader
-        if (mResizedOriginalBitmap != null) {
-            mResizedOriginalBitmap.recycle();
-            mResizedOriginalBitmap = null;
-        }
-        if (mOriginalAllocation != null) {
-            mOriginalAllocation.destroy();
-            mOriginalAllocation = null;
-        }
-        if (mFiltersOnlyOriginalAllocation != null) {
-            mFiltersOnlyOriginalAllocation.destroy();
-            mFiltersOnlyOriginalAllocation = null;
+    public static synchronized Resources getResources() {
+        return sResources;
+    }
+
+    public static synchronized void setResources(Resources resources) {
+        sResources = resources;
+    }
+
+    public static synchronized RenderScript getRenderScriptContext() {
+        return sRS;
+    }
+
+    public static synchronized void setRenderScriptContext(RenderScript RS) {
+        sRS = RS;
+    }
+
+    public static synchronized void createRenderscriptContext(Activity context) {
+        if (sRS != null) {
+            Log.w(LOGTAG, "A prior RS context exists when calling setRenderScriptContext");
+            destroyRenderScriptContext();
         }
-        mPreviousGeometry = null;
-        mPreviewScaleFactor = 1.0f;
+        sRS = RenderScript.create(context);
+        sResources = context.getResources();
+    }
 
-        destroyPixelAllocations();
+    public static synchronized void destroyRenderScriptContext() {
+        sRS.destroy();
+        sRS = null;
+        sResources = null;
+    }
+
+    public synchronized void reset() {
+        synchronized (CachingPipeline.class) {
+            if (getRenderScriptContext() == null) {
+                return;
+            }
+            mOriginalBitmap = null; // just a reference to the bitmap in ImageLoader
+            if (mResizedOriginalBitmap != null) {
+                mResizedOriginalBitmap.recycle();
+                mResizedOriginalBitmap = null;
+            }
+            if (mOriginalAllocation != null) {
+                mOriginalAllocation.destroy();
+                mOriginalAllocation = null;
+            }
+            if (mFiltersOnlyOriginalAllocation != null) {
+                mFiltersOnlyOriginalAllocation.destroy();
+                mFiltersOnlyOriginalAllocation = null;
+            }
+            mPreviousGeometry = null;
+            mPreviewScaleFactor = 1.0f;
+
+            destroyPixelAllocations();
+        }
     }
 
     private synchronized void destroyPixelAllocations() {
@@ -143,7 +184,7 @@ public class CachingPipeline {
             Log.v(LOGTAG, "geometry has changed");
         }
 
-        RenderScript RS = ImageFilterRS.getRenderScriptContext();
+        RenderScript RS = getRenderScriptContext();
 
         Allocation filtersOnlyOriginalAllocation = mFiltersOnlyOriginalAllocation;
         mFiltersOnlyOriginalAllocation = Allocation.createFromBitmap(RS, originalBitmap,
@@ -165,119 +206,138 @@ public class CachingPipeline {
     }
 
     public synchronized void render(RenderingRequest request) {
-        if ((request.getType() != RenderingRequest.PARTIAL_RENDERING
-                && request.getBitmap() == null)
-                || request.getImagePreset() == null) {
-            return;
-        }
-
-        if (DEBUG) {
-            Log.v(LOGTAG, "render image of type " + getType(request));
-        }
-
-        Bitmap bitmap = request.getBitmap();
-        ImagePreset preset = request.getImagePreset();
-        setupEnvironment(preset);
-        mFiltersManager.freeFilterResources(preset);
-
-        if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
-            ImageLoader loader = MasterImage.getImage().getImageLoader();
-            if (loader == null) {
-                Log.w(LOGTAG, "loader not yet setup, cannot handle: " + getType(request));
+        synchronized (CachingPipeline.class) {
+            if (getRenderScriptContext() == null) {
                 return;
             }
-            bitmap = loader.getScaleOneImageForPreset(request.getBounds(),
-                    request.getDestination());
-            if (bitmap == null) {
-                Log.w(LOGTAG, "could not get bitmap for: " + getType(request));
+            if ((request.getType() != RenderingRequest.PARTIAL_RENDERING
+                    && request.getBitmap() == null)
+                    || request.getImagePreset() == null) {
                 return;
             }
-        }
 
-        if (request.getType() == RenderingRequest.FULL_RENDERING
-                || request.getType() == RenderingRequest.GEOMETRY_RENDERING
-                || request.getType() == RenderingRequest.FILTERS_RENDERING) {
-            updateOriginalAllocation(preset);
-        }
+            if (DEBUG) {
+                Log.v(LOGTAG, "render image of type " + getType(request));
+            }
 
-        if (DEBUG) {
-            Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight()
-                    +" ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x"
-                    + mResizedOriginalBitmap.getHeight());
-        }
+            Bitmap bitmap = request.getBitmap();
+            ImagePreset preset = request.getImagePreset();
+            setupEnvironment(preset);
+            mFiltersManager.freeFilterResources(preset);
 
-        if (request.getType() == RenderingRequest.FULL_RENDERING
-                || request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
-            mOriginalAllocation.copyTo(bitmap);
-        } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
-            mFiltersOnlyOriginalAllocation.copyTo(bitmap);
-        }
+            if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
+                ImageLoader loader = MasterImage.getImage().getImageLoader();
+                if (loader == null) {
+                    Log.w(LOGTAG, "loader not yet setup, cannot handle: " + getType(request));
+                    return;
+                }
+                bitmap = loader.getScaleOneImageForPreset(request.getBounds(),
+                        request.getDestination());
+                if (bitmap == null) {
+                    Log.w(LOGTAG, "could not get bitmap for: " + getType(request));
+                    return;
+                }
+            }
 
-        if (request.getType() == RenderingRequest.FULL_RENDERING
-                || request.getType() == RenderingRequest.FILTERS_RENDERING
-                || request.getType() == RenderingRequest.ICON_RENDERING
-                || request.getType() == RenderingRequest.PARTIAL_RENDERING) {
-            Bitmap bmp = preset.apply(bitmap, mEnvironment);
-            request.setBitmap(bmp);
-            mFiltersManager.freeFilterResources(preset);
-        }
+            if (request.getType() == RenderingRequest.FULL_RENDERING
+                    || request.getType() == RenderingRequest.GEOMETRY_RENDERING
+                    || request.getType() == RenderingRequest.FILTERS_RENDERING) {
+                updateOriginalAllocation(preset);
+            }
 
+            if (DEBUG) {
+                Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight()
+                        + " ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x"
+                        + mResizedOriginalBitmap.getHeight());
+            }
+
+            if (request.getType() == RenderingRequest.FULL_RENDERING
+                    || request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
+                mOriginalAllocation.copyTo(bitmap);
+            } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+                mFiltersOnlyOriginalAllocation.copyTo(bitmap);
+            }
+
+            if (request.getType() == RenderingRequest.FULL_RENDERING
+                    || request.getType() == RenderingRequest.FILTERS_RENDERING
+                    || request.getType() == RenderingRequest.ICON_RENDERING
+                    || request.getType() == RenderingRequest.PARTIAL_RENDERING) {
+                Bitmap bmp = preset.apply(bitmap, mEnvironment);
+                request.setBitmap(bmp);
+                mFiltersManager.freeFilterResources(preset);
+            }
+        }
     }
 
     public synchronized Bitmap renderFinalImage(Bitmap bitmap, ImagePreset preset) {
-        setupEnvironment(preset);
-        mEnvironment.setQuality(ImagePreset.QUALITY_FINAL);
-        mEnvironment.setScaleFactor(1.0f);
-        mFiltersManager.freeFilterResources(preset);
-        bitmap = preset.applyGeometry(bitmap, mEnvironment);
-        bitmap = preset.apply(bitmap, mEnvironment);
-        return bitmap;
+        synchronized (CachingPipeline.class) {
+            if (getRenderScriptContext() == null) {
+                return bitmap;
+            }
+            setupEnvironment(preset);
+            mEnvironment.setQuality(ImagePreset.QUALITY_FINAL);
+            mEnvironment.setScaleFactor(1.0f);
+            mFiltersManager.freeFilterResources(preset);
+            bitmap = preset.applyGeometry(bitmap, mEnvironment);
+            bitmap = preset.apply(bitmap, mEnvironment);
+            return bitmap;
+        }
     }
 
     public synchronized Bitmap renderGeometryIcon(Bitmap bitmap, ImagePreset preset) {
-        setupEnvironment(preset);
-        mEnvironment.setQuality(ImagePreset.QUALITY_PREVIEW);
-        mFiltersManager.freeFilterResources(preset);
-        bitmap = preset.applyGeometry(bitmap, mEnvironment);
-        return bitmap;
+        synchronized (CachingPipeline.class) {
+            if (getRenderScriptContext() == null) {
+                return bitmap;
+            }
+            setupEnvironment(preset);
+            mEnvironment.setQuality(ImagePreset.QUALITY_PREVIEW);
+            mFiltersManager.freeFilterResources(preset);
+            bitmap = preset.applyGeometry(bitmap, mEnvironment);
+            return bitmap;
+        }
     }
 
     public synchronized void compute(TripleBufferBitmap buffer, ImagePreset preset, int type) {
-        if (DEBUG) {
-            Log.v(LOGTAG, "compute preset " + preset);
-            preset.showFilters();
-        }
+        synchronized (CachingPipeline.class) {
+            if (getRenderScriptContext() == null) {
+                return;
+            }
+            if (DEBUG) {
+                Log.v(LOGTAG, "compute preset " + preset);
+                preset.showFilters();
+            }
 
-        String thread = Thread.currentThread().getName();
-        long time = System.currentTimeMillis();
-        setupEnvironment(preset);
-        mFiltersManager.freeFilterResources(preset);
+            String thread = Thread.currentThread().getName();
+            long time = System.currentTimeMillis();
+            setupEnvironment(preset);
+            mFiltersManager.freeFilterResources(preset);
 
-        Bitmap resizedOriginalBitmap = mResizedOriginalBitmap;
-        if (updateOriginalAllocation(preset)) {
-            resizedOriginalBitmap = mResizedOriginalBitmap;
-            buffer.updateBitmaps(resizedOriginalBitmap);
-        }
-        Bitmap bitmap = buffer.getProducer();
-        long time2 = System.currentTimeMillis();
+            Bitmap resizedOriginalBitmap = mResizedOriginalBitmap;
+            if (updateOriginalAllocation(preset)) {
+                resizedOriginalBitmap = mResizedOriginalBitmap;
+                buffer.updateBitmaps(resizedOriginalBitmap);
+            }
+            Bitmap bitmap = buffer.getProducer();
+            long time2 = System.currentTimeMillis();
 
-        if (bitmap == null || (bitmap.getWidth() != resizedOriginalBitmap.getWidth())
-                || (bitmap.getHeight() != resizedOriginalBitmap.getHeight())) {
-            buffer.updateBitmaps(resizedOriginalBitmap);
-            bitmap = buffer.getProducer();
-        }
-        mOriginalAllocation.copyTo(bitmap);
+            if (bitmap == null || (bitmap.getWidth() != resizedOriginalBitmap.getWidth())
+                    || (bitmap.getHeight() != resizedOriginalBitmap.getHeight())) {
+                buffer.updateBitmaps(resizedOriginalBitmap);
+                bitmap = buffer.getProducer();
+            }
+            mOriginalAllocation.copyTo(bitmap);
 
-        bitmap = preset.apply(bitmap, mEnvironment);
+            bitmap = preset.apply(bitmap, mEnvironment);
 
-        mFiltersManager.freeFilterResources(preset);
+            mFiltersManager.freeFilterResources(preset);
 
-        time = System.currentTimeMillis() - time;
-        time2 = System.currentTimeMillis() - time2;
-        if (DEBUG) {
-            Log.v(LOGTAG, "Applying type " + type + " filters to bitmap "
-                    + bitmap + " (" + bitmap.getWidth() + " x " + bitmap.getHeight()
-                    + ") took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread);
+            time = System.currentTimeMillis() - time;
+            time2 = System.currentTimeMillis() - time2;
+            if (DEBUG) {
+                Log.v(LOGTAG, "Applying type " + type + " filters to bitmap "
+                        + bitmap + " (" + bitmap.getWidth() + " x " + bitmap.getHeight()
+                        + ") took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread);
+            }
         }
     }
 
@@ -292,11 +352,11 @@ public class CachingPipeline {
     }
 
     public synchronized boolean isInitialized() {
-        return mOriginalBitmap != null;
+        return getRenderScriptContext() != null && mOriginalBitmap != null;
     }
 
     public boolean prepareRenderscriptAllocations(Bitmap bitmap) {
-        RenderScript RS = ImageFilterRS.getRenderScriptContext();
+        RenderScript RS = getRenderScriptContext();
         boolean needsUpdate = false;
         if (mOutPixelsAllocation == null || mInPixelsAllocation == null ||
                 bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) {
index cff0711..c76f7dd 100644 (file)
@@ -29,22 +29,21 @@ public abstract class ImageFilterRS extends ImageFilter {
     private static final String LOGTAG = "ImageFilterRS";
     private boolean DEBUG = false;
 
-    private static volatile RenderScript sRS = null;
-    private static volatile Resources sResources = null;
     private volatile boolean mResourcesLoaded = false;
 
-    // This must be used inside block synchronized on ImageFilterRS class object
     protected abstract void createFilter(android.content.res.Resources res,
             float scaleFactor, int quality);
 
-    // This must be used inside block synchronized on ImageFilterRS class object
     protected abstract void runFilter();
 
-    // This must be used inside block synchronized on ImageFilterRS class object
     protected void update(Bitmap bitmap) {
         getOutPixelsAllocation().copyTo(bitmap);
     }
 
+    protected RenderScript getRenderScriptContext() {
+        return CachingPipeline.getRenderScriptContext();
+    }
+
     protected Allocation getInPixelsAllocation() {
         CachingPipeline pipeline = getEnvironment().getCachingPipeline();
         return pipeline.getInPixelsAllocation();
@@ -61,24 +60,19 @@ public abstract class ImageFilterRS extends ImageFilter {
             return bitmap;
         }
         try {
-            synchronized(ImageFilterRS.class) {
-                if (sRS == null)  {
-                    Log.w(LOGTAG, "Cannot apply before calling createRenderScriptContext");
-                    return bitmap;
-                }
-                CachingPipeline pipeline = getEnvironment().getCachingPipeline();
-                if (DEBUG) {
-                    Log.v(LOGTAG, "apply filter " + getName() + " in pipeline " + pipeline.getName());
-                }
-                pipeline.prepareRenderscriptAllocations(bitmap);
-                createFilter(sResources, scaleFactor, quality);
-                setResourcesLoaded(true);
-                runFilter();
-                update(bitmap);
-                freeResources();
-                if (DEBUG) {
-                    Log.v(LOGTAG, "DONE apply filter " + getName() + " in pipeline " + pipeline.getName());
-                }
+            CachingPipeline pipeline = getEnvironment().getCachingPipeline();
+            if (DEBUG) {
+                Log.v(LOGTAG, "apply filter " + getName() + " in pipeline " + pipeline.getName());
+            }
+            pipeline.prepareRenderscriptAllocations(bitmap);
+            Resources rsc = pipeline.getResources();
+            createFilter(rsc, scaleFactor, quality);
+            setResourcesLoaded(true);
+            runFilter();
+            update(bitmap);
+            freeResources();
+            if (DEBUG) {
+                Log.v(LOGTAG, "DONE apply filter " + getName() + " in pipeline " + pipeline.getName());
             }
         } catch (android.renderscript.RSIllegalArgumentException e) {
             Log.e(LOGTAG, "Illegal argument? " + e);
@@ -93,53 +87,32 @@ public abstract class ImageFilterRS extends ImageFilter {
         return bitmap;
     }
 
-    public static synchronized RenderScript getRenderScriptContext() {
-        return sRS;
-    }
-
-    public static synchronized void createRenderscriptContext(Activity context) {
-        if( sRS != null) {
-            Log.w(LOGTAG, "A prior RS context exists when calling setRenderScriptContext");
-            destroyRenderScriptContext();
-        }
-        sRS = RenderScript.create(context);
-        sResources = context.getResources();
-    }
-
-    public static synchronized void destroyRenderScriptContext() {
-        sRS.destroy();
-        sRS = null;
-        sResources = null;
-    }
-
-    private static synchronized Allocation convertBitmap(Bitmap bitmap) {
-        return Allocation.createFromBitmap(sRS, bitmap,
+    private static Allocation convertBitmap(Bitmap bitmap) {
+        return Allocation.createFromBitmap(CachingPipeline.getRenderScriptContext(), bitmap,
                 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
     }
 
-    private static synchronized Allocation convertRGBAtoA(Bitmap bitmap) {
-        Type.Builder tb_a8 = new Type.Builder(sRS, Element.A_8(sRS));
-        ScriptC_grey greyConvert = new ScriptC_grey(sRS,
-                sRS.getApplicationContext().getResources(), R.raw.grey);
+    private static Allocation convertRGBAtoA(Bitmap bitmap) {
+        RenderScript RS = CachingPipeline.getRenderScriptContext();
+        Type.Builder tb_a8 = new Type.Builder(RS, Element.A_8(RS));
+        ScriptC_grey greyConvert = new ScriptC_grey(RS,
+                RS.getApplicationContext().getResources(), R.raw.grey);
 
         Allocation bitmapTemp = convertBitmap(bitmap);
-        if (bitmapTemp.getType().getElement().isCompatible(Element.A_8(sRS))) {
+        if (bitmapTemp.getType().getElement().isCompatible(Element.A_8(RS))) {
             return bitmapTemp;
         }
 
         tb_a8.setX(bitmapTemp.getType().getX());
         tb_a8.setY(bitmapTemp.getType().getY());
-        Allocation bitmapAlloc = Allocation.createTyped(sRS, tb_a8.create());
+        Allocation bitmapAlloc = Allocation.createTyped(RS, tb_a8.create());
         greyConvert.forEach_RGBAtoA(bitmapTemp, bitmapAlloc);
 
         return bitmapAlloc;
     }
 
     public Allocation loadScaledResourceAlpha(int resource, int inSampleSize) {
-        Resources res = null;
-        synchronized(ImageFilterRS.class) {
-            res = sRS.getApplicationContext().getResources();
-        }
+        Resources res = CachingPipeline.getResources();
         final BitmapFactory.Options options = new BitmapFactory.Options();
         options.inPreferredConfig = Bitmap.Config.ALPHA_8;
         options.inSampleSize      = inSampleSize;
@@ -156,10 +129,7 @@ public abstract class ImageFilterRS extends ImageFilter {
     }
 
     public Allocation loadResource(int resource) {
-        Resources res = null;
-        synchronized(ImageFilterRS.class) {
-            res = sRS.getApplicationContext().getResources();
-        }
+        Resources res = CachingPipeline.getResources();
         final BitmapFactory.Options options = new BitmapFactory.Options();
         options.inPreferredConfig = Bitmap.Config.ARGB_8888;
         Bitmap bitmap = BitmapFactory.decodeResource(
@@ -192,9 +162,7 @@ public abstract class ImageFilterRS extends ImageFilter {
         if (!isResourcesLoaded()) {
             return;
         }
-        synchronized(ImageFilterRS.class) {
-            resetAllocations();
-            setResourcesLoaded(false);
-        }
+        resetAllocations();
+        setResourcesLoaded(false);
     }
 }