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