blob: 19644163a35f6d2c5df0325deaeb13494bde2cea [file] [log] [blame]
joshualittb0a8a372014-09-23 09:50:21 -07001/*
2 * Copyright 2013 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
8#ifndef GrGeometryProcessor_DEFINED
9#define GrGeometryProcessor_DEFINED
10
Robert Phillips787fd9d2021-03-22 14:48:09 -040011#include "src/gpu/GrColor.h"
Brian Salomon48959462021-08-11 13:01:06 -040012#include "src/gpu/GrFragmentProcessor.h"
Robert Phillips787fd9d2021-03-22 14:48:09 -040013#include "src/gpu/GrProcessor.h"
Brian Salomon48959462021-08-11 13:01:06 -040014#include "src/gpu/GrShaderCaps.h"
Robert Phillips787fd9d2021-03-22 14:48:09 -040015#include "src/gpu/GrShaderVar.h"
16#include "src/gpu/GrSwizzle.h"
Brian Salomona59925f2021-09-16 09:25:47 -040017#include "src/gpu/GrUniformAggregator.h"
Brian Salomon48959462021-08-11 13:01:06 -040018#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
19#include "src/gpu/glsl/GrGLSLUniformHandler.h"
20#include "src/gpu/glsl/GrGLSLVarying.h"
Robert Phillips787fd9d2021-03-22 14:48:09 -040021
Brian Salomon48959462021-08-11 13:01:06 -040022#include <unordered_map>
23
24class GrGLSLFPFragmentBuilder;
Brian Salomon48959462021-08-11 13:01:06 -040025class GrGLSLVaryingHandler;
Robert Phillips787fd9d2021-03-22 14:48:09 -040026class GrGLSLUniformHandler;
Brian Salomon48959462021-08-11 13:01:06 -040027class GrGLSLVertexBuilder;
Robert Phillips787fd9d2021-03-22 14:48:09 -040028
joshualitt9b989322014-12-15 14:16:27 -080029/**
Robert Phillips787fd9d2021-03-22 14:48:09 -040030 * The GrGeometryProcessor represents some kind of geometric primitive. This includes the shape
31 * of the primitive and the inherent color of the primitive. The GrGeometryProcessor is
32 * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
33 * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
34 * from the GrGeometryProcessor, so the GrGeometryProcessor must be able to support this
35 * functionality.
36 *
37 * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
38 * GrGeometryProcessor. These loops run on the CPU and to determine known properties of the final
39 * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve
40 * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its
41 * getProcessorAnalysisInputs implementation. These seed values are processed by the
42 * subsequent stages of the rendering pipeline and the output is then fed back into the GrDrawOp
43 * in the applyPipelineOptimizations call, where the op can use the information to inform
44 * decisions about GrGeometryProcessor creation.
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050045 *
46 * Note that all derived classes should hide their constructors and provide a Make factory
Robert Phillips787fd9d2021-03-22 14:48:09 -040047 * function that takes an arena (except for Tesselation-specific classes). This is because
48 * geometry processors can be created in either the record-time or flush-time arenas which
49 * define their lifetimes (i.e., a DDLs life time in the first case and a single flush in
50 * the second case).
joshualitt9b989322014-12-15 14:16:27 -080051 */
Brian Salomon8c8379b2021-08-11 16:19:06 -040052class GrGeometryProcessor : public GrProcessor {
joshualitt9b989322014-12-15 14:16:27 -080053public:
Brian Salomonf95940b2021-08-09 15:56:24 -040054 /**
Brian Salomond89d4452021-08-09 16:42:36 -040055 * Every GrGeometryProcessor must be capable of creating a subclass of ProgramImpl. The
56 * ProgramImpl emits the shader code that implements the GrGeometryProcessor, is attached to the
57 * generated backend API pipeline/program and used to extract uniform data from
58 * GrGeometryProcessor instances.
Brian Salomonf95940b2021-08-09 15:56:24 -040059 */
60 class ProgramImpl;
61
Robert Phillips787fd9d2021-03-22 14:48:09 -040062 class TextureSampler;
63
64 /** Describes a vertex or instance attribute. */
65 class Attribute {
66 public:
67 constexpr Attribute() = default;
68 constexpr Attribute(const char* name,
69 GrVertexAttribType cpuType,
70 GrSLType gpuType)
71 : fName(name), fCPUType(cpuType), fGPUType(gpuType) {
72 SkASSERT(name && gpuType != kVoid_GrSLType);
73 }
74 constexpr Attribute(const Attribute&) = default;
75
76 Attribute& operator=(const Attribute&) = default;
77
78 constexpr bool isInitialized() const { return fGPUType != kVoid_GrSLType; }
79
80 constexpr const char* name() const { return fName; }
81 constexpr GrVertexAttribType cpuType() const { return fCPUType; }
82 constexpr GrSLType gpuType() const { return fGPUType; }
83
84 inline constexpr size_t size() const;
85 constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
86
87 GrShaderVar asShaderVar() const {
88 return {fName, fGPUType, GrShaderVar::TypeModifier::In};
89 }
90
91 private:
92 const char* fName = nullptr;
93 GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
94 GrSLType fGPUType = kVoid_GrSLType;
95 };
96
97 class Iter {
98 public:
99 Iter() : fCurr(nullptr), fRemaining(0) {}
100 Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {}
101 Iter& operator= (const Iter& iter) {
102 fCurr = iter.fCurr;
103 fRemaining = iter.fRemaining;
104 return *this;
105 }
106 Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
107 this->skipUninitialized();
108 }
109
110 bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
111 const Attribute& operator*() const { return *fCurr; }
112 void operator++() {
113 if (fRemaining) {
114 fRemaining--;
115 fCurr++;
116 this->skipUninitialized();
117 }
118 }
119
120 private:
121 void skipUninitialized() {
122 if (!fRemaining) {
123 fCurr = nullptr;
124 } else {
125 while (!fCurr->isInitialized()) {
126 ++fCurr;
127 }
128 }
129 }
130
131 const Attribute* fCurr;
132 int fRemaining;
133 };
134
135 class AttributeSet {
136 public:
137 Iter begin() const { return Iter(fAttributes, fCount); }
138 Iter end() const { return Iter(); }
139
140 int count() const { return fCount; }
141 size_t stride() const { return fStride; }
142
143 private:
144 friend class GrGeometryProcessor;
145
146 void init(const Attribute* attrs, int count) {
147 fAttributes = attrs;
148 fRawCount = count;
149 fCount = 0;
150 fStride = 0;
151 for (int i = 0; i < count; ++i) {
152 if (attrs[i].isInitialized()) {
153 fCount++;
154 fStride += attrs[i].sizeAlign4();
155 }
156 }
157 }
158
159 const Attribute* fAttributes = nullptr;
160 int fRawCount = 0;
161 int fCount = 0;
162 size_t fStride = 0;
163 };
164
165 GrGeometryProcessor(ClassID);
166
167 int numTextureSamplers() const { return fTextureSamplerCnt; }
168 const TextureSampler& textureSampler(int index) const;
169 int numVertexAttributes() const { return fVertexAttributes.fCount; }
170 const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
171 int numInstanceAttributes() const { return fInstanceAttributes.fCount; }
172 const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
173
174 bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); }
175 bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.fCount); }
176
177 /**
178 * A common practice is to populate the the vertex/instance's memory using an implicit array of
179 * structs. In this case, it is best to assert that:
180 * stride == sizeof(struct)
181 */
182 size_t vertexStride() const { return fVertexAttributes.fStride; }
183 size_t instanceStride() const { return fInstanceAttributes.fStride; }
184
185 bool willUseTessellationShaders() const {
186 return fShaders & (kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag);
187 }
188
Robert Phillips787fd9d2021-03-22 14:48:09 -0400189 /**
190 * Computes a key for the transforms owned by an FP based on the shader code that will be
191 * emitted by the primitive processor to implement them.
192 */
193 static uint32_t ComputeCoordTransformsKey(const GrFragmentProcessor& fp);
194
195 static constexpr int kCoordTransformKeyBits = 4;
196
197 /**
Brian Salomon13b28732021-08-06 15:33:58 -0400198 * Adds a key on the GrProcessorKeyBuilder that reflects any variety in the code that the
199 * geometry processor subclass can emit.
Robert Phillips787fd9d2021-03-22 14:48:09 -0400200 */
Brian Salomon13b28732021-08-06 15:33:58 -0400201 virtual void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
Robert Phillips787fd9d2021-03-22 14:48:09 -0400202
203 void getAttributeKey(GrProcessorKeyBuilder* b) const {
204 // Ensure that our CPU and GPU type fields fit together in a 32-bit value, and we never
205 // collide with the "uninitialized" value.
206 static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
207 static_assert(kGrSLTypeCount < (1 << 8), "");
208
209 auto add_attributes = [=](const Attribute* attrs, int attrCount) {
210 for (int i = 0; i < attrCount; ++i) {
211 const Attribute& attr = attrs[i];
212 b->appendComment(attr.isInitialized() ? attr.name() : "unusedAttr");
Brian Salomona59925f2021-09-16 09:25:47 -0400213 b->addBits(8, attr.isInitialized() ? (int)attr.cpuType() : 0xff, "attrType");
214 b->addBits(8, attr.isInitialized() ? (int)attr.gpuType() : 0xff, "attrGpuType");
Robert Phillips787fd9d2021-03-22 14:48:09 -0400215 }
216 };
217 b->add32(fVertexAttributes.fRawCount, "numVertexAttributes");
218 add_attributes(fVertexAttributes.fAttributes, fVertexAttributes.fRawCount);
219 b->add32(fInstanceAttributes.fRawCount, "numInstanceAttributes");
220 add_attributes(fInstanceAttributes.fAttributes, fInstanceAttributes.fRawCount);
221 }
222
Brian Salomonf95940b2021-08-09 15:56:24 -0400223 /**
224 * Returns a new instance of the appropriate implementation class for the given
225 * GrGeometryProcessor.
226 */
227 virtual std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const = 0;
Robert Phillips787fd9d2021-03-22 14:48:09 -0400228
joshualittb0a8a372014-09-23 09:50:21 -0700229protected:
Brian Osman2715bf52019-12-06 14:38:47 -0500230 // GPs that need to use either float or ubyte colors can just call this to get a correctly
Brian Osmanc906d252018-12-04 11:17:46 -0500231 // configured Attribute struct
232 static Attribute MakeColorAttribute(const char* name, bool wideColor) {
233 return { name,
Brian Osman2715bf52019-12-06 14:38:47 -0500234 wideColor ? kFloat4_GrVertexAttribType : kUByte4_norm_GrVertexAttribType,
Brian Osmanc906d252018-12-04 11:17:46 -0500235 kHalf4_GrSLType };
236 }
237
Robert Phillips787fd9d2021-03-22 14:48:09 -0400238 void setVertexAttributes(const Attribute* attrs, int attrCount) {
239 fVertexAttributes.init(attrs, attrCount);
240 }
241 void setInstanceAttributes(const Attribute* attrs, int attrCount) {
242 SkASSERT(attrCount >= 0);
243 fInstanceAttributes.init(attrs, attrCount);
244 }
245 void setWillUseTessellationShaders() {
246 fShaders |= kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag;
247 }
Robert Phillips787fd9d2021-03-22 14:48:09 -0400248 void setTextureSamplerCnt(int cnt) {
249 SkASSERT(cnt >= 0);
250 fTextureSamplerCnt = cnt;
251 }
252
253 /**
254 * Helper for implementing onTextureSampler(). E.g.:
255 * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
256 */
257 template <typename... Args>
258 static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
259 const Args&... samps) {
260 return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
261 }
262 inline static const TextureSampler& IthTextureSampler(int i);
263
joshualittb0a8a372014-09-23 09:50:21 -0700264private:
Brian Salomona59925f2021-09-16 09:25:47 -0400265 GrGeometryProcessor(const GrGeometryProcessor&) = delete;
266
Robert Phillips787fd9d2021-03-22 14:48:09 -0400267 virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
268
269 GrShaderFlags fShaders = kVertex_GrShaderFlag | kFragment_GrShaderFlag;
270
271 AttributeSet fVertexAttributes;
272 AttributeSet fInstanceAttributes;
273
274 int fTextureSamplerCnt = 0;
275 using INHERITED = GrProcessor;
joshualittb0a8a372014-09-23 09:50:21 -0700276};
joshualitt56995b52014-12-11 15:44:02 -0800277
Robert Phillips787fd9d2021-03-22 14:48:09 -0400278//////////////////////////////////////////////////////////////////////////////
279
Brian Salomon48959462021-08-11 13:01:06 -0400280class GrGeometryProcessor::ProgramImpl {
281public:
282 using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
283 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
284 /**
285 * Struct of optional varying that replaces the input coords and bool indicating whether the FP
286 * should take a coord param as an argument. The latter may be false if the coords are simply
287 * unused or if the GP has lifted their computation to a varying emitted by the VS.
288 */
289 struct FPCoords {GrShaderVar coordsVarying; bool hasCoordsParam;};
290 using FPCoordsMap = std::unordered_map<const GrFragmentProcessor*, FPCoords>;
291
292 virtual ~ProgramImpl() = default;
293
294 struct EmitArgs {
295 EmitArgs(GrGLSLVertexBuilder* vertBuilder,
Brian Salomon48959462021-08-11 13:01:06 -0400296 GrGLSLFPFragmentBuilder* fragBuilder,
297 GrGLSLVaryingHandler* varyingHandler,
Brian Salomona59925f2021-09-16 09:25:47 -0400298 GrUniformAggregator::ProcessorUniforms uniforms,
Brian Salomon48959462021-08-11 13:01:06 -0400299 GrGLSLUniformHandler* uniformHandler,
300 const GrShaderCaps* caps,
301 const GrGeometryProcessor& geomProc,
302 const char* outputColor,
303 const char* outputCoverage,
304 const SamplerHandle* texSamplers)
305 : fVertBuilder(vertBuilder)
Brian Salomon48959462021-08-11 13:01:06 -0400306 , fFragBuilder(fragBuilder)
307 , fVaryingHandler(varyingHandler)
Brian Salomona59925f2021-09-16 09:25:47 -0400308 , fUniforms(std::move(uniforms))
Brian Salomon48959462021-08-11 13:01:06 -0400309 , fUniformHandler(uniformHandler)
310 , fShaderCaps(caps)
311 , fGeomProc(geomProc)
312 , fOutputColor(outputColor)
313 , fOutputCoverage(outputCoverage)
314 , fTexSamplers(texSamplers) {}
315 GrGLSLVertexBuilder* fVertBuilder;
Brian Salomon48959462021-08-11 13:01:06 -0400316 GrGLSLFPFragmentBuilder* fFragBuilder;
317 GrGLSLVaryingHandler* fVaryingHandler;
Brian Salomona59925f2021-09-16 09:25:47 -0400318 GrUniformAggregator::ProcessorUniforms fUniforms;
Brian Salomon48959462021-08-11 13:01:06 -0400319 GrGLSLUniformHandler* fUniformHandler;
320 const GrShaderCaps* fShaderCaps;
321 const GrGeometryProcessor& fGeomProc;
322 const char* fOutputColor;
323 const char* fOutputCoverage;
324 const SamplerHandle* fTexSamplers;
325 };
326
327 /**
328 * Emits the code from this geometry processor into the shaders. For any FP in the pipeline that
329 * has its input coords implemented by the GP as a varying, the varying will be accessible in
330 * the returned map and should be used when the FP code is emitted.
331 **/
332 FPCoordsMap emitCode(EmitArgs&, const GrPipeline& pipeline);
333
334 /**
335 * Called after all effect emitCode() functions, to give the processor a chance to write out
336 * additional transformation code now that all uniforms have been emitted.
337 * It generates the final code for assigning transformed coordinates to the varyings recorded
338 * in the call to collectTransforms(). This must happen after FP code emission so that it has
339 * access to any uniforms the FPs registered for uniform sample matrix invocations.
340 */
341 void emitTransformCode(GrGLSLVertexBuilder* vb, GrGLSLUniformHandler* uniformHandler);
342
343 /**
344 * A ProgramImpl instance can be reused with any GrGeometryProcessor that produces the same key.
345 * This function reads data from a GrGeometryProcessor and updates any uniform variables
346 * required by the shaders created in emitCode(). The GrGeometryProcessor parameter is
347 * guaranteed to be of the same type and to have an identical processor key as the
348 * GrGeometryProcessor that created this ProgramImpl.
349 */
350 virtual void setData(const GrGLSLProgramDataManager&,
351 const GrShaderCaps&,
352 const GrGeometryProcessor&) = 0;
353
354 // We use these methods as a temporary back door to inject OpenGL tessellation code. Once
355 // tessellation is supported by SkSL we can remove these.
356 virtual SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
357 const char* versionAndExtensionDecls,
358 const GrGLSLUniformHandler&,
359 const GrShaderCaps&) const {
360 SK_ABORT("Not implemented.");
361 }
362 virtual SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
363 const char* versionAndExtensionDecls,
364 const GrGLSLUniformHandler&,
365 const GrShaderCaps&) const {
366 SK_ABORT("Not implemented.");
367 }
368
369 // GPs that use writeOutputPosition and/or writeLocalCoord must incorporate the matrix type
370 // into their key, and should use this function or one of the other related helpers.
371 static uint32_t ComputeMatrixKey(const GrShaderCaps& caps, const SkMatrix& mat) {
372 if (!caps.reducedShaderMode()) {
373 if (mat.isIdentity()) {
374 return 0b00;
375 }
376 if (mat.isScaleTranslate()) {
377 return 0b01;
378 }
379 }
380 if (!mat.hasPerspective()) {
381 return 0b10;
382 }
383 return 0b11;
384 }
385
386 static uint32_t ComputeMatrixKeys(const GrShaderCaps& shaderCaps,
387 const SkMatrix& viewMatrix,
388 const SkMatrix& localMatrix) {
389 return (ComputeMatrixKey(shaderCaps, viewMatrix) << kMatrixKeyBits) |
390 ComputeMatrixKey(shaderCaps, localMatrix);
391 }
392
393 static uint32_t AddMatrixKeys(const GrShaderCaps& shaderCaps,
394 uint32_t flags,
395 const SkMatrix& viewMatrix,
396 const SkMatrix& localMatrix) {
397 // Shifting to make room for the matrix keys shouldn't lose bits
398 SkASSERT(((flags << (2 * kMatrixKeyBits)) >> (2 * kMatrixKeyBits)) == flags);
399 return (flags << (2 * kMatrixKeyBits)) |
400 ComputeMatrixKeys(shaderCaps, viewMatrix, localMatrix);
401 }
402 static constexpr int kMatrixKeyBits = 2;
403
404protected:
405 void setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder,
406 GrGLSLUniformHandler* uniformHandler,
407 const char* outputName,
408 UniformHandle* colorUniform);
409
410 // A helper for setting the matrix on a uniform handle initialized through
411 // writeOutputPosition or writeLocalCoord. Automatically handles elided uniforms,
412 // scale+translate matrices, and state tracking (if provided state pointer is non-null).
413 static void SetTransform(const GrGLSLProgramDataManager&,
414 const GrShaderCaps&,
415 const UniformHandle& uniform,
416 const SkMatrix& matrix,
417 SkMatrix* state = nullptr);
418
419 struct GrGPArgs {
420 // Used to specify the output variable used by the GP to store its device position. It can
421 // either be a float2 or a float3 (in order to handle perspective). The subclass sets this
422 // in its onEmitCode().
423 GrShaderVar fPositionVar;
424 // Used to specify the variable storing the draw's local coordinates. It can be either a
425 // float2, float3, or void. It can only be void when no FP needs local coordinates. This
426 // variable can be an attribute or local variable, but should not itself be a varying.
427 // ProgramImpl automatically determines if this must be passed to a FS.
428 GrShaderVar fLocalCoordVar;
429 };
430
431 // Helpers for adding code to write the transformed vertex position. The first simple version
432 // just writes a variable named by 'posName' into the position output variable with the
433 // assumption that the position is 2D. The second version transforms the input position by a
434 // view matrix and the output variable is 2D or 3D depending on whether the view matrix is
435 // perspective. Both versions declare the output position variable and will set
436 // GrGPArgs::fPositionVar.
437 static void WriteOutputPosition(GrGLSLVertexBuilder*, GrGPArgs*, const char* posName);
438 static void WriteOutputPosition(GrGLSLVertexBuilder*,
439 GrGLSLUniformHandler*,
440 const GrShaderCaps&,
441 GrGPArgs*,
442 const char* posName,
443 const SkMatrix& viewMatrix,
444 UniformHandle* viewMatrixUniform);
445
446 // Helper to transform an existing variable by a given local matrix (e.g. the inverse view
447 // matrix). It will declare the transformed local coord variable and will set
448 // GrGPArgs::fLocalCoordVar.
449 static void WriteLocalCoord(GrGLSLVertexBuilder*,
450 GrGLSLUniformHandler*,
451 const GrShaderCaps&,
452 GrGPArgs*,
453 GrShaderVar localVar,
454 const SkMatrix& localMatrix,
455 UniformHandle* localMatrixUniform);
456
457private:
458 virtual void onEmitCode(EmitArgs&, GrGPArgs*) = 0;
459
460 // Iterates over the FPs beginning with the passed iter to register additional varyings and
461 // uniforms to support VS-promoted local coord evaluation for the FPs.
462 //
463 // This must happen before FP code emission so that the FPs can find the appropriate varying
464 // handles they use in place of explicit coord sampling; it is automatically called after
465 // onEmitCode() returns using the value stored in GpArgs::fLocalCoordVar and
466 // GpArgs::fPositionVar.
467 FPCoordsMap collectTransforms(GrGLSLVertexBuilder* vb,
468 GrGLSLVaryingHandler* varyingHandler,
469 GrGLSLUniformHandler* uniformHandler,
470 const GrShaderVar& localCoordsVar,
471 const GrShaderVar& positionVar,
472 const GrPipeline& pipeline);
473 struct TransformInfo {
474 // The varying that conveys the coordinates to one or more FPs in the FS.
475 GrGLSLVarying varying;
476 // The coordinate to be transformed. varying is computed from this.
477 GrShaderVar inputCoords;
478 // Used to sort so that ancestor FP varyings are initialized before descendant FP varyings.
479 int traversalOrder;
480 };
481 // Populated by collectTransforms() for use in emitTransformCode(). When we lift the computation
482 // of a FP's input coord to a varying we propagate that varying up the FP tree to the highest
483 // node that shares the same coordinates. This allows multiple FPs in a subtree to share a
484 // varying.
485 std::unordered_map<const GrFragmentProcessor*, TransformInfo> fTransformVaryingsMap;
486};
487
488///////////////////////////////////////////////////////////////////////////
489
Robert Phillips787fd9d2021-03-22 14:48:09 -0400490/**
491 * Used to capture the properties of the GrTextureProxies required/expected by a primitiveProcessor
492 * along with an associated GrSamplerState. The actual proxies used are stored in either the
493 * fixed or dynamic state arrays. TextureSamplers don't perform any coord manipulation to account
494 * for texture origin.
495 */
496class GrGeometryProcessor::TextureSampler {
497public:
498 TextureSampler() = default;
499
500 TextureSampler(GrSamplerState, const GrBackendFormat&, const GrSwizzle&);
501
502 TextureSampler(const TextureSampler&) = delete;
503 TextureSampler& operator=(const TextureSampler&) = delete;
504
505 void reset(GrSamplerState, const GrBackendFormat&, const GrSwizzle&);
506
507 const GrBackendFormat& backendFormat() const { return fBackendFormat; }
508 GrTextureType textureType() const { return fBackendFormat.textureType(); }
509
510 GrSamplerState samplerState() const { return fSamplerState; }
511 const GrSwizzle& swizzle() const { return fSwizzle; }
512
513 bool isInitialized() const { return fIsInitialized; }
514
515private:
516 GrSamplerState fSamplerState;
517 GrBackendFormat fBackendFormat;
518 GrSwizzle fSwizzle;
519 bool fIsInitialized = false;
520};
521
522const GrGeometryProcessor::TextureSampler& GrGeometryProcessor::IthTextureSampler(int i) {
523 SK_ABORT("Illegal texture sampler index");
524 static const TextureSampler kBogus;
525 return kBogus;
526}
527
528//////////////////////////////////////////////////////////////////////////////
529
530/**
531 * Returns the size of the attrib type in bytes.
532 * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build
533 * with C++11.
534 */
535static constexpr inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
536 switch (type) {
537 case kFloat_GrVertexAttribType:
538 return sizeof(float);
539 case kFloat2_GrVertexAttribType:
540 return 2 * sizeof(float);
541 case kFloat3_GrVertexAttribType:
542 return 3 * sizeof(float);
543 case kFloat4_GrVertexAttribType:
544 return 4 * sizeof(float);
545 case kHalf_GrVertexAttribType:
546 return sizeof(uint16_t);
547 case kHalf2_GrVertexAttribType:
548 return 2 * sizeof(uint16_t);
549 case kHalf4_GrVertexAttribType:
550 return 4 * sizeof(uint16_t);
551 case kInt2_GrVertexAttribType:
552 return 2 * sizeof(int32_t);
553 case kInt3_GrVertexAttribType:
554 return 3 * sizeof(int32_t);
555 case kInt4_GrVertexAttribType:
556 return 4 * sizeof(int32_t);
557 case kByte_GrVertexAttribType:
558 return 1 * sizeof(char);
559 case kByte2_GrVertexAttribType:
560 return 2 * sizeof(char);
561 case kByte4_GrVertexAttribType:
562 return 4 * sizeof(char);
563 case kUByte_GrVertexAttribType:
564 return 1 * sizeof(char);
565 case kUByte2_GrVertexAttribType:
566 return 2 * sizeof(char);
567 case kUByte4_GrVertexAttribType:
568 return 4 * sizeof(char);
569 case kUByte_norm_GrVertexAttribType:
570 return 1 * sizeof(char);
571 case kUByte4_norm_GrVertexAttribType:
572 return 4 * sizeof(char);
573 case kShort2_GrVertexAttribType:
574 return 2 * sizeof(int16_t);
575 case kShort4_GrVertexAttribType:
576 return 4 * sizeof(int16_t);
577 case kUShort2_GrVertexAttribType: // fall through
578 case kUShort2_norm_GrVertexAttribType:
579 return 2 * sizeof(uint16_t);
580 case kInt_GrVertexAttribType:
581 return sizeof(int32_t);
582 case kUint_GrVertexAttribType:
583 return sizeof(uint32_t);
584 case kUShort_norm_GrVertexAttribType:
585 return sizeof(uint16_t);
586 case kUShort4_norm_GrVertexAttribType:
587 return 4 * sizeof(uint16_t);
588 }
589 // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is
590 // unreachable and don't complain.
591#if defined(__clang__) || !defined(__GNUC__)
592 SK_ABORT("Unsupported type conversion");
593#endif
594 return 0;
595}
596
597constexpr size_t GrGeometryProcessor::Attribute::size() const {
598 return GrVertexAttribTypeSize(fCPUType);
599}
600
joshualittb0a8a372014-09-23 09:50:21 -0700601#endif