• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "TransferQueue"
27 #define LOG_NDEBUG 1
28 
29 #include "config.h"
30 #include "TransferQueue.h"
31 
32 #if USE(ACCELERATED_COMPOSITING)
33 
34 #include "AndroidLog.h"
35 #include "DrawQuadData.h"
36 #include "GLUtils.h"
37 #include "Tile.h"
38 #include "TileTexture.h"
39 #include "TilesManager.h"
40 #include <android/native_window.h>
41 #include <gui/SurfaceTexture.h>
42 #include <gui/SurfaceTextureClient.h>
43 
44 // For simple webView usage, MINIMAL_SIZE is recommended for memory saving.
45 // In browser case, EFFICIENT_SIZE is preferred.
46 #define MINIMAL_SIZE 1
47 #define EFFICIENT_SIZE 6
48 
49 // Set this to 1 if we would like to take the new GpuUpload approach which
50 // relied on the glCopyTexSubImage2D instead of a glDraw call
51 #define GPU_UPLOAD_WITHOUT_DRAW 1
52 
53 namespace WebCore {
54 
TransferQueue(bool useMinimalMem)55 TransferQueue::TransferQueue(bool useMinimalMem)
56     : m_eglSurface(EGL_NO_SURFACE)
57     , m_transferQueueIndex(0)
58     , m_fboID(0)
59     , m_sharedSurfaceTextureId(0)
60     , m_hasGLContext(true)
61     , m_currentDisplay(EGL_NO_DISPLAY)
62     , m_currentUploadType(DEFAULT_UPLOAD_TYPE)
63 {
64     memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit));
65     m_transferQueueSize = useMinimalMem ? MINIMAL_SIZE : EFFICIENT_SIZE;
66     m_emptyItemCount = m_transferQueueSize;
67     m_transferQueue = new TileTransferData[m_transferQueueSize];
68 }
69 
~TransferQueue()70 TransferQueue::~TransferQueue()
71 {
72     android::Mutex::Autolock lock(m_transferQueueItemLocks);
73     cleanupGLResources();
74     delete[] m_transferQueue;
75 }
76 
77 // Set the queue to be totally empty, abandon the Surface Texture. This should
78 // be called only when we hit a wrong EGL Context in an error situation.
resetQueue()79 void TransferQueue::resetQueue()
80 {
81     android::Mutex::Autolock lock(m_transferQueueItemLocks);
82     emptyAndAbandonQueue();
83     m_sharedSurfaceTextureId = 0;
84 }
85 
86 // This should be called within the m_transferQueueItemLocks.
87 // Now only called by emptyQueue() and destructor.
cleanupGLResources()88 void TransferQueue::cleanupGLResources()
89 {
90     if (m_fboID) {
91         glDeleteFramebuffers(1, &m_fboID);
92         m_fboID = 0;
93     }
94     if (m_sharedSurfaceTextureId) {
95         glDeleteTextures(1, &m_sharedSurfaceTextureId);
96         m_sharedSurfaceTextureId = 0;
97     }
98 }
99 
initGLResources(int width,int height)100 void TransferQueue::initGLResources(int width, int height)
101 {
102     android::Mutex::Autolock lock(m_transferQueueItemLocks);
103     if (!m_sharedSurfaceTextureId) {
104         glGenTextures(1, &m_sharedSurfaceTextureId);
105         sp<BufferQueue> bufferQueue(new BufferQueue(true));
106         m_sharedSurfaceTexture =
107 #if GPU_UPLOAD_WITHOUT_DRAW
108             new android::SurfaceTexture(m_sharedSurfaceTextureId, true,
109                                         GL_TEXTURE_2D, true, bufferQueue);
110 #else
111             new android::SurfaceTexture(m_sharedSurfaceTextureId, true,
112                                         GL_TEXTURE_EXTERNAL_OES, true,
113                                         bufferQueue);
114 #endif
115         m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture);
116         m_sharedSurfaceTexture->setSynchronousMode(true);
117 
118         int extraBuffersNeeded = 0;
119         m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
120                      &extraBuffersNeeded);
121         bufferQueue->setBufferCount(m_transferQueueSize + extraBuffersNeeded);
122 
123         int result = native_window_set_buffers_geometry(m_ANW.get(),
124                 width, height, HAL_PIXEL_FORMAT_RGBA_8888);
125         GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result);
126         result = native_window_set_usage(m_ANW.get(),
127                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
128         GLUtils::checkSurfaceTextureError("native_window_set_usage", result);
129     }
130 
131     if (!m_fboID)
132         glGenFramebuffers(1, &m_fboID);
133 }
134 
135 // When bliting, if the item from the transfer queue is mismatching b/t the
136 // Tile and the content, then the item is considered as obsolete, and
137 // the content is discarded.
checkObsolete(const TileTransferData * data)138 bool TransferQueue::checkObsolete(const TileTransferData* data)
139 {
140     Tile* baseTilePtr = data->savedTilePtr;
141     if (!baseTilePtr) {
142         ALOGV("Invalid savedTilePtr , such that the tile is obsolete");
143         return true;
144     }
145 
146     TileTexture* baseTileTexture = baseTilePtr->backTexture();
147     if (!baseTileTexture || baseTileTexture != data->savedTileTexturePtr) {
148         ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete",
149               baseTileTexture, data->savedTileTexturePtr);
150         return true;
151     }
152 
153     return false;
154 }
155 
blitTileFromQueue(GLuint fboID,TileTexture * destTex,GLuint srcTexId,GLenum srcTexTarget,int index)156 void TransferQueue::blitTileFromQueue(GLuint fboID, TileTexture* destTex,
157                                       GLuint srcTexId, GLenum srcTexTarget,
158                                       int index)
159 {
160 #if GPU_UPLOAD_WITHOUT_DRAW
161     glBindFramebuffer(GL_FRAMEBUFFER, fboID);
162     glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId);
163 
164     int textureWidth = destTex->getSize().width();
165     int textureHeight = destTex->getSize().height();
166 
167     glFramebufferTexture2D(GL_FRAMEBUFFER,
168                            GL_COLOR_ATTACHMENT0,
169                            GL_TEXTURE_2D,
170                            srcTexId,
171                            0);
172 
173     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
174                         textureWidth, textureHeight);
175     if (GLUtils::checkGlError("At the end of blitTileFromQueue()")) {
176 #ifndef DEBUG
177         if (GLUtils::allowGLLog())
178 #endif
179         ALOGE("blitTileFromQueue ERROR: fboId %d, destTexId %d, srcTexId %d,"
180               " textureWidth %d, textureHeight %d", fboID, destTex->m_ownTextureId,
181               srcTexId, textureWidth, textureHeight);
182     }
183 #else
184     // Then set up the FBO and copy the SurfTex content in.
185     glBindFramebuffer(GL_FRAMEBUFFER, fboID);
186     glFramebufferTexture2D(GL_FRAMEBUFFER,
187                            GL_COLOR_ATTACHMENT0,
188                            GL_TEXTURE_2D,
189                            destTex->m_ownTextureId,
190                            0);
191     setGLStateForCopy(destTex->getSize().width(),
192                       destTex->getSize().height());
193     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
194     if (status != GL_FRAMEBUFFER_COMPLETE) {
195         ALOGV("Error: glCheckFramebufferStatus failed");
196         return;
197     }
198 
199     // Use empty rect to set up the special matrix to draw.
200     SkRect rect  = SkRect::MakeEmpty();
201 
202     TextureQuadData data(srcTexId, GL_NEAREST, srcTexTarget, Blit, 0, 0, 1.0, false);
203     TilesManager::instance()->shader()->drawQuad(&data);
204 #endif
205 }
206 
207 // This function must be called inside the m_transferQueueItemLocks, for the
208 // wait and getHasGLContext().
209 // Only called by updateQueueWithBitmap() for now.
readyForUpdate()210 bool TransferQueue::readyForUpdate()
211 {
212     if (!getHasGLContext())
213         return false;
214     // Don't use a while loop since when the WebView tear down, the emptyCount
215     // will still be 0, and we bailed out b/c of GL context lost.
216     if (!m_emptyItemCount)
217         m_transferQueueItemCond.wait(m_transferQueueItemLocks);
218 
219     if (!getHasGLContext())
220         return false;
221 
222     return true;
223 }
224 
225 // Both getHasGLContext and setHasGLContext should be called within the lock.
getHasGLContext()226 bool TransferQueue::getHasGLContext()
227 {
228     return m_hasGLContext;
229 }
230 
setHasGLContext(bool hasContext)231 void TransferQueue::setHasGLContext(bool hasContext)
232 {
233     m_hasGLContext = hasContext;
234 }
235 
236 // Call within a m_transferQueueItemLocks, now called by resetQueue() and
237 // cleanupGLResoucesAndQueue()
emptyAndAbandonQueue()238 void TransferQueue::emptyAndAbandonQueue()
239 {
240     for (int i = 0 ; i < m_transferQueueSize; i++)
241         clearItemInTranferQueue(i);
242     m_emptyItemCount = m_transferQueueSize;
243     clearPureColorQueue();
244 
245     if (m_sharedSurfaceTexture.get()) {
246         m_sharedSurfaceTexture->abandon();
247         m_sharedSurfaceTexture.clear();
248     }
249     // This can prevent the tex gen thread to produce, until next incoming draw.
250     setHasGLContext(false);
251 }
252 
cleanupGLResourcesAndQueue()253 void TransferQueue::cleanupGLResourcesAndQueue()
254 {
255     android::Mutex::Autolock lock(m_transferQueueItemLocks);
256     emptyAndAbandonQueue();
257     cleanupGLResources();
258 }
259 
260 // Set all the content in the queue to pendingDiscard, after this, there will
261 // be nothing added to the queue, and this can be called in any thread.
262 // However, in order to discard the content in the Surface Texture using
263 // updateTexImage, cleanupPendingDiscard need to be called on the UI thread.
264 // Must be called within a m_transferQueueItemLocks.
setPendingDiscard()265 void TransferQueue::setPendingDiscard()
266 {
267     for (int i = 0 ; i < m_transferQueueSize; i++)
268         if (m_transferQueue[i].status == pendingBlit)
269             m_transferQueue[i].status = pendingDiscard;
270 
271     clearPureColorQueue();
272 
273     bool GLContextExisted = getHasGLContext();
274     // Unblock the Tex Gen thread first before Tile Page deletion.
275     // Otherwise, there will be a deadlock while removing operations.
276     setHasGLContext(false);
277 
278     // Only signal once when GL context lost.
279     if (GLContextExisted)
280         m_transferQueueItemCond.signal();
281 }
282 
clearPureColorQueue()283 void TransferQueue::clearPureColorQueue()
284 {
285     for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) {
286         SkSafeUnref(m_pureColorTileQueue[i].savedTilePainter);
287         m_pureColorTileQueue[i].savedTilePainter = 0;
288     }
289     m_pureColorTileQueue.clear();
290 }
291 
updatePureColorTiles()292 void TransferQueue::updatePureColorTiles()
293 {
294     for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) {
295         TileTransferData* data = &m_pureColorTileQueue[i];
296         if (data->status == pendingBlit) {
297             TileTexture* destTexture = 0;
298             bool obsoleteTile = checkObsolete(data);
299             if (!obsoleteTile) {
300                 destTexture = data->savedTilePtr->backTexture();
301                 destTexture->setPureColor(data->pureColor);
302                 destTexture->transferComplete();
303             }
304         } else if (data->status == emptyItem || data->status == pendingDiscard) {
305             // The queue should be clear instead of setting to different status.
306             ALOGV("Warning: Don't expect an emptyItem here.");
307         }
308     }
309     clearPureColorQueue();
310 }
311 
312 // Call on UI thread to copy from the shared Surface Texture to the Tile's texture.
updateDirtyTiles()313 void TransferQueue::updateDirtyTiles()
314 {
315     android::Mutex::Autolock lock(m_transferQueueItemLocks);
316 
317     cleanupPendingDiscard();
318     if (!getHasGLContext())
319         setHasGLContext(true);
320 
321     // Check the pure color tile first, since it is simpler.
322     updatePureColorTiles();
323 
324     // Start from the oldest item, we call the updateTexImage to retrive
325     // the texture and blit that into each Tile's texture.
326     const int nextItemIndex = getNextTransferQueueIndex();
327     int index = nextItemIndex;
328     bool usedFboForUpload = false;
329     for (int k = 0; k < m_transferQueueSize ; k++) {
330         if (m_transferQueue[index].status == pendingBlit) {
331             bool obsoleteTile = checkObsolete(&m_transferQueue[index]);
332             // Save the needed info, update the Surf Tex, clean up the item in
333             // the queue. Then either move on to next item or copy the content.
334             TileTexture* destTexture = 0;
335             if (!obsoleteTile)
336                 destTexture = m_transferQueue[index].savedTilePtr->backTexture();
337 
338             if (m_transferQueue[index].uploadType == GpuUpload) {
339                 status_t result = m_sharedSurfaceTexture->updateTexImage();
340                 if (result != OK)
341                     ALOGE("unexpected error: updateTexImage return %d", result);
342             }
343 
344             if (obsoleteTile) {
345                 ALOGV("Warning: the texture is obsolete for this baseTile");
346                 clearItemInTranferQueue(index);
347                 index = (index + 1) % m_transferQueueSize;
348                 continue;
349             }
350 
351             // guarantee that we have a texture to blit into
352             destTexture->requireGLTexture();
353             GLUtils::checkGlError("before blitTileFromQueue");
354             if (m_transferQueue[index].uploadType == CpuUpload) {
355                 // Here we just need to upload the bitmap content to the GL Texture
356                 GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId,
357                                                  *m_transferQueue[index].bitmap);
358             } else {
359                 if (!usedFboForUpload) {
360                     saveGLState();
361                     usedFboForUpload = true;
362                 }
363                 blitTileFromQueue(m_fboID, destTexture, m_sharedSurfaceTextureId,
364                                   m_sharedSurfaceTexture->getCurrentTextureTarget(),
365                                   index);
366             }
367 
368             destTexture->setPure(false);
369             destTexture->transferComplete();
370             clearItemInTranferQueue(index);
371             ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d",
372                   m_transferQueue[index].savedTilePtr,
373                   destTexture,
374                   destTexture->m_ownTextureId);
375         }
376         index = (index + 1) % m_transferQueueSize;
377     }
378 
379     // Clean up FBO setup. Doing this for both CPU/GPU upload can make the
380     // dynamic switch possible. Moving this out from the loop can save some
381     // milli-seconds.
382     if (usedFboForUpload) {
383         restoreGLState();
384         GLUtils::checkGlError("updateDirtyTiles");
385     }
386 
387     m_emptyItemCount = m_transferQueueSize;
388     m_transferQueueItemCond.signal();
389 }
390 
updateQueueWithBitmap(const TileRenderInfo * renderInfo,const SkBitmap & bitmap)391 void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
392                                           const SkBitmap& bitmap)
393 {
394     if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) {
395         // failed placing bitmap in queue, discard tile's texture so it will be
396         // re-enqueued (and repainted)
397         Tile* tile = renderInfo->baseTile;
398         if (tile)
399             tile->backTextureTransferFail();
400     }
401 }
402 
tryUpdateQueueWithBitmap(const TileRenderInfo * renderInfo,const SkBitmap & bitmap)403 bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
404                                              const SkBitmap& bitmap)
405 {
406     // This lock need to cover the full update since it is possible that queue
407     // will be cleaned up in the middle of this update without the lock.
408     // The Surface Texture will not block us since the readyForUpdate will check
409     // availability of the slots in the queue first.
410     android::Mutex::Autolock lock(m_transferQueueItemLocks);
411     bool ready = readyForUpdate();
412     TextureUploadType currentUploadType = m_currentUploadType;
413     if (!ready) {
414         ALOGV("Quit bitmap update: not ready! for tile x y %d %d",
415               renderInfo->x, renderInfo->y);
416         return false;
417     }
418     if (currentUploadType == GpuUpload) {
419         // a) Dequeue the Surface Texture and write into the buffer
420         if (!m_ANW.get()) {
421             ALOGV("ERROR: ANW is null");
422             return false;
423         }
424 
425         if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap))
426             return false;
427     }
428 
429     // b) After update the Surface Texture, now udpate the transfer queue info.
430     addItemInTransferQueue(renderInfo, currentUploadType, &bitmap);
431 
432     ALOGV("Bitmap updated x, y %d %d, baseTile %p",
433           renderInfo->x, renderInfo->y, renderInfo->baseTile);
434     return true;
435 }
436 
addItemInPureColorQueue(const TileRenderInfo * renderInfo)437 void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo)
438 {
439     // The pure color tiles' queue will be read from UI thread and written in
440     // Tex Gen thread, thus we need to have a lock here.
441     android::Mutex::Autolock lock(m_transferQueueItemLocks);
442     TileTransferData data;
443     addItemCommon(renderInfo, GpuUpload, &data);
444     data.pureColor = renderInfo->pureColor;
445     m_pureColorTileQueue.append(data);
446 }
447 
clearItemInTranferQueue(int index)448 void TransferQueue::clearItemInTranferQueue(int index)
449 {
450     m_transferQueue[index].savedTilePtr = 0;
451     SkSafeUnref(m_transferQueue[index].savedTilePainter);
452     m_transferQueue[index].savedTilePainter = 0;
453     m_transferQueue[index].status = emptyItem;
454 }
455 
456 // Translates the info from TileRenderInfo and others to TileTransferData.
457 // This is used by pure color tiles and normal tiles.
addItemCommon(const TileRenderInfo * renderInfo,TextureUploadType type,TileTransferData * data)458 void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo,
459                                   TextureUploadType type,
460                                   TileTransferData* data)
461 {
462     data->savedTileTexturePtr = renderInfo->baseTile->backTexture();
463     data->savedTilePainter = renderInfo->tilePainter;
464     SkSafeRef(data->savedTilePainter);
465     data->savedTilePtr = renderInfo->baseTile;
466     data->status = pendingBlit;
467     data->uploadType = type;
468 
469     IntRect inval(0, 0, 0, 0);
470 }
471 
472 // Note that there should be lock/unlock around this function call.
473 // Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap.
addItemInTransferQueue(const TileRenderInfo * renderInfo,TextureUploadType type,const SkBitmap * bitmap)474 void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
475                                            TextureUploadType type,
476                                            const SkBitmap* bitmap)
477 {
478     m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize;
479 
480     int index = m_transferQueueIndex;
481     if (m_transferQueue[index].savedTilePtr
482         || m_transferQueue[index].status != emptyItem) {
483         ALOGV("ERROR update a tile which is dirty already @ index %d", index);
484     }
485 
486     TileTransferData* data = &m_transferQueue[index];
487     addItemCommon(renderInfo, type, data);
488     if (type == CpuUpload && bitmap) {
489         // Lazily create the bitmap
490         if (!m_transferQueue[index].bitmap) {
491             m_transferQueue[index].bitmap = new SkBitmap();
492             int w = bitmap->width();
493             int h = bitmap->height();
494             m_transferQueue[index].bitmap->setConfig(bitmap->config(), w, h);
495         }
496         bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config());
497     }
498 
499     m_emptyItemCount--;
500 }
501 
setTextureUploadType(TextureUploadType type)502 void TransferQueue::setTextureUploadType(TextureUploadType type)
503 {
504     android::Mutex::Autolock lock(m_transferQueueItemLocks);
505     if (m_currentUploadType == type)
506         return;
507 
508     setPendingDiscard();
509 
510     m_currentUploadType = type;
511     ALOGD("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload");
512 }
513 
514 // Note: this need to be called within the lock and on the UI thread.
515 // Only called by updateDirtyTiles() and emptyQueue() for now
cleanupPendingDiscard()516 void TransferQueue::cleanupPendingDiscard()
517 {
518     int index = getNextTransferQueueIndex();
519 
520     for (int i = 0 ; i < m_transferQueueSize; i++) {
521         if (m_transferQueue[index].status == pendingDiscard) {
522             // No matter what the current upload type is, as long as there has
523             // been a Surf Tex enqueue operation, this updateTexImage need to
524             // be called to keep things in sync.
525             if (m_transferQueue[index].uploadType == GpuUpload) {
526                 status_t result = m_sharedSurfaceTexture->updateTexImage();
527                 if (result != OK)
528                     ALOGE("unexpected error: updateTexImage return %d", result);
529             }
530 
531             // since tiles in the queue may be from another webview, remove
532             // their textures so that they will be repainted / retransferred
533             Tile* tile = m_transferQueue[index].savedTilePtr;
534             TileTexture* texture = m_transferQueue[index].savedTileTexturePtr;
535             if (tile && texture && texture->owner() == tile) {
536                 // since tile destruction removes textures on the UI thread, the
537                 // texture->owner ptr guarantees the tile is valid
538                 tile->discardBackTexture();
539                 ALOGV("transfer queue discarded tile %p, removed texture", tile);
540             }
541             clearItemInTranferQueue(index);
542         }
543         index = (index + 1) % m_transferQueueSize;
544     }
545 }
546 
saveGLState()547 void TransferQueue::saveGLState()
548 {
549     glGetIntegerv(GL_FRAMEBUFFER_BINDING, m_GLStateBeforeBlit.bufferId);
550     glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport);
551     glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor);
552     glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth);
553 #ifdef DEBUG
554     glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor);
555 #endif
556 }
557 
setGLStateForCopy(int width,int height)558 void TransferQueue::setGLStateForCopy(int width, int height)
559 {
560     // Need to match the texture size.
561     glViewport(0, 0, width, height);
562     glDisable(GL_SCISSOR_TEST);
563     glDisable(GL_DEPTH_TEST);
564     // Clear the content is only for debug purpose.
565 #ifdef DEBUG
566     glClearColor(0, 0, 0, 0);
567     glClear(GL_COLOR_BUFFER_BIT);
568 #endif
569 }
570 
restoreGLState()571 void TransferQueue::restoreGLState()
572 {
573     glBindFramebuffer(GL_FRAMEBUFFER, m_GLStateBeforeBlit.bufferId[0]);
574     glViewport(m_GLStateBeforeBlit.viewport[0],
575                m_GLStateBeforeBlit.viewport[1],
576                m_GLStateBeforeBlit.viewport[2],
577                m_GLStateBeforeBlit.viewport[3]);
578 
579     if (m_GLStateBeforeBlit.scissor[0])
580         glEnable(GL_SCISSOR_TEST);
581 
582     if (m_GLStateBeforeBlit.depth[0])
583         glEnable(GL_DEPTH_TEST);
584 #ifdef DEBUG
585     glClearColor(m_GLStateBeforeBlit.clearColor[0],
586                  m_GLStateBeforeBlit.clearColor[1],
587                  m_GLStateBeforeBlit.clearColor[2],
588                  m_GLStateBeforeBlit.clearColor[3]);
589 #endif
590 }
591 
getNextTransferQueueIndex()592 int TransferQueue::getNextTransferQueueIndex()
593 {
594     return (m_transferQueueIndex + 1) % m_transferQueueSize;
595 }
596 
597 } // namespace WebCore
598 
599 #endif // USE(ACCELERATED_COMPOSITING
600