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