1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com */
7bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
8bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
10bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com#ifndef SkGPipe_DEFINED
11bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com#define SkGPipe_DEFINED
12bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
13dde0956375e87027df2fdd80d430dd819c217aacreed@google.com#include "SkFlattenable.h"
1474b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com#include "SkPicture.h"
1574b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com#include "SkWriter32.h"
16bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
17bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.comclass SkCanvas;
18bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
19bc75483241ac853d1138d7e2cfbfa37b1df4715ereed@google.com// XLib.h might have defined Status already (ugh)
20bc75483241ac853d1138d7e2cfbfa37b1df4715ereed@google.com#ifdef Status
21bc75483241ac853d1138d7e2cfbfa37b1df4715ereed@google.com    #undef Status
22bc75483241ac853d1138d7e2cfbfa37b1df4715ereed@google.com#endif
23bc75483241ac853d1138d7e2cfbfa37b1df4715ereed@google.com
24bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.comclass SkGPipeReader {
25bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.compublic:
2672c9672ce274a3b6cb40800d66374edf25b157a3scroggo@google.com    SkGPipeReader();
27bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com    SkGPipeReader(SkCanvas* target);
28bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com    ~SkGPipeReader();
29bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
30bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com    enum Status {
31bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com        kDone_Status,   //!< no more data expected from reader
32bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com        kEOF_Status,    //!< need more data from reader
331bce0a585733a3e4e5cc1b79eae12b15deee122dyangsu@google.com        kError_Status,  //!< encountered error
341bce0a585733a3e4e5cc1b79eae12b15deee122dyangsu@google.com        kReadAtom_Status//!< finished reading an atom
35bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com    };
36bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
37fb10389403cf1cc771e103016207fde84c5f4825junov@chromium.org    enum PlaybackFlags {
38fb10389403cf1cc771e103016207fde84c5f4825junov@chromium.org        kReadAtom_PlaybackFlag = 0x1, //!< playback a single command from the stream
39fb10389403cf1cc771e103016207fde84c5f4825junov@chromium.org        kSilent_PlaybackFlag   = 0x2, //!< playback without drawing
40fb10389403cf1cc771e103016207fde84c5f4825junov@chromium.org    };
41fb10389403cf1cc771e103016207fde84c5f4825junov@chromium.org
4272c9672ce274a3b6cb40800d66374edf25b157a3scroggo@google.com    void setCanvas(SkCanvas*);
4374b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com
4474b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com    /**
4574b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com     *  Set a function for decoding bitmaps that have encoded data.
4674b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com     */
4774b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com    void setBitmapDecoder(SkPicture::InstallPixelRefProc proc) { fProc = proc; }
4874b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com
49acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    // data must be 4-byte aligned
50acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    // length must be a multiple of 4
51fb10389403cf1cc771e103016207fde84c5f4825junov@chromium.org    Status playback(const void* data, size_t length, uint32_t playbackFlags = 0,
52fb10389403cf1cc771e103016207fde84c5f4825junov@chromium.org                    size_t* bytesRead = NULL);
53bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.comprivate:
5474b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com    SkCanvas*                       fCanvas;
5574b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com    class SkGPipeState*             fState;
5674b7ffda687c66d46ac3cfa4f2baedd4c62e3fbescroggo@google.com    SkPicture::InstallPixelRefProc  fProc;
57bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com};
58bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
59bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com///////////////////////////////////////////////////////////////////////////////
60bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
613cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.comclass SkGPipeCanvas;
623cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com
63acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.comclass SkGPipeController {
64f31663403b1b96c2a1c6717acab5093b0117f187reed@google.compublic:
653cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com    SkGPipeController() : fCanvas(NULL) {}
663cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com    virtual ~SkGPipeController();
673cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com
68f31663403b1b96c2a1c6717acab5093b0117f187reed@google.com    /**
69acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  Called periodically by the writer, to get a working buffer of RAM to
70acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  write into. The actual size of the block is also returned, and must be
71acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  actual >= minRequest. If NULL is returned, then actual is ignored and
72acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  writing will stop.
73f31663403b1b96c2a1c6717acab5093b0117f187reed@google.com     *
74acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  The returned block must be 4-byte aligned, and actual must be a
75acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  multiple of 4.
76acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  minRequest will always be a multiple of 4.
77acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     */
78acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    virtual void* requestBlock(size_t minRequest, size_t* actual) = 0;
79acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com
80acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    /**
81acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  This is called each time some atomic portion of the data has been
82acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  written to the block (most recently returned by requestBlock()).
83acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  If bytes == 0, then the writer has finished.
84f31663403b1b96c2a1c6717acab5093b0117f187reed@google.com     *
85acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com     *  bytes will always be a multiple of 4.
86f31663403b1b96c2a1c6717acab5093b0117f187reed@google.com     */
87acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    virtual void notifyWritten(size_t bytes) = 0;
88284bf502c086d8fd4285f475a02e69d500c40219scroggo@google.com    virtual int numberOfReaders() const { return 1; }
893cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com
903cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.comprivate:
913cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com    friend class SkGPipeWriter;
923cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com    void setCanvas(SkGPipeCanvas*);
933cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com
943cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com    SkGPipeCanvas* fCanvas;
95f31663403b1b96c2a1c6717acab5093b0117f187reed@google.com};
96f31663403b1b96c2a1c6717acab5093b0117f187reed@google.com
97bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.comclass SkGPipeWriter {
98bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.compublic:
99bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com    SkGPipeWriter();
100bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com    ~SkGPipeWriter();
101bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
10249f085dddff10473b6ebf832a974288300224e60bsalomon    bool isRecording() const { return SkToBool(fCanvas); }
103dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
104dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    enum Flags {
105565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com        /**
106565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com         *  Tells the writer that the reader will be in a different process, so
107565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com         *  (for example) we cannot put function pointers in the stream.
108565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com         */
109565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com        kCrossProcess_Flag              = 1 << 0,
11058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
111565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com        /**
112565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com         *  Only meaningful if kCrossProcess_Flag is set. Tells the writer that
113565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com         *  in spite of being cross process, it will have shared address space
11458b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com         *  with the reader, so the two can share large objects (like SkBitmaps).
11558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com         */
11658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com        kSharedAddressSpace_Flag        = 1 << 1,
11758b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
11858b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com        /**
11958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com         *  Tells the writer that there will be multiple threads reading the stream
12058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com         *  simultaneously.
121565254bc9343d0befdfbbb97a3dc6d44c6e18658scroggo@google.com         */
12258b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com        kSimultaneousReaders_Flag       = 1 << 2,
123dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    };
124dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
125a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org    SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0,
126a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org        uint32_t width = kDefaultRecordingCanvasSize,
127a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org        uint32_t height = kDefaultRecordingCanvasSize);
128bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
129acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    // called in destructor, but can be called sooner once you know there
130acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    // should be no more drawing calls made into the recording canvas.
131acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com    void endRecording();
132bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
13377eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org    /**
13477eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org     *  Tells the writer to commit all recorded draw commands to the
13577eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org     *  controller immediately.
13677eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org     *  @param detachCurrentBlock Set to true to request that the next draw
13777eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org     *      command be recorded in a new block.
13877eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org     */
13977eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org    void flushRecording(bool detachCurrentBlock);
14077eec248cbd5a0c2f5f8595e62e3bff5ea363f17junov@chromium.org
14115011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com    /**
14215011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com     * Return the amount of bytes being used for recording. Note that this
14315011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com     * does not include the amount of storage written to the stream, which is
14415011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com     * controlled by the SkGPipeController.
14515011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com     * Currently only returns the amount used for SkBitmaps, since they are
14615011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com     * potentially unbounded (if the client is not calling playback).
14715011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com     */
1482e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org    size_t storageAllocatedForRecording() const;
1492e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org
1502e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org    /**
1512e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org     * Attempt to reduce the storage allocated for recording by evicting
1522e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org     * cache resources.
1532e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org     * @param bytesToFree minimum number of bytes that should be attempted to
1542e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org     *   be freed.
1552e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org     * @return number of bytes actually freed.
1562e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org     */
1572e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org    size_t freeMemoryIfPossible(size_t bytesToFree);
15815011ee5e4068ab6523e432e435473a822ee7d80scroggo@google.com
159bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.comprivate:
160a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org    enum {
161a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org        kDefaultRecordingCanvasSize = 32767,
162a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org    };
163a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org
1643cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com    SkGPipeCanvas* fCanvas;
1653cb969f27de56df0d9116c13f18bd31ee0715f1ascroggo@google.com    SkWriter32     fWriter;
166bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com};
167bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com
168bb6992a9d6e21b3f28068765de0a41c6f2508dfdreed@google.com#endif
169