OSDN Git Service

823da642ae9278c16a8d2cf1bd52e19b5eb29a91
[android-x86/packages-apps-Gallery2.git] / src / com / android / gallery3d / filtershow / pipeline / CachingPipeline.java
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.android.gallery3d.filtershow.pipeline;
18
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.graphics.Bitmap;
22 import android.support.v8.renderscript.Allocation;
23 import android.support.v8.renderscript.RenderScript;
24 import android.util.Log;
25
26 import com.android.gallery3d.filtershow.cache.ImageLoader;
27 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
28 import com.android.gallery3d.filtershow.filters.FiltersManager;
29 import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
30 import com.android.gallery3d.filtershow.imageshow.MasterImage;
31
32 import java.util.Vector;
33
34 public class CachingPipeline implements PipelineInterface {
35     private static final String LOGTAG = "CachingPipeline";
36     private boolean DEBUG = false;
37
38     private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
39
40     private static volatile RenderScript sRS = null;
41
42     private FiltersManager mFiltersManager = null;
43     private volatile Bitmap mOriginalBitmap = null;
44     private volatile Bitmap mResizedOriginalBitmap = null;
45
46     private FilterEnvironment mEnvironment = new FilterEnvironment();
47     private CacheProcessing mCachedProcessing = new CacheProcessing();
48
49
50     private volatile Allocation mOriginalAllocation = null;
51     private volatile Allocation mFiltersOnlyOriginalAllocation =  null;
52
53     protected volatile Allocation mInPixelsAllocation;
54     protected volatile Allocation mOutPixelsAllocation;
55     private volatile int mWidth = 0;
56     private volatile int mHeight = 0;
57
58     private volatile float mPreviewScaleFactor = 1.0f;
59     private volatile float mHighResPreviewScaleFactor = 1.0f;
60     private volatile String mName = "";
61
62     public CachingPipeline(FiltersManager filtersManager, String name) {
63         mFiltersManager = filtersManager;
64         mName = name;
65     }
66
67     public static synchronized RenderScript getRenderScriptContext() {
68         return sRS;
69     }
70
71     public static synchronized void createRenderscriptContext(Context context) {
72         if (sRS != null) {
73             Log.w(LOGTAG, "A prior RS context exists when calling setRenderScriptContext");
74             destroyRenderScriptContext();
75         }
76         sRS = RenderScript.create(context);
77     }
78
79     public static synchronized void destroyRenderScriptContext() {
80         if (sRS != null) {
81             sRS.destroy();
82         }
83         sRS = null;
84     }
85
86     public void stop() {
87         mEnvironment.setStop(true);
88     }
89
90     public synchronized void reset() {
91         synchronized (CachingPipeline.class) {
92             if (getRenderScriptContext() == null) {
93                 return;
94             }
95             mOriginalBitmap = null; // just a reference to the bitmap in ImageLoader
96             if (mResizedOriginalBitmap != null) {
97                 mResizedOriginalBitmap.recycle();
98                 mResizedOriginalBitmap = null;
99             }
100             if (mOriginalAllocation != null) {
101                 mOriginalAllocation.destroy();
102                 mOriginalAllocation = null;
103             }
104             if (mFiltersOnlyOriginalAllocation != null) {
105                 mFiltersOnlyOriginalAllocation.destroy();
106                 mFiltersOnlyOriginalAllocation = null;
107             }
108             mPreviewScaleFactor = 1.0f;
109             mHighResPreviewScaleFactor = 1.0f;
110
111             destroyPixelAllocations();
112         }
113     }
114
115     public Resources getResources() {
116         return sRS.getApplicationContext().getResources();
117     }
118
119     private synchronized void destroyPixelAllocations() {
120         if (DEBUG) {
121             Log.v(LOGTAG, "destroyPixelAllocations in " + getName());
122         }
123         if (mInPixelsAllocation != null) {
124             mInPixelsAllocation.destroy();
125             mInPixelsAllocation = null;
126         }
127         if (mOutPixelsAllocation != null) {
128             mOutPixelsAllocation.destroy();
129             mOutPixelsAllocation = null;
130         }
131         mWidth = 0;
132         mHeight = 0;
133     }
134
135     private String getType(RenderingRequest request) {
136         if (request.getType() == RenderingRequest.ICON_RENDERING) {
137             return "ICON_RENDERING";
138         }
139         if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
140             return "FILTERS_RENDERING";
141         }
142         if (request.getType() == RenderingRequest.FULL_RENDERING) {
143             return "FULL_RENDERING";
144         }
145         if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
146             return "GEOMETRY_RENDERING";
147         }
148         if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
149             return "PARTIAL_RENDERING";
150         }
151         if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
152             return "HIGHRES_RENDERING";
153         }
154         return "UNKNOWN TYPE!";
155     }
156
157     private void setupEnvironment(ImagePreset preset, boolean highResPreview) {
158         mEnvironment.setPipeline(this);
159         mEnvironment.setFiltersManager(mFiltersManager);
160         mEnvironment.setBitmapCache(MasterImage.getImage().getBitmapCache());
161         if (highResPreview) {
162             mEnvironment.setScaleFactor(mHighResPreviewScaleFactor);
163         } else {
164             mEnvironment.setScaleFactor(mPreviewScaleFactor);
165         }
166         mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW);
167         mEnvironment.setImagePreset(preset);
168         mEnvironment.setStop(false);
169     }
170
171     public void setOriginal(Bitmap bitmap) {
172         mOriginalBitmap = bitmap;
173         Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight());
174         ImagePreset preset = MasterImage.getImage().getPreset();
175         setupEnvironment(preset, false);
176         updateOriginalAllocation(preset);
177     }
178
179     private synchronized boolean updateOriginalAllocation(ImagePreset preset) {
180         Bitmap originalBitmap = mOriginalBitmap;
181
182         if (originalBitmap == null) {
183             return false;
184         }
185
186         RenderScript RS = getRenderScriptContext();
187
188         Allocation filtersOnlyOriginalAllocation = mFiltersOnlyOriginalAllocation;
189         mFiltersOnlyOriginalAllocation = Allocation.createFromBitmap(RS, originalBitmap,
190                 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
191         if (filtersOnlyOriginalAllocation != null) {
192             filtersOnlyOriginalAllocation.destroy();
193         }
194
195         Allocation originalAllocation = mOriginalAllocation;
196         mResizedOriginalBitmap = preset.applyGeometry(originalBitmap, mEnvironment);
197         mOriginalAllocation = Allocation.createFromBitmap(RS, mResizedOriginalBitmap,
198                 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
199         if (originalAllocation != null) {
200             originalAllocation.destroy();
201         }
202
203         return true;
204     }
205
206     public void renderHighres(RenderingRequest request) {
207         synchronized (CachingPipeline.class) {
208             if (getRenderScriptContext() == null) {
209                 return;
210             }
211             ImagePreset preset = request.getImagePreset();
212             setupEnvironment(preset, false);
213             Bitmap bitmap = MasterImage.getImage().getOriginalBitmapHighres();
214             if (bitmap == null) {
215                 return;
216             }
217             bitmap = mEnvironment.getBitmapCopy(bitmap);
218             bitmap = preset.applyGeometry(bitmap, mEnvironment);
219
220             mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW);
221             Bitmap bmp = preset.apply(bitmap, mEnvironment);
222             if (!mEnvironment.needsStop()) {
223                 request.setBitmap(bmp);
224             } else {
225                 mEnvironment.cache(bmp);
226             }
227             mFiltersManager.freeFilterResources(preset);
228         }
229     }
230
231     public void renderGeometry(RenderingRequest request) {
232         synchronized (CachingPipeline.class) {
233             if (getRenderScriptContext() == null) {
234                 return;
235             }
236             ImagePreset preset = request.getImagePreset();
237             setupEnvironment(preset, false);
238             Bitmap bitmap = MasterImage.getImage().getOriginalBitmapHighres();
239             if (bitmap == null) {
240                 return;
241             }
242             bitmap = mEnvironment.getBitmapCopy(bitmap);
243             bitmap = preset.applyGeometry(bitmap, mEnvironment);
244             if (!mEnvironment.needsStop()) {
245                 request.setBitmap(bitmap);
246             } else {
247                 mEnvironment.cache(bitmap);
248             }
249             mFiltersManager.freeFilterResources(preset);
250         }
251     }
252
253     public void renderFilters(RenderingRequest request) {
254         synchronized (CachingPipeline.class) {
255             if (getRenderScriptContext() == null) {
256                 return;
257             }
258             ImagePreset preset = request.getImagePreset();
259             setupEnvironment(preset, false);
260             Bitmap bitmap = MasterImage.getImage().getOriginalBitmapHighres();
261             if (bitmap == null) {
262                 return;
263             }
264             bitmap = mEnvironment.getBitmapCopy(bitmap);
265             bitmap = preset.apply(bitmap, mEnvironment);
266             if (!mEnvironment.needsStop()) {
267                 request.setBitmap(bitmap);
268             } else {
269                 mEnvironment.cache(bitmap);
270             }
271             mFiltersManager.freeFilterResources(preset);
272         }
273     }
274
275     public synchronized void render(RenderingRequest request) {
276         // TODO: cleanup/remove GEOMETRY / FILTERS paths
277         synchronized (CachingPipeline.class) {
278             if (getRenderScriptContext() == null) {
279                 return;
280             }
281             if (((request.getType() != RenderingRequest.PARTIAL_RENDERING)
282                     && request.getBitmap() == null)
283                     || request.getImagePreset() == null) {
284                 return;
285             }
286
287             if (DEBUG) {
288                 Log.v(LOGTAG, "render image of type " + getType(request));
289             }
290
291             Bitmap bitmap = request.getBitmap();
292             ImagePreset preset = request.getImagePreset();
293             setupEnvironment(preset, true);
294             mFiltersManager.freeFilterResources(preset);
295
296             if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
297                 MasterImage master = MasterImage.getImage();
298                 bitmap = ImageLoader.getScaleOneImageForPreset(master.getActivity(),
299                         mEnvironment,
300                         master.getUri(), request.getBounds(),
301                         request.getDestination());
302                 if (bitmap == null) {
303                     Log.w(LOGTAG, "could not get bitmap for: " + getType(request));
304                     return;
305                 }
306             }
307
308             if (request.getType() == RenderingRequest.FULL_RENDERING
309                     || request.getType() == RenderingRequest.GEOMETRY_RENDERING
310                     || request.getType() == RenderingRequest.FILTERS_RENDERING) {
311                 updateOriginalAllocation(preset);
312             }
313
314             if (DEBUG) {
315                 Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight()
316                         + " ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x"
317                         + mResizedOriginalBitmap.getHeight());
318             }
319
320             if (request.getType() == RenderingRequest.FULL_RENDERING
321                     || request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
322                 mOriginalAllocation.copyTo(bitmap);
323             } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
324                 mFiltersOnlyOriginalAllocation.copyTo(bitmap);
325             }
326
327             if (request.getType() == RenderingRequest.FULL_RENDERING
328                     || request.getType() == RenderingRequest.FILTERS_RENDERING
329                     || request.getType() == RenderingRequest.ICON_RENDERING
330                     || request.getType() == RenderingRequest.PARTIAL_RENDERING
331                     || request.getType() == RenderingRequest.STYLE_ICON_RENDERING) {
332
333                 if (request.getType() == RenderingRequest.ICON_RENDERING) {
334                     mEnvironment.setQuality(FilterEnvironment.QUALITY_ICON);
335                 } else {
336                     mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW);
337                 }
338
339                 Bitmap bmp = preset.apply(bitmap, mEnvironment);
340                 if (!mEnvironment.needsStop()) {
341                     request.setBitmap(bmp);
342                 }
343                 mFiltersManager.freeFilterResources(preset);
344             }
345         }
346     }
347
348     public synchronized void renderImage(ImagePreset preset, Allocation in, Allocation out) {
349         synchronized (CachingPipeline.class) {
350             if (getRenderScriptContext() == null) {
351                 return;
352             }
353             setupEnvironment(preset, false);
354             mFiltersManager.freeFilterResources(preset);
355             preset.applyFilters(-1, -1, in, out, mEnvironment);
356             boolean copyOut = false;
357             if (preset.nbFilters() > 0) {
358                 copyOut = true;
359             }
360             preset.applyBorder(in, out, copyOut, mEnvironment);
361         }
362     }
363
364     public synchronized Bitmap renderFinalImage(Bitmap bitmap, ImagePreset preset) {
365         synchronized (CachingPipeline.class) {
366             if (getRenderScriptContext() == null) {
367                 return bitmap;
368             }
369             setupEnvironment(preset, false);
370             mEnvironment.setQuality(FilterEnvironment.QUALITY_FINAL);
371             mEnvironment.setScaleFactor(1.0f);
372             mFiltersManager.freeFilterResources(preset);
373             bitmap = preset.applyGeometry(bitmap, mEnvironment);
374             bitmap = preset.apply(bitmap, mEnvironment);
375             return bitmap;
376         }
377     }
378
379     public Bitmap renderGeometryIcon(Bitmap bitmap, ImagePreset preset) {
380         return GeometryMathUtils.applyGeometryRepresentations(preset.getGeometryFilters(), bitmap);
381     }
382
383     public void compute(SharedBuffer buffer, ImagePreset preset, int type) {
384         if (getRenderScriptContext() == null) {
385             return;
386         }
387         setupEnvironment(preset, false);
388         Vector<FilterRepresentation> filters = preset.getFilters();
389         Bitmap result = mCachedProcessing.process(mOriginalBitmap, filters, mEnvironment);
390         buffer.setProducer(result);
391         mEnvironment.cache(result);
392     }
393
394     public synchronized void computeOld(SharedBuffer buffer, ImagePreset preset, int type) {
395         synchronized (CachingPipeline.class) {
396             if (getRenderScriptContext() == null) {
397                 return;
398             }
399             if (DEBUG) {
400                 Log.v(LOGTAG, "compute preset " + preset);
401                 preset.showFilters();
402             }
403
404             String thread = Thread.currentThread().getName();
405             long time = System.currentTimeMillis();
406             setupEnvironment(preset, false);
407             mFiltersManager.freeFilterResources(preset);
408
409             Bitmap resizedOriginalBitmap = mResizedOriginalBitmap;
410             if (updateOriginalAllocation(preset) || buffer.getProducer() == null) {
411                 resizedOriginalBitmap = mResizedOriginalBitmap;
412                 buffer.setProducer(resizedOriginalBitmap);
413                 mEnvironment.cache(buffer.getProducer());
414             }
415
416             Bitmap bitmap = buffer.getProducer().getBitmap();
417             long time2 = System.currentTimeMillis();
418
419             if (bitmap == null || (bitmap.getWidth() != resizedOriginalBitmap.getWidth())
420                     || (bitmap.getHeight() != resizedOriginalBitmap.getHeight())) {
421                 mEnvironment.cache(buffer.getProducer());
422                 buffer.setProducer(resizedOriginalBitmap);
423                 bitmap = buffer.getProducer().getBitmap();
424             }
425             mOriginalAllocation.copyTo(bitmap);
426
427             Bitmap tmpbitmap = preset.apply(bitmap, mEnvironment);
428             if (tmpbitmap != bitmap) {
429                 mEnvironment.cache(buffer.getProducer());
430                 buffer.setProducer(tmpbitmap);
431             }
432
433             mFiltersManager.freeFilterResources(preset);
434
435             time = System.currentTimeMillis() - time;
436             time2 = System.currentTimeMillis() - time2;
437             if (DEBUG) {
438                 Log.v(LOGTAG, "Applying type " + type + " filters to bitmap "
439                         + bitmap + " (" + bitmap.getWidth() + " x " + bitmap.getHeight()
440                         + ") took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread);
441             }
442         }
443     }
444
445     public boolean needsRepaint() {
446         SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer();
447         return buffer.checkRepaintNeeded();
448     }
449
450     public void setPreviewScaleFactor(float previewScaleFactor) {
451         mPreviewScaleFactor = previewScaleFactor;
452     }
453
454     public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
455         mHighResPreviewScaleFactor = highResPreviewScaleFactor;
456     }
457
458     public synchronized boolean isInitialized() {
459         return getRenderScriptContext() != null && mOriginalBitmap != null;
460     }
461
462     public boolean prepareRenderscriptAllocations(Bitmap bitmap) {
463         RenderScript RS = getRenderScriptContext();
464         boolean needsUpdate = false;
465         if (mOutPixelsAllocation == null || mInPixelsAllocation == null ||
466                 bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) {
467             destroyPixelAllocations();
468             Bitmap bitmapBuffer = bitmap;
469             if (bitmap.getConfig() == null || bitmap.getConfig() != BITMAP_CONFIG) {
470                 bitmapBuffer = bitmap.copy(BITMAP_CONFIG, true);
471             }
472             mOutPixelsAllocation = Allocation.createFromBitmap(RS, bitmapBuffer,
473                     Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
474             mInPixelsAllocation = Allocation.createTyped(RS,
475                     mOutPixelsAllocation.getType());
476             needsUpdate = true;
477         }
478         if (RS != null) {
479             mInPixelsAllocation.copyFrom(bitmap);
480         }
481         if (bitmap.getWidth() != mWidth
482                 || bitmap.getHeight() != mHeight) {
483             mWidth = bitmap.getWidth();
484             mHeight = bitmap.getHeight();
485             needsUpdate = true;
486         }
487         if (DEBUG) {
488             Log.v(LOGTAG, "prepareRenderscriptAllocations: " + needsUpdate + " in " + getName());
489         }
490         return needsUpdate;
491     }
492
493     public synchronized Allocation getInPixelsAllocation() {
494         return mInPixelsAllocation;
495     }
496
497     public synchronized Allocation getOutPixelsAllocation() {
498         return mOutPixelsAllocation;
499     }
500
501     public String getName() {
502         return mName;
503     }
504
505     public RenderScript getRSContext() {
506         return CachingPipeline.getRenderScriptContext();
507     }
508 }