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