| /* |
| * 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 "tests/Test.h" |
| |
| #include "src/core/SkPaintParamsKey.h" |
| #include "src/core/SkShaderCodeDictionary.h" |
| |
| #include "src/gpu/graphite/ContextPriv.h" |
| |
| namespace { |
| |
| SkPaintParamsKey create_key_with_data(SkPaintParamsKeyBuilder* builder, |
| int snippetID, |
| SkSpan<const uint8_t> dataPayload) { |
| SkDEBUGCODE(builder->checkReset()); |
| |
| builder->beginBlock(snippetID); |
| builder->addBytes(dataPayload.size(), dataPayload.data()); |
| builder->endBlock(); |
| |
| return builder->lockAsKey(); |
| } |
| |
| SkPaintParamsKey create_key_with_ptr(SkPaintParamsKeyBuilder* builder, |
| int snippetID, |
| SkSpan<const uint8_t> dataPayload, |
| void* pointerData) { |
| SkDEBUGCODE(builder->checkReset()); |
| |
| builder->beginBlock(snippetID); |
| builder->addBytes(dataPayload.size(), dataPayload.data()); |
| builder->addPointer(pointerData); |
| builder->endBlock(); |
| |
| return builder->lockAsKey(); |
| } |
| |
| SkPaintParamsKey create_key(SkPaintParamsKeyBuilder* builder, int snippetID, int size) { |
| SkASSERT(size <= 1024); |
| static constexpr uint8_t kDummyData[1024] = {}; |
| return create_key_with_data(builder, snippetID, SkSpan(kDummyData, size)); |
| } |
| |
| } // anonymous namespace |
| |
| // These are intended to be unit tests of the SkPaintParamsKeyBuilder and SkPaintParamsKey. |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyWithInvalidCodeSnippetIDTest, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite); |
| |
| // Invalid code snippet ID, key creation fails. |
| SkPaintParamsKey key = create_key(&builder, kBuiltInCodeSnippetIDCount, /*size=*/32); |
| REPORTER_ASSERT(reporter, key.isErrorKey()); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyValidBlockSizeTest, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite); |
| |
| // _Just_ on the edge of being too big |
| static const int kMaxBlockDataSize = SkPaintParamsKey::kMaxBlockSize - |
| sizeof(SkPaintParamsKey::Header); |
| static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = { |
| {"data", SkPaintParamsKey::DataPayloadType::kByte, kMaxBlockDataSize}, |
| }; |
| |
| int userSnippetID = dict->addUserDefinedSnippet("keyAlmostTooBig", kDataFields); |
| SkPaintParamsKey key = create_key(&builder, userSnippetID, kMaxBlockDataSize); |
| |
| // Key is created successfully. |
| REPORTER_ASSERT(reporter, key.sizeInBytes() == SkPaintParamsKey::kMaxBlockSize); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyTooLargeBlockSizeTest, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite); |
| |
| // Too big by one byte |
| static const int kBlockDataSize = SkPaintParamsKey::kMaxBlockSize - |
| sizeof(SkPaintParamsKey::Header) + 1; |
| static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = { |
| {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize}, |
| }; |
| |
| int userSnippetID = dict->addUserDefinedSnippet("keyTooBig", kDataFields); |
| SkPaintParamsKey key = create_key(&builder, userSnippetID, kBlockDataSize); |
| |
| // Key creation fails. |
| REPORTER_ASSERT(reporter, key.isErrorKey()); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyEqualityChecksSnippetID, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| static const int kBlockDataSize = 4; |
| static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = { |
| {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize}, |
| }; |
| |
| int userSnippetID1 = dict->addUserDefinedSnippet("key1", kDataFields); |
| int userSnippetID2 = dict->addUserDefinedSnippet("key2", kDataFields); |
| |
| SkPaintParamsKeyBuilder builderA(dict, SkBackend::kGraphite); |
| SkPaintParamsKeyBuilder builderB(dict, SkBackend::kGraphite); |
| SkPaintParamsKeyBuilder builderC(dict, SkBackend::kGraphite); |
| SkPaintParamsKey keyA = create_key(&builderA, userSnippetID1, kBlockDataSize); |
| SkPaintParamsKey keyB = create_key(&builderB, userSnippetID1, kBlockDataSize); |
| SkPaintParamsKey keyC = create_key(&builderC, userSnippetID2, kBlockDataSize); |
| |
| // Verify that keyA matches keyB, and that it does not match keyC. |
| REPORTER_ASSERT(reporter, keyA == keyB); |
| REPORTER_ASSERT(reporter, keyA != keyC); |
| REPORTER_ASSERT(reporter, !(keyA == keyC)); |
| REPORTER_ASSERT(reporter, !(keyA != keyB)); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyEqualityChecksData, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| static const int kBlockDataSize = 4; |
| static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = { |
| {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize}, |
| }; |
| |
| int userSnippetID = dict->addUserDefinedSnippet("key", kDataFields); |
| |
| static constexpr uint8_t kData [kBlockDataSize] = {1, 2, 3, 4}; |
| static constexpr uint8_t kData2[kBlockDataSize] = {1, 2, 3, 99}; |
| |
| SkPaintParamsKeyBuilder builderA(dict, SkBackend::kGraphite); |
| SkPaintParamsKeyBuilder builderB(dict, SkBackend::kGraphite); |
| SkPaintParamsKeyBuilder builderC(dict, SkBackend::kGraphite); |
| SkPaintParamsKey keyA = create_key_with_data(&builderA, userSnippetID, kData); |
| SkPaintParamsKey keyB = create_key_with_data(&builderB, userSnippetID, kData); |
| SkPaintParamsKey keyC = create_key_with_data(&builderC, userSnippetID, kData2); |
| |
| // Verify that keyA matches keyB, and that it does not match keyC. |
| REPORTER_ASSERT(reporter, keyA == keyB); |
| REPORTER_ASSERT(reporter, keyA != keyC); |
| REPORTER_ASSERT(reporter, !(keyA == keyC)); |
| REPORTER_ASSERT(reporter, !(keyA != keyB)); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyEqualityDoesNotCheckPointers, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| static const int kBlockDataSize = 4; |
| static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = { |
| {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize}, |
| {"ptrIndex", SkPaintParamsKey::DataPayloadType::kPointerIndex, 1}, |
| }; |
| |
| int userSnippetID = dict->addUserDefinedSnippet("key", SkSpan(kDataFields)); |
| |
| static constexpr uint8_t kData[kBlockDataSize] = {1, 2, 3, 4}; |
| int arbitraryData1 = 1; |
| int arbitraryData2 = 2; |
| |
| SkPaintParamsKeyBuilder builderA(dict, SkBackend::kGraphite); |
| SkPaintParamsKeyBuilder builderB(dict, SkBackend::kGraphite); |
| SkPaintParamsKeyBuilder builderC(dict, SkBackend::kGraphite); |
| SkPaintParamsKey keyA = create_key_with_ptr(&builderA, userSnippetID, SkSpan(kData), |
| &arbitraryData1); |
| SkPaintParamsKey keyB = create_key_with_ptr(&builderB, userSnippetID, SkSpan(kData), |
| &arbitraryData2); |
| SkPaintParamsKey keyC = create_key_with_ptr(&builderC, userSnippetID, SkSpan(kData), |
| nullptr); |
| |
| // Verify that keyA, keyB, and keyC all match, even though the pointer data does not. |
| REPORTER_ASSERT(reporter, keyA == keyB); |
| REPORTER_ASSERT(reporter, keyB == keyC); |
| REPORTER_ASSERT(reporter, !(keyA != keyB)); |
| REPORTER_ASSERT(reporter, !(keyB != keyC)); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyBlockReaderWorks, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| static const int kCountX = 3; |
| static const int kCountY = 2; |
| static const int kCountZ = 7; |
| static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = { |
| {"ByteX", SkPaintParamsKey::DataPayloadType::kByte, kCountX}, |
| {"Float4Y", SkPaintParamsKey::DataPayloadType::kFloat4, kCountY}, |
| {"IntZ", SkPaintParamsKey::DataPayloadType::kInt, kCountZ}, |
| }; |
| |
| int userSnippetID = dict->addUserDefinedSnippet("key", kDataFields); |
| |
| static constexpr uint8_t kDataX[kCountX] = {1, 2, 3}; |
| static constexpr SkColor4f kDataY[kCountY] = {{4, 5, 6, 7}, {8, 9, 10, 11}}; |
| static constexpr int32_t kDataZ[kCountZ] = {-1234567, 13, 14, 15, 16, 17, 7654321}; |
| |
| SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite); |
| builder.beginBlock(userSnippetID); |
| builder.addBytes(kCountX, kDataX); |
| builder.add (kCountY, kDataY); |
| builder.addInts (kCountZ, kDataZ); |
| builder.endBlock(); |
| |
| SkPaintParamsKey key = builder.lockAsKey(); |
| |
| // Verify that the block reader can extract out our data from the SkPaintParamsKey. |
| SkPaintParamsKey::BlockReader reader = key.reader(dict, /*headerOffset=*/0); |
| REPORTER_ASSERT(reporter, |
| reader.blockSize() == (sizeof(SkPaintParamsKey::Header) + |
| sizeof(kDataX) + sizeof(kDataY) + sizeof(kDataZ))); |
| |
| SkSpan<const uint8_t> readerDataX = reader.bytes(0); |
| REPORTER_ASSERT(reporter, readerDataX.size() == kCountX); |
| REPORTER_ASSERT(reporter, 0 == memcmp(readerDataX.data(), kDataX, sizeof(kDataX))); |
| |
| SkSpan<const SkColor4f> readerDataY = reader.colors(1); |
| REPORTER_ASSERT(reporter, readerDataY.size() == kCountY); |
| REPORTER_ASSERT(reporter, 0 == memcmp(readerDataY.data(), kDataY, sizeof(kDataY))); |
| |
| SkSpan<const int32_t> readerBytesZ = reader.ints(2); |
| REPORTER_ASSERT(reporter, readerBytesZ.size() == kCountZ); |
| REPORTER_ASSERT(reporter, 0 == memcmp(readerBytesZ.data(), kDataZ, sizeof(kDataZ))); |
| } |
| |
| DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyBlockReaderPointersWork, reporter, context) { |
| |
| SkShaderCodeDictionary* dict = context->priv().shaderCodeDictionary(); |
| static const int kCountX = 3; |
| static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = { |
| {"PtrIndexA", SkPaintParamsKey::DataPayloadType::kPointerIndex, 1}, |
| {"DataX", SkPaintParamsKey::DataPayloadType::kByte, kCountX}, |
| {"PtrIndexB", SkPaintParamsKey::DataPayloadType::kPointerIndex, 1}, |
| }; |
| |
| int userSnippetID = dict->addUserDefinedSnippet("key", kDataFields); |
| int arbitraryDataA = 123; |
| int arbitraryDataB = 456; |
| |
| static constexpr uint8_t kDataX[kCountX] = {1, 2, 3}; |
| SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite); |
| |
| builder.beginBlock(userSnippetID); |
| builder.addPointer(&arbitraryDataA); |
| builder.addBytes(sizeof(kDataX), kDataX); |
| builder.addPointer(&arbitraryDataB); |
| builder.endBlock(); |
| |
| SkPaintParamsKey key = builder.lockAsKey(); |
| |
| // Verify that the block reader can extract out our data from the SkPaintParamsKey. |
| SkPaintParamsKey::BlockReader reader = key.reader(dict, /*headerOffset=*/0); |
| REPORTER_ASSERT(reporter, reader.blockSize() == (sizeof(SkPaintParamsKey::Header) + |
| 1 + sizeof(kDataX) + 1)); |
| |
| const void* readerPtrA = reader.pointer(0); |
| REPORTER_ASSERT(reporter, readerPtrA == &arbitraryDataA); |
| |
| SkSpan<const uint8_t> readerDataX = reader.bytes(1); |
| REPORTER_ASSERT(reporter, readerDataX.size() == kCountX); |
| REPORTER_ASSERT(reporter, 0 == memcmp(readerDataX.data(), kDataX, sizeof(kDataX))); |
| |
| const void* readerPtrB = reader.pointer(2); |
| REPORTER_ASSERT(reporter, readerPtrB == &arbitraryDataB); |
| } |