1/*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef TransferQueue_h
27#define TransferQueue_h
28
29#if USE(ACCELERATED_COMPOSITING)
30
31#include "GLUtils.h"
32#include "ShaderProgram.h"
33#include "SkBitmap.h"
34#include <utils/StrongPointer.h>
35#include <utils/threads.h>
36
37namespace WebCore {
38
39class Tile;
40class TilePainter;
41class TileTexture;
42
43struct GLState {
44    GLint bufferId[1];
45    GLint viewport[4];
46    GLboolean scissor[1];
47    GLboolean depth[1];
48    GLfloat clearColor[4];
49};
50
51
52// While in the queue, the Tile can be re-used, the updated bitmap
53// can be discarded. In order to track this obsolete base tiles, we save
54// the Tile's Info to make the comparison.
55// At the time of base tile's dtor or webview destroy, we want to discard
56// all the data in the queue. However, we have to do the Surface Texture
57// update in the same GL context as the UI thread. So we mark the status
58// as pendingDiscard, and delay the Surface Texture operation to the next
59// draw call.
60
61enum TransferItemStatus {
62    emptyItem = 0, // S.T. buffer ready for new content
63    pendingBlit = 1, // Ready for bliting into tile's GL Tex.
64    pendingDiscard = 2 // Waiting for the next draw call to discard
65};
66
67enum TextureUploadType {
68    CpuUpload = 0,
69    GpuUpload = 1
70};
71
72#define DEFAULT_UPLOAD_TYPE GpuUpload
73
74class TileTransferData {
75public:
76    TileTransferData()
77    : status(emptyItem)
78    , savedTilePtr(0)
79    , savedTilePainter(0)
80    , savedTileTexturePtr(0)
81    , uploadType(DEFAULT_UPLOAD_TYPE)
82    , bitmap(0)
83    {
84    }
85
86    ~TileTransferData()
87    {
88        // Bitmap will be created lazily, need to delete them at dtor.
89        delete bitmap;
90    }
91
92    TransferItemStatus status;
93    Tile* savedTilePtr;
94    TilePainter* savedTilePainter; // Ref count the tilePainter to keep the tile alive.
95    TileTexture* savedTileTexturePtr;
96    TextureUploadType uploadType;
97    // This is only useful in Cpu upload code path, so it will be dynamically
98    // lazily allocated.
99    SkBitmap* bitmap;
100
101    // Specific data to the pure color tiles' queue.
102    Color pureColor;
103};
104
105class TransferQueue {
106public:
107    TransferQueue(bool useMinimalMem);
108    ~TransferQueue();
109
110    // This will be called by the browser through nativeSetProperty
111    void setTextureUploadType(TextureUploadType type);
112    void updateDirtyTiles();
113
114    void initGLResources(int width, int height);
115
116    // insert the bitmap into the queue, mark the tile dirty if failing
117    void updateQueueWithBitmap(const TileRenderInfo* renderInfo,
118                               const SkBitmap& bitmap);
119
120    void addItemInTransferQueue(const TileRenderInfo* info,
121                                TextureUploadType type,
122                                const SkBitmap* bitmap);
123    // Check if the item @ index is ready for update.
124    // The lock will be done when returning true.
125    bool readyForUpdate();
126
127    void lockQueue() { m_transferQueueItemLocks.lock(); }
128    void unlockQueue() { m_transferQueueItemLocks.unlock(); }
129
130    void addItemInPureColorQueue(const TileRenderInfo* renderInfo);
131
132    void cleanupGLResourcesAndQueue();
133
134    bool needsInit() { return !m_sharedSurfaceTextureId; }
135    void resetQueue();
136    // This queue can be accessed from UI and TexGen thread, therefore, we need
137    // a lock to protect its access
138    TileTransferData* m_transferQueue;
139
140    android::sp<ANativeWindow> m_ANW;
141
142    // EGL wrapper around m_ANW for use by the GaneshRenderer
143    EGLSurface m_eglSurface;
144
145private:
146    // return true if successfully inserted into queue
147    bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
148                                  const SkBitmap& bitmap);
149    bool getHasGLContext();
150    void setHasGLContext(bool hasContext);
151    void emptyAndAbandonQueue();
152
153    int getNextTransferQueueIndex();
154
155    // Save and restore the GL State while switching from/to FBO.
156    void saveGLState();
157    void setGLStateForCopy(int width, int height);
158    void restoreGLState();
159
160    // Check the current transfer queue item is obsolete or not.
161    bool checkObsolete(const TileTransferData* data);
162
163    void setPendingDiscard();
164    // Before each draw call and the blit operation, clean up all the
165    // pendingDiscard items.
166    void cleanupPendingDiscard();
167    void cleanupGLResources();
168
169    void blitTileFromQueue(GLuint fboID, TileTexture* destTex,
170                           GLuint srcTexId, GLenum srcTexTarget,
171                           int index);
172
173    void clearItemInTranferQueue(int index);
174    void addItemCommon(const TileRenderInfo* renderInfo,
175                       TextureUploadType type, TileTransferData* data);
176
177    void updatePureColorTiles();
178    void clearPureColorQueue();
179    // Note that the m_transferQueueIndex only changed in the TexGen thread
180    // where we are going to move on to update the next item in the queue.
181    int m_transferQueueIndex;
182
183    GLuint m_fboID; // The FBO used for copy the SurfTex to each tile
184
185    GLuint m_sharedSurfaceTextureId;
186
187    // GLContext can be lost when WebView destroyed.
188    bool m_hasGLContext;
189
190    GLState m_GLStateBeforeBlit;
191    android::sp<android::SurfaceTexture> m_sharedSurfaceTexture;
192
193    int m_emptyItemCount;
194
195    // We are using wait/signal to handle our own queue sync.
196    // First of all, if we don't have our own lock, then while WebView is
197    // destroyed, the UI thread will wait for the Tex Gen to get out from
198    // dequeue operation, which will not succeed. B/c at this moment, we
199    // already lost the GL Context.
200    // Now we maintain a counter, which is m_emptyItemCount. When this reach
201    // 0, then we need the Tex Gen thread to wait. UI thread can signal this
202    // wait after calling updateTexImage at the draw call , or after WebView
203    // is destroyed.
204    android::Mutex m_transferQueueItemLocks;
205    android::Condition m_transferQueueItemCond;
206
207    EGLDisplay m_currentDisplay;
208
209    // This should be GpuUpload for production, but for debug purpose or working
210    // around driver/HW issue, we can set it to CpuUpload.
211    TextureUploadType m_currentUploadType;
212
213    // The non-pure-color tile are 1 to 1 mapping with Surface Texture which is
214    // resource limited. To get better performance, it is better to separate
215    // the pure color tile into another queue.
216    WTF::Vector<TileTransferData> m_pureColorTileQueue;
217
218    // The number of items transfer queue can buffer up.
219    int m_transferQueueSize;
220};
221
222} // namespace WebCore
223
224#endif // USE(ACCELERATED_COMPOSITING)
225#endif // TransferQueue_h
226