OSDN Git Service

Switch Gallery over to RS compatibility library.
[android-x86/packages-apps-Gallery2.git] / src / com / android / gallery3d / filtershow / cache / FilteringPipeline.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.cache;
18
19 import android.graphics.Bitmap;
20 import android.os.*;
21 import android.os.Process;
22 import android.support.v8.renderscript.*;
23 import android.util.Log;
24
25 import com.android.gallery3d.filtershow.filters.ImageFilterRS;
26 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
27 import com.android.gallery3d.filtershow.imageshow.MasterImage;
28 import com.android.gallery3d.filtershow.presets.ImagePreset;
29
30 public class FilteringPipeline implements Handler.Callback {
31
32     private final static FilteringPipeline gPipeline = new FilteringPipeline();
33     private static final String LOGTAG = "FilteringPipeline";
34     private ImagePreset mPreviousPreset = null;
35     private ImagePreset mPreviousGeometryPreset = null;
36     private ImagePreset mPreviousFiltersPreset = null;
37     private GeometryMetadata mPreviousGeometry = null;
38
39     private Bitmap mOriginalBitmap = null;
40     private Bitmap mResizedOriginalBitmap = null;
41
42     private boolean DEBUG = false;
43
44     private HandlerThread mHandlerThread = null;
45     private final static int NEW_PRESET = 0;
46     private final static int COMPUTE_PRESET = 1;
47     private final static int COMPUTE_GEOMETRY_PRESET = 2;
48     private final static int COMPUTE_FILTERS_PRESET = 3;
49
50     private boolean mProcessing = false;
51
52     private Handler mProcessingHandler = null;
53     private final Handler mUIHandler = new Handler() {
54         @Override
55         public void handleMessage(Message msg) {
56             switch (msg.what) {
57                 case NEW_PRESET: {
58                     MasterImage.getImage().notifyObservers();
59                     mProcessing = false;
60                     break;
61                 }
62             }
63         }
64     };
65
66     @Override
67     public boolean handleMessage(Message msg) {
68         switch (msg.what) {
69             case COMPUTE_PRESET: {
70                 ImagePreset preset = MasterImage.getImage().getPreset();
71                 TripleBufferBitmap buffer = MasterImage.getImage().getDoubleBuffer();
72                 compute(buffer, preset, COMPUTE_PRESET);
73                 Message uimsg = mUIHandler.obtainMessage(NEW_PRESET);
74                 mUIHandler.sendMessage(uimsg);
75                 break;
76             }
77             case COMPUTE_GEOMETRY_PRESET: {
78                 ImagePreset preset = MasterImage.getImage().getGeometryPreset();
79                 TripleBufferBitmap buffer = MasterImage.getImage().getGeometryOnlyBuffer();
80                 compute(buffer, preset, COMPUTE_GEOMETRY_PRESET);
81                 Message uimsg = mUIHandler.obtainMessage(NEW_PRESET);
82                 mUIHandler.sendMessage(uimsg);
83                 break;
84             }
85             case COMPUTE_FILTERS_PRESET: {
86                 ImagePreset preset = MasterImage.getImage().getFiltersOnlyPreset();
87                 TripleBufferBitmap buffer = MasterImage.getImage().getFiltersOnlyBuffer();
88                 compute(buffer, preset, COMPUTE_FILTERS_PRESET);
89                 Message uimsg = mUIHandler.obtainMessage(NEW_PRESET);
90                 mUIHandler.sendMessage(uimsg);
91                 break;
92             }
93         }
94         return false;
95     }
96
97     private static float RESIZE_FACTOR = 0.8f;
98     private static float MAX_PROCESS_TIME = 100; // in ms
99     private float mResizeFactor = 1.0f;
100     private long mResizeTime = 0;
101
102     private Allocation mOriginalBitmapAllocation = null;
103     private Allocation mOriginalAllocation = null;
104     private Allocation mFiltersOnlyOriginalAllocation =  null;
105
106     private FilteringPipeline() {
107         mHandlerThread = new HandlerThread("FilteringPipeline",
108                 Process.THREAD_PRIORITY_FOREGROUND);
109         mHandlerThread.start();
110         mProcessingHandler = new Handler(mHandlerThread.getLooper(), this);
111     }
112
113     public static FilteringPipeline getPipeline() {
114         return gPipeline;
115     }
116
117     public synchronized void setOriginal(Bitmap bitmap) {
118         mOriginalBitmap = bitmap;
119         Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight());
120         updateOriginalAllocation(MasterImage.getImage().getPreset());
121     }
122
123     public synchronized boolean updateOriginalAllocation(ImagePreset preset) {
124         if (mOriginalBitmap == null) {
125             return false;
126         }
127         /*
128         //FIXME: turn back on the on-the-fly resize.
129         int w = (int) (mOriginalBitmap.getWidth() * mResizeFactor);
130         int h = (int) (mOriginalBitmap.getHeight() * mResizeFactor);
131         if (!needsGeometryRepaint() && mResizedOriginalBitmap != null && w == mResizedOriginalBitmap.getWidth()) {
132             return false;
133         }
134         mResizedOriginalBitmap = Bitmap.createScaledBitmap(mOriginalBitmap, w, h, true);
135         */
136         GeometryMetadata geometry = preset.getGeometry();
137         if (mPreviousGeometry != null && geometry.equals(mPreviousGeometry)) {
138             return false;
139         }
140         RenderScript RS = ImageFilterRS.getRenderScriptContext();
141         if (mFiltersOnlyOriginalAllocation != null) {
142             mFiltersOnlyOriginalAllocation.destroy();
143         }
144         mFiltersOnlyOriginalAllocation = Allocation.createFromBitmap(RS, mOriginalBitmap,
145                 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
146         if (mOriginalAllocation != null) {
147             mOriginalAllocation.destroy();
148         }
149         mResizedOriginalBitmap = preset.applyGeometry(mOriginalBitmap);
150         mOriginalAllocation = Allocation.createFromBitmap(RS, mResizedOriginalBitmap,
151                 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
152         mPreviousGeometry = new GeometryMetadata(geometry);
153         return true;
154     }
155
156     public synchronized void updatePreviewBuffer() {
157         if (mOriginalAllocation == null) {
158             return;
159         }
160         if (mProcessing) {
161             return;
162         }
163         if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
164             return;
165         }
166         if (!needsRepaint()) {
167             return;
168         }
169         Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
170         mProcessingHandler.sendMessage(msg);
171         mProcessing = true;
172     }
173
174     public void updateGeometryOnlyPreviewBuffer() {
175         if (mOriginalAllocation == null) {
176             return;
177         }
178         if (mProcessing) {
179             return;
180         }
181         if (mProcessingHandler.hasMessages(COMPUTE_GEOMETRY_PRESET)) {
182             return;
183         }
184         if (!needsGeometryRepaint()) {
185             return;
186         }
187         Message msg = mProcessingHandler.obtainMessage(COMPUTE_GEOMETRY_PRESET);
188         mProcessingHandler.sendMessage(msg);
189         mProcessing = true;
190     }
191
192     public void updateFiltersOnlyPreviewBuffer() {
193         if (mOriginalAllocation == null) {
194             return;
195         }
196         if (mProcessing) {
197             return;
198         }
199         if (mProcessingHandler.hasMessages(COMPUTE_FILTERS_PRESET)) {
200             return;
201         }
202         if (!needsFiltersRepaint()) {
203             return;
204         }
205         Message msg = mProcessingHandler.obtainMessage(COMPUTE_FILTERS_PRESET);
206         mProcessingHandler.sendMessage(msg);
207         mProcessing = true;
208     }
209
210     private void compute(TripleBufferBitmap buffer, ImagePreset preset, int type) {
211         String thread = Thread.currentThread().getName();
212         long time = System.currentTimeMillis();
213         if (updateOriginalAllocation(preset)) {
214             buffer.updateBitmaps(mResizedOriginalBitmap);
215         }
216         Bitmap bitmap = buffer.getProducer();
217         long time2 = System.currentTimeMillis();
218
219         if (type != COMPUTE_FILTERS_PRESET) {
220             if (bitmap == null || (bitmap.getWidth() != mResizedOriginalBitmap.getWidth())
221                     || (bitmap.getHeight() != mResizedOriginalBitmap.getHeight())) {
222                 buffer.updateBitmaps(mResizedOriginalBitmap);
223                 bitmap = buffer.getProducer();
224             }
225             mOriginalAllocation.copyTo(bitmap);
226         } else {
227             if (bitmap == null || (bitmap.getWidth() != mOriginalBitmap.getWidth())
228                     || (bitmap.getHeight() != mOriginalBitmap.getHeight())) {
229                 buffer.updateBitmaps(mOriginalBitmap);
230                 bitmap = buffer.getProducer();
231             }
232             mFiltersOnlyOriginalAllocation.copyTo(bitmap);
233         }
234
235         if (mOriginalAllocation == null || bitmap == null) {
236             Log.v(LOGTAG, "exiting compute because mOriginalAllocation: " + mOriginalAllocation + " or bitmap: " + bitmap);
237             return;
238         }
239
240         if (type != COMPUTE_GEOMETRY_PRESET) {
241             bitmap = preset.apply(bitmap);
242         }
243
244         buffer.swapProducer();
245         time = System.currentTimeMillis() - time;
246         time2 = System.currentTimeMillis() - time2;
247         if (DEBUG) {
248             Log.v(LOGTAG, "Applying " + type + " filters to bitmap " + bitmap + " took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread);
249         }
250         if (type == COMPUTE_PRESET) {
251             mPreviousPreset = new ImagePreset(preset);
252             if (mResizeFactor > 0.6 && time > MAX_PROCESS_TIME && (System.currentTimeMillis() + 1000 > mResizeTime)) {
253                 mResizeTime = System.currentTimeMillis();
254                 mResizeFactor *= RESIZE_FACTOR;
255             }
256         } else if (type == COMPUTE_GEOMETRY_PRESET) {
257             mPreviousGeometryPreset = new ImagePreset(preset);
258         } else if (type == COMPUTE_FILTERS_PRESET) {
259             mPreviousFiltersPreset = new ImagePreset(preset);
260         }
261     }
262
263     private synchronized boolean needsRepaint() {
264         ImagePreset preset = MasterImage.getImage().getPreset();
265         if (preset == null || mPreviousPreset == null) {
266             return true;
267         }
268         if (preset.equals(mPreviousPreset)) {
269             return false;
270         }
271         return true;
272     }
273
274     private synchronized boolean needsGeometryRepaint() {
275         ImagePreset preset = MasterImage.getImage().getPreset();
276         if (preset == null || mPreviousGeometry == null || mPreviousGeometryPreset == null) {
277             return true;
278         }
279         GeometryMetadata geometry = preset.getGeometry();
280         if (geometry.equals(mPreviousGeometryPreset.getGeometry())) {
281             return false;
282         }
283         return true;
284     }
285
286     private synchronized boolean needsFiltersRepaint() {
287         ImagePreset preset = MasterImage.getImage().getPreset();
288         if (preset == null || mPreviousFiltersPreset == null) {
289             return true;
290         }
291         if (preset.equals(mPreviousFiltersPreset)) {
292             return false;
293         }
294         return true;
295     }
296 }