blob: 1cf85f724946bb1d4a7fecf8f3f93ba117a0a1dd [file] [log] [blame]
Chris Daltonc17bf322017-10-24 10:59:03 -06001/*
2 * Copyright 2017 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#include "GrGLSLVertexGeoBuilder.h"
9
10#include "GrGLSLProgramBuilder.h"
11#include "GrGLSLVarying.h"
12#include "GrTypes.h"
13
14void GrGLSLVertexGeoBuilder::emitNormalizedSkPosition(SkString* out, const char* devPos,
15 const char* rtAdjustName,
16 GrSLType devPosType) {
17 if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
18 if (kFloat3_GrSLType == devPosType) {
19 const char* p = devPos;
20 out->appendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
21 } else {
22 SkASSERT(kFloat2_GrSLType == devPosType);
23 out->appendf("{float2 _posTmp = %s;", devPos);
24 }
25 out->appendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
26 "sk_Position = float4(_posTmp.x * %s.x + %s.y,"
27 "_posTmp.y * %s.z + %s.w, 0, 1);}",
28 rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName);
29 } else if (kFloat3_GrSLType == devPosType) {
30 out->appendf("sk_Position = float4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
31 devPos, rtAdjustName, devPos, rtAdjustName, devPos);
32 } else {
33 SkASSERT(kFloat2_GrSLType == devPosType);
34 out->appendf("sk_Position = float4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
35 devPos, rtAdjustName, rtAdjustName, devPos, rtAdjustName, rtAdjustName);
36 }
37}
38
39void GrGLSLVertexBuilder::onFinalize() {
40 // We could have the GrGeometryProcessor do this, but its just easier to have it performed
41 // here. If we ever need to set variable pointsize, then we can reinvestigate.
42 if (this->getProgramBuilder()->desc()->header().fHasPointSize) {
43 this->codeAppend("sk_PointSize = 1.0;");
44 }
45 fProgramBuilder->varyingHandler()->getVertexDecls(&this->inputs(), &this->outputs());
46}
47
48static const char* input_type_name(GrGLSLGeometryBuilder::InputType in) {
49 using InputType = GrGLSLGeometryBuilder::InputType;
50 switch (in) {
51 case InputType::kPoints: return "points";
52 case InputType::kLines: return "lines";
53 case InputType::kLinesAdjacency: return "lines_adjacency";
54 case InputType::kTriangles: return "triangles";
55 case InputType::kTrianglesAdjacency: return "triangles_adjacency";
56 }
57 SK_ABORT("invalid input type");
58 return "unknown_input";
59}
60
61static const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) {
62 using OutputType = GrGLSLGeometryBuilder::OutputType;
63 switch (out) {
64 case OutputType::kPoints: return "points";
65 case OutputType::kLineStrip: return "line_strip";
66 case OutputType::kTriangleStrip: return "triangle_strip";
67 }
68 SK_ABORT("invalid output type");
69 return "unknown_output";
70}
71
72void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
73 int numInvocations) {
74 SkASSERT(!this->isConfigured());
75 fNumInvocations = numInvocations;
76 this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier);
77 this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(),
78 kIn_InterfaceQualifier);
79 this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier);
80 this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(),
81 kOut_InterfaceQualifier);
82}
83
84void GrGLSLGeometryBuilder::emitVertex(SkString* out, const char* devPos, const char* rtAdjustName,
85 GrSLType devPosType) {
86 this->emitNormalizedSkPosition(out, devPos, rtAdjustName, devPosType);
87 out->append("EmitVertex();");
88}
89
90void GrGLSLGeometryBuilder::endPrimitive() {
91 this->codeAppend("EndPrimitive();");
92}
93
94void GrGLSLGeometryBuilder::onFinalize() {
95 SkASSERT(this->isConfigured());
96 fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
97}