Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2010, Google Inc. All rights reserved. | 2 * Copyright (c) 2010, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "platform/graphics/gpu/DrawingBuffer.h" | 31 #include "platform/graphics/gpu/DrawingBuffer.h" |
| 32 | 32 |
| 33 #include "cc/resources/shared_bitmap.h" | |
| 33 #include "gpu/GLES2/gl2extchromium.h" | 34 #include "gpu/GLES2/gl2extchromium.h" |
| 34 #include "gpu/command_buffer/client/gles2_interface.h" | 35 #include "gpu/command_buffer/client/gles2_interface.h" |
| 35 #include "gpu/command_buffer/common/capabilities.h" | 36 #include "gpu/command_buffer/common/capabilities.h" |
| 36 #include "platform/RuntimeEnabledFeatures.h" | 37 #include "platform/RuntimeEnabledFeatures.h" |
| 37 #include "platform/TraceEvent.h" | 38 #include "platform/TraceEvent.h" |
| 39 #include "platform/graphics/AcceleratedStaticBitmapImage.h" | |
| 38 #include "platform/graphics/GraphicsLayer.h" | 40 #include "platform/graphics/GraphicsLayer.h" |
| 39 #include "platform/graphics/ImageBuffer.h" | 41 #include "platform/graphics/ImageBuffer.h" |
| 40 #include "platform/graphics/gpu/Extensions3DUtil.h" | 42 #include "platform/graphics/gpu/Extensions3DUtil.h" |
| 41 #include "public/platform/Platform.h" | 43 #include "public/platform/Platform.h" |
| 42 #include "public/platform/WebCompositorSupport.h" | 44 #include "public/platform/WebCompositorSupport.h" |
| 43 #include "public/platform/WebExternalBitmap.h" | 45 #include "public/platform/WebExternalBitmap.h" |
| 44 #include "public/platform/WebExternalTextureLayer.h" | 46 #include "public/platform/WebExternalTextureLayer.h" |
| 45 #include "public/platform/WebGraphicsContext3DProvider.h" | 47 #include "public/platform/WebGraphicsContext3DProvider.h" |
| 48 #include "skia/ext/texture_handle.h" | |
| 49 #include "third_party/skia/include/gpu/GrContext.h" | |
| 50 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" | |
| 46 #include "wtf/CheckedNumeric.h" | 51 #include "wtf/CheckedNumeric.h" |
| 47 #include "wtf/PtrUtil.h" | 52 #include "wtf/PtrUtil.h" |
| 48 #include "wtf/typed_arrays/ArrayBufferContents.h" | 53 #include "wtf/typed_arrays/ArrayBufferContents.h" |
| 49 #include <algorithm> | 54 #include <algorithm> |
| 50 #include <memory> | 55 #include <memory> |
| 51 | 56 |
| 52 namespace blink { | 57 namespace blink { |
| 53 | 58 |
| 54 namespace { | 59 namespace { |
| 55 | 60 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 return !m_wantAlphaChannel && getMultisampledRenderbufferFormat() == GL_ RGBA8_OES; | 230 return !m_wantAlphaChannel && getMultisampledRenderbufferFormat() == GL_ RGBA8_OES; |
| 226 } | 231 } |
| 227 | 232 |
| 228 bool rgbEmulation = contextProvider()->getCapabilities().emulate_rgb_buffer_ with_rgba | 233 bool rgbEmulation = contextProvider()->getCapabilities().emulate_rgb_buffer_ with_rgba |
| 229 || (RuntimeEnabledFeatures::webGLImageChromiumEnabled() && contextProvid er()->getCapabilities().chromium_image_rgb_emulation); | 234 || (RuntimeEnabledFeatures::webGLImageChromiumEnabled() && contextProvid er()->getCapabilities().chromium_image_rgb_emulation); |
| 230 return !m_wantAlphaChannel && rgbEmulation; | 235 return !m_wantAlphaChannel && rgbEmulation; |
| 231 } | 236 } |
| 232 | 237 |
| 233 void DrawingBuffer::freeRecycledMailboxes() | 238 void DrawingBuffer::freeRecycledMailboxes() |
| 234 { | 239 { |
| 235 if (m_recycledMailboxQueue.isEmpty()) | 240 while (!m_recycledMailboxQueue.isEmpty()) { |
| 236 return; | 241 RefPtr<RecycledMailbox> recycled = m_recycledMailboxQueue.takeLast(); |
| 237 while (!m_recycledMailboxQueue.isEmpty()) | 242 deleteMailbox(recycled->mailbox, recycled->syncToken); |
| 238 deleteMailbox(m_recycledMailboxQueue.takeLast()); | 243 } |
| 239 } | 244 } |
| 240 | 245 |
| 241 bool DrawingBuffer::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExt ernalBitmap* bitmap) | 246 std::unique_ptr<cc::SharedBitmap> DrawingBuffer::createOrRecycleBitmap() |
| 247 { | |
| 248 for (auto it = m_recycledBitmapQueue.begin(); it != m_recycledBitmapQueue.en d(); ++it) { | |
| 249 if (it->size != m_size) { | |
| 250 m_recycledBitmapQueue.remove(it); | |
| 251 --it; // Removed this position so iterate on it again. | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:54:01
This won't assert if it was the first element that
danakj
2016/08/22 18:45:25
The DequeTest I added deletes element 0 and passes
| |
| 252 } | |
| 253 } | |
| 254 if (!m_recycledBitmapQueue.isEmpty()) { | |
| 255 RecycledBitmap recycled = m_recycledBitmapQueue.takeLast(); | |
| 256 DCHECK(recycled.size == m_size); | |
| 257 return std::move(recycled.bitmap); | |
| 258 } | |
| 259 | |
| 260 return Platform::current()->allocateSharedBitmap(m_size); | |
| 261 } | |
| 262 | |
| 263 bool DrawingBuffer::PrepareTextureMailbox(cc::TextureMailbox* outMailbox, | |
| 264 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback, | |
| 265 bool useSharedMemory) | |
| 242 { | 266 { |
| 243 if (m_destructionInProgress) { | 267 if (m_destructionInProgress) { |
| 244 // It can be hit in the following sequence. | 268 // It can be hit in the following sequence. |
| 245 // 1. WebGL draws something. | 269 // 1. WebGL draws something. |
| 246 // 2. The compositor begins the frame. | 270 // 2. The compositor begins the frame. |
| 247 // 3. Javascript makes a context lost using WEBGL_lose_context extension . | 271 // 3. Javascript makes a context lost using WEBGL_lose_context extension . |
| 248 // 4. Here. | 272 // 4. Here. |
| 249 return false; | 273 return false; |
| 250 } | 274 } |
| 251 ASSERT(!m_isHidden); | 275 ASSERT(!m_isHidden); |
| 252 if (!m_contentsChanged) | 276 if (!m_contentsChanged) |
| 253 return false; | 277 return false; |
| 254 | 278 |
| 255 TRACE_EVENT0("blink,rail", "DrawingBuffer::prepareMailbox"); | 279 TRACE_EVENT0("blink,rail", "DrawingBuffer::prepareMailbox"); |
| 256 | 280 |
| 257 if (m_newMailboxCallback) | 281 if (m_newMailboxCallback) |
| 258 (*m_newMailboxCallback)(); | 282 (*m_newMailboxCallback)(); |
| 259 | 283 |
| 260 // Resolve the multisampled buffer into m_colorBuffer texture. | 284 // Resolve the multisampled buffer into m_colorBuffer texture. |
| 261 if (m_antiAliasingMode != None) | 285 if (m_antiAliasingMode != None) |
| 262 commit(); | 286 commit(); |
| 263 | 287 |
| 264 if (bitmap) { | 288 if (useSharedMemory) { |
| 265 bitmap->setSize(size()); | 289 std::unique_ptr<cc::SharedBitmap> bitmap = createOrRecycleBitmap(); |
| 266 | 290 if (!bitmap) |
| 291 return false; | |
| 267 unsigned char* pixels = bitmap->pixels(); | 292 unsigned char* pixels = bitmap->pixels(); |
| 268 if (!pixels) | 293 DCHECK(pixels); |
| 269 return false; | |
| 270 | 294 |
| 271 bool needPremultiply = m_wantAlphaChannel && !m_premultipliedAlpha; | 295 bool needPremultiply = m_wantAlphaChannel && !m_premultipliedAlpha; |
| 272 WebGLImageConversion::AlphaOp op = needPremultiply ? WebGLImageConversio n::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing; | 296 WebGLImageConversion::AlphaOp op = needPremultiply ? WebGLImageConversio n::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing; |
| 273 readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSki a, op); | 297 readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSki a, op); |
| 298 | |
| 299 *outMailbox = cc::TextureMailbox(bitmap.get(), m_size); | |
| 300 | |
| 301 // This holds a ref on the DrawingBuffer that will keep it alive until t he | |
| 302 // mailbox is released (and while the release callback is running). It a lso | |
| 303 // owns the SharedBitmap. | |
| 304 auto func = WTF::bind(&DrawingBuffer::softwareMailboxReleased, | |
| 305 RefPtr<DrawingBuffer>(this), | |
| 306 WTF::passed(std::move(bitmap)), | |
| 307 m_size); | |
| 308 *outReleaseCallback = cc::SingleReleaseCallback::Create( | |
| 309 convertToBaseCallback(std::move(func))); | |
| 310 return true; | |
| 274 } | 311 } |
| 275 | 312 |
| 276 // We must restore the texture binding since creating new textures, | 313 // We must restore the texture binding since creating new textures, |
| 277 // consuming and producing mailboxes changes it. | 314 // consuming and producing mailboxes changes it. |
| 278 ScopedTextureUnit0BindingRestorer restorer(m_gl, m_activeTextureUnit, m_text ure2DBinding); | 315 ScopedTextureUnit0BindingRestorer restorer(m_gl, m_activeTextureUnit, m_text ure2DBinding); |
| 279 | 316 |
| 280 // First try to recycle an old buffer. | 317 // First try to recycle an old buffer. |
| 281 RefPtr<MailboxInfo> frontColorBufferMailbox = recycledMailbox(); | 318 RefPtr<MailboxInfo> mailboxInfo = takeRecycledMailbox(); |
| 282 | 319 |
| 283 // No buffer available to recycle, create a new one. | 320 // No buffer available to recycle, create a new one. |
| 284 if (!frontColorBufferMailbox) | 321 if (!mailboxInfo) |
| 285 frontColorBufferMailbox = createNewMailbox(createTextureAndAllocateMemor y(m_size)); | 322 mailboxInfo = createNewMailbox(createTextureAndAllocateMemory(m_size)); |
| 286 | 323 |
| 287 if (m_preserveDrawingBuffer == Discard) { | 324 if (m_preserveDrawingBuffer == Discard) { |
| 288 std::swap(frontColorBufferMailbox->textureInfo, m_colorBuffer); | 325 std::swap(mailboxInfo->textureInfo, m_colorBuffer); |
| 289 attachColorBufferToReadFramebuffer(); | 326 attachColorBufferToReadFramebuffer(); |
| 290 | 327 |
| 291 if (m_discardFramebufferSupported) { | 328 if (m_discardFramebufferSupported) { |
| 292 // Explicitly discard framebuffer to save GPU memory bandwidth for t ile-based GPU arch. | 329 // Explicitly discard framebuffer to save GPU memory bandwidth for t ile-based GPU arch. |
| 293 const GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTAC HMENT, GL_STENCIL_ATTACHMENT }; | 330 const GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTAC HMENT, GL_STENCIL_ATTACHMENT }; |
| 294 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); | 331 m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo); |
| 295 m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments); | 332 m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments); |
| 296 } | 333 } |
| 297 } else { | 334 } else { |
| 298 m_gl->CopySubTextureCHROMIUM(m_colorBuffer.textureId, frontColorBufferMa ilbox->textureInfo.textureId, | 335 m_gl->CopySubTextureCHROMIUM(m_colorBuffer.textureId, mailboxInfo->textu reInfo.textureId, |
| 299 0, 0, 0, 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_ FALSE); | 336 0, 0, 0, 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_ FALSE); |
| 300 } | 337 } |
| 301 | 338 |
| 302 restoreFramebufferBindings(); | 339 restoreFramebufferBindings(); |
| 303 m_contentsChanged = false; | 340 m_contentsChanged = false; |
| 304 | 341 |
| 305 m_gl->ProduceTextureDirectCHROMIUM(frontColorBufferMailbox->textureInfo.text ureId, frontColorBufferMailbox->textureInfo.parameters.target, frontColorBufferM ailbox->mailbox.name); | 342 m_gl->ProduceTextureDirectCHROMIUM(mailboxInfo->textureInfo.textureId, mailb oxInfo->textureInfo.parameters.target, mailboxInfo->mailbox.name); |
| 306 const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM(); | 343 const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM(); |
| 307 #if OS(MACOSX) | 344 #if OS(MACOSX) |
| 308 m_gl->DescheduleUntilFinishedCHROMIUM(); | 345 m_gl->DescheduleUntilFinishedCHROMIUM(); |
| 309 #endif | 346 #endif |
| 310 m_gl->Flush(); | 347 m_gl->Flush(); |
| 311 m_gl->GenSyncTokenCHROMIUM(fenceSync, frontColorBufferMailbox->mailbox.syncT oken); | 348 gpu::SyncToken syncToken; |
| 312 frontColorBufferMailbox->mailbox.validSyncToken = true; | 349 m_gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData()); |
| 313 frontColorBufferMailbox->mailbox.allowOverlay = frontColorBufferMailbox->tex tureInfo.imageId != 0; | 350 |
| 314 frontColorBufferMailbox->mailbox.textureTarget = frontColorBufferMailbox->te xtureInfo.parameters.target; | 351 bool isOverlayCandidate = mailboxInfo->textureInfo.imageId != 0; |
| 315 frontColorBufferMailbox->mailbox.textureSize = WebSize(m_size.width(), m_siz e.height()); | 352 bool secureOutputOnly = false; |
| 353 *outMailbox = cc::TextureMailbox( | |
| 354 mailboxInfo->mailbox, syncToken, | |
| 355 mailboxInfo->textureInfo.parameters.target, | |
| 356 gfx::Size(m_size.width(), m_size.height()), | |
| 357 isOverlayCandidate, | |
| 358 secureOutputOnly); | |
| 359 | |
| 360 // This holds a ref on the DrawingBuffer that will keep it alive until the | |
| 361 // mailbox is released (and while the release callback is running). | |
| 362 auto func = WTF::bind(&DrawingBuffer::gpuMailboxReleased, | |
| 363 RefPtr<DrawingBuffer>(this), | |
| 364 mailboxInfo->mailbox); | |
| 365 *outReleaseCallback = cc::SingleReleaseCallback::Create( | |
| 366 convertToBaseCallback(std::move(func))); | |
| 367 | |
| 368 m_frontColorBuffer = { mailboxInfo->mailbox, syncToken, mailboxInfo->texture Info }; | |
| 316 setBufferClearNeeded(true); | 369 setBufferClearNeeded(true); |
| 317 | |
| 318 // set m_parentDrawingBuffer to make sure 'this' stays alive as long as it h as live mailboxes | |
| 319 ASSERT(!frontColorBufferMailbox->m_parentDrawingBuffer); | |
| 320 frontColorBufferMailbox->m_parentDrawingBuffer = this; | |
| 321 *outMailbox = frontColorBufferMailbox->mailbox; | |
| 322 m_frontColorBuffer = { frontColorBufferMailbox->textureInfo, frontColorBuffe rMailbox->mailbox }; | |
| 323 return true; | 370 return true; |
| 324 } | 371 } |
| 325 | 372 |
| 326 void DrawingBuffer::mailboxReleased(const WebExternalTextureMailbox& mailbox, bo ol lostResource) | 373 void DrawingBuffer::gpuMailboxReleased(const gpu::Mailbox& mailbox, const gpu::S yncToken& syncToken, |
| 374 bool lostResource) | |
| 327 { | 375 { |
| 328 if (m_destructionInProgress || m_gl->GetGraphicsResetStatusKHR() != GL_NO_ER ROR || lostResource || m_isHidden) { | 376 if (m_destructionInProgress || m_gl->GetGraphicsResetStatusKHR() != GL_NO_ER ROR || lostResource || m_isHidden) { |
| 329 mailboxReleasedWithoutRecycling(mailbox); | 377 deleteMailbox(mailbox, syncToken); |
| 330 return; | 378 return; |
| 331 } | 379 } |
| 332 | 380 |
| 333 for (size_t i = 0; i < m_textureMailboxes.size(); i++) { | 381 for (size_t i = 0; i < m_textureMailboxes.size(); i++) { |
| 334 RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i]; | 382 RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i]; |
| 335 if (nameEquals(mailboxInfo->mailbox, mailbox)) { | 383 if (mailboxInfo->mailbox == mailbox) { |
| 336 memcpy(mailboxInfo->mailbox.syncToken, mailbox.syncToken, | 384 m_recycledMailboxQueue.prepend(adoptRef(new RecycledMailbox(mailbox, syncToken))); |
| 337 sizeof(mailboxInfo->mailbox.syncToken)); | |
| 338 mailboxInfo->mailbox.validSyncToken = mailbox.validSyncToken; | |
| 339 ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this); | |
| 340 mailboxInfo->m_parentDrawingBuffer.clear(); | |
| 341 m_recycledMailboxQueue.prepend(mailboxInfo->mailbox); | |
| 342 return; | 385 return; |
| 343 } | 386 } |
| 344 } | 387 } |
| 345 ASSERT_NOT_REACHED(); | 388 ASSERT_NOT_REACHED(); |
| 346 } | 389 } |
| 347 | 390 |
| 391 void DrawingBuffer::softwareMailboxReleased(std::unique_ptr<cc::SharedBitmap> bi tmap, const IntSize& size, const gpu::SyncToken& syncToken, bool lostResource) | |
| 392 { | |
| 393 DCHECK(!syncToken.HasData()); // No sync tokens for software resources. | |
| 394 if (m_destructionInProgress || lostResource || m_isHidden || size != m_size) | |
| 395 return; // Just delete the bitmap. | |
| 396 | |
| 397 RecycledBitmap recycled = { std::move(bitmap), m_size }; | |
| 398 m_recycledBitmapQueue.append(std::move(recycled)); | |
| 399 } | |
| 400 | |
| 401 PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() | |
| 402 { | |
| 403 // This can be null if the context is lost before the first call to grContex t(). | |
| 404 GrContext* grContext = m_contextProvider->grContext(); | |
| 405 | |
| 406 cc::TextureMailbox textureMailbox; | |
| 407 std::unique_ptr<cc::SingleReleaseCallback> releaseCallback; | |
| 408 bool useSharedMemory = false; | |
| 409 bool success = false; | |
| 410 if (grContext) | |
| 411 success = PrepareTextureMailbox(&textureMailbox, &releaseCallback, useSh aredMemory); | |
| 412 if (!success) { | |
| 413 // If we can't get a mailbox, return an transparent black ImageBitmap. | |
| 414 // The only situation this could happen is when two or more calls to tra nsferToImageBitmap are made back-to-back, or when the context gets lost. | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:54:01
The intent of transferToStaticBitmapImage is that
danakj
2016/08/22 18:45:24
So I think how this works is if |m_preserveDrawing
Ken Russell (switch to Gerrit)
2016/08/22 19:03:11
Thanks for this explanation - sounds good.
| |
| 415 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(m_size.width() , m_size.height()); | |
| 416 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ; | |
| 417 } | |
| 418 | |
| 419 DCHECK_EQ(m_size.width(), textureMailbox.size_in_pixels().width()); | |
| 420 DCHECK_EQ(m_size.height(), textureMailbox.size_in_pixels().height()); | |
| 421 | |
| 422 // Make our own textureId that is a reference on the same texture backing be ing used as the front | |
| 423 // buffer (which was returned from PrepareTextureMailbox()). | |
| 424 // TODO(danakj): Instead of using PrepareTextureMailbox(), we could just use the actual texture id and | |
| 425 // avoid this whole dance of wait for sync token, consume, generate new sync token. | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:54:01
It's possible this wasn't implemented as desired b
danakj
2016/08/22 19:01:04
I think this is what is happening. We PrepareTextu
Ken Russell (switch to Gerrit)
2016/08/22 19:03:11
I see. Thanks for this explanation. Per our offlin
| |
| 426 m_gl->WaitSyncTokenCHROMIUM(textureMailbox.GetSyncTokenData()); | |
| 427 GLuint textureId = m_gl->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, text ureMailbox.name()); | |
| 428 const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM(); | |
| 429 m_gl->Flush(); | |
| 430 gpu::SyncToken syncToken; | |
| 431 m_gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData()); | |
| 432 // Return the mailbox but report that the resource is lost to prevent trying to use | |
| 433 // the backing for future frames. We keep it alive with our own reference to the | |
| 434 // backing via our |textureId|. | |
| 435 releaseCallback->Run(syncToken, true /* lostResource */); | |
| 436 | |
| 437 // Store that texture id as the backing for an SkImage. | |
| 438 GrGLTextureInfo textureInfo; | |
| 439 textureInfo.fTarget = GL_TEXTURE_2D; | |
| 440 textureInfo.fID = textureId; | |
| 441 GrBackendTextureDesc backendTexture; | |
| 442 backendTexture.fOrigin = kBottomLeft_GrSurfaceOrigin; | |
| 443 backendTexture.fWidth = m_size.width(); | |
| 444 backendTexture.fHeight = m_size.height(); | |
| 445 backendTexture.fConfig = kSkia8888_GrPixelConfig; | |
| 446 backendTexture.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(textu reInfo); | |
| 447 sk_sp<SkImage> skImage = SkImage::MakeFromAdoptedTexture(grContext, backendT exture); | |
| 448 | |
| 449 // Hold a ref on the GrContext for the texture backing the |skImage|. | |
| 450 sk_sp<GrContext> grContextRef = sk_ref_sp(grContext); | |
| 451 // We reuse the same mailbox name from above since our texture id was consum ed from it. | |
| 452 const auto& skImageMailbox = textureMailbox.mailbox(); | |
| 453 // Use the sync token generated after producing the mailbox. Waiting for thi s before trying to use | |
| 454 // the mailbox with some other context will ensure it is valid. We wouldn't need to wait for the | |
| 455 // consume because the texture id it generated would only be valid for the D rawingBuffer's context | |
| 456 // anyways. | |
| 457 const auto& skImageSyncToken = textureMailbox.sync_token(); | |
| 458 | |
| 459 // TODO(xidachen): Create a small pool of recycled textures from ImageBitmap RenderingContext's | |
| 460 // transferFromImageBitmap, and try to use them in DrawingBuffer. | |
| 461 return AcceleratedStaticBitmapImage::create(fromSkSp(skImage), grContextRef, skImageMailbox, skImageSyncToken); | |
| 462 } | |
| 463 | |
| 348 DrawingBuffer::TextureParameters DrawingBuffer::chromiumImageTextureParameters() | 464 DrawingBuffer::TextureParameters DrawingBuffer::chromiumImageTextureParameters() |
| 349 { | 465 { |
| 350 #if OS(MACOSX) | 466 #if OS(MACOSX) |
| 351 // A CHROMIUM_image backed texture requires a specialized set of parameters | 467 // A CHROMIUM_image backed texture requires a specialized set of parameters |
| 352 // on OSX. | 468 // on OSX. |
| 353 TextureParameters parameters; | 469 TextureParameters parameters; |
| 354 parameters.target = GC3D_TEXTURE_RECTANGLE_ARB; | 470 parameters.target = GC3D_TEXTURE_RECTANGLE_ARB; |
| 355 | 471 |
| 356 if (m_wantAlphaChannel) { | 472 if (m_wantAlphaChannel) { |
| 357 parameters.creationInternalColorFormat = GL_RGBA; | 473 parameters.creationInternalColorFormat = GL_RGBA; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 387 parameters.colorFormat = GL_RGBA; | 503 parameters.colorFormat = GL_RGBA; |
| 388 } else { | 504 } else { |
| 389 GLenum format = defaultBufferRequiresAlphaChannelToBePreserved() ? GL_RG BA : GL_RGB; | 505 GLenum format = defaultBufferRequiresAlphaChannelToBePreserved() ? GL_RG BA : GL_RGB; |
| 390 parameters.creationInternalColorFormat = format; | 506 parameters.creationInternalColorFormat = format; |
| 391 parameters.internalColorFormat = format; | 507 parameters.internalColorFormat = format; |
| 392 parameters.colorFormat = format; | 508 parameters.colorFormat = format; |
| 393 } | 509 } |
| 394 return parameters; | 510 return parameters; |
| 395 } | 511 } |
| 396 | 512 |
| 397 void DrawingBuffer::mailboxReleasedWithoutRecycling(const WebExternalTextureMail box& mailbox) | 513 PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::takeRecycledMailbox() |
| 398 { | |
| 399 ASSERT(m_textureMailboxes.size()); | |
| 400 // Ensure not to call the destructor until deleteMailbox() is completed. | |
| 401 RefPtr<DrawingBuffer> self = this; | |
| 402 deleteMailbox(mailbox); | |
| 403 } | |
| 404 | |
| 405 PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::recycledMailbox() | |
| 406 { | 514 { |
| 407 if (m_recycledMailboxQueue.isEmpty()) | 515 if (m_recycledMailboxQueue.isEmpty()) |
| 408 return PassRefPtr<MailboxInfo>(); | 516 return nullptr; |
| 409 | 517 |
| 410 // Creation of image backed mailboxes is very expensive, so be less | 518 // Creation of image backed mailboxes is very expensive, so be less |
| 411 // aggressive about pruning them. | 519 // aggressive about pruning them. |
| 412 size_t cacheLimit = 1; | 520 size_t cacheLimit = 1; |
| 413 if (RuntimeEnabledFeatures::webGLImageChromiumEnabled()) | 521 if (RuntimeEnabledFeatures::webGLImageChromiumEnabled()) |
| 414 cacheLimit = 4; | 522 cacheLimit = 4; |
| 415 | 523 |
| 416 WebExternalTextureMailbox mailbox; | 524 RefPtr<RecycledMailbox> recycled; |
| 417 while (m_recycledMailboxQueue.size() > cacheLimit) { | 525 while (m_recycledMailboxQueue.size() > cacheLimit) { |
| 418 mailbox = m_recycledMailboxQueue.takeLast(); | 526 recycled = m_recycledMailboxQueue.takeLast(); |
| 419 deleteMailbox(mailbox); | 527 deleteMailbox(recycled->mailbox, recycled->syncToken); |
| 420 } | 528 } |
| 421 mailbox = m_recycledMailboxQueue.takeLast(); | 529 recycled = m_recycledMailboxQueue.takeLast(); |
| 530 | |
| 531 if (recycled->syncToken.HasData()) | |
| 532 m_gl->WaitSyncTokenCHROMIUM(recycled->syncToken.GetData()); | |
| 422 | 533 |
| 423 RefPtr<MailboxInfo> mailboxInfo; | 534 RefPtr<MailboxInfo> mailboxInfo; |
| 424 for (size_t i = 0; i < m_textureMailboxes.size(); i++) { | 535 for (size_t i = 0; i < m_textureMailboxes.size(); i++) { |
| 425 if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) { | 536 if (m_textureMailboxes[i]->mailbox == recycled->mailbox) { |
| 426 mailboxInfo = m_textureMailboxes[i]; | 537 mailboxInfo = m_textureMailboxes[i]; |
| 427 break; | 538 break; |
| 428 } | 539 } |
| 429 } | 540 } |
| 430 ASSERT(mailboxInfo); | 541 ASSERT(mailboxInfo); |
| 431 | 542 |
| 432 if (mailboxInfo->mailbox.validSyncToken) { | |
| 433 m_gl->WaitSyncTokenCHROMIUM(mailboxInfo->mailbox.syncToken); | |
| 434 mailboxInfo->mailbox.validSyncToken = false; | |
| 435 } | |
| 436 | |
| 437 if (mailboxInfo->size != m_size) { | 543 if (mailboxInfo->size != m_size) { |
| 438 resizeTextureMemory(&mailboxInfo->textureInfo, m_size); | 544 resizeTextureMemory(&mailboxInfo->textureInfo, m_size); |
| 439 mailboxInfo->size = m_size; | 545 mailboxInfo->size = m_size; |
| 440 } | 546 } |
| 441 | 547 |
| 442 return mailboxInfo.release(); | 548 return mailboxInfo.release(); |
| 443 } | 549 } |
| 444 | 550 |
| 445 PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::createNewMailbox(const Tex tureInfo& info) | 551 PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::createNewMailbox(const Tex tureInfo& info) |
| 446 { | 552 { |
| 447 RefPtr<MailboxInfo> returnMailbox = adoptRef(new MailboxInfo()); | 553 RefPtr<MailboxInfo> returnMailbox = adoptRef(new MailboxInfo); |
| 448 m_gl->GenMailboxCHROMIUM(returnMailbox->mailbox.name); | 554 m_gl->GenMailboxCHROMIUM(returnMailbox->mailbox.name); |
| 449 returnMailbox->textureInfo = info; | 555 returnMailbox->textureInfo = info; |
| 450 returnMailbox->size = m_size; | 556 returnMailbox->size = m_size; |
| 451 m_textureMailboxes.append(returnMailbox); | 557 m_textureMailboxes.append(returnMailbox); |
| 452 return returnMailbox.release(); | 558 return returnMailbox.release(); |
| 453 } | 559 } |
| 454 | 560 |
| 455 void DrawingBuffer::deleteMailbox(const WebExternalTextureMailbox& mailbox) | 561 void DrawingBuffer::deleteMailbox(const gpu::Mailbox& mailbox, const gpu::SyncTo ken& syncToken) |
| 456 { | 562 { |
| 563 if (syncToken.HasData()) | |
| 564 m_gl->WaitSyncTokenCHROMIUM(syncToken.GetConstData()); | |
| 457 for (size_t i = 0; i < m_textureMailboxes.size(); i++) { | 565 for (size_t i = 0; i < m_textureMailboxes.size(); i++) { |
| 458 if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) { | 566 if (m_textureMailboxes[i]->mailbox == mailbox) { |
| 459 if (mailbox.validSyncToken) | |
| 460 m_gl->WaitSyncTokenCHROMIUM(mailbox.syncToken); | |
| 461 | |
| 462 deleteChromiumImageForTexture(&m_textureMailboxes[i]->textureInfo); | 567 deleteChromiumImageForTexture(&m_textureMailboxes[i]->textureInfo); |
| 463 | |
| 464 m_gl->DeleteTextures(1, &m_textureMailboxes[i]->textureInfo.textureI d); | 568 m_gl->DeleteTextures(1, &m_textureMailboxes[i]->textureInfo.textureI d); |
| 465 m_textureMailboxes.remove(i); | 569 m_textureMailboxes.remove(i); |
| 466 return; | 570 return; |
| 467 } | 571 } |
| 468 } | 572 } |
| 469 ASSERT_NOT_REACHED(); | 573 ASSERT_NOT_REACHED(); |
| 470 } | 574 } |
| 471 | 575 |
| 472 bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) | 576 bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) |
| 473 { | 577 { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 restoreFramebufferBindings(); | 634 restoreFramebufferBindings(); |
| 531 } | 635 } |
| 532 m_gl->Flush(); | 636 m_gl->Flush(); |
| 533 } | 637 } |
| 534 | 638 |
| 535 // Assume that the destination target is GL_TEXTURE_2D. | 639 // Assume that the destination target is GL_TEXTURE_2D. |
| 536 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(GL_TEXTURE_2D, internalForm at, destType, level)) | 640 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(GL_TEXTURE_2D, internalForm at, destType, level)) |
| 537 return false; | 641 return false; |
| 538 | 642 |
| 539 // Contexts may be in a different share group. We must transfer the texture through a mailbox first | 643 // Contexts may be in a different share group. We must transfer the texture through a mailbox first |
| 540 WebExternalTextureMailbox mailbox; | |
| 541 GLint textureId = 0; | 644 GLint textureId = 0; |
| 542 GLenum target = 0; | 645 GLenum target = 0; |
| 646 gpu::Mailbox mailbox; | |
| 647 gpu::SyncToken produceSyncToken; | |
| 543 if (sourceBuffer == FrontBuffer && m_frontColorBuffer.texInfo.textureId) { | 648 if (sourceBuffer == FrontBuffer && m_frontColorBuffer.texInfo.textureId) { |
| 544 textureId = m_frontColorBuffer.texInfo.textureId; | 649 textureId = m_frontColorBuffer.texInfo.textureId; |
| 650 target = m_frontColorBuffer.texInfo.parameters.target; | |
| 545 mailbox = m_frontColorBuffer.mailbox; | 651 mailbox = m_frontColorBuffer.mailbox; |
| 546 target = m_frontColorBuffer.texInfo.parameters.target; | 652 produceSyncToken = m_frontColorBuffer.produceSyncToken; |
| 547 } else { | 653 } else { |
| 548 textureId = m_colorBuffer.textureId; | 654 textureId = m_colorBuffer.textureId; |
| 549 target = m_colorBuffer.parameters.target; | 655 target = m_colorBuffer.parameters.target; |
| 550 m_gl->GenMailboxCHROMIUM(mailbox.name); | 656 m_gl->GenMailboxCHROMIUM(mailbox.name); |
| 551 m_gl->ProduceTextureDirectCHROMIUM(textureId, target, mailbox.name); | 657 m_gl->ProduceTextureDirectCHROMIUM(textureId, target, mailbox.name); |
| 552 const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM(); | 658 const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM(); |
| 553 m_gl->Flush(); | 659 m_gl->Flush(); |
| 554 m_gl->GenSyncTokenCHROMIUM(fenceSync, mailbox.syncToken); | 660 m_gl->GenSyncTokenCHROMIUM(fenceSync, produceSyncToken.GetData()); |
| 555 mailbox.validSyncToken = true; | |
| 556 } | 661 } |
| 557 | 662 |
| 558 if (mailbox.validSyncToken) | 663 DCHECK(produceSyncToken.HasData()); |
| 559 gl->WaitSyncTokenCHROMIUM(mailbox.syncToken); | 664 gl->WaitSyncTokenCHROMIUM(produceSyncToken.GetConstData()); |
| 560 GLuint sourceTexture = gl->CreateAndConsumeTextureCHROMIUM(target, mailbox.n ame); | 665 GLuint sourceTexture = gl->CreateAndConsumeTextureCHROMIUM(target, mailbox.n ame); |
| 561 | 666 |
| 562 GLboolean unpackPremultiplyAlphaNeeded = GL_FALSE; | 667 GLboolean unpackPremultiplyAlphaNeeded = GL_FALSE; |
| 563 GLboolean unpackUnpremultiplyAlphaNeeded = GL_FALSE; | 668 GLboolean unpackUnpremultiplyAlphaNeeded = GL_FALSE; |
| 564 if (m_wantAlphaChannel && m_premultipliedAlpha && !premultiplyAlpha) | 669 if (m_wantAlphaChannel && m_premultipliedAlpha && !premultiplyAlpha) |
| 565 unpackUnpremultiplyAlphaNeeded = GL_TRUE; | 670 unpackUnpremultiplyAlphaNeeded = GL_TRUE; |
| 566 else if (m_wantAlphaChannel && !m_premultipliedAlpha && premultiplyAlpha) | 671 else if (m_wantAlphaChannel && !m_premultipliedAlpha && premultiplyAlpha) |
| 567 unpackPremultiplyAlphaNeeded = GL_TRUE; | 672 unpackPremultiplyAlphaNeeded = GL_TRUE; |
| 568 | 673 |
| 569 gl->CopyTextureCHROMIUM(sourceTexture, texture, internalFormat, destType, fl ipY, unpackPremultiplyAlphaNeeded, unpackUnpremultiplyAlphaNeeded); | 674 gl->CopyTextureCHROMIUM(sourceTexture, texture, internalFormat, destType, fl ipY, unpackPremultiplyAlphaNeeded, unpackUnpremultiplyAlphaNeeded); |
| 570 | 675 |
| 571 gl->DeleteTextures(1, &sourceTexture); | 676 gl->DeleteTextures(1, &sourceTexture); |
| 572 | 677 |
| 573 const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM(); | 678 const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM(); |
| 574 | 679 |
| 575 gl->Flush(); | 680 gl->Flush(); |
| 576 GLbyte syncToken[GL_SYNC_TOKEN_SIZE_CHROMIUM] = { 0 }; | 681 gpu::SyncToken syncToken; |
| 577 gl->GenSyncTokenCHROMIUM(fenceSync, syncToken); | 682 gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData()); |
| 578 m_gl->WaitSyncTokenCHROMIUM(syncToken); | 683 m_gl->WaitSyncTokenCHROMIUM(syncToken.GetData()); |
| 579 | 684 |
| 580 return true; | 685 return true; |
| 581 } | 686 } |
| 582 | 687 |
| 583 GLuint DrawingBuffer::framebuffer() const | 688 GLuint DrawingBuffer::framebuffer() const |
| 584 { | 689 { |
| 585 return m_fbo; | 690 return m_fbo; |
| 586 } | 691 } |
| 587 | 692 |
| 588 WebLayer* DrawingBuffer::platformLayer() | 693 WebLayer* DrawingBuffer::platformLayer() |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 607 | 712 |
| 608 m_gl->Flush(); | 713 m_gl->Flush(); |
| 609 } | 714 } |
| 610 | 715 |
| 611 void DrawingBuffer::beginDestruction() | 716 void DrawingBuffer::beginDestruction() |
| 612 { | 717 { |
| 613 ASSERT(!m_destructionInProgress); | 718 ASSERT(!m_destructionInProgress); |
| 614 m_destructionInProgress = true; | 719 m_destructionInProgress = true; |
| 615 | 720 |
| 616 clearPlatformLayer(); | 721 clearPlatformLayer(); |
| 617 | 722 freeRecycledMailboxes(); |
| 618 while (!m_recycledMailboxQueue.isEmpty()) | |
| 619 deleteMailbox(m_recycledMailboxQueue.takeLast()); | |
| 620 | 723 |
| 621 if (m_multisampleFBO) | 724 if (m_multisampleFBO) |
| 622 m_gl->DeleteFramebuffers(1, &m_multisampleFBO); | 725 m_gl->DeleteFramebuffers(1, &m_multisampleFBO); |
| 623 | 726 |
| 624 if (m_fbo) | 727 if (m_fbo) |
| 625 m_gl->DeleteFramebuffers(1, &m_fbo); | 728 m_gl->DeleteFramebuffers(1, &m_fbo); |
| 626 | 729 |
| 627 if (m_multisampleRenderbuffer) | 730 if (m_multisampleRenderbuffer) |
| 628 m_gl->DeleteRenderbuffers(1, &m_multisampleRenderbuffer); | 731 m_gl->DeleteRenderbuffers(1, &m_multisampleRenderbuffer); |
| 629 | 732 |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1112 | 1215 |
| 1113 void DrawingBuffer::restoreTextureBindings() | 1216 void DrawingBuffer::restoreTextureBindings() |
| 1114 { | 1217 { |
| 1115 // This class potentially modifies the bindings for GL_TEXTURE_2D and | 1218 // This class potentially modifies the bindings for GL_TEXTURE_2D and |
| 1116 // GL_TEXTURE_RECTANGLE. Only GL_TEXTURE_2D needs to be restored since | 1219 // GL_TEXTURE_RECTANGLE. Only GL_TEXTURE_2D needs to be restored since |
| 1117 // the public interface for WebGL does not support GL_TEXTURE_RECTANGLE. | 1220 // the public interface for WebGL does not support GL_TEXTURE_RECTANGLE. |
| 1118 m_gl->BindTexture(GL_TEXTURE_2D, m_texture2DBinding); | 1221 m_gl->BindTexture(GL_TEXTURE_2D, m_texture2DBinding); |
| 1119 } | 1222 } |
| 1120 | 1223 |
| 1121 } // namespace blink | 1224 } // namespace blink |
| OLD | NEW |