SkRTShader.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Copyright 2019 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/core/SkData.h"
  8. #include "src/shaders/SkRTShader.h"
  9. #include "src/core/SkArenaAlloc.h"
  10. #include "src/core/SkRasterPipeline.h"
  11. #include "src/core/SkReadBuffer.h"
  12. #include "src/core/SkWriteBuffer.h"
  13. #include "src/sksl/SkSLByteCode.h"
  14. #include "src/sksl/SkSLCompiler.h"
  15. #if SK_SUPPORT_GPU
  16. #include "include/private/GrRecordingContext.h"
  17. #include "src/gpu/GrCaps.h"
  18. #include "src/gpu/GrColorSpaceInfo.h"
  19. #include "src/gpu/GrRecordingContextPriv.h"
  20. #include "src/gpu/SkGr.h"
  21. #include "src/gpu/GrFragmentProcessor.h"
  22. #include "src/gpu/effects/generated/GrMixerEffect.h"
  23. #include "src/gpu/effects/GrSkSLFP.h"
  24. static inline uint32_t new_sksl_unique_id() {
  25. return GrSkSLFP::NewIndex();
  26. }
  27. #else
  28. static inline uint32_t new_sksl_unique_id() {
  29. return 0; // not used w/o GPU
  30. }
  31. #endif
  32. SkRTShader::SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
  33. bool isOpaque)
  34. : SkShaderBase(localMatrix)
  35. , fSkSL(std::move(sksl))
  36. , fInputs(std::move(inputs))
  37. , fUniqueID(new_sksl_unique_id())
  38. , fIsOpaque(isOpaque)
  39. {}
  40. bool SkRTShader::onAppendStages(const SkStageRec& rec) const {
  41. auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
  42. ctx->paintColor = rec.fPaint.getColor4f();
  43. ctx->inputs = fInputs->data();
  44. ctx->ninputs = fInputs->size() / 4;
  45. ctx->shaderConvention = true;
  46. SkAutoMutexExclusive ama(fByteCodeMutex);
  47. if (!fByteCode) {
  48. SkSL::Compiler c;
  49. auto prog = c.convertProgram(SkSL::Program::kGeneric_Kind,
  50. SkSL::String(fSkSL.c_str()),
  51. SkSL::Program::Settings());
  52. if (c.errorCount()) {
  53. SkDebugf("%s\n", c.errorText().c_str());
  54. return false;
  55. }
  56. fByteCode = c.toByteCode(*prog);
  57. if (c.errorCount()) {
  58. SkDebugf("%s\n", c.errorText().c_str());
  59. return false;
  60. }
  61. SkASSERT(fByteCode);
  62. if (!fByteCode->getFunction("main")) {
  63. return false;
  64. }
  65. }
  66. ctx->byteCode = fByteCode.get();
  67. ctx->fn = ctx->byteCode->getFunction("main");
  68. rec.fPipeline->append(SkRasterPipeline::seed_shader);
  69. rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
  70. return true;
  71. }
  72. enum Flags {
  73. kIsOpaque_Flag = 1 << 0,
  74. kHasLocalMatrix_Flag = 1 << 1,
  75. };
  76. void SkRTShader::flatten(SkWriteBuffer& buffer) const {
  77. uint32_t flags = 0;
  78. if (fIsOpaque) {
  79. flags |= kIsOpaque_Flag;
  80. }
  81. if (!this->getLocalMatrix().isIdentity()) {
  82. flags |= kHasLocalMatrix_Flag;
  83. }
  84. buffer.writeString(fSkSL.c_str());
  85. if (fInputs) {
  86. buffer.writeDataAsByteArray(fInputs.get());
  87. } else {
  88. buffer.writeByteArray(nullptr, 0);
  89. }
  90. buffer.write32(flags);
  91. if (flags & kHasLocalMatrix_Flag) {
  92. buffer.writeMatrix(this->getLocalMatrix());
  93. }
  94. }
  95. sk_sp<SkFlattenable> SkRTShader::CreateProc(SkReadBuffer& buffer) {
  96. SkString sksl;
  97. buffer.readString(&sksl);
  98. sk_sp<SkData> inputs = buffer.readByteArrayAsData();
  99. uint32_t flags = buffer.read32();
  100. bool isOpaque = SkToBool(flags & kIsOpaque_Flag);
  101. SkMatrix localM, *localMPtr = nullptr;
  102. if (flags & kHasLocalMatrix_Flag) {
  103. buffer.readMatrix(&localM);
  104. localMPtr = &localM;
  105. }
  106. return sk_sp<SkFlattenable>(new SkRTShader(std::move(sksl), std::move(inputs),
  107. localMPtr, isOpaque));
  108. }
  109. sk_sp<SkShader> SkRuntimeShaderMaker(SkString sksl, sk_sp<SkData> inputs,
  110. const SkMatrix* localMatrix, bool isOpaque) {
  111. return sk_sp<SkShader>(new SkRTShader(std::move(sksl), std::move(inputs),
  112. localMatrix, isOpaque));
  113. }
  114. #if SK_SUPPORT_GPU
  115. std::unique_ptr<GrFragmentProcessor> SkRTShader::asFragmentProcessor(const GrFPArgs& args) const {
  116. return GrSkSLFP::Make(args.fContext, fUniqueID, "runtime-shader", fSkSL,
  117. fInputs->data(), fInputs->size());
  118. }
  119. #endif