blob: 3eca36215ac261ac4846bc5ef51b90588f6c0d83 [file] [log] [blame]
robertphillips@google.comf6747b02012-06-12 00:32:28 +00001/*
2 * Copyright 2012 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 "GrAARectRenderer.h"
9#include "GrRefCnt.h"
10#include "GrGpu.h"
11
12DEFINE_INST_COUNT(GrAARectRenderer)
13
14namespace {
15
16static GrVertexLayout aa_rect_layout(const GrDrawTarget* target,
17 bool useCoverage) {
18 GrVertexLayout layout = 0;
19 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
20 if (NULL != target->getDrawState().getTexture(s)) {
21 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
22 }
23 }
24 if (useCoverage) {
25 layout |= GrDrawTarget::kCoverage_VertexLayoutBit;
26 } else {
27 layout |= GrDrawTarget::kColor_VertexLayoutBit;
28 }
29 return layout;
30}
31
32static void setInsetFan(GrPoint* pts, size_t stride,
33 const GrRect& r, GrScalar dx, GrScalar dy) {
34 pts->setRectFan(r.fLeft + dx, r.fTop + dy,
35 r.fRight - dx, r.fBottom - dy, stride);
36}
37
38};
39
40void GrAARectRenderer::reset() {
41 GrSafeSetNull(fAAFillRectIndexBuffer);
42 GrSafeSetNull(fAAStrokeRectIndexBuffer);
43}
44
45const uint16_t GrAARectRenderer::gFillAARectIdx[] = {
46 0, 1, 5, 5, 4, 0,
47 1, 2, 6, 6, 5, 1,
48 2, 3, 7, 7, 6, 2,
49 3, 0, 4, 4, 7, 3,
50 4, 5, 6, 6, 7, 4,
51};
52
53int GrAARectRenderer::aaFillRectIndexCount() {
54 return GR_ARRAY_COUNT(gFillAARectIdx);
55}
56
57GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
58 if (NULL == fAAFillRectIndexBuffer) {
59 fAAFillRectIndexBuffer = gpu->createIndexBuffer(sizeof(gFillAARectIdx),
60 false);
61 if (NULL != fAAFillRectIndexBuffer) {
62#if GR_DEBUG
63 bool updated =
64#endif
65 fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
66 sizeof(gFillAARectIdx));
67 GR_DEBUGASSERT(updated);
68 }
69 }
70 return fAAFillRectIndexBuffer;
71}
72
73const uint16_t GrAARectRenderer::gStrokeAARectIdx[] = {
74 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
75 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
76 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
77 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
78
79 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
80 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
81 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
82 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
83
84 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
85 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
86 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
87 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
88};
89
90int GrAARectRenderer::aaStrokeRectIndexCount() {
91 return GR_ARRAY_COUNT(gStrokeAARectIdx);
92}
93
94GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu) {
95 if (NULL == fAAStrokeRectIndexBuffer) {
96 fAAStrokeRectIndexBuffer =
97 gpu->createIndexBuffer(sizeof(gStrokeAARectIdx), false);
98 if (NULL != fAAStrokeRectIndexBuffer) {
99#if GR_DEBUG
100 bool updated =
101#endif
102 fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
103 sizeof(gStrokeAARectIdx));
104 GR_DEBUGASSERT(updated);
105 }
106 }
107 return fAAStrokeRectIndexBuffer;
108}
109
110void GrAARectRenderer::fillAARect(GrGpu* gpu,
111 GrDrawTarget* target,
112 const GrRect& devRect,
113 bool useVertexCoverage) {
114 GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
115
116 size_t vsize = GrDrawTarget::VertexSize(layout);
117
118 GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
119 if (!geo.succeeded()) {
120 GrPrintf("Failed to get space for vertices!\n");
121 return;
122 }
123 GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu);
124 if (NULL == indexBuffer) {
125 GrPrintf("Failed to create index buffer!\n");
126 return;
127 }
128
129 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
130
131 GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
132 GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
133
134 setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
135 setInsetFan(fan1Pos, vsize, devRect, GR_ScalarHalf, GR_ScalarHalf);
136
137 verts += sizeof(GrPoint);
138 for (int i = 0; i < 4; ++i) {
139 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
140 }
141
142 GrColor innerColor;
143 if (useVertexCoverage) {
144 innerColor = 0xffffffff;
145 } else {
146 innerColor = target->getDrawState().getColor();
147 }
148
149 verts += 4 * vsize;
150 for (int i = 0; i < 4; ++i) {
151 *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
152 }
153
154 target->setIndexSourceToBuffer(indexBuffer);
155
156 target->drawIndexed(kTriangles_GrPrimitiveType, 0,
157 0, 8, this->aaFillRectIndexCount());
158}
159
160void GrAARectRenderer::strokeAARect(GrGpu* gpu,
161 GrDrawTarget* target,
162 const GrRect& devRect,
163 const GrVec& devStrokeSize,
164 bool useVertexCoverage) {
165 const GrScalar& dx = devStrokeSize.fX;
166 const GrScalar& dy = devStrokeSize.fY;
167 const GrScalar rx = GrMul(dx, GR_ScalarHalf);
168 const GrScalar ry = GrMul(dy, GR_ScalarHalf);
169
170 GrScalar spare;
171 {
172 GrScalar w = devRect.width() - dx;
173 GrScalar h = devRect.height() - dy;
174 spare = GrMin(w, h);
175 }
176
177 if (spare <= 0) {
178 GrRect r(devRect);
179 r.inset(-rx, -ry);
180 this->fillAARect(gpu, target, r, useVertexCoverage);
181 return;
182 }
183 GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
184 size_t vsize = GrDrawTarget::VertexSize(layout);
185
186 GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
187 if (!geo.succeeded()) {
188 GrPrintf("Failed to get space for vertices!\n");
189 return;
190 }
191 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu);
192 if (NULL == indexBuffer) {
193 GrPrintf("Failed to create index buffer!\n");
194 return;
195 }
196
197 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
198
199 GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
200 GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
201 GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
202 GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
203
204 setInsetFan(fan0Pos, vsize, devRect,
205 -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
206 setInsetFan(fan1Pos, vsize, devRect,
207 -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
208 setInsetFan(fan2Pos, vsize, devRect,
209 rx - GR_ScalarHalf, ry - GR_ScalarHalf);
210 setInsetFan(fan3Pos, vsize, devRect,
211 rx + GR_ScalarHalf, ry + GR_ScalarHalf);
212
213 verts += sizeof(GrPoint);
214 for (int i = 0; i < 4; ++i) {
215 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
216 }
217
218 GrColor innerColor;
219 if (useVertexCoverage) {
220 innerColor = 0xffffffff;
221 } else {
222 innerColor = target->getDrawState().getColor();
223 }
224 verts += 4 * vsize;
225 for (int i = 0; i < 8; ++i) {
226 *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
227 }
228
229 verts += 8 * vsize;
230 for (int i = 0; i < 8; ++i) {
231 *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
232 }
233
234 target->setIndexSourceToBuffer(indexBuffer);
235 target->drawIndexed(kTriangles_GrPrimitiveType,
236 0, 0, 16, aaStrokeRectIndexCount());
237}