| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/resources/resource_provider.h" | 5 #include "cc/resources/resource_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| (...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 ResourceIdArray unused; | 889 ResourceIdArray unused; |
| 890 unused.push_back(id); | 890 unused.push_back(id); |
| 891 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused); | 891 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused); |
| 892 } | 892 } |
| 893 } | 893 } |
| 894 } | 894 } |
| 895 | 895 |
| 896 const ResourceProvider::Resource* ResourceProvider::LockForWrite( | 896 const ResourceProvider::Resource* ResourceProvider::LockForWrite( |
| 897 ResourceId id) { | 897 ResourceId id) { |
| 898 Resource* resource = GetResource(id); | 898 Resource* resource = GetResource(id); |
| 899 DCHECK(!resource->locked_for_write); | 899 DCHECK(CanLockForWrite(id)); |
| 900 DCHECK(!resource->lock_for_read_count); | |
| 901 DCHECK_EQ(resource->exported_count, 0); | |
| 902 DCHECK(resource->origin == Resource::Internal); | |
| 903 DCHECK(!resource->lost); | |
| 904 DCHECK(ReadLockFenceHasPassed(resource)); | |
| 905 LazyAllocate(resource); | 900 LazyAllocate(resource); |
| 906 | 901 |
| 907 resource->locked_for_write = true; | 902 resource->locked_for_write = true; |
| 908 return resource; | 903 return resource; |
| 909 } | 904 } |
| 910 | 905 |
| 911 bool ResourceProvider::CanLockForWrite(ResourceId id) { | 906 bool ResourceProvider::CanLockForWrite(ResourceId id) { |
| 912 Resource* resource = GetResource(id); | 907 Resource* resource = GetResource(id); |
| 913 return !resource->locked_for_write && !resource->lock_for_read_count && | 908 return !resource->locked_for_write && !resource->lock_for_read_count && |
| 914 !resource->exported_count && resource->origin == Resource::Internal && | 909 !resource->exported_count && resource->origin == Resource::Internal && |
| 915 !resource->lost && ReadLockFenceHasPassed(resource); | 910 !resource->lost && ReadLockFenceHasPassed(resource); |
| 916 } | 911 } |
| 917 | 912 |
| 918 void ResourceProvider::UnlockForWrite(ResourceId id) { | 913 void ResourceProvider::UnlockForWrite(ResourceId id) { |
| 919 Resource* resource = GetResource(id); | 914 Resource* resource = GetResource(id); |
| 920 DCHECK(resource->locked_for_write); | 915 DCHECK(resource->locked_for_write); |
| 921 DCHECK_EQ(resource->exported_count, 0); | 916 DCHECK_EQ(resource->exported_count, 0); |
| 922 DCHECK(resource->origin == Resource::Internal); | 917 DCHECK(resource->origin == Resource::Internal); |
| 923 resource->locked_for_write = false; | 918 resource->locked_for_write = false; |
| 924 } | 919 } |
| 925 | 920 |
| 921 const ResourceProvider::Resource* |
| 922 ResourceProvider::LockForWriteToGpuMemoryBuffer(ResourceId id) { |
| 923 Resource* resource = GetResource(id); |
| 924 DCHECK_EQ(GLTexture, resource->type); |
| 925 DCHECK(CanLockForWrite(id)); |
| 926 |
| 927 if (!resource->image_id) { |
| 928 resource->allocated = true; |
| 929 GLES2Interface* gl = ContextGL(); |
| 930 DCHECK(gl); |
| 931 resource->image_id = |
| 932 gl->CreateImageCHROMIUM(resource->size.width(), |
| 933 resource->size.height(), |
| 934 TextureToStorageFormat(resource->format), |
| 935 GL_IMAGE_MAP_CHROMIUM); |
| 936 DCHECK(resource->image_id); |
| 937 } |
| 938 |
| 939 resource->locked_for_write = true; |
| 940 return resource; |
| 941 } |
| 942 |
| 943 void ResourceProvider::UnlockForWriteToGpuMemoryBuffer(ResourceId id) { |
| 944 Resource* resource = GetResource(id); |
| 945 DCHECK(resource->locked_for_write); |
| 946 DCHECK_EQ(resource->exported_count, 0); |
| 947 DCHECK(resource->origin == Resource::Internal); |
| 948 DCHECK_EQ(GLTexture, resource->type); |
| 949 |
| 950 resource->locked_for_write = false; |
| 951 resource->dirty_image = true; |
| 952 |
| 953 // GpuMemoryBuffer provides direct access to the memory used by the GPU. |
| 954 // Read lock fences are required to ensure that we're not trying to map a |
| 955 // buffer that is currently in-use by the GPU. |
| 956 resource->read_lock_fences_enabled = true; |
| 957 } |
| 958 |
| 959 const ResourceProvider::Resource* ResourceProvider::LockForWriteToSkSurface( |
| 960 ResourceId id) { |
| 961 Resource* resource = GetResource(id); |
| 962 DCHECK_EQ(GLTexture, resource->type); |
| 963 DCHECK(CanLockForWrite(id)); |
| 964 |
| 965 resource->locked_for_write = true; |
| 966 if (!resource->sk_surface) { |
| 967 class GrContext* gr_context = GrContext(); |
| 968 // TODO(alokp): Implement TestContextProvider::GrContext(). |
| 969 if (!gr_context) |
| 970 return resource; |
| 971 |
| 972 LazyAllocate(resource); |
| 973 |
| 974 GrBackendTextureDesc desc; |
| 975 desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
| 976 desc.fWidth = resource->size.width(); |
| 977 desc.fHeight = resource->size.height(); |
| 978 desc.fConfig = ToGrPixelConfig(resource->format); |
| 979 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
| 980 desc.fTextureHandle = resource->gl_id; |
| 981 skia::RefPtr<GrTexture> gr_texture = |
| 982 skia::AdoptRef(gr_context->wrapBackendTexture(desc)); |
| 983 SkSurface::TextRenderMode text_render_mode = |
| 984 use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode |
| 985 : SkSurface::kStandard_TextRenderMode; |
| 986 resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect( |
| 987 gr_texture->asRenderTarget(), text_render_mode)); |
| 988 } |
| 989 |
| 990 return resource; |
| 991 } |
| 992 |
| 993 void ResourceProvider::UnlockForWriteToSkSurface(ResourceId id) { |
| 994 Resource* resource = GetResource(id); |
| 995 DCHECK(resource->locked_for_write); |
| 996 DCHECK_EQ(resource->exported_count, 0); |
| 997 DCHECK(resource->origin == Resource::Internal); |
| 998 DCHECK_EQ(GLTexture, resource->type); |
| 999 resource->locked_for_write = false; |
| 1000 } |
| 1001 |
| 926 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( | 1002 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( |
| 927 ResourceProvider* resource_provider, | 1003 ResourceProvider* resource_provider, |
| 928 ResourceProvider::ResourceId resource_id) | 1004 ResourceProvider::ResourceId resource_id) |
| 929 : resource_provider_(resource_provider), | 1005 : resource_provider_(resource_provider), |
| 930 resource_id_(resource_id), | 1006 resource_id_(resource_id), |
| 931 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) { | 1007 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) { |
| 932 DCHECK(texture_id_); | 1008 DCHECK(texture_id_); |
| 933 } | 1009 } |
| 934 | 1010 |
| 935 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { | 1011 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 ResourceProvider::PopulateSkBitmapWithResource( | 1077 ResourceProvider::PopulateSkBitmapWithResource( |
| 1002 &sk_bitmap_, resource_provider->LockForWrite(resource_id)); | 1078 &sk_bitmap_, resource_provider->LockForWrite(resource_id)); |
| 1003 DCHECK(valid()); | 1079 DCHECK(valid()); |
| 1004 sk_canvas_.reset(new SkCanvas(sk_bitmap_)); | 1080 sk_canvas_.reset(new SkCanvas(sk_bitmap_)); |
| 1005 } | 1081 } |
| 1006 | 1082 |
| 1007 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { | 1083 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { |
| 1008 resource_provider_->UnlockForWrite(resource_id_); | 1084 resource_provider_->UnlockForWrite(resource_id_); |
| 1009 } | 1085 } |
| 1010 | 1086 |
| 1087 ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: |
| 1088 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider, |
| 1089 ResourceProvider::ResourceId resource_id) |
| 1090 : resource_provider_(resource_provider), |
| 1091 resource_id_(resource_id), |
| 1092 image_id_(resource_provider->LockForWriteToGpuMemoryBuffer(resource_id) |
| 1093 ->image_id), |
| 1094 gpu_memory_buffer_( |
| 1095 resource_provider->ContextGL()->MapImageCHROMIUM(image_id_)) { |
| 1096 resource_provider->ContextGL()->GetImageParameterivCHROMIUM( |
| 1097 image_id_, GL_IMAGE_ROWBYTES_CHROMIUM, &stride_); |
| 1098 } |
| 1099 |
| 1100 ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: |
| 1101 ~ScopedWriteLockGpuMemoryBuffer() { |
| 1102 resource_provider_->ContextGL()->UnmapImageCHROMIUM(image_id_); |
| 1103 resource_provider_->UnlockForWriteToGpuMemoryBuffer(resource_id_); |
| 1104 } |
| 1105 |
| 1106 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr( |
| 1107 ResourceProvider* resource_provider, |
| 1108 ResourceProvider::ResourceId resource_id) |
| 1109 : resource_provider_(resource_provider), |
| 1110 resource_id_(resource_id), |
| 1111 sk_surface_(resource_provider->LockForWriteToSkSurface(resource_id) |
| 1112 ->sk_surface.get()) { |
| 1113 } |
| 1114 |
| 1115 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() { |
| 1116 resource_provider_->UnlockForWriteToSkSurface(resource_id_); |
| 1117 } |
| 1118 |
| 1011 ResourceProvider::ResourceProvider( | 1119 ResourceProvider::ResourceProvider( |
| 1012 OutputSurface* output_surface, | 1120 OutputSurface* output_surface, |
| 1013 SharedBitmapManager* shared_bitmap_manager, | 1121 SharedBitmapManager* shared_bitmap_manager, |
| 1014 BlockingTaskRunner* blocking_main_thread_task_runner, | 1122 BlockingTaskRunner* blocking_main_thread_task_runner, |
| 1015 int highp_threshold_min, | 1123 int highp_threshold_min, |
| 1016 bool use_rgba_4444_texture_format, | 1124 bool use_rgba_4444_texture_format, |
| 1017 size_t id_allocation_chunk_size, | 1125 size_t id_allocation_chunk_size, |
| 1018 bool use_distance_field_text) | 1126 bool use_distance_field_text) |
| 1019 : output_surface_(output_surface), | 1127 : output_surface_(output_surface), |
| 1020 shared_bitmap_manager_(shared_bitmap_manager), | 1128 shared_bitmap_manager_(shared_bitmap_manager), |
| (...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1754 GLuint complete = 1; | 1862 GLuint complete = 1; |
| 1755 gl->GetQueryObjectuivEXT( | 1863 gl->GetQueryObjectuivEXT( |
| 1756 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete); | 1864 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete); |
| 1757 if (!complete) | 1865 if (!complete) |
| 1758 return false; | 1866 return false; |
| 1759 } | 1867 } |
| 1760 | 1868 |
| 1761 resource->pending_set_pixels = false; | 1869 resource->pending_set_pixels = false; |
| 1762 UnlockForWrite(id); | 1870 UnlockForWrite(id); |
| 1763 | 1871 |
| 1872 // Async set pixels commands are not necessarily processed in-sequence with |
| 1873 // drawing commands. Read lock fences are required to ensure that async |
| 1874 // commands don't access the resource while used for drawing. |
| 1875 resource->read_lock_fences_enabled = true; |
| 1876 |
| 1764 return true; | 1877 return true; |
| 1765 } | 1878 } |
| 1766 | 1879 |
| 1767 void ResourceProvider::CreateForTesting(ResourceId id) { | 1880 void ResourceProvider::CreateForTesting(ResourceId id) { |
| 1768 LazyCreate(GetResource(id)); | 1881 LazyCreate(GetResource(id)); |
| 1769 } | 1882 } |
| 1770 | 1883 |
| 1771 GLenum ResourceProvider::TargetForTesting(ResourceId id) { | 1884 GLenum ResourceProvider::TargetForTesting(ResourceId id) { |
| 1772 Resource* resource = GetResource(id); | 1885 Resource* resource = GetResource(id); |
| 1773 return resource->target; | 1886 return resource->target; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1860 DCHECK(resource->image_id); | 1973 DCHECK(resource->image_id); |
| 1861 | 1974 |
| 1862 // Release image currently bound to texture. | 1975 // Release image currently bound to texture. |
| 1863 if (resource->bound_image_id) | 1976 if (resource->bound_image_id) |
| 1864 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id); | 1977 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id); |
| 1865 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id); | 1978 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id); |
| 1866 resource->bound_image_id = resource->image_id; | 1979 resource->bound_image_id = resource->image_id; |
| 1867 resource->dirty_image = false; | 1980 resource->dirty_image = false; |
| 1868 } | 1981 } |
| 1869 | 1982 |
| 1870 void ResourceProvider::EnableReadLockFences(ResourceId id) { | |
| 1871 Resource* resource = GetResource(id); | |
| 1872 resource->read_lock_fences_enabled = true; | |
| 1873 } | |
| 1874 | |
| 1875 void ResourceProvider::AcquireImage(ResourceId id) { | |
| 1876 Resource* resource = GetResource(id); | |
| 1877 DCHECK(resource->origin == Resource::Internal); | |
| 1878 DCHECK_EQ(resource->exported_count, 0); | |
| 1879 DCHECK_EQ(GLTexture, resource->type); | |
| 1880 | |
| 1881 if (resource->image_id) | |
| 1882 return; | |
| 1883 | |
| 1884 resource->allocated = true; | |
| 1885 GLES2Interface* gl = ContextGL(); | |
| 1886 DCHECK(gl); | |
| 1887 resource->image_id = | |
| 1888 gl->CreateImageCHROMIUM(resource->size.width(), | |
| 1889 resource->size.height(), | |
| 1890 TextureToStorageFormat(resource->format), | |
| 1891 GL_IMAGE_MAP_CHROMIUM); | |
| 1892 DCHECK(resource->image_id); | |
| 1893 } | |
| 1894 | |
| 1895 void ResourceProvider::ReleaseImage(ResourceId id) { | |
| 1896 Resource* resource = GetResource(id); | |
| 1897 DCHECK(resource->origin == Resource::Internal); | |
| 1898 DCHECK_EQ(resource->exported_count, 0); | |
| 1899 DCHECK_EQ(GLTexture, resource->type); | |
| 1900 | |
| 1901 if (!resource->image_id) | |
| 1902 return; | |
| 1903 | |
| 1904 GLES2Interface* gl = ContextGL(); | |
| 1905 DCHECK(gl); | |
| 1906 gl->DestroyImageCHROMIUM(resource->image_id); | |
| 1907 resource->image_id = 0; | |
| 1908 resource->bound_image_id = 0; | |
| 1909 resource->dirty_image = false; | |
| 1910 resource->allocated = false; | |
| 1911 } | |
| 1912 | |
| 1913 uint8_t* ResourceProvider::MapImage(ResourceId id, int* stride) { | |
| 1914 Resource* resource = GetResource(id); | |
| 1915 DCHECK(ReadLockFenceHasPassed(resource)); | |
| 1916 DCHECK(resource->origin == Resource::Internal); | |
| 1917 DCHECK_EQ(resource->exported_count, 0); | |
| 1918 DCHECK(resource->image_id); | |
| 1919 | |
| 1920 LockForWrite(id); | |
| 1921 | |
| 1922 GLES2Interface* gl = ContextGL(); | |
| 1923 DCHECK(gl); | |
| 1924 // MapImageCHROMIUM should be called prior to GetImageParameterivCHROMIUM. | |
| 1925 uint8_t* pixels = | |
| 1926 static_cast<uint8_t*>(gl->MapImageCHROMIUM(resource->image_id)); | |
| 1927 gl->GetImageParameterivCHROMIUM( | |
| 1928 resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride); | |
| 1929 return pixels; | |
| 1930 } | |
| 1931 | |
| 1932 void ResourceProvider::UnmapImage(ResourceId id) { | |
| 1933 Resource* resource = GetResource(id); | |
| 1934 DCHECK(resource->origin == Resource::Internal); | |
| 1935 DCHECK_EQ(resource->exported_count, 0); | |
| 1936 DCHECK(resource->image_id); | |
| 1937 DCHECK(resource->locked_for_write); | |
| 1938 | |
| 1939 GLES2Interface* gl = ContextGL(); | |
| 1940 DCHECK(gl); | |
| 1941 gl->UnmapImageCHROMIUM(resource->image_id); | |
| 1942 resource->dirty_image = true; | |
| 1943 | |
| 1944 UnlockForWrite(id); | |
| 1945 } | |
| 1946 | |
| 1947 void ResourceProvider::AcquireSkSurface(ResourceId id) { | |
| 1948 Resource* resource = GetResource(id); | |
| 1949 DCHECK(resource->origin == Resource::Internal); | |
| 1950 DCHECK_EQ(resource->exported_count, 0); | |
| 1951 DCHECK_EQ(GLTexture, resource->type); | |
| 1952 | |
| 1953 if (resource->sk_surface) | |
| 1954 return; | |
| 1955 | |
| 1956 class GrContext* gr_context = GrContext(); | |
| 1957 // TODO(alokp): Implement TestContextProvider::GrContext(). | |
| 1958 if (!gr_context) | |
| 1959 return; | |
| 1960 | |
| 1961 LazyAllocate(resource); | |
| 1962 | |
| 1963 GrBackendTextureDesc desc; | |
| 1964 desc.fFlags = kRenderTarget_GrBackendTextureFlag; | |
| 1965 desc.fWidth = resource->size.width(); | |
| 1966 desc.fHeight = resource->size.height(); | |
| 1967 desc.fConfig = ToGrPixelConfig(resource->format); | |
| 1968 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | |
| 1969 desc.fTextureHandle = resource->gl_id; | |
| 1970 skia::RefPtr<GrTexture> gr_texture = | |
| 1971 skia::AdoptRef(gr_context->wrapBackendTexture(desc)); | |
| 1972 SkSurface::TextRenderMode text_render_mode = | |
| 1973 use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode | |
| 1974 : SkSurface::kStandard_TextRenderMode; | |
| 1975 resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect( | |
| 1976 gr_texture->asRenderTarget(), text_render_mode)); | |
| 1977 } | |
| 1978 | |
| 1979 void ResourceProvider::ReleaseSkSurface(ResourceId id) { | |
| 1980 Resource* resource = GetResource(id); | |
| 1981 DCHECK(resource->origin == Resource::Internal); | |
| 1982 DCHECK_EQ(resource->exported_count, 0); | |
| 1983 DCHECK_EQ(GLTexture, resource->type); | |
| 1984 | |
| 1985 resource->sk_surface.clear(); | |
| 1986 } | |
| 1987 | |
| 1988 SkSurface* ResourceProvider::LockForWriteToSkSurface(ResourceId id) { | |
| 1989 Resource* resource = GetResource(id); | |
| 1990 DCHECK(resource->origin == Resource::Internal); | |
| 1991 DCHECK_EQ(resource->exported_count, 0); | |
| 1992 DCHECK_EQ(GLTexture, resource->type); | |
| 1993 | |
| 1994 LockForWrite(id); | |
| 1995 return resource->sk_surface.get(); | |
| 1996 } | |
| 1997 | |
| 1998 void ResourceProvider::UnlockForWriteToSkSurface(ResourceId id) { | |
| 1999 UnlockForWrite(id); | |
| 2000 } | |
| 2001 | |
| 2002 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) { | 1983 void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) { |
| 2003 TRACE_EVENT0("cc", "ResourceProvider::CopyResource"); | 1984 TRACE_EVENT0("cc", "ResourceProvider::CopyResource"); |
| 2004 | 1985 |
| 2005 Resource* source_resource = GetResource(source_id); | 1986 Resource* source_resource = GetResource(source_id); |
| 2006 DCHECK(!source_resource->lock_for_read_count); | 1987 DCHECK(!source_resource->lock_for_read_count); |
| 2007 DCHECK(source_resource->origin == Resource::Internal); | 1988 DCHECK(source_resource->origin == Resource::Internal); |
| 2008 DCHECK_EQ(source_resource->exported_count, 0); | 1989 DCHECK_EQ(source_resource->exported_count, 0); |
| 2009 DCHECK_EQ(GLTexture, source_resource->type); | 1990 DCHECK_EQ(GLTexture, source_resource->type); |
| 2010 DCHECK(source_resource->allocated); | 1991 DCHECK(source_resource->allocated); |
| 2011 LazyCreate(source_resource); | 1992 LazyCreate(source_resource); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2073 ContextProvider* context_provider = output_surface_->context_provider(); | 2054 ContextProvider* context_provider = output_surface_->context_provider(); |
| 2074 return context_provider ? context_provider->ContextGL() : NULL; | 2055 return context_provider ? context_provider->ContextGL() : NULL; |
| 2075 } | 2056 } |
| 2076 | 2057 |
| 2077 class GrContext* ResourceProvider::GrContext() const { | 2058 class GrContext* ResourceProvider::GrContext() const { |
| 2078 ContextProvider* context_provider = output_surface_->context_provider(); | 2059 ContextProvider* context_provider = output_surface_->context_provider(); |
| 2079 return context_provider ? context_provider->GrContext() : NULL; | 2060 return context_provider ? context_provider->GrContext() : NULL; |
| 2080 } | 2061 } |
| 2081 | 2062 |
| 2082 } // namespace cc | 2063 } // namespace cc |
| OLD | NEW |