[Reland] Use glUnpremultiplyAndDitherCopyCHROMIUM in GPU Raster
This change addresses banding issues by using the newly added
glUnpremultiplyAndDitherCopyCHROMIUM.
In cases where we previously rasterized into a RGBA4444 target, we
instead rasterize into a temporary RGBA8888 target, then do an
unpremultiply/dither copy into the RGBA4444 target.
This means that tiles may be either unpremultiplied or premultiplied, so
we need a way to pipe this information to the GLRenderer, so it can
blend correctly. This change introduces a is_premultiplied property to
ContentDrawQuadBase to handle this.
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: I769a51e6a5f37dd5b9bede42577dbfade17e27e2
Reviewed-on: https://chromium-review.googlesource.com/937991
Reviewed-by: enne <enne@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Eric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543283}
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h
index 1812958..1141b23 100644
--- a/cc/ipc/cc_param_traits_macros.h
+++ b/cc/ipc/cc_param_traits_macros.h
@@ -117,6 +117,7 @@
IPC_STRUCT_TRAITS_MEMBER(tex_coord_rect)
IPC_STRUCT_TRAITS_MEMBER(texture_size)
IPC_STRUCT_TRAITS_MEMBER(swizzle_contents)
+ IPC_STRUCT_TRAITS_MEMBER(is_premultiplied)
IPC_STRUCT_TRAITS_MEMBER(nearest_neighbor)
IPC_STRUCT_TRAITS_MEMBER(force_anti_aliasing_off)
IPC_STRUCT_TRAITS_END()
diff --git a/cc/ipc/cc_param_traits_unittest.cc b/cc/ipc/cc_param_traits_unittest.cc
index 97e58901..867bb9c 100644
--- a/cc/ipc/cc_param_traits_unittest.cc
+++ b/cc/ipc/cc_param_traits_unittest.cc
@@ -405,10 +405,10 @@
pass_cmp->CopyFromAndAppendDrawQuad(texture_in);
TileDrawQuad* tile_in = pass_in->CreateAndAppendDrawQuad<TileDrawQuad>();
- tile_in->SetAll(shared_state3_in, arbitrary_rect2,
- arbitrary_rect1_inside_rect2, arbitrary_bool1,
- arbitrary_resourceid3, arbitrary_rectf1, arbitrary_size1,
- arbitrary_bool2, arbitrary_bool3, arbitrary_bool4);
+ tile_in->SetAll(
+ shared_state3_in, arbitrary_rect2, arbitrary_rect1_inside_rect2,
+ arbitrary_bool1, arbitrary_resourceid3, arbitrary_rectf1, arbitrary_size1,
+ arbitrary_bool2, arbitrary_bool3, arbitrary_bool4, arbitrary_bool5);
pass_cmp->CopyFromAndAppendDrawQuad(tile_in);
YUVVideoDrawQuad* yuvvideo_in =
diff --git a/cc/ipc/cc_serialization_perftest.cc b/cc/ipc/cc_serialization_perftest.cc
index d8741b8..19baf09 100644
--- a/cc/ipc/cc_serialization_perftest.cc
+++ b/cc/ipc/cc_serialization_perftest.cc
@@ -361,10 +361,11 @@
arbitrary_blend_mode2, arbitrary_context_id2);
for (uint32_t j = 0; j < 6; ++j) {
auto* tile_in = pass_in->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
- tile_in->SetAll(
- shared_state2_in, arbitrary_rect2, arbitrary_rect1_inside_rect2,
- arbitrary_bool1, arbitrary_resourceid3, arbitrary_rectf1,
- arbitrary_size1, arbitrary_bool2, arbitrary_bool3, arbitrary_bool4);
+ tile_in->SetAll(shared_state2_in, arbitrary_rect2,
+ arbitrary_rect1_inside_rect2, arbitrary_bool1,
+ arbitrary_resourceid3, arbitrary_rectf1,
+ arbitrary_size1, arbitrary_bool2, arbitrary_bool3,
+ arbitrary_bool4, arbitrary_bool5);
}
}
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 02e162026..b395f9e 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -106,7 +106,8 @@
// don't need any settings. The current approach uses 4 tiles to cover the
// viewport vertically.
gfx::Size CalculateGpuTileSize(const gfx::Size& base_tile_size,
- const gfx::Size& content_bounds) {
+ const gfx::Size& content_bounds,
+ const gfx::Size& max_tile_size) {
int tile_width = base_tile_size.width();
// Increase the height proportionally as the width decreases, and pad by our
@@ -130,6 +131,11 @@
tile_height = std::max(tile_height, kMinHeightForGpuRasteredTile);
+ if (!max_tile_size.IsEmpty()) {
+ tile_width = std::min(tile_width, max_tile_size.width());
+ tile_height = std::min(tile_height, max_tile_size.height());
+ }
+
return gfx::Size(tile_width, tile_height);
}
@@ -470,7 +476,7 @@
offset_visible_geometry_rect, needs_blending,
draw_info.resource_id_for_export(), texture_rect,
draw_info.resource_size(), draw_info.contents_swizzled(),
- nearest_neighbor_,
+ draw_info.is_premultiplied(), nearest_neighbor_,
!layer_tree_impl()->settings().enable_edge_anti_aliasing);
ValidateQuadResources(quad);
has_draw_quad = true;
@@ -940,6 +946,9 @@
int default_tile_width = 0;
int default_tile_height = 0;
if (layer_tree_impl()->use_gpu_rasterization()) {
+ gfx::Size max_tile_size =
+ layer_tree_impl()->settings().max_gpu_raster_tile_size;
+
// Calculate |base_tile_size based| on |gpu_raster_max_texture_size_|,
// adjusting for ceil operations that may occur due to DSF.
gfx::Size base_tile_size = ApplyDsfAdjustment(
@@ -948,14 +957,15 @@
// Set our initial size assuming a |base_tile_size| equal to our
// |viewport_size|.
gfx::Size default_tile_size =
- CalculateGpuTileSize(base_tile_size, content_bounds);
+ CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size);
// Use half-width GPU tiles when the content_width is greater than our
// calculated tile size.
if (content_bounds.width() > default_tile_size.width()) {
// Divide width by 2 and round up.
base_tile_size.set_width((base_tile_size.width() + 1) / 2);
- default_tile_size = CalculateGpuTileSize(base_tile_size, content_bounds);
+ default_tile_size =
+ CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size);
}
default_tile_width = default_tile_size.width();
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index 8385acee..714ddd4 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -68,7 +68,7 @@
for (const auto& rect : quad_rects_) {
auto* quad = render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
quad->SetNew(shared_quad_state, rect, rect, needs_blending, 0,
- gfx::RectF(rect), bounds(), false, false, false);
+ gfx::RectF(rect), bounds(), false, false, false, false);
}
}
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc
index ab3e5f5..fde06ec 100644
--- a/cc/raster/bitmap_raster_buffer_provider.cc
+++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -136,6 +136,11 @@
return ResourceFormatRequiresSwizzle(viz::RGBA_8888);
}
+bool BitmapRasterBufferProvider::IsResourcePremultiplied(
+ bool must_support_alpha) const {
+ return true;
+}
+
bool BitmapRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
return true;
}
diff --git a/cc/raster/bitmap_raster_buffer_provider.h b/cc/raster/bitmap_raster_buffer_provider.h
index 4fc33cc..1f33b863 100644
--- a/cc/raster/bitmap_raster_buffer_provider.h
+++ b/cc/raster/bitmap_raster_buffer_provider.h
@@ -34,6 +34,7 @@
void Flush() override;
viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
bool IsResourceSwizzleRequired(bool must_support_alpha) const override;
+ bool IsResourcePremultiplied(bool must_support_alpha) const override;
bool CanPartialRasterIntoProvidedResource() const override;
bool IsResourceReadyToDraw(
const ResourcePool::InUsePoolResource& resource) const override;
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index 96a97fe..497657f2b 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -28,6 +28,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
+#include "skia/ext/texture_handle.h"
#include "third_party/skia/include/core/SkMultiPictureDraw.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -38,6 +39,73 @@
namespace cc {
namespace {
+class ScopedSkSurfaceForUnpremultiplyAndDither {
+ public:
+ ScopedSkSurfaceForUnpremultiplyAndDither(
+ viz::RasterContextProvider* context_provider,
+ const gfx::Rect& playback_rect,
+ const gfx::Rect& raster_full_rect,
+ const gfx::Size& max_tile_size,
+ GLuint texture_id,
+ const gfx::Size& texture_size,
+ bool use_distance_field_text,
+ bool can_use_lcd_text,
+ int msaa_sample_count)
+ : context_provider_(context_provider),
+ texture_id_(texture_id),
+ offset_(playback_rect.OffsetFromOrigin() -
+ raster_full_rect.OffsetFromOrigin()),
+ size_(playback_rect.size()) {
+ // Determine the |intermediate_size| to use for our 32-bit texture. If we
+ // know the max tile size, use that. This prevents GPU cache explosion due
+ // to using lots of different 32-bit texture sizes. Otherwise just use the
+ // exact size of the target texture.
+ gfx::Size intermediate_size;
+ if (!max_tile_size.IsEmpty()) {
+ DCHECK_GE(max_tile_size.width(), texture_size.width());
+ DCHECK_GE(max_tile_size.height(), texture_size.height());
+ intermediate_size = max_tile_size;
+ } else {
+ intermediate_size = texture_size;
+ }
+
+ // Allocate a 32-bit surface for raster. We will copy from that into our
+ // actual surface in destruction.
+ SkImageInfo n32Info = SkImageInfo::MakeN32Premul(
+ intermediate_size.width(), intermediate_size.height());
+ SkSurfaceProps surface_props =
+ LayerTreeResourceProvider::ScopedSkSurface::ComputeSurfaceProps(
+ use_distance_field_text, can_use_lcd_text);
+ surface_ = SkSurface::MakeRenderTarget(
+ context_provider->GrContext(), SkBudgeted::kNo, n32Info,
+ msaa_sample_count, kTopLeft_GrSurfaceOrigin, &surface_props);
+ }
+
+ ~ScopedSkSurfaceForUnpremultiplyAndDither() {
+ // In lost-context cases, |surface_| may be null and there's nothing
+ // meaningful to do here.
+ if (!surface_)
+ return;
+
+ GrBackendObject handle =
+ surface_->getTextureHandle(SkSurface::kFlushRead_BackendHandleAccess);
+ const GrGLTextureInfo* info =
+ skia::GrBackendObjectToGrGLTextureInfo(handle);
+ context_provider_->ContextGL()->UnpremultiplyAndDitherCopyCHROMIUM(
+ info->fID, texture_id_, offset_.x(), offset_.y(), size_.width(),
+ size_.height());
+ }
+
+ SkSurface* surface() { return surface_.get(); }
+
+ private:
+ viz::RasterContextProvider* context_provider_;
+ GLuint texture_id_;
+ gfx::Vector2d offset_;
+ gfx::Size size_;
+ sk_sp<SkSurface> surface_;
+};
+
static void RasterizeSourceOOP(
const RasterSource* raster_source,
bool resource_has_previous_content,
@@ -87,6 +155,9 @@
raster_source->requires_clear());
ri->EndRasterCHROMIUM();
+ // TODO(ericrk): Handle unpremultiply+dither for 4444 cases.
+ // https://crbug.com/789153
+
ri->DeleteTextures(1, &texture_id);
}
@@ -127,7 +198,9 @@
const RasterSource::PlaybackSettings& playback_settings,
viz::RasterContextProvider* context_provider,
bool use_distance_field_text,
- int msaa_sample_count) {
+ int msaa_sample_count,
+ bool unpremultiply_and_dither,
+ const gfx::Size& max_tile_size) {
gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
GLuint texture_id = ri->CreateAndConsumeTexture(
texture_is_overlay_candidate, gfx::BufferUsage::SCANOUT, resource_format,
@@ -142,12 +215,23 @@
{
ScopedGrContextAccess gr_context_access(context_provider);
- LayerTreeResourceProvider::ScopedSkSurface scoped_surface(
- context_provider->GrContext(), texture_id, texture_target,
- resource_size, resource_format, use_distance_field_text,
- playback_settings.use_lcd_text, msaa_sample_count);
-
- SkSurface* surface = scoped_surface.surface();
+ base::Optional<LayerTreeResourceProvider::ScopedSkSurface> scoped_surface;
+ base::Optional<ScopedSkSurfaceForUnpremultiplyAndDither>
+ scoped_dither_surface;
+ SkSurface* surface;
+ if (!unpremultiply_and_dither) {
+ scoped_surface.emplace(context_provider->GrContext(), texture_id,
+ texture_target, resource_size, resource_format,
+ use_distance_field_text,
+ playback_settings.use_lcd_text, msaa_sample_count);
+ surface = scoped_surface->surface();
+ } else {
+ scoped_dither_surface.emplace(
+ context_provider, playback_rect, raster_full_rect, max_tile_size,
+ texture_id, resource_size, use_distance_field_text,
+ playback_settings.use_lcd_text, msaa_sample_count);
+ surface = scoped_dither_surface->surface();
+ }
// Allocating an SkSurface will fail after a lost context. Pretend we
// rasterized, as the contents of the resource don't matter anymore.
@@ -171,6 +255,15 @@
ri->DeleteTextures(1, &texture_id);
}
+bool ShouldUnpremultiplyAndDitherResource(viz::ResourceFormat format) {
+ switch (format) {
+ case viz::RGBA_4444:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace
// Subclass for InUsePoolResource that holds ownership of a gpu-rastered backing
@@ -266,6 +359,7 @@
bool use_gpu_memory_buffer_resources,
int gpu_rasterization_msaa_sample_count,
viz::ResourceFormat preferred_tile_format,
+ const gfx::Size& max_tile_size,
bool enable_oop_rasterization)
: compositor_context_provider_(compositor_context_provider),
worker_context_provider_(worker_context_provider),
@@ -274,6 +368,7 @@
use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources),
msaa_sample_count_(gpu_rasterization_msaa_sample_count),
preferred_tile_format_(preferred_tile_format),
+ max_tile_size_(max_tile_size),
enable_oop_rasterization_(enable_oop_rasterization) {
DCHECK(compositor_context_provider);
DCHECK(worker_context_provider);
@@ -344,6 +439,12 @@
return false;
}
+bool GpuRasterBufferProvider::IsResourcePremultiplied(
+ bool must_support_alpha) const {
+ return !ShouldUnpremultiplyAndDitherResource(
+ GetResourceFormat(must_support_alpha));
+}
+
bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
// Partial raster doesn't support MSAA, as the MSAA resolve is unaware of clip
// rects.
@@ -448,12 +549,13 @@
transform, playback_settings, worker_context_provider_,
use_distance_field_text_, msaa_sample_count_);
} else {
- RasterizeSource(raster_source, resource_has_previous_content, mailbox,
- texture_target, texture_is_overlay_candidate,
- texture_storage_allocated, resource_size, resource_format,
- color_space, raster_full_rect, playback_rect, transform,
- playback_settings, worker_context_provider_,
- use_distance_field_text_, msaa_sample_count_);
+ RasterizeSource(
+ raster_source, resource_has_previous_content, mailbox, texture_target,
+ texture_is_overlay_candidate, texture_storage_allocated, resource_size,
+ resource_format, color_space, raster_full_rect, playback_rect,
+ transform, playback_settings, worker_context_provider_,
+ use_distance_field_text_, msaa_sample_count_,
+ ShouldUnpremultiplyAndDitherResource(resource_format), max_tile_size_);
}
// Generate sync token for cross context synchronization.
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h
index 18a5ec6..f5ec7f2 100644
--- a/cc/raster/gpu_raster_buffer_provider.h
+++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -28,6 +28,7 @@
bool use_gpu_memory_buffer_resources,
int gpu_rasterization_msaa_sample_count,
viz::ResourceFormat preferred_tile_format,
+ const gfx::Size& max_tile_size,
bool enable_oop_rasterization);
~GpuRasterBufferProvider() override;
@@ -39,6 +40,7 @@
void Flush() override;
viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
bool IsResourceSwizzleRequired(bool must_support_alpha) const override;
+ bool IsResourcePremultiplied(bool must_support_alpha) const override;
bool CanPartialRasterIntoProvidedResource() const override;
bool IsResourceReadyToDraw(
const ResourcePool::InUsePoolResource& resource) const override;
@@ -116,6 +118,7 @@
const bool use_gpu_memory_buffer_resources_;
const int msaa_sample_count_;
const viz::ResourceFormat preferred_tile_format_;
+ const gfx::Size max_tile_size_;
const bool enable_oop_rasterization_;
DISALLOW_COPY_AND_ASSIGN(GpuRasterBufferProvider);
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index d55894c5..6388dc7 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -225,6 +225,13 @@
return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
}
+bool OneCopyRasterBufferProvider::IsResourcePremultiplied(
+ bool must_support_alpha) const {
+ // TODO(ericrk): Handle unpremultiply/dither in one-copy case as well.
+ // https://crbug.com/789153
+ return true;
+}
+
bool OneCopyRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
// While OneCopyRasterBufferProvider has an internal partial raster
// implementation, it cannot directly partial raster into the externally
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h
index d1408d13..26f5454 100644
--- a/cc/raster/one_copy_raster_buffer_provider.h
+++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -44,6 +44,7 @@
void Flush() override;
viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
bool IsResourceSwizzleRequired(bool must_support_alpha) const override;
+ bool IsResourcePremultiplied(bool must_support_alpha) const override;
bool CanPartialRasterIntoProvidedResource() const override;
bool IsResourceReadyToDraw(
const ResourcePool::InUsePoolResource& resource) const override;
diff --git a/cc/raster/raster_buffer_provider.h b/cc/raster/raster_buffer_provider.h
index c25f2e9..12b7e0d 100644
--- a/cc/raster/raster_buffer_provider.h
+++ b/cc/raster/raster_buffer_provider.h
@@ -62,6 +62,9 @@
// Determine if the resource requires swizzling.
virtual bool IsResourceSwizzleRequired(bool must_support_alpha) const = 0;
+ // Determines if the resource is premultiplied.
+ virtual bool IsResourcePremultiplied(bool must_support_alpha) const = 0;
+
// Determine if the RasterBufferProvider can handle partial raster into
// the Resource provided in AcquireBufferForRaster.
virtual bool CanPartialRasterIntoProvidedResource() const = 0;
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index 7531ddd..0f4dfa3e 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -380,7 +380,7 @@
raster_buffer_provider_ = std::make_unique<GpuRasterBufferProvider>(
compositor_context_provider_.get(), worker_context_provider_.get(),
resource_provider_.get(), false, false, 0,
- viz::PlatformColor::BestTextureFormat(), false);
+ viz::PlatformColor::BestTextureFormat(), gfx::Size(), false);
resource_pool_ = std::make_unique<ResourcePool>(
resource_provider_.get(), task_runner_,
ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu,
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index e1634fb..1881694 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -182,7 +182,7 @@
raster_buffer_provider_ = std::make_unique<GpuRasterBufferProvider>(
context_provider_.get(), worker_context_provider_.get(),
resource_provider_.get(), false, false, 0,
- viz::PlatformColor::BestTextureFormat(), false);
+ viz::PlatformColor::BestTextureFormat(), gfx::Size(), false);
pool_ = std::make_unique<ResourcePool>(
resource_provider_.get(), base::ThreadTaskRunnerHandle::Get(),
base::TimeDelta(), ResourcePool::Mode::kGpu, true);
diff --git a/cc/raster/zero_copy_raster_buffer_provider.cc b/cc/raster/zero_copy_raster_buffer_provider.cc
index fd311dd9..c17f9753 100644
--- a/cc/raster/zero_copy_raster_buffer_provider.cc
+++ b/cc/raster/zero_copy_raster_buffer_provider.cc
@@ -250,6 +250,11 @@
return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
}
+bool ZeroCopyRasterBufferProvider::IsResourcePremultiplied(
+ bool must_support_alpha) const {
+ return true;
+}
+
bool ZeroCopyRasterBufferProvider::CanPartialRasterIntoProvidedResource()
const {
return false;
diff --git a/cc/raster/zero_copy_raster_buffer_provider.h b/cc/raster/zero_copy_raster_buffer_provider.h
index 1c6c6ae7..d7a118e 100644
--- a/cc/raster/zero_copy_raster_buffer_provider.h
+++ b/cc/raster/zero_copy_raster_buffer_provider.h
@@ -42,6 +42,7 @@
void Flush() override;
viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
bool IsResourceSwizzleRequired(bool must_support_alpha) const override;
+ bool IsResourcePremultiplied(bool must_support_alpha) const override;
bool CanPartialRasterIntoProvidedResource() const override;
bool IsResourceReadyToDraw(
const ResourcePool::InUsePoolResource& resource) const override;
diff --git a/cc/resources/layer_tree_resource_provider.cc b/cc/resources/layer_tree_resource_provider.cc
index 620ef69..9fb642c 100644
--- a/cc/resources/layer_tree_resource_provider.cc
+++ b/cc/resources/layer_tree_resource_provider.cc
@@ -997,6 +997,21 @@
texture_info.fFormat = TextureStorageFormat(format);
GrBackendTexture backend_texture(size.width(), size.height(),
GrMipMapped::kNo, texture_info);
+ SkSurfaceProps surface_props =
+ ComputeSurfaceProps(use_distance_field_text, can_use_lcd_text);
+ surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
+ gr_context, backend_texture, kTopLeft_GrSurfaceOrigin, msaa_sample_count,
+ ResourceFormatToClosestSkColorType(format), nullptr, &surface_props);
+}
+
+LayerTreeResourceProvider::ScopedSkSurface::~ScopedSkSurface() {
+ if (surface_)
+ surface_->prepareForExternalIO();
+}
+
+SkSurfaceProps LayerTreeResourceProvider::ScopedSkSurface::ComputeSurfaceProps(
+ bool use_distance_field_text,
+ bool can_use_lcd_text) {
uint32_t flags =
use_distance_field_text ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
// Use unknown pixel geometry to disable LCD text.
@@ -1006,14 +1021,7 @@
surface_props =
SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
}
- surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
- gr_context, backend_texture, kTopLeft_GrSurfaceOrigin, msaa_sample_count,
- ResourceFormatToClosestSkColorType(format), nullptr, &surface_props);
-}
-
-LayerTreeResourceProvider::ScopedSkSurface::~ScopedSkSurface() {
- if (surface_)
- surface_->prepareForExternalIO();
+ return surface_props;
}
void LayerTreeResourceProvider::ValidateResource(viz::ResourceId id) const {
diff --git a/cc/resources/layer_tree_resource_provider.h b/cc/resources/layer_tree_resource_provider.h
index 531762a..6d81451 100644
--- a/cc/resources/layer_tree_resource_provider.h
+++ b/cc/resources/layer_tree_resource_provider.h
@@ -294,6 +294,9 @@
SkSurface* surface() const { return surface_.get(); }
+ static SkSurfaceProps ComputeSurfaceProps(bool use_distance_field_text,
+ bool can_use_lcd_text);
+
private:
sk_sp<SkSurface> surface_;
diff --git a/cc/test/fake_raster_buffer_provider.cc b/cc/test/fake_raster_buffer_provider.cc
index 4ca560e..efed6c9 100644
--- a/cc/test/fake_raster_buffer_provider.cc
+++ b/cc/test/fake_raster_buffer_provider.cc
@@ -44,6 +44,11 @@
return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
}
+bool FakeRasterBufferProviderImpl::IsResourcePremultiplied(
+ bool must_support_alpha) const {
+ return true;
+}
+
bool FakeRasterBufferProviderImpl::CanPartialRasterIntoProvidedResource()
const {
return true;
diff --git a/cc/test/fake_raster_buffer_provider.h b/cc/test/fake_raster_buffer_provider.h
index 2b0bf18..159cb39 100644
--- a/cc/test/fake_raster_buffer_provider.h
+++ b/cc/test/fake_raster_buffer_provider.h
@@ -23,6 +23,7 @@
void Flush() override;
viz::ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
bool IsResourceSwizzleRequired(bool must_support_alpha) const override;
+ bool IsResourcePremultiplied(bool must_support_alpha) const override;
bool CanPartialRasterIntoProvidedResource() const override;
bool IsResourceReadyToDraw(
const ResourcePool::InUsePoolResource& resource) const override;
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index 499db82..2a5c16b 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -71,7 +71,7 @@
return std::make_unique<GpuRasterBufferProvider>(
compositor_context_provider, worker_context_provider,
resource_provider, false, false, 0,
- viz::PlatformColor::BestTextureFormat(), false);
+ viz::PlatformColor::BestTextureFormat(), gfx::Size(), false);
case ZERO_COPY:
EXPECT_TRUE(compositor_context_provider);
EXPECT_TRUE(gpu_memory_buffer_manager);
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index 8f22f73..10bcbe4 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -216,7 +216,7 @@
to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
scaled_tile_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
resource2, gfx::RectF(0, 0, 50, 50),
- gfx::Size(50, 50), false, false, false);
+ gfx::Size(50, 50), false, false, false, false);
viz::SharedQuadState* transformed_state =
to_pass->CreateAndAppendSharedQuadState();
@@ -227,9 +227,10 @@
transformed_state->quad_to_target_transform * rotation;
auto* transformed_tile_quad =
to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
- transformed_tile_quad->SetNew(
- transformed_state, rect, visible_rect, needs_blending, resource3,
- gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false, false);
+ transformed_tile_quad->SetNew(transformed_state, rect, visible_rect,
+ needs_blending, resource3,
+ gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100),
+ false, false, false, false);
viz::SharedQuadState* shared_state2 =
to_pass->CreateAndAppendSharedQuadState();
@@ -239,7 +240,7 @@
auto* tile_quad = to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
tile_quad->SetNew(shared_state2, rect, visible_rect, needs_blending,
resource4, gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100),
- false, false, false);
+ false, false, false, false);
viz::ResourceId plane_resources[4];
for (int i = 0; i < 4; ++i) {
@@ -417,7 +418,7 @@
to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
scaled_tile_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
mapped_resource2, gfx::RectF(0, 0, 50, 50),
- gfx::Size(50, 50), false, false, false);
+ gfx::Size(50, 50), false, false, false, false);
viz::SharedQuadState* transformed_state =
to_pass->CreateAndAppendSharedQuadState();
@@ -428,9 +429,10 @@
transformed_state->quad_to_target_transform * rotation;
viz::TileDrawQuad* transformed_tile_quad =
to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
- transformed_tile_quad->SetNew(
- transformed_state, rect, visible_rect, needs_blending, mapped_resource3,
- gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false, false);
+ transformed_tile_quad->SetNew(transformed_state, rect, visible_rect,
+ needs_blending, mapped_resource3,
+ gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100),
+ false, false, false, false);
viz::SharedQuadState* shared_state2 =
to_pass->CreateAndAppendSharedQuadState();
@@ -441,7 +443,7 @@
to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
tile_quad->SetNew(shared_state2, rect, visible_rect, needs_blending,
mapped_resource4, gfx::RectF(0, 0, 100, 100),
- gfx::Size(100, 100), false, false, false);
+ gfx::Size(100, 100), false, false, false, false);
viz::YUVVideoDrawQuad* yuv_quad =
to_pass->CreateAndAppendDrawQuad<viz::YUVVideoDrawQuad>();
diff --git a/cc/tiles/tile_draw_info.cc b/cc/tiles/tile_draw_info.cc
index 0e51c2b2..0c09fa28 100644
--- a/cc/tiles/tile_draw_info.cc
+++ b/cc/tiles/tile_draw_info.cc
@@ -22,7 +22,8 @@
void TileDrawInfo::SetResource(ResourcePool::InUsePoolResource resource,
bool resource_is_checker_imaged,
- bool contents_swizzled) {
+ bool contents_swizzled,
+ bool is_premultiplied) {
DCHECK(!resource_);
DCHECK(resource);
@@ -30,6 +31,7 @@
is_resource_ready_to_draw_ = false;
resource_is_checker_imaged_ = resource_is_checker_imaged;
contents_swizzled_ = contents_swizzled;
+ is_premultiplied_ = is_premultiplied;
resource_ = std::move(resource);
}
@@ -45,6 +47,7 @@
is_resource_ready_to_draw_ = false;
resource_is_checker_imaged_ = false;
contents_swizzled_ = false;
+ is_premultiplied_ = false;
return std::move(resource_);
}
diff --git a/cc/tiles/tile_draw_info.h b/cc/tiles/tile_draw_info.h
index 5ae3cbe0..c401258 100644
--- a/cc/tiles/tile_draw_info.h
+++ b/cc/tiles/tile_draw_info.h
@@ -73,6 +73,7 @@
}
bool contents_swizzled() const { return contents_swizzled_; }
+ bool is_premultiplied() const { return is_premultiplied_; }
bool requires_resource() const {
return mode_ == RESOURCE_MODE || mode_ == OOM_MODE;
@@ -101,7 +102,8 @@
void SetResource(ResourcePool::InUsePoolResource resource,
bool resource_is_checker_imaged,
- bool contents_swizzled);
+ bool contents_swizzled,
+ bool is_premultiplied);
ResourcePool::InUsePoolResource TakeResource();
void set_resource_ready_for_draw() {
@@ -120,6 +122,7 @@
SkColor solid_color_ = SK_ColorWHITE;
ResourcePool::InUsePoolResource resource_;
bool contents_swizzled_ = false;
+ bool is_premultiplied_ = false;
bool is_resource_ready_to_draw_ = false;
// Set to true if |resource_| was rasterized with checker-imaged content. The
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 4815f07..e5ed9cd 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -1272,9 +1272,11 @@
TileDrawInfo& draw_info = tile->draw_info();
bool needs_swizzle =
raster_buffer_provider_->IsResourceSwizzleRequired(!tile->is_opaque());
+ bool is_premultiplied =
+ raster_buffer_provider_->IsResourcePremultiplied(!tile->is_opaque());
draw_info.SetResource(std::move(resource),
raster_task_was_scheduled_with_checker_images,
- needs_swizzle);
+ needs_swizzle, is_premultiplied);
if (raster_task_was_scheduled_with_checker_images)
num_of_tiles_with_checker_images_++;
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index 1c4a90d..4170c15 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -205,7 +205,7 @@
gpu::GPU_IO, gpu::CommandBufferId::FromUnsafeValue(1), 1);
}
resource_pool_->PrepareForExport(resource);
- draw_info.SetResource(std::move(resource), false, false);
+ draw_info.SetResource(std::move(resource), false, false, false);
draw_info.set_resource_ready_for_draw();
}
}
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index adbca55..be3c78f 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2640,7 +2640,8 @@
compositor_context_provider, worker_context_provider,
resource_provider_.get(), settings_.use_distance_field_text,
settings_.resource_settings.use_gpu_memory_buffer_resources,
- msaa_sample_count, settings_.preferred_tile_format, oop_raster_enabled);
+ msaa_sample_count, settings_.preferred_tile_format,
+ settings_.max_gpu_raster_tile_size, oop_raster_enabled);
}
bool use_zero_copy = settings_.use_zero_copy;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index eab889e7..4869951 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -8299,7 +8299,7 @@
test_blending_draw_quad->SetNew(
shared_quad_state, quad_rect_, visible_quad_rect, needs_blending,
resource_id_, gfx::RectF(0.f, 0.f, 1.f, 1.f), gfx::Size(1, 1), false,
- false, false);
+ false, false, false);
EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
EXPECT_EQ(has_render_surface_,
diff --git a/cc/trees/layer_tree_host_pixeltest_tiles.cc b/cc/trees/layer_tree_host_pixeltest_tiles.cc
index 7156d69..b2c81a9 100644
--- a/cc/trees/layer_tree_host_pixeltest_tiles.cc
+++ b/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -24,6 +24,8 @@
FULL_ONE_COPY,
PARTIAL_GPU,
FULL_GPU,
+ PARTIAL_GPU_LOW_BIT_DEPTH,
+ FULL_GPU_LOW_BIT_DEPTH,
PARTIAL_BITMAP,
FULL_BITMAP,
};
@@ -55,6 +57,16 @@
settings->gpu_rasterization_forced = true;
settings->use_partial_raster = false;
break;
+ case PARTIAL_GPU_LOW_BIT_DEPTH:
+ settings->gpu_rasterization_forced = true;
+ settings->use_partial_raster = true;
+ settings->preferred_tile_format = viz::RGBA_4444;
+ break;
+ case FULL_GPU_LOW_BIT_DEPTH:
+ settings->gpu_rasterization_forced = true;
+ settings->use_partial_raster = false;
+ settings->preferred_tile_format = viz::RGBA_4444;
+ break;
}
}
@@ -81,6 +93,8 @@
case FULL_ONE_COPY:
case PARTIAL_GPU:
case FULL_GPU:
+ case PARTIAL_GPU_LOW_BIT_DEPTH:
+ case FULL_GPU_LOW_BIT_DEPTH:
test_type = PIXEL_TEST_GL;
break;
case PARTIAL_BITMAP:
@@ -120,9 +134,12 @@
PaintFlags flags;
flags.setStyle(PaintFlags::kFill_Style);
- flags.setColor(SK_ColorBLUE);
+ // Use custom colors with 0xF2 rather than the default blue/yellow (which
+ // use 0xFF), as the default won't show dither patterns as it exactly maps
+ // to a 16-bit color.
+ flags.setColor(SkColorSetRGB(0x00, 0x00, 0xF2));
display_list->push<DrawRectOp>(gfx::RectToSkRect(blue_rect), flags);
- flags.setColor(SK_ColorYELLOW);
+ flags.setColor(SkColorSetRGB(0xF2, 0xF2, 0x00));
display_list->push<DrawRectOp>(gfx::RectToSkRect(yellow_rect), flags);
display_list->EndPaintOfUnpaired(PaintableRegion());
@@ -247,6 +264,20 @@
base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png")));
}
+TEST_F(LayerTreeHostTilesTestPartialInvalidation,
+ PartialRaster_SingleThread_GpuRaster_LowBitDepth) {
+ RunRasterPixelTest(false, PARTIAL_GPU_LOW_BIT_DEPTH, picture_layer_,
+ base::FilePath(FILE_PATH_LITERAL(
+ "blue_yellow_partial_flipped_dither.png")));
+}
+
+TEST_F(LayerTreeHostTilesTestPartialInvalidation,
+ FullRaster_SingleThread_GpuRaster_LowBitDepth) {
+ RunRasterPixelTest(
+ false, FULL_GPU_LOW_BIT_DEPTH, picture_layer_,
+ base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped_dither.png")));
+}
+
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index dfbc8a5..189d7d7 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -71,6 +71,9 @@
double background_animation_rate = 1.0;
gfx::Size default_tile_size;
gfx::Size max_untiled_layer_size;
+ // If set, indicates the largest tile size we will use for GPU Raster. If not
+ // set, no limit is enforced.
+ gfx::Size max_gpu_raster_tile_size;
gfx::Size minimum_occlusion_tracking_size;
// 3000 pixels should give sufficient area for prepainting.
// Note this value is specified with an ideal contents scale in mind. That
diff --git a/components/viz/common/quads/content_draw_quad_base.cc b/components/viz/common/quads/content_draw_quad_base.cc
index f19b0b2..fc84e35 100644
--- a/components/viz/common/quads/content_draw_quad_base.cc
+++ b/components/viz/common/quads/content_draw_quad_base.cc
@@ -23,6 +23,7 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off) {
DrawQuad::SetAll(shared_quad_state, material, rect, visible_rect,
@@ -30,6 +31,7 @@
this->tex_coord_rect = tex_coord_rect;
this->texture_size = texture_size;
this->swizzle_contents = swizzle_contents;
+ this->is_premultiplied = is_premultiplied;
this->nearest_neighbor = nearest_neighbor;
this->force_anti_aliasing_off = force_anti_aliasing_off;
}
@@ -42,6 +44,7 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off) {
DrawQuad::SetAll(shared_quad_state, material, rect, visible_rect,
@@ -49,6 +52,7 @@
this->tex_coord_rect = tex_coord_rect;
this->texture_size = texture_size;
this->swizzle_contents = swizzle_contents;
+ this->is_premultiplied = is_premultiplied;
this->nearest_neighbor = nearest_neighbor;
this->force_anti_aliasing_off = force_anti_aliasing_off;
}
diff --git a/components/viz/common/quads/content_draw_quad_base.h b/components/viz/common/quads/content_draw_quad_base.h
index 473fb4a..9b738be 100644
--- a/components/viz/common/quads/content_draw_quad_base.h
+++ b/components/viz/common/quads/content_draw_quad_base.h
@@ -28,6 +28,7 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off);
@@ -39,12 +40,14 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off);
gfx::RectF tex_coord_rect;
gfx::Size texture_size;
bool swizzle_contents = false;
+ bool is_premultiplied = false;
bool nearest_neighbor = false;
bool force_anti_aliasing_off = false;
diff --git a/components/viz/common/quads/draw_quad_unittest.cc b/components/viz/common/quads/draw_quad_unittest.cc
index d53adc0..c225a7c 100644
--- a/components/viz/common/quads/draw_quad_unittest.cc
+++ b/components/viz/common/quads/draw_quad_unittest.cc
@@ -352,13 +352,15 @@
gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f);
gfx::Size texture_size(85, 32);
bool swizzle_contents = true;
+ bool contents_premultiplied = true;
bool nearest_neighbor = true;
bool force_anti_aliasing_off = false;
CREATE_SHARED_STATE();
CREATE_QUAD_NEW(TileDrawQuad, visible_rect, needs_blending, resource_id,
tex_coord_rect, texture_size, swizzle_contents,
- nearest_neighbor, force_anti_aliasing_off);
+ contents_premultiplied, nearest_neighbor,
+ force_anti_aliasing_off);
EXPECT_EQ(DrawQuad::TILED_CONTENT, copy_quad->material);
EXPECT_EQ(visible_rect, copy_quad->visible_rect);
EXPECT_EQ(needs_blending, copy_quad->needs_blending);
@@ -369,7 +371,8 @@
EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
CREATE_QUAD_ALL(TileDrawQuad, resource_id, tex_coord_rect, texture_size,
- swizzle_contents, nearest_neighbor, force_anti_aliasing_off);
+ swizzle_contents, contents_premultiplied, nearest_neighbor,
+ force_anti_aliasing_off);
EXPECT_EQ(DrawQuad::TILED_CONTENT, copy_quad->material);
EXPECT_EQ(resource_id, copy_quad->resource_id());
EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
@@ -599,13 +602,15 @@
gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f);
gfx::Size texture_size(85, 32);
bool swizzle_contents = true;
+ bool contents_premultiplied = true;
bool nearest_neighbor = true;
bool force_anti_aliasing_off = false;
CREATE_SHARED_STATE();
CREATE_QUAD_NEW(TileDrawQuad, visible_rect, needs_blending, resource_id,
tex_coord_rect, texture_size, swizzle_contents,
- nearest_neighbor, force_anti_aliasing_off);
+ contents_premultiplied, nearest_neighbor,
+ force_anti_aliasing_off);
EXPECT_EQ(resource_id, quad_new->resource_id());
EXPECT_EQ(1, IterateAndCount(quad_new));
EXPECT_EQ(resource_id + 1, quad_new->resource_id());
diff --git a/components/viz/common/quads/picture_draw_quad.cc b/components/viz/common/quads/picture_draw_quad.cc
index 4df5c55..2a51e85 100644
--- a/components/viz/common/quads/picture_draw_quad.cc
+++ b/components/viz/common/quads/picture_draw_quad.cc
@@ -32,8 +32,8 @@
ContentDrawQuadBase::SetNew(
shared_quad_state, DrawQuad::PICTURE_CONTENT, rect, visible_rect,
needs_blending, tex_coord_rect, texture_size,
- !PlatformColor::SameComponentOrder(texture_format), nearest_neighbor,
- false);
+ !PlatformColor::SameComponentOrder(texture_format), false,
+ nearest_neighbor, false);
this->content_rect = content_rect;
this->contents_scale = contents_scale;
this->display_item_list = std::move(display_item_list);
@@ -55,8 +55,8 @@
ContentDrawQuadBase::SetAll(
shared_quad_state, DrawQuad::PICTURE_CONTENT, rect, visible_rect,
needs_blending, tex_coord_rect, texture_size,
- !PlatformColor::SameComponentOrder(texture_format), nearest_neighbor,
- false);
+ !PlatformColor::SameComponentOrder(texture_format), false,
+ nearest_neighbor, false);
this->content_rect = content_rect;
this->contents_scale = contents_scale;
this->display_item_list = std::move(display_item_list);
diff --git a/components/viz/common/quads/tile_draw_quad.cc b/components/viz/common/quads/tile_draw_quad.cc
index 07836c0..72e8dee 100644
--- a/components/viz/common/quads/tile_draw_quad.cc
+++ b/components/viz/common/quads/tile_draw_quad.cc
@@ -22,12 +22,13 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off) {
ContentDrawQuadBase::SetNew(shared_quad_state, DrawQuad::TILED_CONTENT, rect,
visible_rect, needs_blending, tex_coord_rect,
- texture_size, swizzle_contents, nearest_neighbor,
- force_anti_aliasing_off);
+ texture_size, swizzle_contents, is_premultiplied,
+ nearest_neighbor, force_anti_aliasing_off);
resources.ids[kResourceIdIndex] = resource_id;
resources.count = 1;
}
@@ -40,12 +41,13 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off) {
ContentDrawQuadBase::SetAll(shared_quad_state, DrawQuad::TILED_CONTENT, rect,
visible_rect, needs_blending, tex_coord_rect,
- texture_size, swizzle_contents, nearest_neighbor,
- force_anti_aliasing_off);
+ texture_size, swizzle_contents, is_premultiplied,
+ nearest_neighbor, force_anti_aliasing_off);
resources.ids[kResourceIdIndex] = resource_id;
resources.count = 1;
}
diff --git a/components/viz/common/quads/tile_draw_quad.h b/components/viz/common/quads/tile_draw_quad.h
index 3d51c5df..3fd00ed 100644
--- a/components/viz/common/quads/tile_draw_quad.h
+++ b/components/viz/common/quads/tile_draw_quad.h
@@ -30,6 +30,7 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off);
@@ -44,6 +45,7 @@
const gfx::RectF& tex_coord_rect,
const gfx::Size& texture_size,
bool swizzle_contents,
+ bool is_premultiplied,
bool nearest_neighbor,
bool force_anti_aliasing_off);
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 7b96160..e6e852a 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -1942,8 +1942,10 @@
SetUseProgram(
ProgramKey::Tile(tex_coord_precision, sampler, USE_AA,
- quad->swizzle_contents ? DO_SWIZZLE : NO_SWIZZLE, false,
- false, tint_gl_composited_content_),
+ quad->swizzle_contents ? DO_SWIZZLE : NO_SWIZZLE,
+ quad->is_premultiplied ? PREMULTIPLIED_ALPHA
+ : NON_PREMULTIPLIED_ALPHA,
+ false, false, tint_gl_composited_content_),
quad_resource_lock.color_space(),
current_frame()->current_render_pass->color_space);
@@ -2029,6 +2031,8 @@
SetUseProgram(
ProgramKey::Tile(tex_coord_precision, sampler, NO_AA,
quad->swizzle_contents ? DO_SWIZZLE : NO_SWIZZLE,
+ quad->is_premultiplied ? PREMULTIPLIED_ALPHA
+ : NON_PREMULTIPLIED_ALPHA,
!quad->ShouldDrawWithBlending(), has_tex_clamp_rect,
tint_gl_composited_content_),
quad_resource_lock.color_space(),
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index 5fee46e..de23d53e 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -290,26 +290,46 @@
TestShader(ProgramKey::Texture(precision, sampler, NON_PREMULTIPLIED_ALPHA,
true, false, false));
- TestShader(ProgramKey::Tile(precision, sampler, USE_AA, NO_SWIZZLE, false,
- false, false));
- TestShader(ProgramKey::Tile(precision, sampler, USE_AA, DO_SWIZZLE, false,
- false, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE, false,
- false, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE, false,
- false, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE, true,
- false, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE, true,
- false, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE, false,
- true, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE, false,
- true, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE, true,
- true, false));
- TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE, true,
- true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, USE_AA, NO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, USE_AA, DO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, true, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, true, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, false, true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, false, true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, true, true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ PREMULTIPLIED_ALPHA, true, true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, USE_AA, NO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, USE_AA, DO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, false, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, true, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, true, false, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, false, true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, false, true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, NO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, true, true, false));
+ TestShader(ProgramKey::Tile(precision, sampler, NO_AA, DO_SWIZZLE,
+ NON_PREMULTIPLIED_ALPHA, true, true, false));
// Iterate over alpha plane, nv12, and color_lut parameters.
UVTextureMode uv_modes[2] = {UV_TEXTURE_MODE_UV, UV_TEXTURE_MODE_U_V};
diff --git a/components/viz/service/display/program_binding.cc b/components/viz/service/display/program_binding.cc
index 742c7a2..9436dc3 100644
--- a/components/viz/service/display/program_binding.cc
+++ b/components/viz/service/display/program_binding.cc
@@ -63,6 +63,7 @@
SamplerType sampler,
AAMode aa_mode,
SwizzleMode swizzle_mode,
+ PremultipliedAlphaMode premultiplied_alpha,
bool is_opaque,
bool has_tex_clamp_rect,
bool tint_color) {
@@ -75,6 +76,7 @@
result.is_opaque_ = is_opaque;
result.has_tex_clamp_rect_ = has_tex_clamp_rect;
result.has_tint_color_matrix_ = tint_color;
+ result.premultiplied_alpha_ = premultiplied_alpha;
return result;
}
diff --git a/components/viz/service/display/program_binding.h b/components/viz/service/display/program_binding.h
index 42fed4d..8b28c57 100644
--- a/components/viz/service/display/program_binding.h
+++ b/components/viz/service/display/program_binding.h
@@ -82,6 +82,7 @@
SamplerType sampler,
AAMode aa_mode,
SwizzleMode swizzle_mode,
+ PremultipliedAlphaMode premultiplied_alpha,
bool is_opaque,
bool has_tex_clamp_rect,
bool tint_color);
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index 7fa21dd..e7c3158 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -2801,6 +2801,7 @@
CreateTestRenderPass(id, rect, transform_to_root);
bool swizzle_contents = true;
+ bool contents_premultiplied = true;
bool needs_blending = false;
bool nearest_neighbor = true;
bool force_anti_aliasing_off = true;
@@ -2813,7 +2814,8 @@
TileDrawQuad* hole = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
hole->SetNew(hole_shared_state, rect, rect, needs_blending, mapped_resource,
gfx::RectF(gfx::Rect(tile_size)), tile_size, swizzle_contents,
- nearest_neighbor, force_anti_aliasing_off);
+ contents_premultiplied, nearest_neighbor,
+ force_anti_aliasing_off);
gfx::Transform green_quad_to_target_transform;
SharedQuadState* green_shared_state = CreateTestSharedQuadState(
@@ -3196,6 +3198,7 @@
TYPED_TEST(RendererPixelTest, TileDrawQuadNearestNeighbor) {
gfx::Rect viewport(this->device_viewport_size_);
bool swizzle_contents = true;
+ bool contents_premultiplied = true;
bool needs_blending = true;
bool nearest_neighbor = true;
bool force_anti_aliasing_off = false;
@@ -3238,7 +3241,8 @@
auto* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
quad->SetNew(shared_state, viewport, viewport, needs_blending,
mapped_resource, gfx::RectF(gfx::Rect(tile_size)), tile_size,
- swizzle_contents, nearest_neighbor, force_anti_aliasing_off);
+ swizzle_contents, contents_premultiplied, nearest_neighbor,
+ force_anti_aliasing_off);
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -3726,6 +3730,7 @@
TEST_F(GLRendererPixelTest, TileQuadClamping) {
gfx::Rect viewport(this->device_viewport_size_);
bool swizzle_contents = true;
+ bool contents_premultiplied = true;
bool needs_blending = true;
bool nearest_neighbor = false;
bool use_aa = false;
@@ -3779,7 +3784,8 @@
auto* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
quad->SetNew(quad_shared, gfx::Rect(layer_size), gfx::Rect(layer_size),
needs_blending, mapped_resource, tex_coord_rect, tile_size,
- swizzle_contents, nearest_neighbor, use_aa);
+ swizzle_contents, contents_premultiplied, nearest_neighbor,
+ use_aa);
// Green background.
SharedQuadState* background_shared =
diff --git a/components/viz/service/display/software_renderer_unittest.cc b/components/viz/service/display/software_renderer_unittest.cc
index 6f4f4e0f..899bc24c 100644
--- a/components/viz/service/display/software_renderer_unittest.cc
+++ b/components/viz/service/display/software_renderer_unittest.cc
@@ -198,11 +198,11 @@
auto* inner_quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
inner_quad->SetNew(shared_quad_state, inner_rect, inner_rect, needs_blending,
mapped_resource_cyan, gfx::RectF(gfx::SizeF(inner_size)),
- inner_size, false, false, false);
+ inner_size, false, false, false, false);
auto* outer_quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
outer_quad->SetNew(shared_quad_state, outer_rect, outer_rect, needs_blending,
mapped_resource_yellow, gfx::RectF(gfx::SizeF(outer_size)),
- outer_size, false, false, false);
+ outer_size, false, false, false, false);
RenderPassList list;
list.push_back(std::move(root_render_pass));
@@ -260,7 +260,7 @@
auto* quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
quad->SetNew(shared_quad_state, tile_rect, tile_rect, needs_blending,
mapped_resource_cyan, gfx::RectF(gfx::SizeF(tile_size)),
- tile_size, false, false, false);
+ tile_size, false, false, false, false);
quad->visible_rect = visible_rect;
RenderPassList list;
diff --git a/components/viz/test/data/blue_yellow_flipped.png b/components/viz/test/data/blue_yellow_flipped.png
index 04d17b6..cd5259fa 100644
--- a/components/viz/test/data/blue_yellow_flipped.png
+++ b/components/viz/test/data/blue_yellow_flipped.png
Binary files differ
diff --git a/components/viz/test/data/blue_yellow_flipped_dither.png b/components/viz/test/data/blue_yellow_flipped_dither.png
new file mode 100644
index 0000000..0908ffe
--- /dev/null
+++ b/components/viz/test/data/blue_yellow_flipped_dither.png
Binary files differ
diff --git a/components/viz/test/data/blue_yellow_partial_flipped.png b/components/viz/test/data/blue_yellow_partial_flipped.png
index 60648b7..1a127847 100644
--- a/components/viz/test/data/blue_yellow_partial_flipped.png
+++ b/components/viz/test/data/blue_yellow_partial_flipped.png
Binary files differ
diff --git a/components/viz/test/data/blue_yellow_partial_flipped_dither.png b/components/viz/test/data/blue_yellow_partial_flipped_dither.png
new file mode 100644
index 0000000..1edf658
--- /dev/null
+++ b/components/viz/test/data/blue_yellow_partial_flipped_dither.png
Binary files differ
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index c819f5b..1e882a24 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -553,6 +553,11 @@
base::SysInfo::AmountOfPhysicalMemoryMB() <= 512 &&
!using_synchronous_compositor) {
settings.preferred_tile_format = viz::RGBA_4444;
+ // We need to allocate an additional RGBA_8888 intermediate for each tile
+ // rasterization when rastering to RGBA_4444 to allow for dithering.
+ // Setting a reasonable sized max tile size allows this intermediate to
+ // be consistently reused.
+ settings.max_gpu_raster_tile_size = gfx::Size(512, 256);
}
}
diff --git a/services/viz/public/cpp/compositing/quads_struct_traits.cc b/services/viz/public/cpp/compositing/quads_struct_traits.cc
index 412c5d3..d7967fc 100644
--- a/services/viz/public/cpp/compositing/quads_struct_traits.cc
+++ b/services/viz/public/cpp/compositing/quads_struct_traits.cc
@@ -158,6 +158,7 @@
}
quad->swizzle_contents = data.swizzle_contents();
+ quad->is_premultiplied = data.is_premultiplied();
quad->nearest_neighbor = data.nearest_neighbor();
quad->force_anti_aliasing_off = data.force_anti_aliasing_off();
quad->resources.ids[viz::TileDrawQuad::kResourceIdIndex] = data.resource_id();
diff --git a/services/viz/public/cpp/compositing/quads_struct_traits.h b/services/viz/public/cpp/compositing/quads_struct_traits.h
index c7b07abc..c5fd0ec9 100644
--- a/services/viz/public/cpp/compositing/quads_struct_traits.h
+++ b/services/viz/public/cpp/compositing/quads_struct_traits.h
@@ -350,6 +350,11 @@
return quad->swizzle_contents;
}
+ static bool is_premultiplied(const viz::DrawQuad& input) {
+ const viz::TileDrawQuad* quad = viz::TileDrawQuad::MaterialCast(&input);
+ return quad->is_premultiplied;
+ }
+
static bool nearest_neighbor(const viz::DrawQuad& input) {
const viz::TileDrawQuad* quad = viz::TileDrawQuad::MaterialCast(&input);
return quad->nearest_neighbor;
diff --git a/services/viz/public/interfaces/compositing/quads.mojom b/services/viz/public/interfaces/compositing/quads.mojom
index a8b9bc1..39dcb53 100644
--- a/services/viz/public/interfaces/compositing/quads.mojom
+++ b/services/viz/public/interfaces/compositing/quads.mojom
@@ -78,6 +78,7 @@
gfx.mojom.RectF tex_coord_rect;
gfx.mojom.Size texture_size;
bool swizzle_contents;
+ bool is_premultiplied;
uint32 resource_id;
bool nearest_neighbor;
bool force_anti_aliasing_off;