* Copyright 2022 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/tessellate/FixedCountBufferUtils.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkPoint_impl.h"
#include "include/private/base/SkTArray.h"
#include "src/base/SkMathPriv.h"
#include "src/gpu/BufferWriter.h"
#include <array>
#include <utility>
using namespace skia_private;
namespace skgpu::tess {
namespace {
void write_curve_index_buffer_base_index(VertexWriter vertexWriter,
size_t bufferSize,
uint16_t baseIndex) {
int triangleCount = bufferSize / (sizeof(uint16_t) * 3);
SkASSERT(triangleCount >= 1);
TArray<std::array<uint16_t, 3>> indexData(triangleCount);
const auto* neighborInLastResolveLevel = &indexData.push_back({baseIndex,
(uint16_t)(baseIndex + 2),
(uint16_t)(baseIndex + 1)});
int maxResolveLevel = SkPrevLog2(triangleCount + 1);
uint16_t nextIndex = baseIndex + 3;
SkASSERT(NumCurveTrianglesAtResolveLevel(maxResolveLevel) == triangleCount);
for (int resolveLevel = 2; resolveLevel <= maxResolveLevel; ++resolveLevel) {
SkDEBUGCODE(auto* firstTriangleInCurrentResolveLevel = indexData.end());
int numOuterTrianglelsInResolveLevel = 1 << (resolveLevel - 1);
SkASSERT(numOuterTrianglelsInResolveLevel % 2 == 0);
int numTrianglePairsInResolveLevel = numOuterTrianglelsInResolveLevel >> 1;
for (int i = 0; i < numTrianglePairsInResolveLevel; ++i) {
indexData.push_back({(*neighborInLastResolveLevel)[0],
nextIndex++,
(*neighborInLastResolveLevel)[1]});
indexData.push_back({(*neighborInLastResolveLevel)[1],
nextIndex++,
(*neighborInLastResolveLevel)[2]});
++neighborInLastResolveLevel;
}
SkASSERT(neighborInLastResolveLevel == firstTriangleInCurrentResolveLevel);
}
SkASSERT(indexData.size() == triangleCount);
SkASSERT(nextIndex == baseIndex + triangleCount + 2);
vertexWriter << VertexWriter::Array(indexData.data(), indexData.size());
}
}
void FixedCountCurves::WriteVertexBuffer(VertexWriter vertexWriter, size_t bufferSize) {
SkASSERT(bufferSize >= sizeof(SkPoint) * 2);
int vertexCount = bufferSize / sizeof(SkPoint);
SkASSERT(vertexCount > 3);
SkDEBUGCODE(auto end = vertexWriter.mark(vertexCount * sizeof(SkPoint));)
vertexWriter << (float)0 << (float)0;
vertexWriter << (float)0 << (float)1;
int maxResolveLevel = SkPrevLog2(vertexCount - 1);
SkASSERT((1 << maxResolveLevel) + 1 == vertexCount);
for (int resolveLevel = 1; resolveLevel <= maxResolveLevel; ++resolveLevel) {
int numSegmentsInResolveLevel = 1 << resolveLevel;
for (int i = 1; i < numSegmentsInResolveLevel; i += 2) {
vertexWriter << (float)resolveLevel << (float)i;
}
}
SkASSERT(vertexWriter.mark() == end);
}
void FixedCountCurves::WriteIndexBuffer(VertexWriter vertexWriter, size_t bufferSize) {
write_curve_index_buffer_base_index(std::move(vertexWriter), bufferSize, 0);
}
void FixedCountWedges::WriteVertexBuffer(VertexWriter vertexWriter, size_t bufferSize) {
SkASSERT(bufferSize >= sizeof(SkPoint));
vertexWriter << -1.f << -1.f;
FixedCountCurves::WriteVertexBuffer(std::move(vertexWriter), bufferSize - sizeof(SkPoint));
}
void FixedCountWedges::WriteIndexBuffer(VertexWriter vertexWriter, size_t bufferSize) {
SkASSERT(bufferSize >= sizeof(uint16_t) * 3);
vertexWriter << (uint16_t)0 << (uint16_t)1 << (uint16_t)2;
write_curve_index_buffer_base_index(std::move(vertexWriter),
bufferSize - sizeof(uint16_t) * 3,
1);
}
void FixedCountStrokes::WriteVertexBuffer(VertexWriter vertexWriter, size_t bufferSize) {
int edgeCount = bufferSize / (sizeof(float) * 2);
for (int i = 0; i < edgeCount; ++i) {
vertexWriter << (float)i << (float)-i;
}
}
}