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 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 if (!recycled_color_buffer_queue_.IsEmpty()) { | 569 if (!recycled_color_buffer_queue_.IsEmpty()) { |
570 RefPtr<ColorBuffer> recycled = recycled_color_buffer_queue_.TakeLast(); | 570 RefPtr<ColorBuffer> recycled = recycled_color_buffer_queue_.TakeLast(); |
571 if (recycled->receive_sync_token.HasData()) | 571 if (recycled->receive_sync_token.HasData()) |
572 gl_->WaitSyncTokenCHROMIUM(recycled->receive_sync_token.GetData()); | 572 gl_->WaitSyncTokenCHROMIUM(recycled->receive_sync_token.GetData()); |
573 DCHECK(recycled->size == size_); | 573 DCHECK(recycled->size == size_); |
574 return recycled; | 574 return recycled; |
575 } | 575 } |
576 return CreateColorBuffer(size_); | 576 return CreateColorBuffer(size_); |
577 } | 577 } |
578 | 578 |
| 579 DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer:: |
| 580 ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer* drawing_buffer) |
| 581 : drawing_buffer_(drawing_buffer) { |
| 582 doing_work_ = drawing_buffer->SetupRGBEmulationForBlitFramebuffer(); |
| 583 } |
| 584 |
| 585 DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer:: |
| 586 ~ScopedRGBEmulationForBlitFramebuffer() { |
| 587 if (doing_work_) { |
| 588 drawing_buffer_->CleanupRGBEmulationForBlitFramebuffer(); |
| 589 } |
| 590 } |
| 591 |
579 DrawingBuffer::ColorBuffer::ColorBuffer( | 592 DrawingBuffer::ColorBuffer::ColorBuffer( |
580 DrawingBuffer* drawing_buffer, | 593 DrawingBuffer* drawing_buffer, |
581 const ColorBufferParameters& parameters, | 594 const ColorBufferParameters& parameters, |
582 const IntSize& size, | 595 const IntSize& size, |
583 GLuint texture_id, | 596 GLuint texture_id, |
584 GLuint image_id, | 597 GLuint image_id, |
585 std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer) | 598 std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer) |
586 : drawing_buffer(drawing_buffer), | 599 : drawing_buffer(drawing_buffer), |
587 parameters(parameters), | 600 parameters(parameters), |
588 size(size), | 601 size(size), |
589 texture_id(texture_id), | 602 texture_id(texture_id), |
590 image_id(image_id), | 603 image_id(image_id), |
591 gpu_memory_buffer(std::move(gpu_memory_buffer)) { | 604 gpu_memory_buffer(std::move(gpu_memory_buffer)) { |
592 drawing_buffer->ContextGL()->GenMailboxCHROMIUM(mailbox.name); | 605 drawing_buffer->ContextGL()->GenMailboxCHROMIUM(mailbox.name); |
593 } | 606 } |
594 | 607 |
595 DrawingBuffer::ColorBuffer::~ColorBuffer() { | 608 DrawingBuffer::ColorBuffer::~ColorBuffer() { |
596 gpu::gles2::GLES2Interface* gl = drawing_buffer->gl_; | 609 gpu::gles2::GLES2Interface* gl = drawing_buffer->gl_; |
597 if (receive_sync_token.HasData()) | 610 if (receive_sync_token.HasData()) |
598 gl->WaitSyncTokenCHROMIUM(receive_sync_token.GetConstData()); | 611 gl->WaitSyncTokenCHROMIUM(receive_sync_token.GetConstData()); |
599 if (image_id) { | 612 if (image_id) { |
600 gl->BindTexture(parameters.target, texture_id); | 613 gl->BindTexture(parameters.target, texture_id); |
601 gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id); | 614 gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id); |
| 615 if (rgb_workaround_texture_id) { |
| 616 gl->BindTexture(parameters.target, rgb_workaround_texture_id); |
| 617 gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id); |
| 618 } |
602 gl->DestroyImageCHROMIUM(image_id); | 619 gl->DestroyImageCHROMIUM(image_id); |
603 switch (parameters.target) { | 620 switch (parameters.target) { |
604 case GL_TEXTURE_2D: | 621 case GL_TEXTURE_2D: |
605 // Restore the texture binding for GL_TEXTURE_2D, since the client will | 622 // Restore the texture binding for GL_TEXTURE_2D, since the client will |
606 // expect the previous state. | 623 // expect the previous state. |
607 if (drawing_buffer->client_) | 624 if (drawing_buffer->client_) |
608 drawing_buffer->client_->DrawingBufferClientRestoreTexture2DBinding(); | 625 drawing_buffer->client_->DrawingBufferClientRestoreTexture2DBinding(); |
609 break; | 626 break; |
610 case GC3D_TEXTURE_RECTANGLE_ARB: | 627 case GC3D_TEXTURE_RECTANGLE_ARB: |
611 // Rectangle textures aren't exposed to WebGL, so don't bother | 628 // Rectangle textures aren't exposed to WebGL, so don't bother |
612 // restoring this state (there is no meaningful way to restore it). | 629 // restoring this state (there is no meaningful way to restore it). |
613 break; | 630 break; |
614 default: | 631 default: |
615 NOTREACHED(); | 632 NOTREACHED(); |
616 break; | 633 break; |
617 } | 634 } |
618 gpu_memory_buffer.reset(); | 635 gpu_memory_buffer.reset(); |
619 } | 636 } |
620 gl->DeleteTextures(1, &texture_id); | 637 gl->DeleteTextures(1, &texture_id); |
| 638 if (rgb_workaround_texture_id) { |
| 639 // Avoid deleting this texture if it was unused. |
| 640 gl->DeleteTextures(1, &rgb_workaround_texture_id); |
| 641 } |
621 } | 642 } |
622 | 643 |
623 bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) { | 644 bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) { |
624 ScopedStateRestorer scoped_state_restorer(this); | 645 ScopedStateRestorer scoped_state_restorer(this); |
625 | 646 |
626 if (gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { | 647 if (gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { |
627 // Need to try to restore the context again later. | 648 // Need to try to restore the context again later. |
628 return false; | 649 return false; |
629 } | 650 } |
630 | 651 |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1251 if (ShouldUseChromiumImage() && | 1272 if (ShouldUseChromiumImage() && |
1252 ContextProvider()->GetCapabilities().chromium_image_rgb_emulation) | 1273 ContextProvider()->GetCapabilities().chromium_image_rgb_emulation) |
1253 return GL_RGBA8_OES; | 1274 return GL_RGBA8_OES; |
1254 if (ContextProvider() | 1275 if (ContextProvider() |
1255 ->GetCapabilities() | 1276 ->GetCapabilities() |
1256 .disable_webgl_rgb_multisampling_usage) | 1277 .disable_webgl_rgb_multisampling_usage) |
1257 return GL_RGBA8_OES; | 1278 return GL_RGBA8_OES; |
1258 return GL_RGB8_OES; | 1279 return GL_RGB8_OES; |
1259 } | 1280 } |
1260 | 1281 |
| 1282 bool DrawingBuffer::SetupRGBEmulationForBlitFramebuffer() { |
| 1283 // We only need to do this work if: |
| 1284 // - The user has selected alpha:false and antialias:false |
| 1285 // - We are using CHROMIUM_image with RGB emulation |
| 1286 // macOS is the only platform on which this is necessary. |
| 1287 |
| 1288 if (want_alpha_channel_ || anti_aliasing_mode_ != kNone) |
| 1289 return false; |
| 1290 |
| 1291 if (!(ShouldUseChromiumImage() && |
| 1292 ContextProvider()->GetCapabilities().chromium_image_rgb_emulation)) |
| 1293 return false; |
| 1294 |
| 1295 if (!back_color_buffer_) |
| 1296 return false; |
| 1297 |
| 1298 // If for some reason the back buffer doesn't have a CHROMIUM_image, |
| 1299 // don't proceed with this workaround. |
| 1300 if (!back_color_buffer_->image_id) |
| 1301 return false; |
| 1302 |
| 1303 // Before allowing the BlitFramebuffer call to go through, it's necessary |
| 1304 // to swap out the RGBA texture that's bound to the CHROMIUM_image |
| 1305 // instance with an RGB texture. BlitFramebuffer requires the internal |
| 1306 // formats of the source and destination to match when doing a |
| 1307 // multisample resolve, and the best way to achieve this without adding |
| 1308 // more full-screen blits is to hook up a true RGB texture to the |
| 1309 // underlying IOSurface. Unfortunately, on macOS, this rendering path |
| 1310 // destroys the alpha channel and requires a fixup afterward, which is |
| 1311 // why it isn't used all the time. |
| 1312 |
| 1313 GLuint rgb_texture = back_color_buffer_->rgb_workaround_texture_id; |
| 1314 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB; |
| 1315 if (!rgb_texture) { |
| 1316 gl_->GenTextures(1, &rgb_texture); |
| 1317 gl_->BindTexture(target, rgb_texture); |
| 1318 gl_->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 1319 gl_->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 1320 gl_->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 1321 gl_->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 1322 |
| 1323 // Bind this texture to the CHROMIUM_image instance that the color |
| 1324 // buffer owns. This is an expensive operation, so it's important that |
| 1325 // the result be cached. |
| 1326 gl_->BindTexImage2DWithInternalformatCHROMIUM(target, GL_RGB, |
| 1327 back_color_buffer_->image_id); |
| 1328 back_color_buffer_->rgb_workaround_texture_id = rgb_texture; |
| 1329 } |
| 1330 |
| 1331 gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0, |
| 1332 target, rgb_texture, 0); |
| 1333 return true; |
| 1334 } |
| 1335 |
| 1336 void DrawingBuffer::CleanupRGBEmulationForBlitFramebuffer() { |
| 1337 // This will only be called if SetupRGBEmulationForBlitFramebuffer was. |
| 1338 // Put the framebuffer back the way it was, and clear the alpha channel. |
| 1339 DCHECK(back_color_buffer_); |
| 1340 DCHECK(back_color_buffer_->image_id); |
| 1341 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB; |
| 1342 gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0, |
| 1343 target, back_color_buffer_->texture_id, 0); |
| 1344 // Clear the alpha channel. |
| 1345 gl_->ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); |
| 1346 gl_->Disable(GL_SCISSOR_TEST); |
| 1347 gl_->ClearColor(0, 0, 0, 1); |
| 1348 gl_->Clear(GL_COLOR_BUFFER_BIT); |
| 1349 DCHECK(client_); |
| 1350 client_->DrawingBufferClientRestoreScissorTest(); |
| 1351 client_->DrawingBufferClientRestoreMaskAndClearValues(); |
| 1352 } |
| 1353 |
1261 DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer( | 1354 DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer( |
1262 DrawingBuffer* drawing_buffer) | 1355 DrawingBuffer* drawing_buffer) |
1263 : drawing_buffer_(drawing_buffer) { | 1356 : drawing_buffer_(drawing_buffer) { |
1264 // If this is a nested restorer, save the previous restorer. | 1357 // If this is a nested restorer, save the previous restorer. |
1265 previous_state_restorer_ = drawing_buffer->state_restorer_; | 1358 previous_state_restorer_ = drawing_buffer->state_restorer_; |
1266 drawing_buffer_->state_restorer_ = this; | 1359 drawing_buffer_->state_restorer_ = this; |
1267 } | 1360 } |
1268 | 1361 |
1269 DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() { | 1362 DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() { |
1270 DCHECK_EQ(drawing_buffer_->state_restorer_, this); | 1363 DCHECK_EQ(drawing_buffer_->state_restorer_, this); |
(...skipping 17 matching lines...) Expand all Loading... |
1288 if (pixel_unpack_buffer_binding_dirty_) | 1381 if (pixel_unpack_buffer_binding_dirty_) |
1289 client->DrawingBufferClientRestorePixelUnpackBufferBinding(); | 1382 client->DrawingBufferClientRestorePixelUnpackBufferBinding(); |
1290 } | 1383 } |
1291 | 1384 |
1292 bool DrawingBuffer::ShouldUseChromiumImage() { | 1385 bool DrawingBuffer::ShouldUseChromiumImage() { |
1293 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() && | 1386 return RuntimeEnabledFeatures::webGLImageChromiumEnabled() && |
1294 chromium_image_usage_ == kAllowChromiumImage; | 1387 chromium_image_usage_ == kAllowChromiumImage; |
1295 } | 1388 } |
1296 | 1389 |
1297 } // namespace blink | 1390 } // namespace blink |
OLD | NEW |