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