OSDN Git Service

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