blob: 1dd9de3c7276d207d2620652bfb3520676d2619b [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/graphite/RasterPathAtlas.h"
#include "include/core/SkColorSpace.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/core/SkIPoint16.h"
#include "src/gpu/graphite/AtlasProvider.h"
#include "src/gpu/graphite/DrawContext.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/RasterPathUtils.h"
#include "src/gpu/graphite/RecorderPriv.h"
namespace skgpu::graphite {
static constexpr uint32_t kDefaultAtlasDim = 4096;
static constexpr uint32_t kSmallPathPlotWidth = 512;
static constexpr uint32_t kSmallPathPlotHeight = 256;
RasterPathAtlas::RasterPathAtlas(Recorder* recorder)
: PathAtlas(recorder, kDefaultAtlasDim, kDefaultAtlasDim)
, fCachedAtlasMgr(fWidth, fHeight, fWidth, fHeight, recorder->priv().caps())
, fSmallPathAtlasMgr(std::max(fWidth/2, kSmallPathPlotWidth),
std::max(fHeight/2, kSmallPathPlotHeight),
kSmallPathPlotWidth, kSmallPathPlotHeight,
recorder->priv().caps())
, fUncachedAtlasMgr(fWidth, fHeight, fWidth, fHeight, recorder->priv().caps()) {
SkASSERT(recorder);
}
void RasterPathAtlas::recordUploads(DrawContext* dc) {
fCachedAtlasMgr.recordUploads(dc, fRecorder);
fSmallPathAtlasMgr.recordUploads(dc, fRecorder);
fUncachedAtlasMgr.recordUploads(dc, fRecorder);
}
const TextureProxy* RasterPathAtlas::onAddShape(const Shape& shape,
const Transform& transform,
const SkStrokeRec& strokeRec,
skvx::half2 maskSize,
skvx::half2* outPos) {
skgpu::UniqueKey maskKey;
bool hasKey = shape.hasKey();
if (hasKey) {
constexpr int kMaxSmallPathSize = 162;
// Try to locate or add to cached DrawAtlas
const TextureProxy* proxy = nullptr;
if (maskSize.x() <= kMaxSmallPathSize && maskSize.y() <= kMaxSmallPathSize) {
proxy = fSmallPathAtlasMgr.findOrCreateEntry(fRecorder,
shape,
transform,
strokeRec,
maskSize,
outPos);
}
if (!proxy) {
proxy = fCachedAtlasMgr.findOrCreateEntry(fRecorder,
shape,
transform,
strokeRec,
maskSize,
outPos);
}
if (proxy) {
return proxy;
}
}
// try to add to uncached DrawAtlas
AtlasLocator loc;
return fUncachedAtlasMgr.addToAtlas(fRecorder,
shape,
transform,
strokeRec,
maskSize,
outPos,
&loc);
}
/////////////////////////////////////////////////////////////////////////////////////////
bool RasterPathAtlas::RasterAtlasMgr::onAddToAtlas(const Shape& shape,
const Transform& transform,
const SkStrokeRec& strokeRec,
SkIRect shapeBounds,
const AtlasLocator& locator) {
// Rasterize path to backing pixmap.
// This pixmap will be the size of the Plot that contains the given rect, not the entire atlas,
// and hence the position we render at will be relative to that Plot.
// The value of outPos is relative to the entire texture, to be used for texture coords.
SkAutoPixmapStorage dst;
SkIPoint renderPos = fDrawAtlas->prepForRender(locator, &dst);
RasterMaskHelper helper(&dst);
if (!helper.init(fDrawAtlas->plotSize())) {
return false;
}
// Offset to plot location and draw
shapeBounds.offset(renderPos.x()+kEntryPadding, renderPos.y()+kEntryPadding);
helper.drawShape(shape, transform, strokeRec, shapeBounds);
return true;
}
} // namespace skgpu::graphite