15bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com/*
25bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Copyright 2011 Google Inc.
35bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com *
45bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Use of this source code is governed by a BSD-style license that can be
55bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * found in the LICENSE file.
6d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com */
7d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
8d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
95bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com
10d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com#ifndef SkGPipe_DEFINED
11d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com#define SkGPipe_DEFINED
12d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
13fe6d81c22e1f4ceeb67e2b857674eb38bda8ffd8reed@google.com#include "SkFlattenable.h"
14da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com#include "SkPicture.h"
15da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com#include "SkWriter32.h"
16d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
17d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.comclass SkCanvas;
18d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
199343fc93e5c18d7632ad2aaceb8aeb59dc8d2cfcreed@google.com// XLib.h might have defined Status already (ugh)
209343fc93e5c18d7632ad2aaceb8aeb59dc8d2cfcreed@google.com#ifdef Status
219343fc93e5c18d7632ad2aaceb8aeb59dc8d2cfcreed@google.com    #undef Status
229343fc93e5c18d7632ad2aaceb8aeb59dc8d2cfcreed@google.com#endif
239343fc93e5c18d7632ad2aaceb8aeb59dc8d2cfcreed@google.com
24d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.comclass SkGPipeReader {
25d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.compublic:
26c55e5aad7046475cfe53c0e68ef89ae31c605ad4scroggo@google.com    SkGPipeReader();
27d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com    SkGPipeReader(SkCanvas* target);
28d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com    ~SkGPipeReader();
29d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
30d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com    enum Status {
31d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com        kDone_Status,   //!< no more data expected from reader
32d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com        kEOF_Status,    //!< need more data from reader
339cc4baf1dec7c7f6b34f0db037a004e97d7e4201yangsu@google.com        kError_Status,  //!< encountered error
349cc4baf1dec7c7f6b34f0db037a004e97d7e4201yangsu@google.com        kReadAtom_Status//!< finished reading an atom
35d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com    };
36d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
377c6664b9c8b7046cf68a5f86cc6d9809b244bd71junov@chromium.org    enum PlaybackFlags {
387c6664b9c8b7046cf68a5f86cc6d9809b244bd71junov@chromium.org        kReadAtom_PlaybackFlag = 0x1, //!< playback a single command from the stream
397c6664b9c8b7046cf68a5f86cc6d9809b244bd71junov@chromium.org        kSilent_PlaybackFlag   = 0x2, //!< playback without drawing
407c6664b9c8b7046cf68a5f86cc6d9809b244bd71junov@chromium.org    };
417c6664b9c8b7046cf68a5f86cc6d9809b244bd71junov@chromium.org
42c55e5aad7046475cfe53c0e68ef89ae31c605ad4scroggo@google.com    void setCanvas(SkCanvas*);
43da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com
44da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com    /**
45da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com     *  Set a function for decoding bitmaps that have encoded data.
46da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com     */
47da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com    void setBitmapDecoder(SkPicture::InstallPixelRefProc proc) { fProc = proc; }
48da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com
49dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    // data must be 4-byte aligned
50dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    // length must be a multiple of 4
517c6664b9c8b7046cf68a5f86cc6d9809b244bd71junov@chromium.org    Status playback(const void* data, size_t length, uint32_t playbackFlags = 0,
527c6664b9c8b7046cf68a5f86cc6d9809b244bd71junov@chromium.org                    size_t* bytesRead = NULL);
53d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.comprivate:
54da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com    SkCanvas*                       fCanvas;
55da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com    class SkGPipeState*             fState;
56da4fa6fab2822f08ef9f68917de6dd6dc3a883d7scroggo@google.com    SkPicture::InstallPixelRefProc  fProc;
57d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com};
58d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
59d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com///////////////////////////////////////////////////////////////////////////////
60d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
612e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.comclass SkGPipeCanvas;
622e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com
63dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.comclass SkGPipeController {
64c16a7b69f767d8a1608964eaea352d27fcf4658dreed@google.compublic:
652e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com    SkGPipeController() : fCanvas(NULL) {}
662e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com    virtual ~SkGPipeController();
672e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com
68c16a7b69f767d8a1608964eaea352d27fcf4658dreed@google.com    /**
69dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  Called periodically by the writer, to get a working buffer of RAM to
70dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  write into. The actual size of the block is also returned, and must be
71dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  actual >= minRequest. If NULL is returned, then actual is ignored and
72dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  writing will stop.
73c16a7b69f767d8a1608964eaea352d27fcf4658dreed@google.com     *
74dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  The returned block must be 4-byte aligned, and actual must be a
75dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  multiple of 4.
76dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  minRequest will always be a multiple of 4.
77dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     */
78dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    virtual void* requestBlock(size_t minRequest, size_t* actual) = 0;
79dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com
80dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    /**
81dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  This is called each time some atomic portion of the data has been
82dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  written to the block (most recently returned by requestBlock()).
83dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  If bytes == 0, then the writer has finished.
84c16a7b69f767d8a1608964eaea352d27fcf4658dreed@google.com     *
85dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com     *  bytes will always be a multiple of 4.
86c16a7b69f767d8a1608964eaea352d27fcf4658dreed@google.com     */
87dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    virtual void notifyWritten(size_t bytes) = 0;
883d87332c5f217ab77b5afdea98e0c592d3ed7177scroggo@google.com    virtual int numberOfReaders() const { return 1; }
892e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com
902e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.comprivate:
912e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com    friend class SkGPipeWriter;
922e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com    void setCanvas(SkGPipeCanvas*);
932e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com
942e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com    SkGPipeCanvas* fCanvas;
95c16a7b69f767d8a1608964eaea352d27fcf4658dreed@google.com};
96c16a7b69f767d8a1608964eaea352d27fcf4658dreed@google.com
97d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.comclass SkGPipeWriter {
98d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.compublic:
99d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com    SkGPipeWriter();
100d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com    ~SkGPipeWriter();
101d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
102d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com    bool isRecording() const { return NULL != fCanvas; }
103fe6d81c22e1f4ceeb67e2b857674eb38bda8ffd8reed@google.com
104fe6d81c22e1f4ceeb67e2b857674eb38bda8ffd8reed@google.com    enum Flags {
10521a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com        /**
10621a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com         *  Tells the writer that the reader will be in a different process, so
10721a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com         *  (for example) we cannot put function pointers in the stream.
10821a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com         */
10921a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com        kCrossProcess_Flag              = 1 << 0,
110ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com
11121a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com        /**
11221a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com         *  Only meaningful if kCrossProcess_Flag is set. Tells the writer that
11321a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com         *  in spite of being cross process, it will have shared address space
114ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com         *  with the reader, so the two can share large objects (like SkBitmaps).
115ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com         */
116ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com        kSharedAddressSpace_Flag        = 1 << 1,
117ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com
118ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com        /**
119ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com         *  Tells the writer that there will be multiple threads reading the stream
120ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com         *  simultaneously.
12121a56d70754e439a2e0e9901f832c03fa0c7f85ascroggo@google.com         */
122ea155c4294f320f667cfa534109163729fbe9590scroggo@google.com        kSimultaneousReaders_Flag       = 1 << 2,
123fe6d81c22e1f4ceeb67e2b857674eb38bda8ffd8reed@google.com    };
124fe6d81c22e1f4ceeb67e2b857674eb38bda8ffd8reed@google.com
1253b406e7776668715fce278a806d84f8a55bcc53djunov@chromium.org    SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0,
1263b406e7776668715fce278a806d84f8a55bcc53djunov@chromium.org        uint32_t width = kDefaultRecordingCanvasSize,
1273b406e7776668715fce278a806d84f8a55bcc53djunov@chromium.org        uint32_t height = kDefaultRecordingCanvasSize);
128d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
129dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    // called in destructor, but can be called sooner once you know there
130dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    // should be no more drawing calls made into the recording canvas.
131dfd8f38cfabda080d4aefbf8de7dfc8617aae8cdreed@google.com    void endRecording();
132d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
133e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org    /**
134e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org     *  Tells the writer to commit all recorded draw commands to the
135e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org     *  controller immediately.
136e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org     *  @param detachCurrentBlock Set to true to request that the next draw
137e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org     *      command be recorded in a new block.
138e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org     */
139e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org    void flushRecording(bool detachCurrentBlock);
140e5e1e7d999711ca9a3a9303531a79464f3d87ce8junov@chromium.org
141556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com    /**
142556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com     * Return the amount of bytes being used for recording. Note that this
143556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com     * does not include the amount of storage written to the stream, which is
144556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com     * controlled by the SkGPipeController.
145556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com     * Currently only returns the amount used for SkBitmaps, since they are
146556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com     * potentially unbounded (if the client is not calling playback).
147556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com     */
1486c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org    size_t storageAllocatedForRecording() const;
1496c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org
1506c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org    /**
1516c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org     * Attempt to reduce the storage allocated for recording by evicting
1526c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org     * cache resources.
1536c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org     * @param bytesToFree minimum number of bytes that should be attempted to
1546c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org     *   be freed.
1556c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org     * @return number of bytes actually freed.
1566c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org     */
1576c331d1751bbba5311f12d8bb8071afac1d4c525junov@chromium.org    size_t freeMemoryIfPossible(size_t bytesToFree);
158556930849b8dc0146aa8ded30a5043a9114b3f2bscroggo@google.com
159d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.comprivate:
1603b406e7776668715fce278a806d84f8a55bcc53djunov@chromium.org    enum {
1613b406e7776668715fce278a806d84f8a55bcc53djunov@chromium.org        kDefaultRecordingCanvasSize = 32767,
1623b406e7776668715fce278a806d84f8a55bcc53djunov@chromium.org    };
1633b406e7776668715fce278a806d84f8a55bcc53djunov@chromium.org
1642e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com    SkGPipeCanvas* fCanvas;
1652e37e2b709e0d38ad3689ee4e520f2f3b3bad9a3scroggo@google.com    SkWriter32     fWriter;
166d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com};
167d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com
168d873bc41331cc176b7368fa73ca9dcff01c08a2freed@google.com#endif
169