| /* | 
 |  * Copyright 2011 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 |  | 
 |  | 
 | #ifndef SkGPipe_DEFINED | 
 | #define SkGPipe_DEFINED | 
 |  | 
 | #include "SkFlattenable.h" | 
 | #include "SkPicture.h" | 
 | #include "SkWriter32.h" | 
 |  | 
 | class SkCanvas; | 
 |  | 
 | // XLib.h might have defined Status already (ugh) | 
 | #ifdef Status | 
 |     #undef Status | 
 | #endif | 
 |  | 
 | class SkGPipeReader { | 
 | public: | 
 |     SkGPipeReader(); | 
 |     SkGPipeReader(SkCanvas* target); | 
 |     ~SkGPipeReader(); | 
 |  | 
 |     enum Status { | 
 |         kDone_Status,   //!< no more data expected from reader | 
 |         kEOF_Status,    //!< need more data from reader | 
 |         kError_Status,  //!< encountered error | 
 |         kReadAtom_Status//!< finished reading an atom | 
 |     }; | 
 |  | 
 |     enum PlaybackFlags { | 
 |         kReadAtom_PlaybackFlag = 0x1, //!< playback a single command from the stream | 
 |         kSilent_PlaybackFlag   = 0x2, //!< playback without drawing | 
 |     }; | 
 |  | 
 |     void setCanvas(SkCanvas*); | 
 |  | 
 |     /** | 
 |      *  Set a function for decoding bitmaps that have encoded data. | 
 |      */ | 
 |     void setBitmapDecoder(SkPicture::InstallPixelRefProc proc) { fProc = proc; } | 
 |  | 
 |     // data must be 4-byte aligned | 
 |     // length must be a multiple of 4 | 
 |     Status playback(const void* data, size_t length, uint32_t playbackFlags = 0, | 
 |                     size_t* bytesRead = NULL); | 
 | private: | 
 |     SkCanvas*                       fCanvas; | 
 |     class SkGPipeState*             fState; | 
 |     SkPicture::InstallPixelRefProc  fProc; | 
 | }; | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | class SkGPipeCanvas; | 
 |  | 
 | class SkGPipeController { | 
 | public: | 
 |     SkGPipeController() : fCanvas(NULL) {} | 
 |     virtual ~SkGPipeController(); | 
 |  | 
 |     /** | 
 |      *  Called periodically by the writer, to get a working buffer of RAM to | 
 |      *  write into. The actual size of the block is also returned, and must be | 
 |      *  actual >= minRequest. If NULL is returned, then actual is ignored and | 
 |      *  writing will stop. | 
 |      * | 
 |      *  The returned block must be 4-byte aligned, and actual must be a | 
 |      *  multiple of 4. | 
 |      *  minRequest will always be a multiple of 4. | 
 |      */ | 
 |     virtual void* requestBlock(size_t minRequest, size_t* actual) = 0; | 
 |  | 
 |     /** | 
 |      *  This is called each time some atomic portion of the data has been | 
 |      *  written to the block (most recently returned by requestBlock()). | 
 |      *  If bytes == 0, then the writer has finished. | 
 |      * | 
 |      *  bytes will always be a multiple of 4. | 
 |      */ | 
 |     virtual void notifyWritten(size_t bytes) = 0; | 
 |     virtual int numberOfReaders() const { return 1; } | 
 |  | 
 | private: | 
 |     friend class SkGPipeWriter; | 
 |     void setCanvas(SkGPipeCanvas*); | 
 |  | 
 |     SkGPipeCanvas* fCanvas; | 
 | }; | 
 |  | 
 | class SkGPipeWriter { | 
 | public: | 
 |     SkGPipeWriter(); | 
 |     ~SkGPipeWriter(); | 
 |  | 
 |     bool isRecording() const { return NULL != fCanvas; } | 
 |  | 
 |     enum Flags { | 
 |         /** | 
 |          *  Tells the writer that the reader will be in a different process, so | 
 |          *  (for example) we cannot put function pointers in the stream. | 
 |          */ | 
 |         kCrossProcess_Flag              = 1 << 0, | 
 |  | 
 |         /** | 
 |          *  Only meaningful if kCrossProcess_Flag is set. Tells the writer that | 
 |          *  in spite of being cross process, it will have shared address space | 
 |          *  with the reader, so the two can share large objects (like SkBitmaps). | 
 |          */ | 
 |         kSharedAddressSpace_Flag        = 1 << 1, | 
 |  | 
 |         /** | 
 |          *  Tells the writer that there will be multiple threads reading the stream | 
 |          *  simultaneously. | 
 |          */ | 
 |         kSimultaneousReaders_Flag       = 1 << 2, | 
 |     }; | 
 |  | 
 |     SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0, | 
 |         uint32_t width = kDefaultRecordingCanvasSize, | 
 |         uint32_t height = kDefaultRecordingCanvasSize); | 
 |  | 
 |     // called in destructor, but can be called sooner once you know there | 
 |     // should be no more drawing calls made into the recording canvas. | 
 |     void endRecording(); | 
 |  | 
 |     /** | 
 |      *  Tells the writer to commit all recorded draw commands to the | 
 |      *  controller immediately. | 
 |      *  @param detachCurrentBlock Set to true to request that the next draw | 
 |      *      command be recorded in a new block. | 
 |      */ | 
 |     void flushRecording(bool detachCurrentBlock); | 
 |  | 
 |     /** | 
 |      * Return the amount of bytes being used for recording. Note that this | 
 |      * does not include the amount of storage written to the stream, which is | 
 |      * controlled by the SkGPipeController. | 
 |      * Currently only returns the amount used for SkBitmaps, since they are | 
 |      * potentially unbounded (if the client is not calling playback). | 
 |      */ | 
 |     size_t storageAllocatedForRecording() const; | 
 |  | 
 |     /** | 
 |      * Attempt to reduce the storage allocated for recording by evicting | 
 |      * cache resources. | 
 |      * @param bytesToFree minimum number of bytes that should be attempted to | 
 |      *   be freed. | 
 |      * @return number of bytes actually freed. | 
 |      */ | 
 |     size_t freeMemoryIfPossible(size_t bytesToFree); | 
 |  | 
 | private: | 
 |     enum { | 
 |         kDefaultRecordingCanvasSize = 32767, | 
 |     }; | 
 |  | 
 |     SkGPipeCanvas* fCanvas; | 
 |     SkWriter32     fWriter; | 
 | }; | 
 |  | 
 | #endif |