Commit 98afd4cc authored by Khushal's avatar Khushal Committed by Commit Bot

blink: Refactor ImageFrameGenerator to support multi-thread use.

Currently ImageFrameGenerator can only be used for decoding from a
single thread at a time, with the access to any decoder for this
generator protected using the same mutex. This can result in janks where
the same image is being animated by multiple compositors in the same
process, since the decode tasks from these compositors can not execute
in parallel.

In order to allow multiple threads to use different decoders backed by
the same generator, this change splits the piece in the generator which
uses the decoder into a ImageDecoderWrapper. This makes it explicit that
different decoders can be used concurrently, as long as the access is
synchronized with a mutex per decoder.

The change should be a no-op.

R=chrishtr@chromium.org

Bug: 872753
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Ib31ca739fbf858e0dc292dc9b47f9fd4a087956d
Reviewed-on: https://chromium-review.googlesource.com/1185629Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Khushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585740}
parent 5008021c
......@@ -974,6 +974,8 @@ jumbo_component("platform") {
"graphics/image_animation_policy.h",
"graphics/image_data_buffer.cc",
"graphics/image_data_buffer.h",
"graphics/image_decoder_wrapper.cc",
"graphics/image_decoder_wrapper.h",
"graphics/image_decoding_store.cc",
"graphics/image_decoding_store.h",
"graphics/image_frame_generator.cc",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_DECODER_WRAPPER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_DECODER_WRAPPER_H_
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/skia/include/core/SkSize.h"
namespace blink {
class ImageDecoderFactory;
class ImageFrameGenerator;
class SegmentReader;
class ImageDecoderWrapper {
public:
ImageDecoderWrapper(ImageFrameGenerator* generator,
SegmentReader* data,
const SkISize& scaled_size,
ImageDecoder::AlphaOption alpha_option,
ColorBehavior decoder_color_behavior,
ImageDecoder::HighBitDepthDecodingOption decoding_option,
size_t index,
const SkImageInfo& info,
void* pixels,
size_t row_bytes,
bool all_data_received);
~ImageDecoderWrapper();
// Returns true if the decode succeeded.
bool Decode(ImageDecoderFactory* factory,
size_t* frame_count,
bool* has_alpha);
// Indicates that the decode failed due to a corrupt image.
bool decode_failed() const { return decode_failed_; }
private:
bool ShouldDecodeToExternalMemory(size_t frame_count,
bool has_cached_decoder) const;
bool ShouldRemoveDecoder(bool frame_was_completely_decoded,
bool decoded_to_external_memory) const;
void PurgeAllFramesIfNecessary(ImageDecoder* decoder,
bool frame_was_completely_decoded,
size_t frame_count) const;
std::unique_ptr<ImageDecoder> CreateDecoderWithData(
ImageDecoderFactory* factory) const;
const ImageFrameGenerator* const generator_;
SegmentReader* data_;
const SkISize scaled_size_;
ImageDecoder::AlphaOption alpha_option_;
const ColorBehavior decoder_color_behavior_;
const ImageDecoder::HighBitDepthDecodingOption decoding_option_;
size_t frame_index_;
const SkImageInfo info_;
void* pixels_;
size_t row_bytes_;
bool all_data_received_;
bool decode_failed_ = false;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_DECODER_WRAPPER_H_
......@@ -128,46 +128,25 @@ class PLATFORM_EXPORT ImageFrameGenerator final
void SetHasAlpha(size_t index, bool has_alpha);
SkBitmap TryToResumeDecode(SegmentReader*,
bool all_data_received,
size_t index,
const SkISize& scaled_size,
SkBitmap::Allocator&,
ImageDecoder::AlphaOption,
ImageDecoder::HighBitDepthDecodingOption);
// This method should only be called while decode_mutex_ is locked.
// Returns a pointer to frame |index|'s ImageFrame, if available.
// Sets |used_external_allocator| to true if the the image was decoded into
// |external_allocator|'s memory.
ImageFrame* Decode(SegmentReader*,
bool all_data_received,
size_t index,
ImageDecoder**,
SkBitmap::Allocator& external_allocator,
ImageDecoder::AlphaOption,
ImageDecoder::HighBitDepthDecodingOption,
const SkISize& scaled_size,
bool& used_external_allocator);
const SkISize full_size_;
// Parameters used to create internal ImageDecoder objects.
const ColorBehavior decoder_color_behavior_;
const bool is_multi_frame_;
bool decode_failed_;
bool yuv_decoding_failed_;
size_t frame_count_;
Vector<bool> has_alpha_;
std::vector<SkISize> supported_sizes_;
std::unique_ptr<ImageDecoderFactory> image_decoder_factory_;
const std::vector<SkISize> supported_sizes_;
// Prevents multiple decode operations on the same data.
// Prevents multiple decode operations on the same data. Used in non-yuv
// decoding which supports concurrent decoding from the same generator.
Mutex decode_mutex_;
// Protect concurrent access to has_alpha_.
Mutex alpha_mutex_;
// Prevents concurrent access to all variables below.
Mutex generator_mutex_;
bool decode_failed_ = false;
bool yuv_decoding_failed_ = false;
size_t frame_count_ = 0u;
Vector<bool> has_alpha_;
std::unique_ptr<ImageDecoderFactory> image_decoder_factory_;
DISALLOW_COPY_AND_ASSIGN(ImageFrameGenerator);
};
......
......@@ -111,6 +111,8 @@ class MockImageDecoder : public ImageDecoder {
client_->MemoryAllocatorSet();
}
bool IsForTesting() const override { return true; }
private:
void DecodeSize() override {}
......
......@@ -150,6 +150,8 @@ size_t ImageDecoder::FrameCount() {
}
ImageFrame* ImageDecoder::DecodeFrameBufferAtIndex(size_t index) {
TRACE_EVENT0("blink", "ImageDecoder::DecodeFrameBufferAtIndex");
if (index >= FrameCount())
return nullptr;
ImageFrame* frame = &frame_buffer_cache_[index];
......
......@@ -333,6 +333,8 @@ class PLATFORM_EXPORT ImageDecoder {
virtual bool DecodeToYUV() { return false; }
virtual void SetImagePlanes(std::unique_ptr<ImagePlanes>) {}
virtual bool IsForTesting() const { return false; }
protected:
ImageDecoder(AlphaOption alpha_option,
HighBitDepthDecodingOption high_bit_depth_decoding_option,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment