blob: e66d8c06819ab0ba28eb4853203b40dfef71e377 [file]
/*
* Copyright 2026 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef skgpu_graphite_geom_EndCaps_DEFINED
#define skgpu_graphite_geom_EndCaps_DEFINED
#include <array>
#include <cstdint>
#include <type_traits>
#include <utility>
#include "include/private/SkLog.h"
#include "include/private/SkTArray.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/sparse_strips/SparseStripsConfig.h"
namespace skgpu::graphite {
// TODO (thomsmit): Rename "NullCaps" to "Overflow" caps for clarity
// Container holding the "EndCaps" produced by SparseStrips rendering. An EndCap stores the
// antialiased portion of the path rendering, and spans a variable non-zero number of tiles.
class EndCaps {
public:
struct EndCap {
EndCap(uint16_t x, uint16_t y, uint16_t width, int32_t alphaIndex, uint16_t texPage)
: fX(x), fY(y), fWidth(width), fTexPage(texPage), fAlphaIndex(alphaIndex)
, fPadding(0xffffffff) {}
uint16_t fX; // Top left coordinates of the EndCap.
uint16_t fY; // ``
uint16_t fWidth; // The width of the EndCap in pixels
uint16_t fTexPage; // The associated page in the EndCap's backing texture
int32_t fAlphaIndex; // The EndCap's offset into the alpha buffer.
uint32_t fPadding; // Pad to vec4 alignment
};
static_assert(sizeof(EndCap) == 16);
static_assert(std::is_trivially_copyable_v<EndCap>);
EndCaps() = default;
void addCap(uint16_t x,
uint16_t y,
uint16_t width,
int32_t alphaIndex,
uint16_t texPage) {
fCaps.push_back(EndCap(x, y, width, alphaIndex, texPage));
}
void markFirstNullCap() {
if (fFirstNullCapIndex == kInvalidIndex) {
fFirstNullCapIndex = static_cast<int32_t>(fCaps.size());
}
}
void setProxy(int slot, sk_sp<TextureProxy> proxy) {
SkASSERT(slot >= 0 && slot < SparseStripConfig::kMaxTexturePages);
fProxies[slot] = std::move(proxy);
}
const skia_private::TArray<EndCap>& caps() const { return fCaps; }
skia_private::TArray<EndCap>& caps() { return fCaps; }
const std::array<sk_sp<TextureProxy>, SparseStripConfig::kMaxTexturePages>& proxies() const {
return fProxies;
}
bool empty() const { return fCaps.empty(); }
size_t size() const { return fCaps.size(); }
bool hasNullCaps() const { return fFirstNullCapIndex != kInvalidIndex; }
int32_t firstNullCapIndex() const { return fFirstNullCapIndex; }
void setFirstNullCapIndex(int32_t index) { fFirstNullCapIndex = index; }
void clearNullCaps() { fFirstNullCapIndex = kInvalidIndex; }
int32_t drawStartIndex() const { return fDrawStartIndex; }
int32_t drawEndIndex() const {
return this->hasNullCaps() ? fFirstNullCapIndex : static_cast<int32_t>(fCaps.size());
}
void setDrawStartIndex(int32_t index) { fDrawStartIndex = index; }
void clear() {
fCaps.clear();
for (auto& proxy : fProxies) {
proxy.reset();
}
fDrawStartIndex = 0;
fFirstNullCapIndex = kInvalidIndex;
}
private:
static constexpr int32_t kInvalidIndex = -1;
skia_private::TArray<EndCap> fCaps;
std::array<sk_sp<TextureProxy>, SparseStripConfig::kMaxTexturePages> fProxies;
int32_t fDrawStartIndex = 0;
int32_t fFirstNullCapIndex = kInvalidIndex;
};
} // namespace skgpu::graphite
#endif // skgpu_graphite_geom_EndCaps_DEFINED