/* * 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.cache; import android.graphics.Bitmap; import android.os.*; import android.os.Process; import android.support.v8.renderscript.*; import android.util.Log; import com.android.gallery3d.filtershow.filters.FiltersManager; import com.android.gallery3d.filtershow.filters.ImageFilterRS; import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; import com.android.gallery3d.filtershow.imageshow.MasterImage; import com.android.gallery3d.filtershow.pipeline.SharedBuffer; import com.android.gallery3d.filtershow.presets.ImagePreset; 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: { SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer(); buffer.swapConsumer(); 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: { ImagePreset preset = (ImagePreset) msg.obj; SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer(); mPreviewPipeline.compute(buffer, preset, COMPUTE_PRESET); buffer.swapProducer(); 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; } 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(); } } }