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

Side by Side Diff: cc/output/gl_renderer.cc

Issue 23455060: mix-blend-mode implementation for accelerated layers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added compositor_bindungs Created 7 years, 2 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 // Copyright 2010 The Chromium Authors. All rights reserved. 1 // Copyright 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/output/gl_renderer.h" 5 #include "cc/output/gl_renderer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 // Flush the GL context so rendering results from this context are 596 // Flush the GL context so rendering results from this context are
597 // visible in the compositor's context. 597 // visible in the compositor's context.
598 offscreen_contexts->Context3d()->flush(); 598 offscreen_contexts->Context3d()->flush();
599 599
600 // Use the compositor's GL context again. 600 // Use the compositor's GL context again.
601 renderer->Context()->makeContextCurrent(); 601 renderer->Context()->makeContextCurrent();
602 602
603 return device.accessBitmap(false); 603 return device.accessBitmap(false);
604 } 604 }
605 605
606 scoped_ptr<ScopedResource> GLRenderer::DrawBackgroundFilters( 606 static SkBitmap ApplyBlendModeWithBackdrop(GLRenderer* renderer,
607 ContextProvider* offscreen_contexts,
608 SkBitmap source_bitmap_with_filters,
609 ScopedResource* source_texture_resource,
610 ScopedResource* background_texture_resource,
611 SkXfermode::Mode blendMode) {
612 if (!offscreen_contexts || !offscreen_contexts->GrContext())
613 return source_bitmap_with_filters;
614
615 DCHECK(background_texture_resource);
616 DCHECK(source_texture_resource);
617
618 gfx::Size source_size = source_texture_resource->size();
619 gfx::Size background_size = background_texture_resource->size();
620
621 DCHECK_LE(background_size.width(), source_size.width());
622 DCHECK_LE(background_size.height(), source_size.height());
623
624 int source_texture_with_filters_id;
625 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
626 if (source_bitmap_with_filters.getTexture()) {
627 DCHECK(source_size.width() == source_bitmap_with_filters.width());
enne (OOO) 2013/10/11 18:14:35 DCHECK_EQ, please.
rosca 2013/10/16 14:54:47 Done.
628 DCHECK(source_size.height() == source_bitmap_with_filters.height());
629 GrTexture* texture =
630 reinterpret_cast<GrTexture*>(source_bitmap_with_filters.getTexture());
631 source_texture_with_filters_id = texture->getTextureHandle();
632 } else {
633 lock.reset(
634 new ResourceProvider::ScopedReadLockGL(renderer->resource_provider(),
635 source_texture_resource->id()));
636 source_texture_with_filters_id = lock->texture_id();
637 }
638
639 ResourceProvider::ScopedReadLockGL lock_background(
640 renderer->resource_provider(), background_texture_resource->id());
641
642 // Flush the compositor context to ensure that textures there are available
643 // in the shared context. Do this after locking/creating the compositor
644 // texture.
645 renderer->resource_provider()->Flush();
646
647 // Make sure skia uses the correct GL context.
648 offscreen_contexts->Context3d()->makeContextCurrent();
649
650 // Wrap the source texture in a Ganesh platform texture.
651 GrBackendTextureDesc backend_texture_description;
652 backend_texture_description.fConfig = kSkia8888_GrPixelConfig;
653 backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin;
654
655 backend_texture_description.fWidth = source_size.width();
656 backend_texture_description.fHeight = source_size.height();
657 backend_texture_description.fTextureHandle = source_texture_with_filters_id;
658 skia::RefPtr<GrTexture> source_texture =
659 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture(
660 backend_texture_description));
661
662 backend_texture_description.fWidth = background_size.width();
663 backend_texture_description.fHeight = background_size.height();
664 backend_texture_description.fTextureHandle = lock_background.texture_id();
665 skia::RefPtr<GrTexture> background_texture =
666 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture(
667 backend_texture_description));
668
669 // Place the platform texture inside an SkBitmap.
670 SkBitmap source;
671 source.setConfig(SkBitmap::kARGB_8888_Config,
672 source_size.width(), source_size.height());
673 skia::RefPtr<SkGrPixelRef> source_pixel_ref =
674 skia::AdoptRef(new SkGrPixelRef(source_texture.get()));
675 source.setPixelRef(source_pixel_ref.get());
676
677 SkBitmap background;
678 background.setConfig(SkBitmap::kARGB_8888_Config,
679 background_size.width(), background_size.height());
680 skia::RefPtr<SkGrPixelRef> background_pixel_ref =
681 skia::AdoptRef(new SkGrPixelRef(background_texture.get()));
682 background.setPixelRef(background_pixel_ref.get());
683
684 // Create a scratch texture for backing store.
685 GrTextureDesc desc;
686 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
687 desc.fSampleCnt = 0;
688 desc.fWidth = source.width();
689 desc.fHeight = source.height();
690 desc.fConfig = kSkia8888_GrPixelConfig;
691 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
692 GrAutoScratchTexture scratch_texture(
693 offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch);
694 skia::RefPtr<GrTexture> backing_store =
695 skia::AdoptRef(scratch_texture.detach());
696
697 // Create a device and canvas using that backing store.
698 SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get());
699 SkCanvas canvas(&device);
700
701 // Draw the source bitmap through the filter to the canvas.
702 canvas.clear(SK_ColorTRANSPARENT);
703 canvas.drawSprite(background, 0, 0);
704 SkPaint paint;
705 paint.setXfermodeMode(blendMode);
706 canvas.drawSprite(source, 0, 0, &paint);
707
708 // Flush skia context so that all the rendered stuff appears on the
709 // texture.
710 offscreen_contexts->GrContext()->flush();
711
712 // Flush the GL context so rendering results from this context are
713 // visible in the compositor's context.
714 offscreen_contexts->Context3d()->flush();
715
716 // Use the compositor's GL context again.
717 renderer->Context()->makeContextCurrent();
718
719 return device.accessBitmap(false);
720 }
721
722 scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters(
607 DrawingFrame* frame, 723 DrawingFrame* frame,
608 const RenderPassDrawQuad* quad, 724 const RenderPassDrawQuad* quad,
609 const gfx::Transform& contents_device_transform, 725 const gfx::Transform& contents_device_transform,
610 const gfx::Transform& contents_device_transform_inverse) { 726 const gfx::Transform& contents_device_transform_inverse,
727 bool* background_changed) {
611 // This method draws a background filter, which applies a filter to any pixels 728 // This method draws a background filter, which applies a filter to any pixels
612 // behind the quad and seen through its background. The algorithm works as 729 // behind the quad and seen through its background. The algorithm works as
613 // follows: 730 // follows:
614 // 1. Compute a bounding box around the pixels that will be visible through 731 // 1. Compute a bounding box around the pixels that will be visible through
615 // the quad. 732 // the quad.
616 // 2. Read the pixels in the bounding box into a buffer R. 733 // 2. Read the pixels in the bounding box into a buffer R.
617 // 3. Apply the background filter to R, so that it is applied in the pixels' 734 // 3. Apply the background filter to R, so that it is applied in the pixels'
618 // coordinate space. 735 // coordinate space.
619 // 4. Apply the quad's inverse transform to map the pixels in R into the 736 // 4. Apply the quad's inverse transform to map the pixels in R into the
620 // quad's content space. This implicitly clips R by the content bounds of the 737 // quad's content space. This implicitly clips R by the content bounds of the
621 // quad since the destination texture has bounds matching the quad's content. 738 // quad since the destination texture has bounds matching the quad's content.
622 // 5. Draw the background texture for the contents using the same transform as 739 // 5. Draw the background texture for the contents using the same transform as
623 // used to draw the contents itself. This is done without blending to replace 740 // used to draw the contents itself. This is done without blending to replace
624 // the current background pixels with the new filtered background. 741 // the current background pixels with the new filtered background.
625 // 6. Draw the contents of the quad over drop of the new background with 742 // 6. Draw the contents of the quad over drop of the new background with
626 // blending, as per usual. The filtered background pixels will show through 743 // blending, as per usual. The filtered background pixels will show through
627 // any non-opaque pixels in this draws. 744 // any non-opaque pixels in this draws.
628 // 745 //
629 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. 746 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
630 747
631 // TODO(danakj): When this algorithm changes, update 748 // TODO(danakj): When this algorithm changes, update
632 // LayerTreeHost::PrioritizeTextures() accordingly. 749 // LayerTreeHost::PrioritizeTextures() accordingly.
633 750
634 FilterOperations filters = 751 FilterOperations filters =
635 RenderSurfaceFilters::Optimize(quad->background_filters); 752 RenderSurfaceFilters::Optimize(quad->background_filters);
636 DCHECK(!filters.IsEmpty()); 753 DCHECK(!filters.IsEmpty() ||
754 quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode);
637 755
638 // TODO(danakj): We only allow background filters on an opaque render surface 756 // TODO(danakj): We only allow background filters on an opaque render surface
639 // because other surfaces may contain translucent pixels, and the contents 757 // because other surfaces may contain translucent pixels, and the contents
640 // behind those translucent pixels wouldn't have the filter applied. 758 // behind those translucent pixels wouldn't have the filter applied.
641 if (frame->current_render_pass->has_transparent_background) 759 bool apply_background_filters = !filters.IsEmpty() &&
642 return scoped_ptr<ScopedResource>(); 760 !frame->current_render_pass->has_transparent_background;
643 DCHECK(!frame->current_texture); 761 DCHECK(!frame->current_texture);
644 762
645 // TODO(danakj): Do a single readback for both the surface and replica and 763 // TODO(danakj): Do a single readback for both the surface and replica and
646 // cache the filtered results (once filter textures are not reused). 764 // cache the filtered results (once filter textures are not reused).
647 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( 765 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
648 contents_device_transform, SharedGeometryQuad().BoundingBox())); 766 contents_device_transform, SharedGeometryQuad().BoundingBox()));
649 767
650 int top, right, bottom, left; 768 int top, right, bottom, left;
651 filters.GetOutsets(&top, &right, &bottom, &left); 769 filters.GetOutsets(&top, &right, &bottom, &left);
652 window_rect.Inset(-left, -top, -right, -bottom); 770 window_rect.Inset(-left, -top, -right, -bottom);
653 771
654 window_rect.Intersect( 772 window_rect.Intersect(
655 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); 773 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect));
656 774
657 scoped_ptr<ScopedResource> device_background_texture = 775 scoped_ptr<ScopedResource> device_background_texture =
658 ScopedResource::create(resource_provider_); 776 ScopedResource::create(resource_provider_);
659 if (!device_background_texture->Allocate(window_rect.size(), 777 if (!device_background_texture->Allocate(window_rect.size(),
660 ResourceProvider::TextureUsageAny, 778 ResourceProvider::TextureUsageAny,
661 RGBA_8888)) { 779 RGBA_8888)) {
662 return scoped_ptr<ScopedResource>(); 780 return scoped_ptr<ScopedResource>();
663 } else { 781 } else {
664 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, 782 ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
665 device_background_texture->id()); 783 device_background_texture->id());
666 GetFramebufferTexture(lock.texture_id(), 784 GetFramebufferTextureSubImage(lock.texture_id(),
667 device_background_texture->format(), 785 window_rect);
668 window_rect);
669 } 786 }
670 787
671 SkBitmap filtered_device_background = 788 int filtered_device_background_texture_id = 0;
672 ApplyFilters(this,
673 frame->offscreen_context_provider,
674 filters,
675 device_background_texture.get());
676 if (!filtered_device_background.getTexture())
677 return scoped_ptr<ScopedResource>();
678 789
679 GrTexture* texture = 790 SkBitmap filtered_device_background;
680 reinterpret_cast<GrTexture*>(filtered_device_background.getTexture()); 791 if (apply_background_filters)
681 int filtered_device_background_texture_id = texture->getTextureHandle(); 792 filtered_device_background = ApplyFilters(this,
793 frame->offscreen_context_provider, filters,
794 device_background_texture.get());
795 if (background_changed)
796 *background_changed = filtered_device_background.getTexture();
797
798 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
799 if (filtered_device_background.getTexture()) {
800 GrTexture* texture =
801 reinterpret_cast<GrTexture*>(filtered_device_background.getTexture());
802 filtered_device_background_texture_id = texture->getTextureHandle();
803 } else {
804 lock.reset(new ResourceProvider::ScopedReadLockGL(resource_provider_,
805 device_background_texture->id()));
806 filtered_device_background_texture_id = lock->texture_id();
807 }
682 808
683 scoped_ptr<ScopedResource> background_texture = 809 scoped_ptr<ScopedResource> background_texture =
684 ScopedResource::create(resource_provider_); 810 ScopedResource::create(resource_provider_);
685 if (!background_texture->Allocate(quad->rect.size(), 811 if (!background_texture->Allocate(quad->rect.size(),
686 ResourceProvider::TextureUsageFramebuffer, 812 ResourceProvider::TextureUsageFramebuffer,
687 RGBA_8888)) 813 RGBA_8888))
688 return scoped_ptr<ScopedResource>(); 814 return scoped_ptr<ScopedResource>();
689 815
690 const RenderPass* target_render_pass = frame->current_render_pass; 816 const RenderPass* target_render_pass = frame->current_render_pass;
691 bool using_background_texture = 817 bool using_background_texture =
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 gfx::Transform contents_device_transform = 868 gfx::Transform contents_device_transform =
743 frame->window_matrix * frame->projection_matrix * quad_rect_matrix; 869 frame->window_matrix * frame->projection_matrix * quad_rect_matrix;
744 contents_device_transform.FlattenTo2d(); 870 contents_device_transform.FlattenTo2d();
745 871
746 // Can only draw surface if device matrix is invertible. 872 // Can only draw surface if device matrix is invertible.
747 gfx::Transform contents_device_transform_inverse( 873 gfx::Transform contents_device_transform_inverse(
748 gfx::Transform::kSkipInitialization); 874 gfx::Transform::kSkipInitialization);
749 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) 875 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
750 return; 876 return;
751 877
878 bool applyBlendMode =
enne (OOO) 2013/10/11 18:14:35 apply_blend_mode
rosca 2013/10/16 14:54:47 Done.
879 quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode;
880 bool backgroundChanged = false;
enne (OOO) 2013/10/11 18:14:35 background_changed
rosca 2013/10/16 14:54:47 Done.
752 scoped_ptr<ScopedResource> background_texture; 881 scoped_ptr<ScopedResource> background_texture;
753 if (!quad->background_filters.IsEmpty()) { 882 if (!quad->background_filters.IsEmpty() || applyBlendMode) {
754 // The pixels from the filtered background should completely replace the 883 // The pixels from the filtered background should completely replace the
755 // current pixel values. 884 // current pixel values.
756 bool disable_blending = blend_enabled(); 885 bool disable_blending = blend_enabled();
757 if (disable_blending) 886 if (disable_blending)
758 SetBlendEnabled(false); 887 SetBlendEnabled(false);
759 888
760 background_texture = DrawBackgroundFilters( 889 background_texture = GetBackgroundWithFilters(
761 frame, 890 frame,
762 quad, 891 quad,
763 contents_device_transform, 892 contents_device_transform,
764 contents_device_transform_inverse); 893 contents_device_transform_inverse,
894 &backgroundChanged);
765 895
766 if (disable_blending) 896 if (disable_blending)
767 SetBlendEnabled(true); 897 SetBlendEnabled(true);
768 } 898 }
769 899
770 // TODO(senorblanco): Cache this value so that we don't have to do it for both 900 // TODO(senorblanco): Cache this value so that we don't have to do it for both
771 // the surface and its replica. Apply filters to the contents texture. 901 // the surface and its replica. Apply filters to the contents texture.
772 SkBitmap filter_bitmap; 902 SkBitmap filter_bitmap;
773 SkScalar color_matrix[20]; 903 SkScalar color_matrix[20];
774 bool use_color_matrix = false; 904 bool use_color_matrix = false;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 color_matrix, optimized_filters.at(0).matrix(), sizeof(color_matrix)); 938 color_matrix, optimized_filters.at(0).matrix(), sizeof(color_matrix));
809 use_color_matrix = true; 939 use_color_matrix = true;
810 } else { 940 } else {
811 filter_bitmap = ApplyFilters(this, 941 filter_bitmap = ApplyFilters(this,
812 frame->offscreen_context_provider, 942 frame->offscreen_context_provider,
813 optimized_filters, 943 optimized_filters,
814 contents_texture); 944 contents_texture);
815 } 945 }
816 } 946 }
817 947
948 if (background_texture && applyBlendMode) {
949 filter_bitmap = ApplyBlendModeWithBackdrop(this,
950 frame->offscreen_context_provider,
951 filter_bitmap,
952 contents_texture,
953 background_texture.get(),
954 quad->shared_quad_state->blend_mode);
955 }
956
818 // Draw the background texture if there is one. 957 // Draw the background texture if there is one.
819 if (background_texture) { 958 if (background_texture && backgroundChanged) {
820 DCHECK(background_texture->size() == quad->rect.size()); 959 DCHECK(background_texture->size() == quad->rect.size());
821 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 960 ResourceProvider::ScopedReadLockGL lock(resource_provider_,
822 background_texture->id()); 961 background_texture->id());
823 962
824 // The background_texture is oriented the same as the frame buffer. The 963 // The background_texture is oriented the same as the frame buffer. The
825 // transform we are copying with has a vertical flip, so flip the contents 964 // transform we are copying with has a vertical flip, so flip the contents
826 // in the shader to maintain orientation 965 // in the shader to maintain orientation
827 bool flip_vertically = true; 966 bool flip_vertically = true;
828 967
829 CopyTextureToFramebuffer(frame, 968 CopyTextureToFramebuffer(frame,
(...skipping 1629 matching lines...) Expand 10 before | Expand all | Expand 10 after
2459 scoped_ptr<SkAutoLockPixels> lock, 2598 scoped_ptr<SkAutoLockPixels> lock,
2460 scoped_ptr<CopyOutputRequest> request, 2599 scoped_ptr<CopyOutputRequest> request,
2461 bool success) { 2600 bool success) {
2462 DCHECK(request->force_bitmap_result()); 2601 DCHECK(request->force_bitmap_result());
2463 2602
2464 lock.reset(); 2603 lock.reset();
2465 if (success) 2604 if (success)
2466 request->SendBitmapResult(bitmap.Pass()); 2605 request->SendBitmapResult(bitmap.Pass());
2467 } 2606 }
2468 2607
2608 void GLRenderer::GetFramebufferTextureSubImage(unsigned texture_id,
2609 gfx::Rect window_rect) {
2610 DCHECK(texture_id);
2611 DCHECK_GE(window_rect.x(), 0);
2612 DCHECK_GE(window_rect.y(), 0);
2613 DCHECK_LE(window_rect.right(), current_surface_size_.width());
2614 DCHECK_LE(window_rect.bottom(), current_surface_size_.height());
2615
2616 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
2617 GLC(context_,
2618 context_->copyTexSubImage2D(GL_TEXTURE_2D,
2619 0, 0, 0,
2620 window_rect.x(), window_rect.y(),
2621 window_rect.width(), window_rect.height()));
2622 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
2623 }
2624
2469 void GLRenderer::GetFramebufferTexture( 2625 void GLRenderer::GetFramebufferTexture(
2470 unsigned texture_id, ResourceFormat texture_format, gfx::Rect window_rect) { 2626 unsigned texture_id, ResourceFormat texture_format, gfx::Rect window_rect) {
2471 DCHECK(texture_id); 2627 DCHECK(texture_id);
2472 DCHECK_GE(window_rect.x(), 0); 2628 DCHECK_GE(window_rect.x(), 0);
2473 DCHECK_GE(window_rect.y(), 0); 2629 DCHECK_GE(window_rect.y(), 0);
2474 DCHECK_LE(window_rect.right(), current_surface_size_.width()); 2630 DCHECK_LE(window_rect.right(), current_surface_size_.width());
2475 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); 2631 DCHECK_LE(window_rect.bottom(), current_surface_size_.height());
2476 2632
2477 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); 2633 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
2478 GLC(context_, 2634 GLC(context_,
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
3138 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas 3294 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas
3139 // implementation. 3295 // implementation.
3140 return gr_context_ && context_->getContextAttributes().stencil; 3296 return gr_context_ && context_->getContextAttributes().stencil;
3141 } 3297 }
3142 3298
3143 bool GLRenderer::IsContextLost() { 3299 bool GLRenderer::IsContextLost() {
3144 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); 3300 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR);
3145 } 3301 }
3146 3302
3147 } // namespace cc 3303 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698