OLD | NEW |
---|---|
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 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
556 // Flush the GL context so rendering results from this context are | 556 // Flush the GL context so rendering results from this context are |
557 // visible in the compositor's context. | 557 // visible in the compositor's context. |
558 offscreen_contexts->Context3d()->flush(); | 558 offscreen_contexts->Context3d()->flush(); |
559 | 559 |
560 // Use the compositor's GL context again. | 560 // Use the compositor's GL context again. |
561 renderer->Context()->makeContextCurrent(); | 561 renderer->Context()->makeContextCurrent(); |
562 | 562 |
563 return device.accessBitmap(false); | 563 return device.accessBitmap(false); |
564 } | 564 } |
565 | 565 |
566 scoped_ptr<ScopedResource> GLRenderer::DrawBackgroundFilters( | 566 static SkBitmap ApplyBlendModeWithBackdrop( |
567 GLRenderer* renderer, | |
568 ContextProvider* offscreen_contexts, | |
569 SkBitmap source_bitmap_with_filters, | |
570 ScopedResource* source_texture_resource, | |
571 ScopedResource* background_texture_resource, | |
572 SkXfermode::Mode blendMode) { | |
573 if (!offscreen_contexts || !offscreen_contexts->GrContext()) | |
574 return source_bitmap_with_filters; | |
575 | |
576 DCHECK(background_texture_resource); | |
577 DCHECK(source_texture_resource); | |
578 | |
579 gfx::Size source_size = source_texture_resource->size(); | |
580 gfx::Size background_size = background_texture_resource->size(); | |
581 | |
582 DCHECK_LE(background_size.width(), source_size.width()); | |
583 DCHECK_LE(background_size.height(), source_size.height()); | |
584 | |
585 int source_texture_with_filters_id; | |
586 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; | |
587 if (source_bitmap_with_filters.getTexture()) { | |
588 DCHECK_EQ(source_size.width(), source_bitmap_with_filters.width()); | |
589 DCHECK_EQ(source_size.height(), source_bitmap_with_filters.height()); | |
590 GrTexture* texture = | |
591 reinterpret_cast<GrTexture*>(source_bitmap_with_filters.getTexture()); | |
592 source_texture_with_filters_id = texture->getTextureHandle(); | |
593 } else { | |
594 lock.reset(new ResourceProvider::ScopedReadLockGL( | |
595 renderer->resource_provider(), source_texture_resource->id())); | |
596 source_texture_with_filters_id = lock->texture_id(); | |
597 } | |
598 | |
599 ResourceProvider::ScopedReadLockGL lock_background( | |
600 renderer->resource_provider(), background_texture_resource->id()); | |
601 | |
602 // Flush the compositor context to ensure that textures there are available | |
603 // in the shared context. Do this after locking/creating the compositor | |
604 // texture. | |
605 renderer->resource_provider()->Flush(); | |
606 | |
607 // Make sure skia uses the correct GL context. | |
608 offscreen_contexts->Context3d()->makeContextCurrent(); | |
609 | |
610 // Wrap the source texture in a Ganesh platform texture. | |
611 GrBackendTextureDesc backend_texture_description; | |
612 backend_texture_description.fConfig = kSkia8888_GrPixelConfig; | |
613 backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin; | |
614 | |
615 backend_texture_description.fWidth = source_size.width(); | |
616 backend_texture_description.fHeight = source_size.height(); | |
617 backend_texture_description.fTextureHandle = source_texture_with_filters_id; | |
618 skia::RefPtr<GrTexture> source_texture = | |
619 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( | |
620 backend_texture_description)); | |
621 | |
622 backend_texture_description.fWidth = background_size.width(); | |
623 backend_texture_description.fHeight = background_size.height(); | |
624 backend_texture_description.fTextureHandle = lock_background.texture_id(); | |
625 skia::RefPtr<GrTexture> background_texture = | |
626 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( | |
627 backend_texture_description)); | |
628 | |
629 // Place the platform texture inside an SkBitmap. | |
630 SkBitmap source; | |
631 source.setConfig( | |
632 SkBitmap::kARGB_8888_Config, source_size.width(), source_size.height()); | |
633 skia::RefPtr<SkGrPixelRef> source_pixel_ref = | |
634 skia::AdoptRef(new SkGrPixelRef(source_texture.get())); | |
635 source.setPixelRef(source_pixel_ref.get()); | |
636 | |
637 SkBitmap background; | |
638 background.setConfig(SkBitmap::kARGB_8888_Config, | |
639 background_size.width(), | |
640 background_size.height()); | |
641 skia::RefPtr<SkGrPixelRef> background_pixel_ref = | |
642 skia::AdoptRef(new SkGrPixelRef(background_texture.get())); | |
643 background.setPixelRef(background_pixel_ref.get()); | |
644 | |
645 // Create a scratch texture for backing store. | |
646 GrTextureDesc desc; | |
647 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; | |
648 desc.fSampleCnt = 0; | |
649 desc.fWidth = source.width(); | |
650 desc.fHeight = source.height(); | |
651 desc.fConfig = kSkia8888_GrPixelConfig; | |
652 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; | |
653 GrAutoScratchTexture scratch_texture( | |
654 offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch); | |
655 skia::RefPtr<GrTexture> backing_store = | |
656 skia::AdoptRef(scratch_texture.detach()); | |
657 | |
658 // Create a device and canvas using that backing store. | |
659 SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get()); | |
660 SkCanvas canvas(&device); | |
661 | |
662 // Draw the source bitmap through the filter to the canvas. | |
663 canvas.clear(SK_ColorTRANSPARENT); | |
664 canvas.drawSprite(background, 0, 0); | |
665 SkPaint paint; | |
666 paint.setXfermodeMode(blendMode); | |
667 canvas.drawSprite(source, 0, 0, &paint); | |
668 | |
669 // Flush skia context so that all the rendered stuff appears on the | |
670 // texture. | |
671 offscreen_contexts->GrContext()->flush(); | |
672 | |
673 // Flush the GL context so rendering results from this context are | |
674 // visible in the compositor's context. | |
675 offscreen_contexts->Context3d()->flush(); | |
676 | |
677 // Use the compositor's GL context again. | |
678 renderer->Context()->makeContextCurrent(); | |
679 | |
680 return device.accessBitmap(false); | |
681 } | |
682 | |
683 scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( | |
567 DrawingFrame* frame, | 684 DrawingFrame* frame, |
568 const RenderPassDrawQuad* quad, | 685 const RenderPassDrawQuad* quad, |
569 const gfx::Transform& contents_device_transform, | 686 const gfx::Transform& contents_device_transform, |
570 const gfx::Transform& contents_device_transform_inverse) { | 687 const gfx::Transform& contents_device_transform_inverse, |
688 bool* background_changed) { | |
571 // This method draws a background filter, which applies a filter to any pixels | 689 // This method draws a background filter, which applies a filter to any pixels |
572 // behind the quad and seen through its background. The algorithm works as | 690 // behind the quad and seen through its background. The algorithm works as |
573 // follows: | 691 // follows: |
574 // 1. Compute a bounding box around the pixels that will be visible through | 692 // 1. Compute a bounding box around the pixels that will be visible through |
575 // the quad. | 693 // the quad. |
576 // 2. Read the pixels in the bounding box into a buffer R. | 694 // 2. Read the pixels in the bounding box into a buffer R. |
577 // 3. Apply the background filter to R, so that it is applied in the pixels' | 695 // 3. Apply the background filter to R, so that it is applied in the pixels' |
578 // coordinate space. | 696 // coordinate space. |
579 // 4. Apply the quad's inverse transform to map the pixels in R into the | 697 // 4. Apply the quad's inverse transform to map the pixels in R into the |
580 // quad's content space. This implicitly clips R by the content bounds of the | 698 // quad's content space. This implicitly clips R by the content bounds of the |
581 // quad since the destination texture has bounds matching the quad's content. | 699 // quad since the destination texture has bounds matching the quad's content. |
582 // 5. Draw the background texture for the contents using the same transform as | 700 // 5. Draw the background texture for the contents using the same transform as |
583 // used to draw the contents itself. This is done without blending to replace | 701 // used to draw the contents itself. This is done without blending to replace |
584 // the current background pixels with the new filtered background. | 702 // the current background pixels with the new filtered background. |
585 // 6. Draw the contents of the quad over drop of the new background with | 703 // 6. Draw the contents of the quad over drop of the new background with |
586 // blending, as per usual. The filtered background pixels will show through | 704 // blending, as per usual. The filtered background pixels will show through |
587 // any non-opaque pixels in this draws. | 705 // any non-opaque pixels in this draws. |
588 // | 706 // |
589 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. | 707 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. |
590 | 708 |
591 // TODO(danakj): When this algorithm changes, update | 709 // TODO(danakj): When this algorithm changes, update |
592 // LayerTreeHost::PrioritizeTextures() accordingly. | 710 // LayerTreeHost::PrioritizeTextures() accordingly. |
593 | 711 |
594 // TODO(danakj): We only allow background filters on an opaque render surface | 712 // TODO(danakj): We only allow background filters on an opaque render surface |
595 // because other surfaces may contain translucent pixels, and the contents | 713 // because other surfaces may contain translucent pixels, and the contents |
596 // behind those translucent pixels wouldn't have the filter applied. | 714 // behind those translucent pixels wouldn't have the filter applied. |
597 if (frame->current_render_pass->has_transparent_background) | 715 bool apply_background_filters = |
598 return scoped_ptr<ScopedResource>(); | 716 !frame->current_render_pass->has_transparent_background; |
599 DCHECK(!frame->current_texture); | 717 DCHECK(!frame->current_texture); |
600 | 718 |
601 // TODO(ajuma): Add support for reference filters once | 719 // TODO(ajuma): Add support for reference filters once |
602 // FilterOperations::GetOutsets supports reference filters. | 720 // FilterOperations::GetOutsets supports reference filters. |
603 if (quad->background_filters.HasReferenceFilter()) | 721 if (apply_background_filters && quad->background_filters.HasReferenceFilter()) |
604 return scoped_ptr<ScopedResource>(); | 722 apply_background_filters = false; |
605 | 723 |
606 // TODO(danakj): Do a single readback for both the surface and replica and | 724 // TODO(danakj): Do a single readback for both the surface and replica and |
607 // cache the filtered results (once filter textures are not reused). | 725 // cache the filtered results (once filter textures are not reused). |
608 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( | 726 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( |
609 contents_device_transform, SharedGeometryQuad().BoundingBox())); | 727 contents_device_transform, SharedGeometryQuad().BoundingBox())); |
610 | 728 |
611 int top, right, bottom, left; | 729 int top, right, bottom, left; |
612 quad->background_filters.GetOutsets(&top, &right, &bottom, &left); | 730 quad->background_filters.GetOutsets(&top, &right, &bottom, &left); |
613 window_rect.Inset(-left, -top, -right, -bottom); | 731 window_rect.Inset(-left, -top, -right, -bottom); |
614 | 732 |
615 window_rect.Intersect( | 733 window_rect.Intersect( |
616 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); | 734 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); |
617 | 735 |
618 scoped_ptr<ScopedResource> device_background_texture = | 736 scoped_ptr<ScopedResource> device_background_texture = |
619 ScopedResource::create(resource_provider_); | 737 ScopedResource::create(resource_provider_); |
620 if (!device_background_texture->Allocate(window_rect.size(), | 738 if (!device_background_texture->Allocate(window_rect.size(), |
621 ResourceProvider::TextureUsageAny, | 739 ResourceProvider::TextureUsageAny, |
622 RGBA_8888)) { | 740 RGBA_8888)) { |
623 return scoped_ptr<ScopedResource>(); | 741 return scoped_ptr<ScopedResource>(); |
624 } else { | 742 } else { |
625 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | 743 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
626 device_background_texture->id()); | 744 device_background_texture->id()); |
627 GetFramebufferTexture(lock.texture_id(), | 745 GetFramebufferTextureSubImage(lock.texture_id(), window_rect); |
628 device_background_texture->format(), | |
629 window_rect); | |
630 } | 746 } |
631 | 747 |
748 int filtered_device_background_texture_id = 0; | |
632 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( | 749 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( |
633 quad->background_filters, device_background_texture->size()); | 750 quad->background_filters, device_background_texture->size()); |
634 | 751 |
635 SkBitmap filtered_device_background = | 752 SkBitmap filtered_device_background; |
636 ApplyImageFilter(this, | 753 if (apply_background_filters) |
637 frame->offscreen_context_provider, | 754 filtered_device_background = |
638 quad->rect.origin(), | 755 ApplyImageFilter(this, |
639 filter.get(), | 756 frame->offscreen_context_provider, |
640 device_background_texture.get()); | 757 quad->rect.origin(), |
641 if (!filtered_device_background.getTexture()) | 758 filter.get(), |
642 return scoped_ptr<ScopedResource>(); | 759 device_background_texture.get()); |
760 if (background_changed) | |
761 *background_changed = (filtered_device_background.getTexture() != NULL); | |
643 | 762 |
644 GrTexture* texture = | 763 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; |
645 reinterpret_cast<GrTexture*>(filtered_device_background.getTexture()); | 764 if (filtered_device_background.getTexture()) { |
646 int filtered_device_background_texture_id = texture->getTextureHandle(); | 765 GrTexture* texture = |
766 reinterpret_cast<GrTexture*>(filtered_device_background.getTexture()); | |
767 filtered_device_background_texture_id = texture->getTextureHandle(); | |
768 } else { | |
769 lock.reset(new ResourceProvider::ScopedReadLockGL( | |
770 resource_provider_, device_background_texture->id())); | |
771 filtered_device_background_texture_id = lock->texture_id(); | |
772 } | |
647 | 773 |
648 scoped_ptr<ScopedResource> background_texture = | 774 scoped_ptr<ScopedResource> background_texture = |
649 ScopedResource::create(resource_provider_); | 775 ScopedResource::create(resource_provider_); |
650 if (!background_texture->Allocate(quad->rect.size(), | 776 if (!background_texture->Allocate(quad->rect.size(), |
651 ResourceProvider::TextureUsageFramebuffer, | 777 ResourceProvider::TextureUsageFramebuffer, |
652 RGBA_8888)) | 778 RGBA_8888)) |
653 return scoped_ptr<ScopedResource>(); | 779 return scoped_ptr<ScopedResource>(); |
654 | 780 |
655 const RenderPass* target_render_pass = frame->current_render_pass; | 781 const RenderPass* target_render_pass = frame->current_render_pass; |
656 bool using_background_texture = | 782 bool using_background_texture = |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
707 gfx::Transform contents_device_transform = | 833 gfx::Transform contents_device_transform = |
708 frame->window_matrix * frame->projection_matrix * quad_rect_matrix; | 834 frame->window_matrix * frame->projection_matrix * quad_rect_matrix; |
709 contents_device_transform.FlattenTo2d(); | 835 contents_device_transform.FlattenTo2d(); |
710 | 836 |
711 // Can only draw surface if device matrix is invertible. | 837 // Can only draw surface if device matrix is invertible. |
712 gfx::Transform contents_device_transform_inverse( | 838 gfx::Transform contents_device_transform_inverse( |
713 gfx::Transform::kSkipInitialization); | 839 gfx::Transform::kSkipInitialization); |
714 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) | 840 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) |
715 return; | 841 return; |
716 | 842 |
843 bool apply_blend_mode = | |
844 quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode; | |
845 bool background_changed = false; | |
717 scoped_ptr<ScopedResource> background_texture; | 846 scoped_ptr<ScopedResource> background_texture; |
718 if (!quad->background_filters.IsEmpty()) { | 847 if (!quad->background_filters.IsEmpty() || apply_blend_mode) { |
719 // The pixels from the filtered background should completely replace the | 848 // The pixels from the filtered background should completely replace the |
720 // current pixel values. | 849 // current pixel values. |
721 bool disable_blending = blend_enabled(); | 850 bool disable_blending = blend_enabled(); |
722 if (disable_blending) | 851 if (disable_blending) |
723 SetBlendEnabled(false); | 852 SetBlendEnabled(false); |
724 | 853 |
725 background_texture = DrawBackgroundFilters( | 854 background_texture = |
726 frame, | 855 GetBackgroundWithFilters(frame, |
727 quad, | 856 quad, |
728 contents_device_transform, | 857 contents_device_transform, |
729 contents_device_transform_inverse); | 858 contents_device_transform_inverse, |
859 &background_changed); | |
730 | 860 |
731 if (disable_blending) | 861 if (disable_blending) |
732 SetBlendEnabled(true); | 862 SetBlendEnabled(true); |
733 } | 863 } |
734 | 864 |
735 // TODO(senorblanco): Cache this value so that we don't have to do it for both | 865 // TODO(senorblanco): Cache this value so that we don't have to do it for both |
736 // the surface and its replica. Apply filters to the contents texture. | 866 // the surface and its replica. Apply filters to the contents texture. |
737 SkBitmap filter_bitmap; | 867 SkBitmap filter_bitmap; |
738 SkScalar color_matrix[20]; | 868 SkScalar color_matrix[20]; |
739 bool use_color_matrix = false; | 869 bool use_color_matrix = false; |
(...skipping 18 matching lines...) Expand all Loading... | |
758 } else { | 888 } else { |
759 filter_bitmap = ApplyImageFilter(this, | 889 filter_bitmap = ApplyImageFilter(this, |
760 frame->offscreen_context_provider, | 890 frame->offscreen_context_provider, |
761 quad->rect.origin(), | 891 quad->rect.origin(), |
762 filter.get(), | 892 filter.get(), |
763 contents_texture); | 893 contents_texture); |
764 } | 894 } |
765 } | 895 } |
766 } | 896 } |
767 | 897 |
898 if (background_texture && apply_blend_mode) { | |
899 filter_bitmap = | |
900 ApplyBlendModeWithBackdrop(this, | |
901 frame->offscreen_context_provider, | |
902 filter_bitmap, | |
903 contents_texture, | |
904 background_texture.get(), | |
905 quad->shared_quad_state->blend_mode); | |
906 } | |
907 | |
768 // Draw the background texture if there is one. | 908 // Draw the background texture if there is one. |
769 if (background_texture) { | 909 if (background_texture && background_changed) { |
770 DCHECK(background_texture->size() == quad->rect.size()); | 910 DCHECK(background_texture->size() == quad->rect.size()); |
771 ResourceProvider::ScopedReadLockGL lock(resource_provider_, | 911 ResourceProvider::ScopedReadLockGL lock(resource_provider_, |
772 background_texture->id()); | 912 background_texture->id()); |
773 | 913 |
774 // The background_texture is oriented the same as the frame buffer. The | 914 // The background_texture is oriented the same as the frame buffer. The |
775 // transform we are copying with has a vertical flip, so flip the contents | 915 // transform we are copying with has a vertical flip, so flip the contents |
776 // in the shader to maintain orientation | 916 // in the shader to maintain orientation |
777 bool flip_vertically = true; | 917 bool flip_vertically = true; |
778 | 918 |
779 CopyTextureToFramebuffer(frame, | 919 CopyTextureToFramebuffer(frame, |
(...skipping 1630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2410 scoped_ptr<SkAutoLockPixels> lock, | 2550 scoped_ptr<SkAutoLockPixels> lock, |
2411 scoped_ptr<CopyOutputRequest> request, | 2551 scoped_ptr<CopyOutputRequest> request, |
2412 bool success) { | 2552 bool success) { |
2413 DCHECK(request->force_bitmap_result()); | 2553 DCHECK(request->force_bitmap_result()); |
2414 | 2554 |
2415 lock.reset(); | 2555 lock.reset(); |
2416 if (success) | 2556 if (success) |
2417 request->SendBitmapResult(bitmap.Pass()); | 2557 request->SendBitmapResult(bitmap.Pass()); |
2418 } | 2558 } |
2419 | 2559 |
2560 void GLRenderer::GetFramebufferTextureSubImage(unsigned texture_id, | |
enne (OOO)
2013/11/01 18:49:02
I still feel a little bit uneasy about this API.
rosca
2013/11/04 17:14:34
I found a way to avoid using this API. Knaab has a
| |
2561 gfx::Rect window_rect) { | |
2562 DCHECK(texture_id); | |
2563 DCHECK_GE(window_rect.x(), 0); | |
2564 DCHECK_GE(window_rect.y(), 0); | |
2565 DCHECK_LE(window_rect.right(), current_surface_size_.width()); | |
2566 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); | |
2567 | |
2568 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); | |
2569 GLC(context_, | |
2570 context_->copyTexSubImage2D(GL_TEXTURE_2D, | |
2571 0, | |
2572 0, | |
2573 0, | |
2574 window_rect.x(), | |
2575 window_rect.y(), | |
2576 window_rect.width(), | |
2577 window_rect.height())); | |
2578 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0)); | |
2579 } | |
2580 | |
2420 void GLRenderer::GetFramebufferTexture( | 2581 void GLRenderer::GetFramebufferTexture( |
2421 unsigned texture_id, ResourceFormat texture_format, gfx::Rect window_rect) { | 2582 unsigned texture_id, ResourceFormat texture_format, gfx::Rect window_rect) { |
2422 DCHECK(texture_id); | 2583 DCHECK(texture_id); |
2423 DCHECK_GE(window_rect.x(), 0); | 2584 DCHECK_GE(window_rect.x(), 0); |
2424 DCHECK_GE(window_rect.y(), 0); | 2585 DCHECK_GE(window_rect.y(), 0); |
2425 DCHECK_LE(window_rect.right(), current_surface_size_.width()); | 2586 DCHECK_LE(window_rect.right(), current_surface_size_.width()); |
2426 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); | 2587 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); |
2427 | 2588 |
2428 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); | 2589 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); |
2429 GLC(context_, | 2590 GLC(context_, |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3089 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas | 3250 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas |
3090 // implementation. | 3251 // implementation. |
3091 return gr_context_ && context_->getContextAttributes().stencil; | 3252 return gr_context_ && context_->getContextAttributes().stencil; |
3092 } | 3253 } |
3093 | 3254 |
3094 bool GLRenderer::IsContextLost() { | 3255 bool GLRenderer::IsContextLost() { |
3095 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); | 3256 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); |
3096 } | 3257 } |
3097 | 3258 |
3098 } // namespace cc | 3259 } // namespace cc |
OLD | NEW |