Home | History | Annotate | Download | only in cache
      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.cache;
     18 
     19 import android.graphics.Bitmap;
     20 import android.os.*;
     21 import android.os.Process;
     22 import android.support.v8.renderscript.*;
     23 import android.util.Log;
     24 
     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.presets.ImagePreset;
     30 
     31 public class FilteringPipeline implements Handler.Callback {
     32 
     33     private static volatile FilteringPipeline sPipeline = null;
     34     private static final String LOGTAG = "FilteringPipeline";
     35     private boolean DEBUG = false;
     36 
     37     private static long HIRES_DELAY = 300; // in ms
     38 
     39     private volatile boolean mPipelineIsOn = false;
     40 
     41     private CachingPipeline mAccessoryPipeline = null;
     42     private CachingPipeline mPreviewPipeline = null;
     43     private CachingPipeline mHighresPreviewPipeline = null;
     44 
     45     private HandlerThread mHandlerThread = null;
     46     private final static int NEW_PRESET = 0;
     47     private final static int NEW_RENDERING_REQUEST = 1;
     48     private final static int COMPUTE_PRESET = 2;
     49     private final static int COMPUTE_RENDERING_REQUEST = 3;
     50     private final static int COMPUTE_PARTIAL_RENDERING_REQUEST = 4;
     51     private final static int COMPUTE_HIGHRES_RENDERING_REQUEST = 5;
     52 
     53     private volatile boolean mHasUnhandledPreviewRequest = false;
     54 
     55     private String getType(int value) {
     56         if (value == COMPUTE_RENDERING_REQUEST) {
     57             return "COMPUTE_RENDERING_REQUEST";
     58         }
     59         if (value == COMPUTE_PARTIAL_RENDERING_REQUEST) {
     60             return "COMPUTE_PARTIAL_RENDERING_REQUEST";
     61         }
     62         if (value == COMPUTE_HIGHRES_RENDERING_REQUEST) {
     63             return "COMPUTE_HIGHRES_RENDERING_REQUEST";
     64         }
     65         return "UNKNOWN TYPE";
     66     }
     67 
     68     private Handler mProcessingHandler = null;
     69     private final Handler mUIHandler = new Handler() {
     70         @Override
     71         public void handleMessage(Message msg) {
     72             switch (msg.what) {
     73                 case NEW_PRESET: {
     74                     TripleBufferBitmap buffer = MasterImage.getImage().getDoubleBuffer();
     75                     buffer.swapConsumer();
     76                     MasterImage.getImage().notifyObservers();
     77                     if (mHasUnhandledPreviewRequest) {
     78                         updatePreviewBuffer();
     79                     }
     80                     break;
     81                 }
     82                 case NEW_RENDERING_REQUEST: {
     83                     RenderingRequest request = (RenderingRequest) msg.obj;
     84                     request.markAvailable();
     85                     break;
     86                 }
     87             }
     88         }
     89     };
     90 
     91     @Override
     92     public boolean handleMessage(Message msg) {
     93         if (!mPipelineIsOn) {
     94             return false;
     95         }
     96         switch (msg.what) {
     97             case COMPUTE_PRESET: {
     98                 ImagePreset preset = (ImagePreset) msg.obj;
     99                 TripleBufferBitmap buffer = MasterImage.getImage().getDoubleBuffer();
    100                 mPreviewPipeline.compute(buffer, preset, COMPUTE_PRESET);
    101                 buffer.swapProducer();
    102                 Message uimsg = mUIHandler.obtainMessage(NEW_PRESET);
    103                 mUIHandler.sendMessage(uimsg);
    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         }
    172         Message msg = mProcessingHandler.obtainMessage(type);
    173         msg.obj = request;
    174         if (type == COMPUTE_PARTIAL_RENDERING_REQUEST
    175                 || type == COMPUTE_HIGHRES_RENDERING_REQUEST) {
    176             if (mProcessingHandler.hasMessages(msg.what)) {
    177                 mProcessingHandler.removeMessages(msg.what);
    178             }
    179             mProcessingHandler.sendMessageDelayed(msg, HIRES_DELAY);
    180         } else {
    181             mProcessingHandler.sendMessage(msg);
    182         }
    183     }
    184 
    185     public void updatePreviewBuffer() {
    186         if (!mPipelineIsOn) {
    187             return;
    188         }
    189         mHasUnhandledPreviewRequest = true;
    190         mHighresPreviewPipeline.stop();
    191         if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
    192             return;
    193         }
    194         if (!mPreviewPipeline.needsRepaint()) {
    195             return;
    196         }
    197         if (MasterImage.getImage().getPreset() == null) {
    198             return;
    199         }
    200         Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
    201         msg.obj = MasterImage.getImage().getPreset();
    202         mHasUnhandledPreviewRequest = false;
    203         mProcessingHandler.sendMessageAtFrontOfQueue(msg);
    204     }
    205 
    206     public void setPreviewScaleFactor(float previewScaleFactor) {
    207         mAccessoryPipeline.setPreviewScaleFactor(previewScaleFactor);
    208         mPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
    209         mHighresPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
    210     }
    211 
    212     public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
    213         mAccessoryPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
    214         mPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
    215         mHighresPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
    216     }
    217 
    218     public static synchronized void reset() {
    219         sPipeline.mAccessoryPipeline.reset();
    220         sPipeline.mPreviewPipeline.reset();
    221         sPipeline.mHighresPreviewPipeline.reset();
    222         sPipeline.mHandlerThread.quit();
    223         sPipeline = null;
    224     }
    225 
    226     public void turnOnPipeline(boolean t) {
    227         mPipelineIsOn = t;
    228         if (mPipelineIsOn) {
    229             assert(mPreviewPipeline.isInitialized());
    230             assert(mAccessoryPipeline.isInitialized());
    231             assert(mHighresPreviewPipeline.isInitialized());
    232             updatePreviewBuffer();
    233         }
    234     }
    235 }
    236