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.pipeline;
19 import android.graphics.Bitmap;
21 import android.os.Process;
22 import android.util.Log;
24 import com.android.gallery3d.filtershow.cache.ImageLoader;
25 import com.android.gallery3d.filtershow.filters.FiltersManager;
26 import com.android.gallery3d.filtershow.imageshow.MasterImage;
28 public class FilteringPipeline implements Handler.Callback {
30 private static volatile FilteringPipeline sPipeline = null;
31 private static final String LOGTAG = "FilteringPipeline";
32 private boolean DEBUG = false;
34 private static long HIRES_DELAY = 300; // in ms
36 private volatile boolean mPipelineIsOn = false;
38 private CachingPipeline mAccessoryPipeline = null;
39 private CachingPipeline mPreviewPipeline = null;
40 private CachingPipeline mHighresPreviewPipeline = null;
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;
50 private volatile boolean mHasUnhandledPreviewRequest = false;
52 private String getType(int value) {
53 if (value == COMPUTE_RENDERING_REQUEST) {
54 return "COMPUTE_RENDERING_REQUEST";
56 if (value == COMPUTE_PARTIAL_RENDERING_REQUEST) {
57 return "COMPUTE_PARTIAL_RENDERING_REQUEST";
59 if (value == COMPUTE_HIGHRES_RENDERING_REQUEST) {
60 return "COMPUTE_HIGHRES_RENDERING_REQUEST";
62 return "UNKNOWN TYPE";
65 private Handler mProcessingHandler = null;
66 private final Handler mUIHandler = new Handler() {
68 public void handleMessage(Message msg) {
71 MasterImage.getImage().notifyObservers();
72 if (mHasUnhandledPreviewRequest) {
73 updatePreviewBuffer();
77 case NEW_RENDERING_REQUEST: {
78 RenderingRequest request = (RenderingRequest) msg.obj;
79 request.markAvailable();
87 public boolean handleMessage(Message msg) {
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);
107 case COMPUTE_RENDERING_REQUEST:
108 case COMPUTE_PARTIAL_RENDERING_REQUEST:
109 case COMPUTE_HIGHRES_RENDERING_REQUEST: {
112 Log.v(LOGTAG, "Compute Request: " + getType(msg.what));
115 RenderingRequest request = (RenderingRequest) msg.obj;
116 if (msg.what == COMPUTE_HIGHRES_RENDERING_REQUEST) {
117 mHighresPreviewPipeline.render(request);
119 mAccessoryPipeline.render(request);
121 if (request.getBitmap() != null) {
122 Message uimsg = mUIHandler.obtainMessage(NEW_RENDERING_REQUEST);
124 mUIHandler.sendMessage(uimsg);
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");
145 public synchronized static FilteringPipeline getPipeline() {
146 if (sPipeline == null) {
147 sPipeline = new FilteringPipeline();
152 public void setOriginal(Bitmap bitmap) {
154 Log.e(LOGTAG, "setOriginal called after pipeline initialization!");
157 mAccessoryPipeline.setOriginal(bitmap);
158 mPreviewPipeline.setOriginal(bitmap);
159 mHighresPreviewPipeline.setOriginal(bitmap);
162 public void postRenderingRequest(RenderingRequest request) {
163 if (!mPipelineIsOn) {
166 int type = COMPUTE_RENDERING_REQUEST;
167 if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
168 type = COMPUTE_PARTIAL_RENDERING_REQUEST;
170 if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
171 type = COMPUTE_HIGHRES_RENDERING_REQUEST;
172 ImageLoader imageLoader = MasterImage.getImage().getImageLoader();
173 if (imageLoader.getOriginalBitmapHighres() == null) {
177 Message msg = mProcessingHandler.obtainMessage(type);
179 if (type == COMPUTE_PARTIAL_RENDERING_REQUEST
180 || type == COMPUTE_HIGHRES_RENDERING_REQUEST) {
181 if (mProcessingHandler.hasMessages(msg.what)) {
182 mProcessingHandler.removeMessages(msg.what);
184 mProcessingHandler.sendMessageDelayed(msg, HIRES_DELAY);
186 mProcessingHandler.sendMessage(msg);
190 public void updatePreviewBuffer() {
191 if (!mPipelineIsOn) {
194 mHasUnhandledPreviewRequest = true;
195 mHighresPreviewPipeline.stop();
196 if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
199 if (!mPreviewPipeline.needsRepaint()) {
202 if (MasterImage.getImage().getPreset() == null) {
205 Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
206 msg.obj = MasterImage.getImage().getPreset();
207 mHasUnhandledPreviewRequest = false;
208 mProcessingHandler.sendMessageAtFrontOfQueue(msg);
211 public void setPreviewScaleFactor(float previewScaleFactor) {
212 mAccessoryPipeline.setPreviewScaleFactor(previewScaleFactor);
213 mPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
214 mHighresPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
217 public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
218 mAccessoryPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
219 mPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
220 mHighresPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
223 public static synchronized void reset() {
224 sPipeline.mAccessoryPipeline.reset();
225 sPipeline.mPreviewPipeline.reset();
226 sPipeline.mHighresPreviewPipeline.reset();
227 sPipeline.mHandlerThread.quit();
231 public void turnOnPipeline(boolean t) {
234 assert(mPreviewPipeline.isInitialized());
235 assert(mAccessoryPipeline.isInitialized());
236 assert(mHighresPreviewPipeline.isInitialized());
237 updatePreviewBuffer();