diff options
author | nicolasroard <nicolasroard@google.com> | 2013-03-27 22:10:01 -0700 |
---|---|---|
committer | nicolasroard <nicolasroard@google.com> | 2013-03-27 23:28:15 -0700 |
commit | 83facdef714b729aeab4d51919206d95a7afb165 (patch) | |
tree | 116257518dc9e6a359dc16baf8c7cfa7b76784c9 | |
parent | 6d2104b2dd31e39e8f3c178375d4d91055a24a54 (diff) | |
download | android_packages_apps_Snap-83facdef714b729aeab4d51919206d95a7afb165.tar.gz android_packages_apps_Snap-83facdef714b729aeab4d51919206d95a7afb165.tar.bz2 android_packages_apps_Snap-83facdef714b729aeab4d51919206d95a7afb165.zip |
Fix deadlock.
Move the RenderScript context and Resources to CachingPipeline.
bug:8491107
Change-Id: I912555c87b060e4515cc1a4c66c8a8c9c840532d
3 files changed, 201 insertions, 172 deletions
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index 14a51392c..409f1e366 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -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(); } diff --git a/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java b/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java index f2b17fc0c..bc1d4505d 100644 --- a/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java +++ b/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java @@ -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) { diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java index cff071142..c76f7dda6 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java @@ -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); } } |