Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp

Issue 2831733003: Fix blits from multisampled renderbuffers to alpha:false WebGL back buffer. (Closed)
Patch Set: Preemptively rebased. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 if (!recycled_color_buffer_queue_.IsEmpty()) { 584 if (!recycled_color_buffer_queue_.IsEmpty()) {
585 RefPtr<ColorBuffer> recycled = recycled_color_buffer_queue_.TakeLast(); 585 RefPtr<ColorBuffer> recycled = recycled_color_buffer_queue_.TakeLast();
586 if (recycled->receive_sync_token.HasData()) 586 if (recycled->receive_sync_token.HasData())
587 gl_->WaitSyncTokenCHROMIUM(recycled->receive_sync_token.GetData()); 587 gl_->WaitSyncTokenCHROMIUM(recycled->receive_sync_token.GetData());
588 DCHECK(recycled->size == size_); 588 DCHECK(recycled->size == size_);
589 return recycled; 589 return recycled;
590 } 590 }
591 return CreateColorBuffer(size_); 591 return CreateColorBuffer(size_);
592 } 592 }
593 593
594 DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer::
595 ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer* drawing_buffer)
596 : drawing_buffer_(drawing_buffer) {
597 doing_work_ = drawing_buffer->SetupRGBEmulationForBlitFramebuffer();
598 }
599
600 DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer::
601 ~ScopedRGBEmulationForBlitFramebuffer() {
602 if (doing_work_) {
603 drawing_buffer_->CleanupRGBEmulationForBlitFramebuffer();
604 }
605 }
606
594 DrawingBuffer::ColorBuffer::ColorBuffer( 607 DrawingBuffer::ColorBuffer::ColorBuffer(
595 DrawingBuffer* drawing_buffer, 608 DrawingBuffer* drawing_buffer,
596 const ColorBufferParameters& parameters, 609 const ColorBufferParameters& parameters,
597 const IntSize& size, 610 const IntSize& size,
598 GLuint texture_id, 611 GLuint texture_id,
599 GLuint image_id, 612 GLuint image_id,
600 std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer) 613 std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer)
601 : drawing_buffer(drawing_buffer), 614 : drawing_buffer(drawing_buffer),
602 parameters(parameters), 615 parameters(parameters),
603 size(size), 616 size(size),
604 texture_id(texture_id), 617 texture_id(texture_id),
605 image_id(image_id), 618 image_id(image_id),
606 gpu_memory_buffer(std::move(gpu_memory_buffer)) { 619 gpu_memory_buffer(std::move(gpu_memory_buffer)) {
607 drawing_buffer->ContextGL()->GenMailboxCHROMIUM(mailbox.name); 620 drawing_buffer->ContextGL()->GenMailboxCHROMIUM(mailbox.name);
608 } 621 }
609 622
610 DrawingBuffer::ColorBuffer::~ColorBuffer() { 623 DrawingBuffer::ColorBuffer::~ColorBuffer() {
611 gpu::gles2::GLES2Interface* gl = drawing_buffer->gl_; 624 gpu::gles2::GLES2Interface* gl = drawing_buffer->gl_;
612 if (receive_sync_token.HasData()) 625 if (receive_sync_token.HasData())
613 gl->WaitSyncTokenCHROMIUM(receive_sync_token.GetConstData()); 626 gl->WaitSyncTokenCHROMIUM(receive_sync_token.GetConstData());
614 if (image_id) { 627 if (image_id) {
615 gl->BindTexture(parameters.target, texture_id); 628 gl->BindTexture(parameters.target, texture_id);
616 gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id); 629 gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id);
630 if (rgb_workaround_texture_id) {
631 gl->BindTexture(parameters.target, rgb_workaround_texture_id);
632 gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id);
633 }
617 gl->DestroyImageCHROMIUM(image_id); 634 gl->DestroyImageCHROMIUM(image_id);
618 switch (parameters.target) { 635 switch (parameters.target) {
619 case GL_TEXTURE_2D: 636 case GL_TEXTURE_2D:
620 // Restore the texture binding for GL_TEXTURE_2D, since the client will 637 // Restore the texture binding for GL_TEXTURE_2D, since the client will
621 // expect the previous state. 638 // expect the previous state.
622 if (drawing_buffer->client_) 639 if (drawing_buffer->client_)
623 drawing_buffer->client_->DrawingBufferClientRestoreTexture2DBinding(); 640 drawing_buffer->client_->DrawingBufferClientRestoreTexture2DBinding();
624 break; 641 break;
625 case GC3D_TEXTURE_RECTANGLE_ARB: 642 case GC3D_TEXTURE_RECTANGLE_ARB:
626 // Rectangle textures aren't exposed to WebGL, so don't bother 643 // Rectangle textures aren't exposed to WebGL, so don't bother
627 // restoring this state (there is no meaningful way to restore it). 644 // restoring this state (there is no meaningful way to restore it).
628 break; 645 break;
629 default: 646 default:
630 NOTREACHED(); 647 NOTREACHED();
631 break; 648 break;
632 } 649 }
633 gpu_memory_buffer.reset(); 650 gpu_memory_buffer.reset();
634 } 651 }
635 gl->DeleteTextures(1, &texture_id); 652 gl->DeleteTextures(1, &texture_id);
653 gl->DeleteTextures(1, &rgb_workaround_texture_id);
636 } 654 }
637 655
638 bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) { 656 bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
639 ScopedStateRestorer scoped_state_restorer(this); 657 ScopedStateRestorer scoped_state_restorer(this);
640 658
641 if (gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { 659 if (gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
642 // Need to try to restore the context again later. 660 // Need to try to restore the context again later.
643 return false; 661 return false;
644 } 662 }
645 663
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 if (ShouldUseChromiumImage() && 1284 if (ShouldUseChromiumImage() &&
1267 ContextProvider()->GetCapabilities().chromium_image_rgb_emulation) 1285 ContextProvider()->GetCapabilities().chromium_image_rgb_emulation)
1268 return GL_RGBA8_OES; 1286 return GL_RGBA8_OES;
1269 if (ContextProvider() 1287 if (ContextProvider()
1270 ->GetCapabilities() 1288 ->GetCapabilities()
1271 .disable_webgl_rgb_multisampling_usage) 1289 .disable_webgl_rgb_multisampling_usage)
1272 return GL_RGBA8_OES; 1290 return GL_RGBA8_OES;
1273 return GL_RGB8_OES; 1291 return GL_RGB8_OES;
1274 } 1292 }
1275 1293
1294 bool DrawingBuffer::SetupRGBEmulationForBlitFramebuffer() {
1295 // We only need to do this work if:
1296 // - The user has selected alpha:false and antialias:false
1297 // - We are using CHROMIUM_image with RGB emulation
1298 // macOS is the only platform on which this is necessary.
1299
1300 if (want_alpha_channel_ || anti_aliasing_mode_ != kNone)
1301 return false;
1302
1303 if (!(ShouldUseChromiumImage() &&
1304 ContextProvider()->GetCapabilities().chromium_image_rgb_emulation))
1305 return false;
1306
1307 if (!back_color_buffer_)
1308 return false;
1309
1310 // If for some reason the back buffer doesn't have a CHROMIUM_image,
1311 // don't proceed with this workaround.
1312 if (!back_color_buffer_->image_id)
1313 return false;
1314
1315 // Before allowing the BlitFramebuffer call to go through, it's necessary
1316 // to swap out the RGBA texture that's bound to the CHROMIUM_image
1317 // instance with an RGB texture. BlitFramebuffer requires the internal
1318 // formats of the source and destination to match when doing a
1319 // multisample resolve, and the best way to achieve this without adding
1320 // more full-screen blits is to hook up a true RGB texture to the
1321 // underlying IOSurface. Unfortunately, on macOS, this rendering path
1322 // destroys the alpha channel and requires a fixup afterward, which is
1323 // why it isn't used all the time.
1324
1325 GLuint rgb_texture = back_color_buffer_->rgb_workaround_texture_id;
1326 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
1327 if (!rgb_texture) {
1328 gl_->GenTextures(1, &rgb_texture);
1329 gl_->BindTexture(target, rgb_texture);
1330 gl_->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1331 gl_->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1332 gl_->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1333 gl_->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1334
1335 // Bind this texture to the CHROMIUM_image instance that the color
1336 // buffer owns. This is an expensive operation, so it's important that
1337 // the result be cached.
1338 gl_->BindTexImage2DWithInternalformatCHROMIUM(target, GL_RGB,
1339 back_color_buffer_->image_id);
1340 back_color_buffer_->rgb_workaround_texture_id = rgb_texture;
1341 }
1342
1343 gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0,
1344 target, rgb_texture, 0);
1345 return true;
1346 }
1347
1348 void DrawingBuffer::CleanupRGBEmulationForBlitFramebuffer() {
1349 // This will only be called if SetupRGBEmulationForBlitFramebuffer was.
1350 // Put the framebuffer back the way it was, and clear the alpha channel.
1351 DCHECK(back_color_buffer_);
1352 DCHECK(back_color_buffer_->image_id);
1353 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
1354 gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0,
1355 target, back_color_buffer_->texture_id, 0);
1356 // Clear the alpha channel.
1357 gl_->ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
1358 gl_->Disable(GL_SCISSOR_TEST);
1359 gl_->ClearColor(0, 0, 0, 1);
1360 gl_->Clear(GL_COLOR_BUFFER_BIT);
1361 DCHECK(client_);
1362 client_->DrawingBufferClientRestoreScissorTest();
1363 client_->DrawingBufferClientRestoreMaskAndClearValues();
1364 }
1365
1276 DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer( 1366 DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer(
1277 DrawingBuffer* drawing_buffer) 1367 DrawingBuffer* drawing_buffer)
1278 : drawing_buffer_(drawing_buffer) { 1368 : drawing_buffer_(drawing_buffer) {
1279 // If this is a nested restorer, save the previous restorer. 1369 // If this is a nested restorer, save the previous restorer.
1280 previous_state_restorer_ = drawing_buffer->state_restorer_; 1370 previous_state_restorer_ = drawing_buffer->state_restorer_;
1281 drawing_buffer_->state_restorer_ = this; 1371 drawing_buffer_->state_restorer_ = this;
1282 } 1372 }
1283 1373
1284 DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() { 1374 DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() {
1285 DCHECK_EQ(drawing_buffer_->state_restorer_, this); 1375 DCHECK_EQ(drawing_buffer_->state_restorer_, this);
(...skipping 17 matching lines...) Expand all
1303 if (pixel_unpack_buffer_binding_dirty_) 1393 if (pixel_unpack_buffer_binding_dirty_)
1304 client->DrawingBufferClientRestorePixelUnpackBufferBinding(); 1394 client->DrawingBufferClientRestorePixelUnpackBufferBinding();
1305 } 1395 }
1306 1396
1307 bool DrawingBuffer::ShouldUseChromiumImage() { 1397 bool DrawingBuffer::ShouldUseChromiumImage() {
1308 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() && 1398 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() &&
1309 chromium_image_usage_ == kAllowChromiumImage; 1399 chromium_image_usage_ == kAllowChromiumImage;
1310 } 1400 }
1311 1401
1312 } // namespace blink 1402 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698