PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::recycledMailbox() { if (m_recycledMailboxQueue.isEmpty()) return PassRefPtr<MailboxInfo>(); WebExternalTextureMailbox mailbox; while (!m_recycledMailboxQueue.isEmpty()) { mailbox = m_recycledMailboxQueue.takeLast(); // Never have more than one mailbox in the released state. if (!m_recycledMailboxQueue.isEmpty()) deleteMailbox(mailbox); } RefPtr<MailboxInfo> mailboxInfo; for (size_t i = 0; i < m_textureMailboxes.size(); i++) { if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) { mailboxInfo = m_textureMailboxes[i]; break; } } ASSERT(mailboxInfo); if (mailboxInfo->mailbox.validSyncToken) { m_gl->WaitSyncTokenCHROMIUM(mailboxInfo->mailbox.syncToken); mailboxInfo->mailbox.validSyncToken = false; } if (mailboxInfo->size != m_size) { resizeTextureMemory(&mailboxInfo->textureInfo, m_size); mailboxInfo->size = m_size; } return mailboxInfo.release(); }
void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource) { bool contextLost = !m_isSurfaceValid || m_contextProvider->context3d()->isContextLost(); ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this); // Mailboxes are typically released in FIFO order, so we iterate // from the end of m_mailboxes. auto releasedMailboxInfo = m_mailboxes.end(); auto firstMailbox = m_mailboxes.begin(); while (true) { --releasedMailboxInfo; if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) { break; } if (releasedMailboxInfo == firstMailbox) { // Reached last entry without finding a match, should never happen. // FIXME: This used to be an ASSERT, and was (temporarily?) changed to a // CRASH to facilitate the investigation of crbug.com/443898. CRASH(); } } if (!contextLost) { // Invalidate texture state in case the compositor altered it since the copy-on-write. if (releasedMailboxInfo->m_image) { if (mailbox.syncPoint) { context()->waitSyncPoint(mailbox.syncPoint); } GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); if (texture) { if (lostResource) { texture->abandon(); } else { texture->textureParamsModified(); } } } } RefPtr<Canvas2DLayerBridge> selfRef; if (m_destructionInProgress) { // To avoid memory use after free, take a scoped self-reference // to postpone destruction until the end of this function. selfRef = this; } // The destruction of 'releasedMailboxInfo' will: // 1) Release the self reference held by the mailboxInfo, which may trigger // the self-destruction of this Canvas2DLayerBridge // 2) Release the SkImage, which will return the texture to skia's scratch // texture pool. m_mailboxes.remove(releasedMailboxInfo); Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); }
void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource) { ASSERT(isAccelerated()); bool contextLost = !m_surface || m_contextProvider->context3d()->isContextLost(); ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this); // Mailboxes are typically released in FIFO order, so we iterate // from the end of m_mailboxes. auto releasedMailboxInfo = m_mailboxes.end(); auto firstMailbox = m_mailboxes.begin(); while (true) { --releasedMailboxInfo; if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) { break; } ASSERT(releasedMailboxInfo != firstMailbox); } if (!contextLost) { // Invalidate texture state in case the compositor altered it since the copy-on-write. if (releasedMailboxInfo->m_image) { if (mailbox.validSyncToken) { context()->waitSyncToken(mailbox.syncToken); } GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); if (texture) { if (lostResource) { texture->abandon(); } else { texture->textureParamsModified(); } } } } RefPtr<Canvas2DLayerBridge> selfRef; if (m_destructionInProgress) { // To avoid memory use after free, take a scoped self-reference // to postpone destruction until the end of this function. selfRef = this; } // The destruction of 'releasedMailboxInfo' will: // 1) Release the self reference held by the mailboxInfo, which may trigger // the self-destruction of this Canvas2DLayerBridge // 2) Release the SkImage, which will return the texture to skia's scratch // texture pool. m_mailboxes.remove(releasedMailboxInfo); }
void DrawingBuffer::deleteMailbox(const WebExternalTextureMailbox& mailbox) { for (size_t i = 0; i < m_textureMailboxes.size(); i++) { if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) { if (mailbox.validSyncToken) m_gl->WaitSyncTokenCHROMIUM(mailbox.syncToken); deleteChromiumImageForTexture(&m_textureMailboxes[i]->textureInfo); m_gl->DeleteTextures(1, &m_textureMailboxes[i]->textureInfo.textureId); m_textureMailboxes.remove(i); return; } } ASSERT_NOT_REACHED(); }
void DrawingBuffer::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource) { if (m_destructionInProgress || m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR || lostResource || m_isHidden) { mailboxReleasedWithoutRecycling(mailbox); return; } for (size_t i = 0; i < m_textureMailboxes.size(); i++) { RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i]; if (nameEquals(mailboxInfo->mailbox, mailbox)) { memcpy(mailboxInfo->mailbox.syncToken, mailbox.syncToken, sizeof(mailboxInfo->mailbox.syncToken)); mailboxInfo->mailbox.validSyncToken = mailbox.validSyncToken; ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this); mailboxInfo->m_parentDrawingBuffer.clear(); m_recycledMailboxQueue.prepend(mailboxInfo->mailbox); return; } } ASSERT_NOT_REACHED(); }