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 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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()); | |
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::CreateBackgroundTextureWithFilters( | |
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() || quad->blend_mode != SkXfermode::kSrcOver_Mode); |
637 | 754 |
638 // TODO(danakj): We only allow background filters on an opaque render surface | 755 // TODO(danakj): We only allow background filters on an opaque render surface |
639 // because other surfaces may contain translucent pixels, and the contents | 756 // because other surfaces may contain translucent pixels, and the contents |
640 // behind those translucent pixels wouldn't have the filter applied. | 757 // behind those translucent pixels wouldn't have the filter applied. |
641 if (frame->current_render_pass->has_transparent_background) | 758 bool apply_background_filters = !filters.IsEmpty() && |
642 return scoped_ptr<ScopedResource>(); | 759 !frame->current_render_pass->has_transparent_background; |
643 DCHECK(!frame->current_texture); | 760 DCHECK(!frame->current_texture); |
644 | 761 |
645 // TODO(danakj): Do a single readback for both the surface and replica and | 762 // TODO(danakj): Do a single readback for both the surface and replica and |
646 // cache the filtered results (once filter textures are not reused). | 763 // cache the filtered results (once filter textures are not reused). |
647 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( | 764 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( |
648 contents_device_transform, SharedGeometryQuad().BoundingBox())); | 765 contents_device_transform, SharedGeometryQuad().BoundingBox())); |
649 | 766 |
650 int top, right, bottom, left; | 767 int top, right, bottom, left; |
651 filters.GetOutsets(&top, &right, &bottom, &left); | 768 filters.GetOutsets(&top, &right, &bottom, &left); |
652 window_rect.Inset(-left, -top, -right, -bottom); | 769 window_rect.Inset(-left, -top, -right, -bottom); |
653 | 770 |
654 window_rect.Intersect( | 771 window_rect.Intersect( |
655 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); | 772 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); |
656 | 773 |
657 scoped_ptr<ScopedResource> device_background_texture = | 774 scoped_ptr<ScopedResource> device_background_texture = |
658 ScopedResource::create(resource_provider_); | 775 ScopedResource::create(resource_provider_); |
659 if (!device_background_texture->Allocate(window_rect.size(), | 776 if (!device_background_texture->Allocate(window_rect.size(), |
660 ResourceProvider::TextureUsageAny, | 777 ResourceProvider::TextureUsageAny, |
661 RGBA_8888)) { | 778 RGBA_8888)) { |
662 return scoped_ptr<ScopedResource>(); | 779 return scoped_ptr<ScopedResource>(); |
663 } else { | 780 } else { |
664 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | 781 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
665 device_background_texture->id()); | 782 device_background_texture->id()); |
666 GetFramebufferTexture(lock.texture_id(), | 783 GetFramebufferTextureSubImage(lock.texture_id(), |
667 device_background_texture->format(), | 784 gfx::Point(), |
668 window_rect); | 785 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 | |
796 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; | |
797 if (filtered_device_background.getTexture()) { | |
798 GrTexture* texture = | |
799 reinterpret_cast<GrTexture*>(filtered_device_background.getTexture()); | |
800 filtered_device_background_texture_id = texture->getTextureHandle(); | |
801 background_changed = true; | |
802 } else { | |
803 lock.reset(new ResourceProvider::ScopedReadLockGL(resource_provider_, | |
804 device_background_texture->id())); | |
805 filtered_device_background_texture_id = lock->texture_id(); | |
806 background_changed = false; | |
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 Loading... | |
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 = quad->blend_mode != SkXfermode::kSrcOver_Mode; | |
879 bool backgroundChanged = false; | |
752 scoped_ptr<ScopedResource> background_texture; | 880 scoped_ptr<ScopedResource> background_texture; |
753 if (!quad->background_filters.IsEmpty()) { | 881 if (!quad->background_filters.IsEmpty() || applyBlendMode) { |
754 // The pixels from the filtered background should completely replace the | 882 // The pixels from the filtered background should completely replace the |
755 // current pixel values. | 883 // current pixel values. |
756 bool disable_blending = blend_enabled(); | 884 bool disable_blending = blend_enabled(); |
757 if (disable_blending) | 885 if (disable_blending) |
758 SetBlendEnabled(false); | 886 SetBlendEnabled(false); |
759 | 887 |
760 background_texture = DrawBackgroundFilters( | 888 background_texture = CreateBackgroundTextureWithFilters( |
761 frame, | 889 frame, |
762 quad, | 890 quad, |
763 contents_device_transform, | 891 contents_device_transform, |
764 contents_device_transform_inverse); | 892 contents_device_transform_inverse, |
893 backgroundChanged); | |
765 | 894 |
766 if (disable_blending) | 895 if (disable_blending) |
767 SetBlendEnabled(true); | 896 SetBlendEnabled(true); |
768 } | 897 } |
769 | 898 |
770 // TODO(senorblanco): Cache this value so that we don't have to do it for both | 899 // 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. | 900 // the surface and its replica. Apply filters to the contents texture. |
772 SkBitmap filter_bitmap; | 901 SkBitmap filter_bitmap; |
773 SkScalar color_matrix[20]; | 902 SkScalar color_matrix[20]; |
774 bool use_color_matrix = false; | 903 bool use_color_matrix = false; |
(...skipping 27 matching lines...) Expand all Loading... | |
802 color_matrix, optimized_filters.at(0).matrix(), sizeof(color_matrix)); | 931 color_matrix, optimized_filters.at(0).matrix(), sizeof(color_matrix)); |
803 use_color_matrix = true; | 932 use_color_matrix = true; |
804 } else { | 933 } else { |
805 filter_bitmap = ApplyFilters(this, | 934 filter_bitmap = ApplyFilters(this, |
806 frame->offscreen_context_provider, | 935 frame->offscreen_context_provider, |
807 optimized_filters, | 936 optimized_filters, |
808 contents_texture); | 937 contents_texture); |
809 } | 938 } |
810 } | 939 } |
811 | 940 |
941 if (background_texture && applyBlendMode) { | |
942 filter_bitmap = ApplyBlendModeWithBackdrop(this, | |
943 frame->offscreen_context_provider, filter_bitmap, | |
944 contents_texture, background_texture.get(), quad->blend_mode); | |
945 } | |
946 | |
812 // Draw the background texture if there is one. | 947 // Draw the background texture if there is one. |
813 if (background_texture) { | 948 if (background_texture && backgroundChanged) { |
814 DCHECK(background_texture->size() == quad->rect.size()); | 949 DCHECK(background_texture->size() == quad->rect.size()); |
815 ResourceProvider::ScopedReadLockGL lock(resource_provider_, | 950 ResourceProvider::ScopedReadLockGL lock(resource_provider_, |
816 background_texture->id()); | 951 background_texture->id()); |
817 | 952 |
818 // The background_texture is oriented the same as the frame buffer. The | 953 // The background_texture is oriented the same as the frame buffer. The |
819 // transform we are copying with has a vertical flip, so flip the contents | 954 // transform we are copying with has a vertical flip, so flip the contents |
820 // in the shader to maintain orientation | 955 // in the shader to maintain orientation |
821 bool flip_vertically = true; | 956 bool flip_vertically = true; |
822 | 957 |
823 CopyTextureToFramebuffer(frame, | 958 CopyTextureToFramebuffer(frame, |
(...skipping 1629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2453 scoped_ptr<SkAutoLockPixels> lock, | 2588 scoped_ptr<SkAutoLockPixels> lock, |
2454 scoped_ptr<CopyOutputRequest> request, | 2589 scoped_ptr<CopyOutputRequest> request, |
2455 bool success) { | 2590 bool success) { |
2456 DCHECK(request->force_bitmap_result()); | 2591 DCHECK(request->force_bitmap_result()); |
2457 | 2592 |
2458 lock.reset(); | 2593 lock.reset(); |
2459 if (success) | 2594 if (success) |
2460 request->SendBitmapResult(bitmap.Pass()); | 2595 request->SendBitmapResult(bitmap.Pass()); |
2461 } | 2596 } |
2462 | 2597 |
2598 void GLRenderer::GetFramebufferTextureSubImage(unsigned texture_id, | |
2599 gfx::Point offset, | |
2600 gfx::Rect window_rect) { | |
2601 DCHECK(texture_id); | |
2602 DCHECK_GE(window_rect.x(), 0); | |
2603 DCHECK_GE(window_rect.y(), 0); | |
2604 DCHECK_LE(window_rect.right(), current_surface_size_.width()); | |
2605 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); | |
2606 | |
2607 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); | |
2608 GLC(context_, | |
2609 context_->copyTexSubImage2D(GL_TEXTURE_2D, | |
shawnsingh
2013/09/25 05:33:53
Will this be certainly fast on all drivers/hardwar
rosca
2013/09/25 18:00:00
Are you referring to the copyTexSubImage2D functio
| |
2610 0, | |
2611 offset.x(), | |
2612 offset.y(), | |
2613 window_rect.x(), | |
2614 window_rect.y(), | |
2615 window_rect.width(), | |
2616 window_rect.height())); | |
2617 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0)); | |
2618 } | |
2619 | |
2463 void GLRenderer::GetFramebufferTexture( | 2620 void GLRenderer::GetFramebufferTexture( |
2464 unsigned texture_id, ResourceFormat texture_format, gfx::Rect window_rect) { | 2621 unsigned texture_id, ResourceFormat texture_format, gfx::Rect window_rect) { |
2465 DCHECK(texture_id); | 2622 DCHECK(texture_id); |
2466 DCHECK_GE(window_rect.x(), 0); | 2623 DCHECK_GE(window_rect.x(), 0); |
2467 DCHECK_GE(window_rect.y(), 0); | 2624 DCHECK_GE(window_rect.y(), 0); |
2468 DCHECK_LE(window_rect.right(), current_surface_size_.width()); | 2625 DCHECK_LE(window_rect.right(), current_surface_size_.width()); |
2469 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); | 2626 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); |
2470 | 2627 |
2471 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); | 2628 GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); |
2472 GLC(context_, | 2629 GLC(context_, |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3132 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas | 3289 // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas |
3133 // implementation. | 3290 // implementation. |
3134 return gr_context_ && context_->getContextAttributes().stencil; | 3291 return gr_context_ && context_->getContextAttributes().stencil; |
3135 } | 3292 } |
3136 | 3293 |
3137 bool GLRenderer::IsContextLost() { | 3294 bool GLRenderer::IsContextLost() { |
3138 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); | 3295 return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); |
3139 } | 3296 } |
3140 | 3297 |
3141 } // namespace cc | 3298 } // namespace cc |
OLD | NEW |