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 
17 class SkCanvas;
18 
19 // XLib.h might have defined Status already (ugh)
20 #ifdef Status
21     #undef Status
22 #endif
23 
24 class SkGPipeReader {
25 public:
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      */
setBitmapDecoder(SkPicture::InstallPixelRefProc proc)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);
53 private:
54     SkCanvas*                       fCanvas;
55     class SkGPipeState*             fState;
56     SkPicture::InstallPixelRefProc  fProc;
57 };
58 
59 ///////////////////////////////////////////////////////////////////////////////
60 
61 class SkGPipeCanvas;
62 
63 class SkGPipeController {
64 public:
SkGPipeController()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;
numberOfReaders()88     virtual int numberOfReaders() const { return 1; }
89 
90 private:
91     friend class SkGPipeWriter;
92     void setCanvas(SkGPipeCanvas*);
93 
94     SkGPipeCanvas* fCanvas;
95 };
96 
97 class SkGPipeWriter {
98 public:
99     SkGPipeWriter();
100     ~SkGPipeWriter();
101 
isRecording()102     bool isRecording() const { return SkToBool(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 
159 private:
160     enum {
161         kDefaultRecordingCanvasSize = 32767,
162     };
163 
164     SkGPipeCanvas* fCanvas;
165     SkWriter32     fWriter;
166 };
167 
168 #endif
169