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 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |