OSDN Git Service

Move classes to pipeline package
[android-x86/packages-apps-Gallery2.git] / src / com / android / gallery3d / filtershow / pipeline / 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.pipeline;
18
19 import android.graphics.Bitmap;
20 import android.os.*;
21 import android.os.Process;
22 import android.util.Log;
23
24 import com.android.gallery3d.filtershow.cache.ImageLoader;
25 import com.android.gallery3d.filtershow.filters.FiltersManager;
26 import com.android.gallery3d.filtershow.imageshow.MasterImage;
27
28 public class FilteringPipeline implements Handler.Callback {
29
30     private static volatile FilteringPipeline sPipeline = null;
31     private static final String LOGTAG = "FilteringPipeline";
32     private boolean DEBUG = false;
33
34     private static long HIRES_DELAY = 300; // in ms
35
36     private volatile boolean mPipelineIsOn = false;
37
38     private CachingPipeline mAccessoryPipeline = null;
39     private CachingPipeline mPreviewPipeline = null;
40     private CachingPipeline mHighresPreviewPipeline = null;
41
42     private HandlerThread mHandlerThread = null;
43     private final static int NEW_PRESET = 0;
44     private final static int NEW_RENDERING_REQUEST = 1;
45     private final static int COMPUTE_PRESET = 2;
46     private final static int COMPUTE_RENDERING_REQUEST = 3;
47     private final static int COMPUTE_PARTIAL_RENDERING_REQUEST = 4;
48     private final static int COMPUTE_HIGHRES_RENDERING_REQUEST = 5;
49
50     private volatile boolean mHasUnhandledPreviewRequest = false;
51
52     private String getType(int value) {
53         if (value == COMPUTE_RENDERING_REQUEST) {
54             return "COMPUTE_RENDERING_REQUEST";
55         }
56         if (value == COMPUTE_PARTIAL_RENDERING_REQUEST) {
57             return "COMPUTE_PARTIAL_RENDERING_REQUEST";
58         }
59         if (value == COMPUTE_HIGHRES_RENDERING_REQUEST) {
60             return "COMPUTE_HIGHRES_RENDERING_REQUEST";
61         }
62         return "UNKNOWN TYPE";
63     }
64
65     private Handler mProcessingHandler = null;
66     private final Handler mUIHandler = new Handler() {
67         @Override
68         public void handleMessage(Message msg) {
69             switch (msg.what) {
70                 case NEW_PRESET: {
71                     MasterImage.getImage().notifyObservers();
72                     if (mHasUnhandledPreviewRequest) {
73                         updatePreviewBuffer();
74                     }
75                     break;
76                 }
77                 case NEW_RENDERING_REQUEST: {
78                     RenderingRequest request = (RenderingRequest) msg.obj;
79                     request.markAvailable();
80                     break;
81                 }
82             }
83         }
84     };
85
86     @Override
87     public boolean handleMessage(Message msg) {
88         if (!mPipelineIsOn) {
89             return false;
90         }
91         switch (msg.what) {
92             case COMPUTE_PRESET: {
93                 SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer();
94                 SharedPreset preset = MasterImage.getImage().getPreviewPreset();
95                 ImagePreset renderingPreset = preset.dequeuePreset();
96                 if (renderingPreset != null) {
97                     mPreviewPipeline.compute(buffer, renderingPreset, COMPUTE_PRESET);
98                     // set the preset we used in the buffer for later inspection UI-side
99                     buffer.getProducer().setPreset(renderingPreset);
100                     buffer.getProducer().sync();
101                     buffer.swapProducer(); // push back the result
102                     Message uimsg = mUIHandler.obtainMessage(NEW_PRESET);
103                     mUIHandler.sendMessage(uimsg);
104                 }
105                 break;
106             }
107             case COMPUTE_RENDERING_REQUEST:
108             case COMPUTE_PARTIAL_RENDERING_REQUEST:
109             case COMPUTE_HIGHRES_RENDERING_REQUEST: {
110
111                 if (DEBUG) {
112                     Log.v(LOGTAG, "Compute Request: " + getType(msg.what));
113                 }
114
115                 RenderingRequest request = (RenderingRequest) msg.obj;
116                 if (msg.what == COMPUTE_HIGHRES_RENDERING_REQUEST) {
117                     mHighresPreviewPipeline.render(request);
118                 } else {
119                     mAccessoryPipeline.render(request);
120                 }
121                 if (request.getBitmap() != null) {
122                     Message uimsg = mUIHandler.obtainMessage(NEW_RENDERING_REQUEST);
123                     uimsg.obj = request;
124                     mUIHandler.sendMessage(uimsg);
125                 }
126                 break;
127             }
128         }
129         return false;
130     }
131
132     private FilteringPipeline() {
133         mHandlerThread = new HandlerThread("FilteringPipeline",
134                 Process.THREAD_PRIORITY_FOREGROUND);
135         mHandlerThread.start();
136         mProcessingHandler = new Handler(mHandlerThread.getLooper(), this);
137         mAccessoryPipeline = new CachingPipeline(
138                 FiltersManager.getManager(), "Accessory");
139         mPreviewPipeline = new CachingPipeline(
140                 FiltersManager.getPreviewManager(), "Preview");
141         mHighresPreviewPipeline = new CachingPipeline(
142                 FiltersManager.getHighresManager(), "Highres");
143     }
144
145     public synchronized static FilteringPipeline getPipeline() {
146         if (sPipeline == null) {
147             sPipeline = new FilteringPipeline();
148         }
149         return sPipeline;
150     }
151
152     public void setOriginal(Bitmap bitmap) {
153         if (mPipelineIsOn) {
154             Log.e(LOGTAG, "setOriginal called after pipeline initialization!");
155             return;
156         }
157         mAccessoryPipeline.setOriginal(bitmap);
158         mPreviewPipeline.setOriginal(bitmap);
159         mHighresPreviewPipeline.setOriginal(bitmap);
160     }
161
162     public void postRenderingRequest(RenderingRequest request) {
163         if (!mPipelineIsOn) {
164             return;
165         }
166         int type = COMPUTE_RENDERING_REQUEST;
167         if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
168             type = COMPUTE_PARTIAL_RENDERING_REQUEST;
169         }
170         if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
171             type = COMPUTE_HIGHRES_RENDERING_REQUEST;
172             ImageLoader imageLoader = MasterImage.getImage().getImageLoader();
173             if (imageLoader.getOriginalBitmapHighres() == null) {
174                 return;
175             }
176         }
177         Message msg = mProcessingHandler.obtainMessage(type);
178         msg.obj = request;
179         if (type == COMPUTE_PARTIAL_RENDERING_REQUEST
180                 || type == COMPUTE_HIGHRES_RENDERING_REQUEST) {
181             if (mProcessingHandler.hasMessages(msg.what)) {
182                 mProcessingHandler.removeMessages(msg.what);
183             }
184             mProcessingHandler.sendMessageDelayed(msg, HIRES_DELAY);
185         } else {
186             mProcessingHandler.sendMessage(msg);
187         }
188     }
189
190     public void updatePreviewBuffer() {
191         if (!mPipelineIsOn) {
192             return;
193         }
194         mHasUnhandledPreviewRequest = true;
195         mHighresPreviewPipeline.stop();
196         if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
197             return;
198         }
199         if (!mPreviewPipeline.needsRepaint()) {
200             return;
201         }
202         if (MasterImage.getImage().getPreset() == null) {
203             return;
204         }
205         Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
206         msg.obj = MasterImage.getImage().getPreset();
207         mHasUnhandledPreviewRequest = false;
208         mProcessingHandler.sendMessageAtFrontOfQueue(msg);
209     }
210
211     public void setPreviewScaleFactor(float previewScaleFactor) {
212         mAccessoryPipeline.setPreviewScaleFactor(previewScaleFactor);
213         mPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
214         mHighresPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
215     }
216
217     public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
218         mAccessoryPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
219         mPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
220         mHighresPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
221     }
222
223     public static synchronized void reset() {
224         sPipeline.mAccessoryPipeline.reset();
225         sPipeline.mPreviewPipeline.reset();
226         sPipeline.mHighresPreviewPipeline.reset();
227         sPipeline.mHandlerThread.quit();
228         sPipeline = null;
229     }
230
231     public void turnOnPipeline(boolean t) {
232         mPipelineIsOn = t;
233         if (mPipelineIsOn) {
234             assert(mPreviewPipeline.isInitialized());
235             assert(mAccessoryPipeline.isInitialized());
236             assert(mHighresPreviewPipeline.isInitialized());
237             updatePreviewBuffer();
238         }
239     }
240 }