1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9
10#ifndef SkGPipe_DEFINED
11#define SkGPipe_DEFINED
12
13#include "SkFlattenable.h"
14#include "SkPicture.h"
15#include "SkWriter32.h"
16
17class SkCanvas;
18
19// XLib.h might have defined Status already (ugh)
20#ifdef Status
21    #undef Status
22#endif
23
24class SkGPipeReader {
25public:
26    SkGPipeReader();
27    SkGPipeReader(SkCanvas* target);
28    ~SkGPipeReader();
29
30    enum Status {
31        kDone_Status,   //!< no more data expected from reader
32        kEOF_Status,    //!< need more data from reader
33        kError_Status,  //!< encountered error
34        kReadAtom_Status//!< finished reading an atom
35    };
36
37    enum PlaybackFlags {
38        kReadAtom_PlaybackFlag = 0x1, //!< playback a single command from the stream
39        kSilent_PlaybackFlag   = 0x2, //!< playback without drawing
40    };
41
42    void setCanvas(SkCanvas*);
43
44    /**
45     *  Set a function for decoding bitmaps that have encoded data.
46     */
47    void setBitmapDecoder(SkPicture::InstallPixelRefProc proc) { fProc = proc; }
48
49    // data must be 4-byte aligned
50    // length must be a multiple of 4
51    Status playback(const void* data, size_t length, uint32_t playbackFlags = 0,
52                    size_t* bytesRead = NULL);
53private:
54    SkCanvas*                       fCanvas;
55    class SkGPipeState*             fState;
56    SkPicture::InstallPixelRefProc  fProc;
57};
58
59///////////////////////////////////////////////////////////////////////////////
60
61class SkGPipeCanvas;
62
63class SkGPipeController {
64public:
65    SkGPipeController() : fCanvas(NULL) {}
66    virtual ~SkGPipeController();
67
68    /**
69     *  Called periodically by the writer, to get a working buffer of RAM to
70     *  write into. The actual size of the block is also returned, and must be
71     *  actual >= minRequest. If NULL is returned, then actual is ignored and
72     *  writing will stop.
73     *
74     *  The returned block must be 4-byte aligned, and actual must be a
75     *  multiple of 4.
76     *  minRequest will always be a multiple of 4.
77     */
78    virtual void* requestBlock(size_t minRequest, size_t* actual) = 0;
79
80    /**
81     *  This is called each time some atomic portion of the data has been
82     *  written to the block (most recently returned by requestBlock()).
83     *  If bytes == 0, then the writer has finished.
84     *
85     *  bytes will always be a multiple of 4.
86     */
87    virtual void notifyWritten(size_t bytes) = 0;
88    virtual int numberOfReaders() const { return 1; }
89
90private:
91    friend class SkGPipeWriter;
92    void setCanvas(SkGPipeCanvas*);
93
94    SkGPipeCanvas* fCanvas;
95};
96
97class SkGPipeWriter {
98public:
99    SkGPipeWriter();
100    ~SkGPipeWriter();
101
102    bool isRecording() const { return NULL != fCanvas; }
103
104    enum Flags {
105        /**
106         *  Tells the writer that the reader will be in a different process, so
107         *  (for example) we cannot put function pointers in the stream.
108         */
109        kCrossProcess_Flag              = 1 << 0,
110
111        /**
112         *  Only meaningful if kCrossProcess_Flag is set. Tells the writer that
113         *  in spite of being cross process, it will have shared address space
114         *  with the reader, so the two can share large objects (like SkBitmaps).
115         */
116        kSharedAddressSpace_Flag        = 1 << 1,
117
118        /**
119         *  Tells the writer that there will be multiple threads reading the stream
120         *  simultaneously.
121         */
122        kSimultaneousReaders_Flag       = 1 << 2,
123    };
124
125    SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0,
126        uint32_t width = kDefaultRecordingCanvasSize,
127        uint32_t height = kDefaultRecordingCanvasSize);
128
129    // called in destructor, but can be called sooner once you know there
130    // should be no more drawing calls made into the recording canvas.
131    void endRecording();
132
133    /**
134     *  Tells the writer to commit all recorded draw commands to the
135     *  controller immediately.
136     *  @param detachCurrentBlock Set to true to request that the next draw
137     *      command be recorded in a new block.
138     */
139    void flushRecording(bool detachCurrentBlock);
140
141    /**
142     * Return the amount of bytes being used for recording. Note that this
143     * does not include the amount of storage written to the stream, which is
144     * controlled by the SkGPipeController.
145     * Currently only returns the amount used for SkBitmaps, since they are
146     * potentially unbounded (if the client is not calling playback).
147     */
148    size_t storageAllocatedForRecording() const;
149
150    /**
151     * Attempt to reduce the storage allocated for recording by evicting
152     * cache resources.
153     * @param bytesToFree minimum number of bytes that should be attempted to
154     *   be freed.
155     * @return number of bytes actually freed.
156     */
157    size_t freeMemoryIfPossible(size_t bytesToFree);
158
159private:
160    enum {
161        kDefaultRecordingCanvasSize = 32767,
162    };
163
164    SkGPipeCanvas* fCanvas;
165    SkWriter32     fWriter;
166};
167
168#endif
169