void TransferQueue::updatePureColorTiles() { for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) { TileTransferData* data = &m_pureColorTileQueue[i]; if (data->status == pendingBlit) { TileTexture* destTexture = 0; bool obsoleteTile = checkObsolete(data); if (!obsoleteTile) { destTexture = data->savedTilePtr->backTexture(); destTexture->setPureColor(data->pureColor); destTexture->transferComplete(); } } else if (data->status == emptyItem || data->status == pendingDiscard) { // The queue should be clear instead of setting to different status. ALOGV("Warning: Don't expect an emptyItem here."); } } clearPureColorQueue(); }
// Call on UI thread to copy from the shared Surface Texture to the Tile's texture. void TransferQueue::updateDirtyTiles() { android::Mutex::Autolock lock(m_transferQueueItemLocks); cleanupPendingDiscard(); if (!getHasGLContext()) setHasGLContext(true); // Check the pure color tile first, since it is simpler. updatePureColorTiles(); // Start from the oldest item, we call the updateTexImage to retrive // the texture and blit that into each Tile's texture. const int nextItemIndex = getNextTransferQueueIndex(); int index = nextItemIndex; bool usedFboForUpload = false; for (int k = 0; k < m_transferQueueSize ; k++) { if (m_transferQueue[index].status == pendingBlit) { bool obsoleteTile = checkObsolete(&m_transferQueue[index]); // Save the needed info, update the Surf Tex, clean up the item in // the queue. Then either move on to next item or copy the content. TileTexture* destTexture = 0; if (!obsoleteTile) destTexture = m_transferQueue[index].savedTilePtr->backTexture(); if (m_transferQueue[index].uploadType == GpuUpload) { status_t result = m_sharedSurfaceTexture->updateTexImage(); if (result != OK) ALOGE("unexpected error: updateTexImage return %d", result); } if (obsoleteTile) { ALOGV("Warning: the texture is obsolete for this baseTile"); clearItemInTranferQueue(index); index = (index + 1) % m_transferQueueSize; continue; } // guarantee that we have a texture to blit into destTexture->requireGLTexture(); GLUtils::checkGlError("before blitTileFromQueue"); if (m_transferQueue[index].uploadType == CpuUpload) { // Here we just need to upload the bitmap content to the GL Texture GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, *m_transferQueue[index].bitmap); } else { if (!usedFboForUpload) { saveGLState(); usedFboForUpload = true; } blitTileFromQueue(m_fboID, destTexture, m_sharedSurfaceTextureId, m_sharedSurfaceTexture->getCurrentTextureTarget(), index); } destTexture->setPure(false); destTexture->transferComplete(); clearItemInTranferQueue(index); ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", m_transferQueue[index].savedTilePtr, destTexture, destTexture->m_ownTextureId); } index = (index + 1) % m_transferQueueSize; } // Clean up FBO setup. Doing this for both CPU/GPU upload can make the // dynamic switch possible. Moving this out from the loop can save some // milli-seconds. if (usedFboForUpload) { restoreGLState(); GLUtils::checkGlError("updateDirtyTiles"); } m_emptyItemCount = m_transferQueueSize; m_transferQueueItemCond.signal(); }