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.cache;
19 import android.graphics.Bitmap;
21 import android.os.Process;
22 import android.support.v8.renderscript.*;
23 import android.util.Log;
25 import com.android.gallery3d.filtershow.filters.FiltersManager;
26 import com.android.gallery3d.filtershow.filters.ImageFilterRS;
27 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
28 import com.android.gallery3d.filtershow.imageshow.MasterImage;
29 import com.android.gallery3d.filtershow.pipeline.SharedBuffer;
30 import com.android.gallery3d.filtershow.pipeline.SharedPreset;
31 import com.android.gallery3d.filtershow.presets.ImagePreset;
33 public class FilteringPipeline implements Handler.Callback {
35 private static volatile FilteringPipeline sPipeline = null;
36 private static final String LOGTAG = "FilteringPipeline";
37 private boolean DEBUG = false;
39 private static long HIRES_DELAY = 300; // in ms
41 private volatile boolean mPipelineIsOn = false;
43 private CachingPipeline mAccessoryPipeline = null;
44 private CachingPipeline mPreviewPipeline = null;
45 private CachingPipeline mHighresPreviewPipeline = null;
47 private HandlerThread mHandlerThread = null;
48 private final static int NEW_PRESET = 0;
49 private final static int NEW_RENDERING_REQUEST = 1;
50 private final static int COMPUTE_PRESET = 2;
51 private final static int COMPUTE_RENDERING_REQUEST = 3;
52 private final static int COMPUTE_PARTIAL_RENDERING_REQUEST = 4;
53 private final static int COMPUTE_HIGHRES_RENDERING_REQUEST = 5;
55 private volatile boolean mHasUnhandledPreviewRequest = false;
57 private String getType(int value) {
58 if (value == COMPUTE_RENDERING_REQUEST) {
59 return "COMPUTE_RENDERING_REQUEST";
61 if (value == COMPUTE_PARTIAL_RENDERING_REQUEST) {
62 return "COMPUTE_PARTIAL_RENDERING_REQUEST";
64 if (value == COMPUTE_HIGHRES_RENDERING_REQUEST) {
65 return "COMPUTE_HIGHRES_RENDERING_REQUEST";
67 return "UNKNOWN TYPE";
70 private Handler mProcessingHandler = null;
71 private final Handler mUIHandler = new Handler() {
73 public void handleMessage(Message msg) {
76 MasterImage.getImage().notifyObservers();
77 if (mHasUnhandledPreviewRequest) {
78 updatePreviewBuffer();
82 case NEW_RENDERING_REQUEST: {
83 RenderingRequest request = (RenderingRequest) msg.obj;
84 request.markAvailable();
92 public boolean handleMessage(Message msg) {
97 case COMPUTE_PRESET: {
98 SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer();
99 SharedPreset preset = MasterImage.getImage().getPreviewPreset();
100 ImagePreset renderingPreset = preset.dequeuePreset();
101 if (renderingPreset != null) {
102 mPreviewPipeline.compute(buffer, renderingPreset, COMPUTE_PRESET);
103 // set the preset we used in the buffer for later inspection UI-side
104 buffer.getProducer().setPreset(renderingPreset);
105 buffer.getProducer().sync();
106 buffer.swapProducer(); // push back the result
107 Message uimsg = mUIHandler.obtainMessage(NEW_PRESET);
108 mUIHandler.sendMessage(uimsg);
112 case COMPUTE_RENDERING_REQUEST:
113 case COMPUTE_PARTIAL_RENDERING_REQUEST:
114 case COMPUTE_HIGHRES_RENDERING_REQUEST: {
117 Log.v(LOGTAG, "Compute Request: " + getType(msg.what));
120 RenderingRequest request = (RenderingRequest) msg.obj;
121 if (msg.what == COMPUTE_HIGHRES_RENDERING_REQUEST) {
122 mHighresPreviewPipeline.render(request);
124 mAccessoryPipeline.render(request);
126 if (request.getBitmap() != null) {
127 Message uimsg = mUIHandler.obtainMessage(NEW_RENDERING_REQUEST);
129 mUIHandler.sendMessage(uimsg);
137 private FilteringPipeline() {
138 mHandlerThread = new HandlerThread("FilteringPipeline",
139 Process.THREAD_PRIORITY_FOREGROUND);
140 mHandlerThread.start();
141 mProcessingHandler = new Handler(mHandlerThread.getLooper(), this);
142 mAccessoryPipeline = new CachingPipeline(
143 FiltersManager.getManager(), "Accessory");
144 mPreviewPipeline = new CachingPipeline(
145 FiltersManager.getPreviewManager(), "Preview");
146 mHighresPreviewPipeline = new CachingPipeline(
147 FiltersManager.getHighresManager(), "Highres");
150 public synchronized static FilteringPipeline getPipeline() {
151 if (sPipeline == null) {
152 sPipeline = new FilteringPipeline();
157 public void setOriginal(Bitmap bitmap) {
159 Log.e(LOGTAG, "setOriginal called after pipeline initialization!");
162 mAccessoryPipeline.setOriginal(bitmap);
163 mPreviewPipeline.setOriginal(bitmap);
164 mHighresPreviewPipeline.setOriginal(bitmap);
167 public void postRenderingRequest(RenderingRequest request) {
168 if (!mPipelineIsOn) {
171 int type = COMPUTE_RENDERING_REQUEST;
172 if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
173 type = COMPUTE_PARTIAL_RENDERING_REQUEST;
175 if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
176 type = COMPUTE_HIGHRES_RENDERING_REQUEST;
177 ImageLoader imageLoader = MasterImage.getImage().getImageLoader();
178 if (imageLoader.getOriginalBitmapHighres() == null) {
182 Message msg = mProcessingHandler.obtainMessage(type);
184 if (type == COMPUTE_PARTIAL_RENDERING_REQUEST
185 || type == COMPUTE_HIGHRES_RENDERING_REQUEST) {
186 if (mProcessingHandler.hasMessages(msg.what)) {
187 mProcessingHandler.removeMessages(msg.what);
189 mProcessingHandler.sendMessageDelayed(msg, HIRES_DELAY);
191 mProcessingHandler.sendMessage(msg);
195 public void updatePreviewBuffer() {
196 if (!mPipelineIsOn) {
199 mHasUnhandledPreviewRequest = true;
200 mHighresPreviewPipeline.stop();
201 if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
204 if (!mPreviewPipeline.needsRepaint()) {
207 if (MasterImage.getImage().getPreset() == null) {
210 Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
211 msg.obj = MasterImage.getImage().getPreset();
212 mHasUnhandledPreviewRequest = false;
213 mProcessingHandler.sendMessageAtFrontOfQueue(msg);
216 public void setPreviewScaleFactor(float previewScaleFactor) {
217 mAccessoryPipeline.setPreviewScaleFactor(previewScaleFactor);
218 mPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
219 mHighresPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
222 public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
223 mAccessoryPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
224 mPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
225 mHighresPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
228 public static synchronized void reset() {
229 sPipeline.mAccessoryPipeline.reset();
230 sPipeline.mPreviewPipeline.reset();
231 sPipeline.mHighresPreviewPipeline.reset();
232 sPipeline.mHandlerThread.quit();
236 public void turnOnPipeline(boolean t) {
239 assert(mPreviewPipeline.isInitialized());
240 assert(mAccessoryPipeline.isInitialized());
241 assert(mHighresPreviewPipeline.isInitialized());
242 updatePreviewBuffer();