2 * Copyright (C) 2013 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.gallery3d.filtershow.cache;
19 import android.graphics.Bitmap;
20 import android.support.v8.renderscript.Allocation;
21 import android.support.v8.renderscript.RenderScript;
22 import android.util.Log;
23 import com.android.gallery3d.filtershow.filters.FiltersManager;
24 import com.android.gallery3d.filtershow.filters.ImageFilterRS;
25 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
26 import com.android.gallery3d.filtershow.imageshow.MasterImage;
27 import com.android.gallery3d.filtershow.presets.ImagePreset;
29 public class CachingPipeline {
30 private static final String LOGTAG = "CachingPipeline";
31 private boolean DEBUG = false;
33 private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
35 private FiltersManager mFiltersManager = null;
36 private volatile Bitmap mOriginalBitmap = null;
37 private volatile Bitmap mResizedOriginalBitmap = null;
39 private volatile Allocation mOriginalAllocation = null;
40 private volatile Allocation mFiltersOnlyOriginalAllocation = null;
42 protected volatile Allocation mInPixelsAllocation;
43 protected volatile Allocation mOutPixelsAllocation;
44 private volatile int mWidth = 0;
45 private volatile int mHeight = 0;
47 private volatile GeometryMetadata mPreviousGeometry = null;
48 private volatile float mPreviewScaleFactor = 1.0f;
49 private volatile String mName = "";
51 public CachingPipeline(FiltersManager filtersManager, String name) {
52 mFiltersManager = filtersManager;
56 public synchronized void reset() {
57 mOriginalBitmap = null; // just a reference to the bitmap in ImageLoader
58 if (mResizedOriginalBitmap != null) {
59 mResizedOriginalBitmap.recycle();
60 mResizedOriginalBitmap = null;
62 if (mOriginalAllocation != null) {
63 mOriginalAllocation.destroy();
64 mOriginalAllocation = null;
66 if (mFiltersOnlyOriginalAllocation != null) {
67 mFiltersOnlyOriginalAllocation.destroy();
68 mFiltersOnlyOriginalAllocation = null;
70 mPreviousGeometry = null;
71 mPreviewScaleFactor = 1.0f;
73 destroyPixelAllocations();
76 private synchronized void destroyPixelAllocations() {
78 Log.v(LOGTAG, "destroyPixelAllocations in " + getName());
80 if (mInPixelsAllocation != null) {
81 mInPixelsAllocation.destroy();
82 mInPixelsAllocation = null;
84 if (mOutPixelsAllocation != null) {
85 mOutPixelsAllocation.destroy();
86 mOutPixelsAllocation = null;
92 private String getType(RenderingRequest request) {
93 if (request.getType() == RenderingRequest.ICON_RENDERING) {
94 return "ICON_RENDERING";
96 if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
97 return "FILTERS_RENDERING";
99 if (request.getType() == RenderingRequest.FULL_RENDERING) {
100 return "FULL_RENDERING";
102 if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
103 return "GEOMETRY_RENDERING";
105 if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
106 return "PARTIAL_RENDERING";
108 return "UNKNOWN TYPE!";
111 private void setPresetParameters(ImagePreset preset) {
112 preset.setScaleFactor(mPreviewScaleFactor);
113 preset.setQuality(ImagePreset.QUALITY_PREVIEW);
114 preset.setupEnvironment(mFiltersManager);
115 preset.getEnvironment().setCachingPipeline(this);
118 public void setOriginal(Bitmap bitmap) {
119 mOriginalBitmap = bitmap;
120 Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight());
121 ImagePreset preset = MasterImage.getImage().getPreset();
122 preset.setupEnvironment(mFiltersManager);
123 updateOriginalAllocation(preset);
126 private synchronized boolean updateOriginalAllocation(ImagePreset preset) {
127 Bitmap originalBitmap = mOriginalBitmap;
129 if (originalBitmap == null) {
133 GeometryMetadata geometry = preset.getGeometry();
134 if (mPreviousGeometry != null && geometry.equals(mPreviousGeometry)) {
139 Log.v(LOGTAG, "geometry has changed");
142 RenderScript RS = ImageFilterRS.getRenderScriptContext();
144 Allocation filtersOnlyOriginalAllocation = mFiltersOnlyOriginalAllocation;
145 mFiltersOnlyOriginalAllocation = Allocation.createFromBitmap(RS, originalBitmap,
146 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
147 if (filtersOnlyOriginalAllocation != null) {
148 filtersOnlyOriginalAllocation.destroy();
151 Allocation originalAllocation = mOriginalAllocation;
152 mResizedOriginalBitmap = preset.applyGeometry(originalBitmap);
153 mOriginalAllocation = Allocation.createFromBitmap(RS, mResizedOriginalBitmap,
154 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
155 if (originalAllocation != null) {
156 originalAllocation.destroy();
159 mPreviousGeometry = new GeometryMetadata(geometry);
163 public synchronized void render(RenderingRequest request) {
164 if ((request.getType() != RenderingRequest.PARTIAL_RENDERING
165 && request.getBitmap() == null)
166 || request.getImagePreset() == null) {
171 Log.v(LOGTAG, "render image of type " + getType(request));
174 Bitmap bitmap = request.getBitmap();
175 ImagePreset preset = request.getImagePreset();
176 setPresetParameters(preset);
177 mFiltersManager.freeFilterResources(preset);
179 if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
180 ImageLoader loader = MasterImage.getImage().getImageLoader();
181 if (loader == null) {
182 Log.w(LOGTAG, "loader not yet setup, cannot handle: " + getType(request));
185 bitmap = loader.getScaleOneImageForPreset(null, preset,
186 request.getBounds(), request.getDestination(), false);
187 if (bitmap == null) {
188 Log.w(LOGTAG, "could not get bitmap for: " + getType(request));
193 if (request.getType() == RenderingRequest.FULL_RENDERING
194 || request.getType() == RenderingRequest.GEOMETRY_RENDERING
195 || request.getType() == RenderingRequest.FILTERS_RENDERING) {
196 updateOriginalAllocation(preset);
200 Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight()
201 +" ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x"
202 + mResizedOriginalBitmap.getHeight());
205 if (request.getType() == RenderingRequest.FULL_RENDERING
206 || request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
207 mOriginalAllocation.copyTo(bitmap);
208 } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
209 mFiltersOnlyOriginalAllocation.copyTo(bitmap);
212 if (request.getType() == RenderingRequest.FULL_RENDERING
213 || request.getType() == RenderingRequest.FILTERS_RENDERING
214 || request.getType() == RenderingRequest.ICON_RENDERING
215 || request.getType() == RenderingRequest.PARTIAL_RENDERING) {
216 Bitmap bmp = preset.apply(bitmap);
217 request.setBitmap(bmp);
218 mFiltersManager.freeFilterResources(preset);
223 public synchronized Bitmap renderFinalImage(Bitmap bitmap, ImagePreset preset) {
224 setPresetParameters(preset);
225 mFiltersManager.freeFilterResources(preset);
226 bitmap = preset.applyGeometry(bitmap);
227 bitmap = preset.apply(bitmap);
231 public synchronized void compute(TripleBufferBitmap buffer, ImagePreset preset, int type) {
233 Log.v(LOGTAG, "compute preset " + preset);
234 preset.showFilters();
237 String thread = Thread.currentThread().getName();
238 long time = System.currentTimeMillis();
239 setPresetParameters(preset);
240 mFiltersManager.freeFilterResources(preset);
242 Bitmap resizedOriginalBitmap = mResizedOriginalBitmap;
243 if (updateOriginalAllocation(preset)) {
244 resizedOriginalBitmap = mResizedOriginalBitmap;
245 buffer.updateBitmaps(resizedOriginalBitmap);
247 Bitmap bitmap = buffer.getProducer();
248 long time2 = System.currentTimeMillis();
250 if (bitmap == null || (bitmap.getWidth() != resizedOriginalBitmap.getWidth())
251 || (bitmap.getHeight() != resizedOriginalBitmap.getHeight())) {
252 buffer.updateBitmaps(resizedOriginalBitmap);
253 bitmap = buffer.getProducer();
255 mOriginalAllocation.copyTo(bitmap);
257 bitmap = preset.apply(bitmap);
259 mFiltersManager.freeFilterResources(preset);
261 time = System.currentTimeMillis() - time;
262 time2 = System.currentTimeMillis() - time2;
264 Log.v(LOGTAG, "Applying type " + type + " filters to bitmap "
265 + bitmap + " (" + bitmap.getWidth() + " x " + bitmap.getHeight()
266 + ") took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread);
270 public boolean needsRepaint() {
271 TripleBufferBitmap buffer = MasterImage.getImage().getDoubleBuffer();
272 return buffer.checkRepaintNeeded();
276 public void setPreviewScaleFactor(float previewScaleFactor) {
277 mPreviewScaleFactor = previewScaleFactor;
280 public synchronized boolean isInitialized() {
281 return mOriginalBitmap != null;
284 public boolean prepareRenderscriptAllocations(Bitmap bitmap) {
285 RenderScript RS = ImageFilterRS.getRenderScriptContext();
286 boolean needsUpdate = false;
287 if (mOutPixelsAllocation == null || mInPixelsAllocation == null ||
288 bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) {
289 destroyPixelAllocations();
290 Bitmap bitmapBuffer = bitmap;
291 if (bitmap.getConfig() == null || bitmap.getConfig() != BITMAP_CONFIG) {
292 bitmapBuffer = bitmap.copy(BITMAP_CONFIG, true);
294 mOutPixelsAllocation = Allocation.createFromBitmap(RS, bitmapBuffer,
295 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
296 mInPixelsAllocation = Allocation.createTyped(RS,
297 mOutPixelsAllocation.getType());
300 mInPixelsAllocation.copyFrom(bitmap);
301 if (bitmap.getWidth() != mWidth
302 || bitmap.getHeight() != mHeight) {
303 mWidth = bitmap.getWidth();
304 mHeight = bitmap.getHeight();
308 Log.v(LOGTAG, "prepareRenderscriptAllocations: " + needsUpdate + " in " + getName());
313 public synchronized Allocation getInPixelsAllocation() {
314 return mInPixelsAllocation;
317 public synchronized Allocation getOutPixelsAllocation() {
318 return mOutPixelsAllocation;
321 public String getName() {