Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/excluded_files
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
../../../flutter/display_list/display_list_unittests.cc
../../../flutter/display_list/dl_color_unittests.cc
../../../flutter/display_list/dl_paint_unittests.cc
../../../flutter/display_list/dl_storage_unittests.cc
../../../flutter/display_list/dl_vertices_unittests.cc
../../../flutter/display_list/effects/dl_color_filter_unittests.cc
../../../flutter/display_list/effects/dl_color_source_unittests.cc
Expand Down
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -42525,6 +42525,8 @@ ORIGIN: ../../../flutter/display_list/dl_op_records.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_paint.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_paint.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_sampling_options.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_storage.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_storage.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_tile_mode.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_vertices.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_vertices.h + ../../../flutter/LICENSE
Expand Down Expand Up @@ -45386,6 +45388,8 @@ FILE: ../../../flutter/display_list/dl_op_records.h
FILE: ../../../flutter/display_list/dl_paint.cc
FILE: ../../../flutter/display_list/dl_paint.h
FILE: ../../../flutter/display_list/dl_sampling_options.h
FILE: ../../../flutter/display_list/dl_storage.cc
FILE: ../../../flutter/display_list/dl_storage.h
FILE: ../../../flutter/display_list/dl_tile_mode.h
FILE: ../../../flutter/display_list/dl_vertices.cc
FILE: ../../../flutter/display_list/dl_vertices.h
Expand Down
3 changes: 3 additions & 0 deletions display_list/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ source_set("display_list") {
"dl_paint.cc",
"dl_paint.h",
"dl_sampling_options.h",
"dl_storage.cc",
"dl_storage.h",
"dl_tile_mode.h",
"dl_vertices.cc",
"dl_vertices.h",
Expand Down Expand Up @@ -111,6 +113,7 @@ if (enable_unittests) {
"display_list_unittests.cc",
"dl_color_unittests.cc",
"dl_paint_unittests.cc",
"dl_storage_unittests.cc",
"dl_vertices_unittests.cc",
"effects/dl_color_filter_unittests.cc",
"effects/dl_color_source_unittests.cc",
Expand Down
123 changes: 55 additions & 68 deletions display_list/display_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ const SaveLayerOptions SaveLayerOptions::kWithAttributes =
kNoAttributes.with_renders_with_attributes();

DisplayList::DisplayList()
: byte_count_(0),
op_count_(0),
: op_count_(0),
nested_byte_count_(0),
nested_op_count_(0),
total_depth_(0),
Expand All @@ -27,25 +26,13 @@ DisplayList::DisplayList()
modifies_transparent_black_(false),
root_has_backdrop_filter_(false),
root_is_unbounded_(false),
max_root_blend_mode_(DlBlendMode::kClear) {}

// Eventually we should rework DisplayListBuilder to compute these and
// deliver the vector alongside the storage.
static std::vector<size_t> MakeOffsets(const DisplayListStorage& storage,
size_t byte_count) {
std::vector<size_t> offsets;
const uint8_t* start = storage.get();
const uint8_t* end = start + byte_count;
const uint8_t* ptr = start;
while (ptr < end) {
offsets.push_back(ptr - start);
ptr += reinterpret_cast<const DLOp*>(ptr)->size;
}
return offsets;
max_root_blend_mode_(DlBlendMode::kClear) {
FML_DCHECK(offsets_.size() == 0u);
FML_DCHECK(storage_.size() == 0u);
}

DisplayList::DisplayList(DisplayListStorage&& storage,
size_t byte_count,
std::vector<size_t>&& offsets,
uint32_t op_count,
size_t nested_byte_count,
uint32_t nested_op_count,
Expand All @@ -59,8 +46,7 @@ DisplayList::DisplayList(DisplayListStorage&& storage,
bool root_is_unbounded,
sk_sp<const DlRTree> rtree)
: storage_(std::move(storage)),
offsets_(MakeOffsets(storage_, byte_count)),
byte_count_(byte_count),
offsets_(std::move(offsets)),
op_count_(op_count),
nested_byte_count_(nested_byte_count),
nested_op_count_(nested_op_count),
Expand All @@ -73,11 +59,12 @@ DisplayList::DisplayList(DisplayListStorage&& storage,
root_has_backdrop_filter_(root_has_backdrop_filter),
root_is_unbounded_(root_is_unbounded),
max_root_blend_mode_(max_root_blend_mode),
rtree_(std::move(rtree)) {}
rtree_(std::move(rtree)) {
FML_DCHECK(storage_.capacity() == storage_.size());
}

DisplayList::~DisplayList() {
const uint8_t* ptr = storage_.get();
DisposeOps(ptr, ptr + byte_count_);
DisposeOps(storage_, offsets_);
}

uint32_t DisplayList::next_unique_id() {
Expand Down Expand Up @@ -132,7 +119,7 @@ void DisplayList::RTreeResultsToIndexVector(
return;
}
}
const uint8_t* ptr = storage_.get() + offsets_[index];
const uint8_t* ptr = storage_.base() + offsets_[index];
const DLOp* op = reinterpret_cast<const DLOp*>(ptr);
switch (GetOpCategory(op->type)) {
case DisplayListOpCategory::kAttribute:
Expand Down Expand Up @@ -193,7 +180,7 @@ void DisplayList::RTreeResultsToIndexVector(
}

void DisplayList::Dispatch(DlOpReceiver& receiver) const {
const uint8_t* base = storage_.get();
const uint8_t* base = storage_.base();
for (size_t offset : offsets_) {
DispatchOneOp(receiver, base + offset);
}
Expand All @@ -213,7 +200,7 @@ void DisplayList::Dispatch(DlOpReceiver& receiver,
Dispatch(receiver);
} else {
auto op_indices = GetCulledIndices(cull_rect);
const uint8_t* base = storage_.get();
const uint8_t* base = storage_.base();
for (DlIndex index : op_indices) {
DispatchOneOp(receiver, base + offsets_[index]);
}
Expand All @@ -240,11 +227,14 @@ void DisplayList::DispatchOneOp(DlOpReceiver& receiver,
}
}

void DisplayList::DisposeOps(const uint8_t* ptr, const uint8_t* end) {
while (ptr < end) {
auto op = reinterpret_cast<const DLOp*>(ptr);
ptr += op->size;
FML_DCHECK(ptr <= end);
void DisplayList::DisposeOps(const DisplayListStorage& storage,
const std::vector<size_t>& offsets) {
const uint8_t* base = storage.base();
if (!base) {
return;
}
for (size_t offset : offsets) {
auto op = reinterpret_cast<const DLOp*>(base + offset);
switch (op->type) {
#define DL_OP_DISPOSE(name) \
case DisplayListOpType::k##name: \
Expand Down Expand Up @@ -362,10 +352,9 @@ DisplayListOpType DisplayList::GetOpType(DlIndex index) const {
}

size_t offset = offsets_[index];
FML_DCHECK(offset < byte_count_);
auto ptr = storage_.get() + offset;
FML_DCHECK(offset < storage_.size());
auto ptr = storage_.base() + offset;
auto op = reinterpret_cast<const DLOp*>(ptr);
FML_DCHECK(ptr + op->size <= storage_.get() + byte_count_);
return op->type;
}

Expand Down Expand Up @@ -399,34 +388,32 @@ bool DisplayList::Dispatch(DlOpReceiver& receiver, DlIndex index) const {
}

size_t offset = offsets_[index];
FML_DCHECK(offset < byte_count_);
auto ptr = storage_.get() + offset;
FML_DCHECK(offset + reinterpret_cast<const DLOp*>(ptr)->size <= byte_count_);
FML_DCHECK(offset < storage_.size());
auto ptr = storage_.base() + offset;

DispatchOneOp(receiver, ptr);

return true;
}

static bool CompareOps(const uint8_t* ptrA,
const uint8_t* endA,
const uint8_t* ptrB,
const uint8_t* endB) {
static bool CompareOps(const DisplayListStorage& storageA,
const std::vector<size_t>& offsetsA,
const DisplayListStorage& storageB,
const std::vector<size_t>& offsetsB) {
const uint8_t* base_a = storageA.base();
const uint8_t* base_b = storageB.base();
// These conditions are checked by the caller...
FML_DCHECK((endA - ptrA) == (endB - ptrB));
FML_DCHECK(ptrA != ptrB);
const uint8_t* bulk_start_a = ptrA;
const uint8_t* bulk_start_b = ptrB;
while (ptrA < endA && ptrB < endB) {
auto opA = reinterpret_cast<const DLOp*>(ptrA);
auto opB = reinterpret_cast<const DLOp*>(ptrB);
if (opA->type != opB->type || opA->size != opB->size) {
FML_DCHECK(offsetsA.size() == offsetsB.size());
FML_DCHECK(base_a != base_b);
size_t bulk_start = 0u;
for (size_t i = 0; i < offsetsA.size(); i++) {
size_t offset = offsetsA[i];
FML_DCHECK(offsetsB[i] == offset);
auto opA = reinterpret_cast<const DLOp*>(base_a + offset);
auto opB = reinterpret_cast<const DLOp*>(base_b + offset);
if (opA->type != opB->type) {
return false;
}
ptrA += opA->size;
ptrB += opB->size;
FML_DCHECK(ptrA <= endA);
FML_DCHECK(ptrB <= endB);
DisplayListCompare result;
switch (opA->type) {
#define DL_OP_EQUALS(name) \
Expand All @@ -451,23 +438,23 @@ static bool CompareOps(const uint8_t* ptrA,
case DisplayListCompare::kEqual:
// Check if we have a backlog of bytes to bulk compare and then
// reset the bulk compare pointers to the address following this op
auto bulk_bytes = reinterpret_cast<const uint8_t*>(opA) - bulk_start_a;
if (bulk_bytes > 0) {
if (memcmp(bulk_start_a, bulk_start_b, bulk_bytes) != 0) {
if (bulk_start < offset) {
const uint8_t* bulk_start_a = base_a + bulk_start;
const uint8_t* bulk_start_b = base_b + bulk_start;
if (memcmp(bulk_start_a, bulk_start_b, offset - bulk_start) != 0) {
return false;
}
}
bulk_start_a = ptrA;
bulk_start_b = ptrB;
bulk_start =
i + 1 < offsetsA.size() ? offsetsA[i + 1] : storageA.size();
break;
}
}
if (ptrA != endA || ptrB != endB) {
return false;
}
if (bulk_start_a < ptrA) {
if (bulk_start < storageA.size()) {
// Perform a final bulk compare if we have remaining bytes waiting
if (memcmp(bulk_start_a, bulk_start_b, ptrA - bulk_start_a) != 0) {
const uint8_t* bulk_start_a = base_a + bulk_start;
const uint8_t* bulk_start_b = base_b + bulk_start;
if (memcmp(bulk_start_a, bulk_start_b, storageA.size() - bulk_start) != 0) {
return false;
}
}
Expand All @@ -478,15 +465,15 @@ bool DisplayList::Equals(const DisplayList* other) const {
if (this == other) {
return true;
}
if (byte_count_ != other->byte_count_ || op_count_ != other->op_count_) {
if (offsets_.size() != other->offsets_.size() ||
storage_.size() != other->storage_.size() ||
op_count_ != other->op_count_) {
return false;
}
const uint8_t* ptr = storage_.get();
const uint8_t* o_ptr = other->storage_.get();
if (ptr == o_ptr) {
if (storage_.base() == other->storage_.base()) {
return true;
}
return CompareOps(ptr, ptr + byte_count_, o_ptr, o_ptr + other->byte_count_);
return CompareOps(storage_, offsets_, other->storage_, other->offsets_);
}

} // namespace flutter
38 changes: 6 additions & 32 deletions display_list/display_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@
#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_

#include <memory>
#include <optional>

#include "flutter/display_list/dl_blend_mode.h"
#include "flutter/display_list/dl_sampling_options.h"
#include "flutter/display_list/dl_storage.h"
#include "flutter/display_list/geometry/dl_geometry_types.h"
#include "flutter/display_list/geometry/dl_rtree.h"
#include "flutter/fml/logging.h"

// The Flutter DisplayList mechanism encapsulates a persistent sequence of
// rendering operations.
Expand Down Expand Up @@ -263,28 +259,6 @@ class SaveLayerOptions {
};
};

// Manages a buffer allocated with malloc.
class DisplayListStorage {
public:
DisplayListStorage() = default;
DisplayListStorage(DisplayListStorage&&) = default;

uint8_t* get() { return ptr_.get(); }

const uint8_t* get() const { return ptr_.get(); }

void realloc(size_t count) {
ptr_.reset(static_cast<uint8_t*>(std::realloc(ptr_.release(), count)));
FML_CHECK(ptr_);
}

private:
struct FreeDeleter {
void operator()(uint8_t* p) { std::free(p); }
};
std::unique_ptr<uint8_t, FreeDeleter> ptr_;
};

using DlIndex = uint32_t;

// The base class that contains a sequence of rendering operations
Expand All @@ -304,7 +278,7 @@ class DisplayList : public SkRefCnt {
// but nested ops are only included if requested. The defaults used
// here for these accessors follow that pattern.
size_t bytes(bool nested = true) const {
return sizeof(DisplayList) + byte_count_ +
return sizeof(DisplayList) + storage_.size() +
(nested ? nested_byte_count_ : 0);
}

Expand Down Expand Up @@ -530,7 +504,7 @@ class DisplayList : public SkRefCnt {

private:
DisplayList(DisplayListStorage&& ptr,
size_t byte_count,
std::vector<size_t>&& offsets,
uint32_t op_count,
size_t nested_byte_count,
uint32_t nested_op_count,
Expand All @@ -546,13 +520,13 @@ class DisplayList : public SkRefCnt {

static uint32_t next_unique_id();

static void DisposeOps(const uint8_t* ptr, const uint8_t* end);
static void DisposeOps(const DisplayListStorage& storage,
const std::vector<size_t>& offsets);

const DisplayListStorage storage_;
const std::vector<size_t> offsets_;
const size_t byte_count_;
const uint32_t op_count_;

const uint32_t op_count_;
const size_t nested_byte_count_;
const uint32_t nested_op_count_;

Expand Down
Loading