diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/pipeline/FilteringPipeline.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/pipeline/FilteringPipeline.java | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilteringPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/FilteringPipeline.java new file mode 100644 index 000000000..1fec62197 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/pipeline/FilteringPipeline.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.filtershow.pipeline; + +import android.graphics.Bitmap; +import android.os.*; +import android.os.Process; +import android.util.Log; + +import com.android.gallery3d.filtershow.cache.ImageLoader; +import com.android.gallery3d.filtershow.filters.FiltersManager; +import com.android.gallery3d.filtershow.imageshow.MasterImage; + +public class FilteringPipeline implements Handler.Callback { + + private static volatile FilteringPipeline sPipeline = null; + private static final String LOGTAG = "FilteringPipeline"; + private boolean DEBUG = false; + + private static long HIRES_DELAY = 300; // in ms + + private volatile boolean mPipelineIsOn = false; + + private CachingPipeline mAccessoryPipeline = null; + private CachingPipeline mPreviewPipeline = null; + private CachingPipeline mHighresPreviewPipeline = null; + + private HandlerThread mHandlerThread = null; + private final static int NEW_PRESET = 0; + private final static int NEW_RENDERING_REQUEST = 1; + private final static int COMPUTE_PRESET = 2; + private final static int COMPUTE_RENDERING_REQUEST = 3; + private final static int COMPUTE_PARTIAL_RENDERING_REQUEST = 4; + private final static int COMPUTE_HIGHRES_RENDERING_REQUEST = 5; + + private volatile boolean mHasUnhandledPreviewRequest = false; + + private String getType(int value) { + if (value == COMPUTE_RENDERING_REQUEST) { + return "COMPUTE_RENDERING_REQUEST"; + } + if (value == COMPUTE_PARTIAL_RENDERING_REQUEST) { + return "COMPUTE_PARTIAL_RENDERING_REQUEST"; + } + if (value == COMPUTE_HIGHRES_RENDERING_REQUEST) { + return "COMPUTE_HIGHRES_RENDERING_REQUEST"; + } + return "UNKNOWN TYPE"; + } + + private Handler mProcessingHandler = null; + private final Handler mUIHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case NEW_PRESET: { + MasterImage.getImage().notifyObservers(); + if (mHasUnhandledPreviewRequest) { + updatePreviewBuffer(); + } + break; + } + case NEW_RENDERING_REQUEST: { + RenderingRequest request = (RenderingRequest) msg.obj; + request.markAvailable(); + break; + } + } + } + }; + + @Override + public boolean handleMessage(Message msg) { + if (!mPipelineIsOn) { + return false; + } + switch (msg.what) { + case COMPUTE_PRESET: { + SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer(); + SharedPreset preset = MasterImage.getImage().getPreviewPreset(); + ImagePreset renderingPreset = preset.dequeuePreset(); + if (renderingPreset != null) { + mPreviewPipeline.compute(buffer, renderingPreset, COMPUTE_PRESET); + // set the preset we used in the buffer for later inspection UI-side + buffer.getProducer().setPreset(renderingPreset); + buffer.getProducer().sync(); + buffer.swapProducer(); // push back the result + Message uimsg = mUIHandler.obtainMessage(NEW_PRESET); + mUIHandler.sendMessage(uimsg); + } + break; + } + case COMPUTE_RENDERING_REQUEST: + case COMPUTE_PARTIAL_RENDERING_REQUEST: + case COMPUTE_HIGHRES_RENDERING_REQUEST: { + + if (DEBUG) { + Log.v(LOGTAG, "Compute Request: " + getType(msg.what)); + } + + RenderingRequest request = (RenderingRequest) msg.obj; + if (msg.what == COMPUTE_HIGHRES_RENDERING_REQUEST) { + mHighresPreviewPipeline.render(request); + } else { + mAccessoryPipeline.render(request); + } + if (request.getBitmap() != null) { + Message uimsg = mUIHandler.obtainMessage(NEW_RENDERING_REQUEST); + uimsg.obj = request; + mUIHandler.sendMessage(uimsg); + } + break; + } + } + return false; + } + + private FilteringPipeline() { + mHandlerThread = new HandlerThread("FilteringPipeline", + Process.THREAD_PRIORITY_FOREGROUND); + mHandlerThread.start(); + mProcessingHandler = new Handler(mHandlerThread.getLooper(), this); + mAccessoryPipeline = new CachingPipeline( + FiltersManager.getManager(), "Accessory"); + mPreviewPipeline = new CachingPipeline( + FiltersManager.getPreviewManager(), "Preview"); + mHighresPreviewPipeline = new CachingPipeline( + FiltersManager.getHighresManager(), "Highres"); + } + + public synchronized static FilteringPipeline getPipeline() { + if (sPipeline == null) { + sPipeline = new FilteringPipeline(); + } + return sPipeline; + } + + public void setOriginal(Bitmap bitmap) { + if (mPipelineIsOn) { + Log.e(LOGTAG, "setOriginal called after pipeline initialization!"); + return; + } + mAccessoryPipeline.setOriginal(bitmap); + mPreviewPipeline.setOriginal(bitmap); + mHighresPreviewPipeline.setOriginal(bitmap); + } + + public void postRenderingRequest(RenderingRequest request) { + if (!mPipelineIsOn) { + return; + } + int type = COMPUTE_RENDERING_REQUEST; + if (request.getType() == RenderingRequest.PARTIAL_RENDERING) { + type = COMPUTE_PARTIAL_RENDERING_REQUEST; + } + if (request.getType() == RenderingRequest.HIGHRES_RENDERING) { + type = COMPUTE_HIGHRES_RENDERING_REQUEST; + ImageLoader imageLoader = MasterImage.getImage().getImageLoader(); + if (imageLoader.getOriginalBitmapHighres() == null) { + return; + } + } + Message msg = mProcessingHandler.obtainMessage(type); + msg.obj = request; + if (type == COMPUTE_PARTIAL_RENDERING_REQUEST + || type == COMPUTE_HIGHRES_RENDERING_REQUEST) { + if (mProcessingHandler.hasMessages(msg.what)) { + mProcessingHandler.removeMessages(msg.what); + } + mProcessingHandler.sendMessageDelayed(msg, HIRES_DELAY); + } else { + mProcessingHandler.sendMessage(msg); + } + } + + public void updatePreviewBuffer() { + if (!mPipelineIsOn) { + return; + } + mHasUnhandledPreviewRequest = true; + mHighresPreviewPipeline.stop(); + if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) { + return; + } + if (!mPreviewPipeline.needsRepaint()) { + return; + } + if (MasterImage.getImage().getPreset() == null) { + return; + } + Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET); + msg.obj = MasterImage.getImage().getPreset(); + mHasUnhandledPreviewRequest = false; + mProcessingHandler.sendMessageAtFrontOfQueue(msg); + } + + public void setPreviewScaleFactor(float previewScaleFactor) { + mAccessoryPipeline.setPreviewScaleFactor(previewScaleFactor); + mPreviewPipeline.setPreviewScaleFactor(previewScaleFactor); + mHighresPreviewPipeline.setPreviewScaleFactor(previewScaleFactor); + } + + public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) { + mAccessoryPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor); + mPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor); + mHighresPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor); + } + + public static synchronized void reset() { + sPipeline.mAccessoryPipeline.reset(); + sPipeline.mPreviewPipeline.reset(); + sPipeline.mHighresPreviewPipeline.reset(); + sPipeline.mHandlerThread.quit(); + sPipeline = null; + } + + public void turnOnPipeline(boolean t) { + mPipelineIsOn = t; + if (mPipelineIsOn) { + assert(mPreviewPipeline.isInitialized()); + assert(mAccessoryPipeline.isInitialized()); + assert(mHighresPreviewPipeline.isInitialized()); + updatePreviewBuffer(); + } + } +} |