diff options
author | nicolasroard <nicolasroard@google.com> | 2013-07-02 15:46:23 -0700 |
---|---|---|
committer | nicolasroard <nicolasroard@google.com> | 2013-07-02 15:46:23 -0700 |
commit | f51cdda5060a742863d0d74d57040d48d9ab394d (patch) | |
tree | 34e6d4dda59fd68bb7075466ee8b7de5a6c31c18 /src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java | |
parent | 68ff24597aa829f4ef4d9bd1ab21c3ff9e42f217 (diff) | |
download | android_packages_apps_Snap-f51cdda5060a742863d0d74d57040d48d9ab394d.tar.gz android_packages_apps_Snap-f51cdda5060a742863d0d74d57040d48d9ab394d.tar.bz2 android_packages_apps_Snap-f51cdda5060a742863d0d74d57040d48d9ab394d.zip |
Move classes to pipeline package
Change-Id: I9d664537d845d9daeb352c8006d0296a3f546dca
Diffstat (limited to 'src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java new file mode 100644 index 000000000..88cf8ede2 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.filtershow.pipeline; + +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; +import android.util.Log; + +import com.android.gallery3d.filtershow.cache.ImageLoader; +import com.android.gallery3d.filtershow.filters.FiltersManager; +import com.android.gallery3d.filtershow.filters.ImageFilterGeometry; +import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; +import com.android.gallery3d.filtershow.imageshow.MasterImage; + +public class CachingPipeline implements PipelineInterface { + private static final String LOGTAG = "CachingPipeline"; + private boolean DEBUG = false; + + 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; + + private FilterEnvironment mEnvironment = new FilterEnvironment(); + + private volatile Allocation mOriginalAllocation = null; + private volatile Allocation mFiltersOnlyOriginalAllocation = null; + + protected volatile Allocation mInPixelsAllocation; + protected volatile Allocation mOutPixelsAllocation; + private volatile int mWidth = 0; + private volatile int mHeight = 0; + + private volatile GeometryMetadata mPreviousGeometry = null; + private volatile float mPreviewScaleFactor = 1.0f; + private volatile float mHighResPreviewScaleFactor = 1.0f; + private volatile String mName = ""; + + private ImageFilterGeometry mGeometry = null; + + public CachingPipeline(FiltersManager filtersManager, String name) { + mFiltersManager = filtersManager; + mName = name; + } + + 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() { + if (sRS != null) { + sRS.destroy(); + } + sRS = null; + sResources = null; + } + + public void stop() { + mEnvironment.setStop(true); + } + + 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; + mHighResPreviewScaleFactor = 1.0f; + + destroyPixelAllocations(); + } + } + + public Resources getResources() { + return sRS.getApplicationContext().getResources(); + } + + private synchronized void destroyPixelAllocations() { + if (DEBUG) { + Log.v(LOGTAG, "destroyPixelAllocations in " + getName()); + } + if (mInPixelsAllocation != null) { + mInPixelsAllocation.destroy(); + mInPixelsAllocation = null; + } + if (mOutPixelsAllocation != null) { + mOutPixelsAllocation.destroy(); + mOutPixelsAllocation = null; + } + mWidth = 0; + mHeight = 0; + } + + private String getType(RenderingRequest request) { + if (request.getType() == RenderingRequest.ICON_RENDERING) { + return "ICON_RENDERING"; + } + if (request.getType() == RenderingRequest.FILTERS_RENDERING) { + return "FILTERS_RENDERING"; + } + if (request.getType() == RenderingRequest.FULL_RENDERING) { + return "FULL_RENDERING"; + } + if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) { + return "GEOMETRY_RENDERING"; + } + if (request.getType() == RenderingRequest.PARTIAL_RENDERING) { + return "PARTIAL_RENDERING"; + } + if (request.getType() == RenderingRequest.HIGHRES_RENDERING) { + return "HIGHRES_RENDERING"; + } + return "UNKNOWN TYPE!"; + } + + private void setupEnvironment(ImagePreset preset, boolean highResPreview) { + mEnvironment.setPipeline(this); + mEnvironment.setFiltersManager(mFiltersManager); + if (highResPreview) { + mEnvironment.setScaleFactor(mHighResPreviewScaleFactor); + } else { + mEnvironment.setScaleFactor(mPreviewScaleFactor); + } + mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); + mEnvironment.setImagePreset(preset); + mEnvironment.setStop(false); + } + + public void setOriginal(Bitmap bitmap) { + mOriginalBitmap = bitmap; + Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight()); + ImagePreset preset = MasterImage.getImage().getPreset(); + setupEnvironment(preset, false); + updateOriginalAllocation(preset); + } + + private synchronized boolean updateOriginalAllocation(ImagePreset preset) { + Bitmap originalBitmap = mOriginalBitmap; + + if (originalBitmap == null) { + return false; + } + + GeometryMetadata geometry = preset.getGeometry(); + if (mPreviousGeometry != null && geometry.equals(mPreviousGeometry)) { + return false; + } + + if (DEBUG) { + Log.v(LOGTAG, "geometry has changed"); + } + + RenderScript RS = getRenderScriptContext(); + + Allocation filtersOnlyOriginalAllocation = mFiltersOnlyOriginalAllocation; + mFiltersOnlyOriginalAllocation = Allocation.createFromBitmap(RS, originalBitmap, + Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); + if (filtersOnlyOriginalAllocation != null) { + filtersOnlyOriginalAllocation.destroy(); + } + + Allocation originalAllocation = mOriginalAllocation; + mResizedOriginalBitmap = preset.applyGeometry(originalBitmap, mEnvironment); + mOriginalAllocation = Allocation.createFromBitmap(RS, mResizedOriginalBitmap, + Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); + if (originalAllocation != null) { + originalAllocation.destroy(); + } + + mPreviousGeometry = new GeometryMetadata(geometry); + return true; + } + + public synchronized void render(RenderingRequest request) { + synchronized (CachingPipeline.class) { + if (getRenderScriptContext() == null) { + return; + } + if (((request.getType() != RenderingRequest.PARTIAL_RENDERING + && request.getType() != RenderingRequest.HIGHRES_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, + request.getType() != RenderingRequest.HIGHRES_RENDERING); + 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)); + 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.HIGHRES_RENDERING) { + ImageLoader loader = MasterImage.getImage().getImageLoader(); + bitmap = loader.getOriginalBitmapHighres(); + if (bitmap != null) { + bitmap = preset.applyGeometry(bitmap, mEnvironment); + } + } + + 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 + || request.getType() == RenderingRequest.HIGHRES_RENDERING + || request.getType() == RenderingRequest.STYLE_ICON_RENDERING) { + + if (request.getType() == RenderingRequest.ICON_RENDERING) { + mEnvironment.setQuality(FilterEnvironment.QUALITY_ICON); + } else { + mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); + } + + Bitmap bmp = preset.apply(bitmap, mEnvironment); + if (!mEnvironment.needsStop()) { + request.setBitmap(bmp); + } + mFiltersManager.freeFilterResources(preset); + } + } + } + + public synchronized void renderImage(ImagePreset preset, Allocation in, Allocation out) { + synchronized (CachingPipeline.class) { + if (getRenderScriptContext() == null) { + return; + } + setupEnvironment(preset, false); + mFiltersManager.freeFilterResources(preset); + preset.applyFilters(-1, -1, in, out, mEnvironment); + boolean copyOut = false; + if (preset.nbFilters() > 0) { + copyOut = true; + } + preset.applyBorder(in, out, copyOut, mEnvironment); + } + } + + public synchronized Bitmap renderFinalImage(Bitmap bitmap, ImagePreset preset) { + synchronized (CachingPipeline.class) { + if (getRenderScriptContext() == null) { + return bitmap; + } + setupEnvironment(preset, false); + mEnvironment.setQuality(FilterEnvironment.QUALITY_FINAL); + mEnvironment.setScaleFactor(1.0f); + mFiltersManager.freeFilterResources(preset); + bitmap = preset.applyGeometry(bitmap, mEnvironment); + bitmap = preset.apply(bitmap, mEnvironment); + return bitmap; + } + } + + public Bitmap renderGeometryIcon(Bitmap bitmap, ImagePreset preset) { + // Called by RenderRequest on the main thread + // TODO: change this -- we should reuse a pool of bitmaps instead... + if (mGeometry == null) { + mGeometry = new ImageFilterGeometry(); + } + mGeometry.useRepresentation(preset.getGeometry()); + return mGeometry.apply(bitmap, mPreviewScaleFactor, + FilterEnvironment.QUALITY_PREVIEW); + } + + public synchronized void compute(SharedBuffer buffer, ImagePreset preset, int type) { + 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, false); + mFiltersManager.freeFilterResources(preset); + + Bitmap resizedOriginalBitmap = mResizedOriginalBitmap; + if (updateOriginalAllocation(preset) || buffer.getProducer() == null) { + resizedOriginalBitmap = mResizedOriginalBitmap; + buffer.setProducer(resizedOriginalBitmap); + mEnvironment.cache(buffer.getProducer()); + } + + Bitmap bitmap = buffer.getProducer().getBitmap(); + long time2 = System.currentTimeMillis(); + + if (bitmap == null || (bitmap.getWidth() != resizedOriginalBitmap.getWidth()) + || (bitmap.getHeight() != resizedOriginalBitmap.getHeight())) { + mEnvironment.cache(buffer.getProducer()); + buffer.setProducer(resizedOriginalBitmap); + bitmap = buffer.getProducer().getBitmap(); + } + mOriginalAllocation.copyTo(bitmap); + + Bitmap tmpbitmap = preset.apply(bitmap, mEnvironment); + if (tmpbitmap != bitmap) { + mEnvironment.cache(buffer.getProducer()); + buffer.setProducer(tmpbitmap); + } + + 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); + } + } + } + + public boolean needsRepaint() { + SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer(); + return buffer.checkRepaintNeeded(); + } + + public void setPreviewScaleFactor(float previewScaleFactor) { + mPreviewScaleFactor = previewScaleFactor; + } + + public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) { + mHighResPreviewScaleFactor = highResPreviewScaleFactor; + } + + public synchronized boolean isInitialized() { + return getRenderScriptContext() != null && mOriginalBitmap != null; + } + + public boolean prepareRenderscriptAllocations(Bitmap bitmap) { + RenderScript RS = getRenderScriptContext(); + boolean needsUpdate = false; + if (mOutPixelsAllocation == null || mInPixelsAllocation == null || + bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) { + destroyPixelAllocations(); + Bitmap bitmapBuffer = bitmap; + if (bitmap.getConfig() == null || bitmap.getConfig() != BITMAP_CONFIG) { + bitmapBuffer = bitmap.copy(BITMAP_CONFIG, true); + } + mOutPixelsAllocation = Allocation.createFromBitmap(RS, bitmapBuffer, + Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); + mInPixelsAllocation = Allocation.createTyped(RS, + mOutPixelsAllocation.getType()); + needsUpdate = true; + } + if (RS != null) { + mInPixelsAllocation.copyFrom(bitmap); + } + if (bitmap.getWidth() != mWidth + || bitmap.getHeight() != mHeight) { + mWidth = bitmap.getWidth(); + mHeight = bitmap.getHeight(); + needsUpdate = true; + } + if (DEBUG) { + Log.v(LOGTAG, "prepareRenderscriptAllocations: " + needsUpdate + " in " + getName()); + } + return needsUpdate; + } + + public synchronized Allocation getInPixelsAllocation() { + return mInPixelsAllocation; + } + + public synchronized Allocation getOutPixelsAllocation() { + return mOutPixelsAllocation; + } + + public String getName() { + return mName; + } + + public RenderScript getRSContext() { + return CachingPipeline.getRenderScriptContext(); + } +} |