1 /* 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 "GrGpu.h" 10 #include "gl/builders/GrGLFullProgramBuilder.h" 11 #include "gl/GrGLProcessor.h" 12 #include "gl/GrGLGeometryProcessor.h" 13 #include "GrTBackendProcessorFactory.h" 14 #include "SkColorPriv.h" 15 #include "GrGeometryProcessor.h" 16 17 /////////////////////////////////////////////////////////////////////////////// 18 class GrGLAlignedRectEffect; 19 20 // Axis Aligned special case 21 class GrAlignedRectEffect : public GrGeometryProcessor { 22 public: 23 static GrGeometryProcessor* Create() { 24 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gAlignedRectEffect, GrAlignedRectEffect, ()); 25 gAlignedRectEffect->ref(); 26 return gAlignedRectEffect; 27 } 28 29 virtual ~GrAlignedRectEffect() {} 30 31 static const char* Name() { return "AlignedRectEdge"; } 32 33 virtual void getConstantColorComponents(GrColor* color, 34 uint32_t* validFlags) const SK_OVERRIDE { 35 *validFlags = 0; 36 } 37 38 const GrShaderVar& inRect() const { return fInRect; } 39 40 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { 41 return GrTBackendGeometryProcessorFactory<GrAlignedRectEffect>::getInstance(); 42 } 43 44 class GLProcessor : public GrGLGeometryProcessor { 45 public: 46 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) 47 : INHERITED (factory) {} 48 49 virtual void emitCode(GrGLFullProgramBuilder* builder, 50 const GrGeometryProcessor& geometryProcessor, 51 const GrProcessorKey& key, 52 const char* outputColor, 53 const char* inputColor, 54 const TransformedCoordsArray&, 55 const TextureSamplerArray& samplers) SK_OVERRIDE { 56 // setup the varying for the Axis aligned rect effect 57 // xy -> interpolated offset 58 // zw -> w/2+0.5, h/2+0.5 59 const char *vsRectName, *fsRectName; 60 builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName); 61 62 const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect(); 63 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); 64 vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, inRect.c_str()); 65 66 GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 67 // TODO: compute all these offsets, spans, and scales in the VS 68 fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName); 69 fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName); 70 fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); 71 // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects 72 // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. 73 fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); 74 fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); 75 // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum 76 // value of coverage that is used. In other words it is the coverage that is 77 // used in the interior of the rect after the ramp. 78 fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); 79 fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); 80 81 // Compute the coverage for the rect's width 82 fsBuilder->codeAppendf( 83 "\tfloat coverage = scaleW*clamp((%s.z-abs(%s.x))/spanW, 0.0, 1.0);\n", fsRectName, 84 fsRectName); 85 // Compute the coverage for the rect's height and merge with the width 86 fsBuilder->codeAppendf( 87 "\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0, 1.0);\n", 88 fsRectName, fsRectName); 89 90 91 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, 92 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str()); 93 } 94 95 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} 96 97 virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {} 98 99 private: 100 typedef GrGLGeometryProcessor INHERITED; 101 }; 102 103 104 private: 105 GrAlignedRectEffect() 106 : fInRect(this->addVertexAttrib(GrShaderVar("inRect", 107 kVec4f_GrSLType, 108 GrShaderVar::kAttribute_TypeModifier))) { 109 } 110 111 const GrShaderVar& fInRect; 112 113 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; } 114 115 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 116 117 typedef GrGeometryProcessor INHERITED; 118 }; 119 120 121 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrAlignedRectEffect); 122 123 GrGeometryProcessor* GrAlignedRectEffect::TestCreate(SkRandom* random, 124 GrContext* context, 125 const GrDrawTargetCaps&, 126 GrTexture* textures[]) { 127 return GrAlignedRectEffect::Create(); 128 } 129 130 /////////////////////////////////////////////////////////////////////////////// 131 class GrGLRectEffect; 132 133 /** 134 * The output of this effect is a modulation of the input color and coverage 135 * for an arbitrarily oriented rect. The rect is specified as: 136 * Center of the rect 137 * Unit vector point down the height of the rect 138 * Half width + 0.5 139 * Half height + 0.5 140 * The center and vector are stored in a vec4 varying ("RectEdge") with the 141 * center in the xy components and the vector in the zw components. 142 * The munged width and height are stored in a vec2 varying ("WidthHeight") 143 * with the width in x and the height in y. 144 */ 145 146 class GrRectEffect : public GrGeometryProcessor { 147 public: 148 static GrGeometryProcessor* Create() { 149 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gRectEffect, GrRectEffect, ()); 150 gRectEffect->ref(); 151 return gRectEffect; 152 } 153 154 virtual ~GrRectEffect() {} 155 156 static const char* Name() { return "RectEdge"; } 157 158 virtual void getConstantColorComponents(GrColor* color, 159 uint32_t* validFlags) const SK_OVERRIDE { 160 *validFlags = 0; 161 } 162 163 const GrShaderVar& inRectEdge() const { return fInRectEdge; } 164 const GrShaderVar& inWidthHeight() const { return fInWidthHeight; } 165 166 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { 167 return GrTBackendGeometryProcessorFactory<GrRectEffect>::getInstance(); 168 } 169 170 class GLProcessor : public GrGLGeometryProcessor { 171 public: 172 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) 173 : INHERITED (factory) {} 174 175 virtual void emitCode(GrGLFullProgramBuilder* builder, 176 const GrGeometryProcessor& geometryProcessor, 177 const GrProcessorKey& key, 178 const char* outputColor, 179 const char* inputColor, 180 const TransformedCoordsArray&, 181 const TextureSamplerArray& samplers) SK_OVERRIDE { 182 // setup the varying for the center point and the unit vector 183 // that points down the height of the rect 184 const char *vsRectEdgeName, *fsRectEdgeName; 185 builder->addVarying(kVec4f_GrSLType, "RectEdge", 186 &vsRectEdgeName, &fsRectEdgeName); 187 188 const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>(); 189 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); 190 vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str()); 191 192 // setup the varying for width/2+.5 and height/2+.5 193 const char *vsWidthHeightName, *fsWidthHeightName; 194 builder->addVarying(kVec2f_GrSLType, "WidthHeight", 195 &vsWidthHeightName, &fsWidthHeightName); 196 vsBuilder->codeAppendf("%s = %s;", 197 vsWidthHeightName, 198 rectEffect.inWidthHeight().c_str()); 199 200 GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 201 // TODO: compute all these offsets, spans, and scales in the VS 202 fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName); 203 fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName); 204 fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); 205 // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects 206 // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. 207 fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); 208 fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); 209 // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum 210 // value of coverage that is used. In other words it is the coverage that is 211 // used in the interior of the rect after the ramp. 212 fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); 213 fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); 214 215 // Compute the coverage for the rect's width 216 fsBuilder->codeAppendf("\tvec2 offset = %s.xy - %s.xy;\n", 217 fsBuilder->fragmentPosition(), fsRectEdgeName); 218 fsBuilder->codeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n", 219 fsRectEdgeName, fsRectEdgeName); 220 fsBuilder->codeAppendf( 221 "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);\n", 222 fsWidthHeightName); 223 224 // Compute the coverage for the rect's height and merge with the width 225 fsBuilder->codeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n", 226 fsRectEdgeName); 227 fsBuilder->codeAppendf( 228 "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n", 229 fsWidthHeightName); 230 231 232 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, 233 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str()); 234 } 235 236 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} 237 238 virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {} 239 240 private: 241 typedef GrGLGeometryProcessor INHERITED; 242 }; 243 244 245 246 private: 247 GrRectEffect() 248 : fInRectEdge(this->addVertexAttrib(GrShaderVar("inRectEdge", 249 kVec4f_GrSLType, 250 GrShaderVar::kAttribute_TypeModifier))) 251 , fInWidthHeight(this->addVertexAttrib( 252 GrShaderVar("inWidthHeight", 253 kVec2f_GrSLType, 254 GrShaderVar::kAttribute_TypeModifier))) { 255 this->setWillReadFragmentPosition(); 256 } 257 258 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; } 259 260 const GrShaderVar& fInRectEdge; 261 const GrShaderVar& fInWidthHeight; 262 263 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 264 265 typedef GrGeometryProcessor INHERITED; 266 }; 267 268 269 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRectEffect); 270 271 GrGeometryProcessor* GrRectEffect::TestCreate(SkRandom* random, 272 GrContext* context, 273 const GrDrawTargetCaps&, 274 GrTexture* textures[]) { 275 return GrRectEffect::Create(); 276 } 277 278 /////////////////////////////////////////////////////////////////////////////// 279 280 namespace { 281 extern const GrVertexAttrib gAARectAttribs[] = { 282 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 283 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding}, 284 {kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_GrVertexAttribBinding}, 285 }; 286 287 // Should the coverage be multiplied into the color attrib or use a separate attrib. 288 enum CoverageAttribType { 289 kUseColor_CoverageAttribType, 290 kUseCoverage_CoverageAttribType, 291 }; 292 } 293 294 static CoverageAttribType set_rect_attribs(GrDrawState* drawState) { 295 if (drawState->canTweakAlphaForCoverage()) { 296 drawState->setVertexAttribs<gAARectAttribs>(2, sizeof(SkPoint) + sizeof(SkColor)); 297 return kUseColor_CoverageAttribType; 298 } else { 299 drawState->setVertexAttribs<gAARectAttribs>(3, sizeof(SkPoint) + 2 * sizeof(SkColor)); 300 return kUseCoverage_CoverageAttribType; 301 } 302 } 303 304 static void set_inset_fan(SkPoint* pts, size_t stride, 305 const SkRect& r, SkScalar dx, SkScalar dy) { 306 pts->setRectFan(r.fLeft + dx, r.fTop + dy, 307 r.fRight - dx, r.fBottom - dy, stride); 308 } 309 310 void GrAARectRenderer::reset() { 311 SkSafeSetNull(fAAFillRectIndexBuffer); 312 SkSafeSetNull(fAAMiterStrokeRectIndexBuffer); 313 SkSafeSetNull(fAABevelStrokeRectIndexBuffer); 314 } 315 316 static const uint16_t gFillAARectIdx[] = { 317 0, 1, 5, 5, 4, 0, 318 1, 2, 6, 6, 5, 1, 319 2, 3, 7, 7, 6, 2, 320 3, 0, 4, 4, 7, 3, 321 4, 5, 6, 6, 7, 4, 322 }; 323 324 static const int kIndicesPerAAFillRect = SK_ARRAY_COUNT(gFillAARectIdx); 325 static const int kVertsPerAAFillRect = 8; 326 static const int kNumAAFillRectsInIndexBuffer = 256; 327 328 GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) { 329 static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect * 330 sizeof(uint16_t) * 331 kNumAAFillRectsInIndexBuffer; 332 333 if (NULL == fAAFillRectIndexBuffer) { 334 fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false); 335 if (fAAFillRectIndexBuffer) { 336 uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->map(); 337 bool useTempData = (NULL == data); 338 if (useTempData) { 339 data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect); 340 } 341 for (int i = 0; i < kNumAAFillRectsInIndexBuffer; ++i) { 342 // Each AA filled rect is drawn with 8 vertices and 10 triangles (8 around 343 // the inner rect (for AA) and 2 for the inner rect. 344 int baseIdx = i * kIndicesPerAAFillRect; 345 uint16_t baseVert = (uint16_t)(i * kVertsPerAAFillRect); 346 for (int j = 0; j < kIndicesPerAAFillRect; ++j) { 347 data[baseIdx+j] = baseVert + gFillAARectIdx[j]; 348 } 349 } 350 if (useTempData) { 351 if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) { 352 SkFAIL("Can't get AA Fill Rect indices into buffer!"); 353 } 354 SkDELETE_ARRAY(data); 355 } else { 356 fAAFillRectIndexBuffer->unmap(); 357 } 358 } 359 } 360 361 return fAAFillRectIndexBuffer; 362 } 363 364 static const uint16_t gMiterStrokeAARectIdx[] = { 365 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, 366 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, 367 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, 368 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, 369 370 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, 371 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, 372 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4, 373 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4, 374 375 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8, 376 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8, 377 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8, 378 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8, 379 }; 380 381 /** 382 * As in miter-stroke, index = a + b, and a is the current index, b is the shift 383 * from the first index. The index layout: 384 * outer AA line: 0~3, 4~7 385 * outer edge: 8~11, 12~15 386 * inner edge: 16~19 387 * inner AA line: 20~23 388 * Following comes a bevel-stroke rect and its indices: 389 * 390 * 4 7 391 * ********************************* 392 * * ______________________________ * 393 * * / 12 15 \ * 394 * * / \ * 395 * 0 * |8 16_____________________19 11 | * 3 396 * * | | | | * 397 * * | | **************** | | * 398 * * | | * 20 23 * | | * 399 * * | | * * | | * 400 * * | | * 21 22 * | | * 401 * * | | **************** | | * 402 * * | |____________________| | * 403 * 1 * |9 17 18 10| * 2 404 * * \ / * 405 * * \13 __________________________14/ * 406 * * * 407 * ********************************** 408 * 5 6 409 */ 410 static const uint16_t gBevelStrokeAARectIdx[] = { 411 // Draw outer AA, from outer AA line to outer edge, shift is 0. 412 0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0, 413 1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0, 414 5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0, 415 6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0, 416 2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0, 417 3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0, 418 7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0, 419 4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0, 420 421 // Draw the stroke, from outer edge to inner edge, shift is 8. 422 0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8, 423 1 + 8, 5 + 8, 9 + 8, 424 5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8, 425 6 + 8, 2 + 8, 10 + 8, 426 2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8, 427 3 + 8, 7 + 8, 11 + 8, 428 7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8, 429 4 + 8, 0 + 8, 8 + 8, 430 431 // Draw the inner AA, from inner edge to inner AA line, shift is 16. 432 0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16, 433 1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16, 434 2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16, 435 3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16, 436 }; 437 438 int GrAARectRenderer::aaStrokeRectIndexCount(bool miterStroke) { 439 return miterStroke ? SK_ARRAY_COUNT(gMiterStrokeAARectIdx) : 440 SK_ARRAY_COUNT(gBevelStrokeAARectIdx); 441 } 442 443 GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke) { 444 if (miterStroke) { 445 if (NULL == fAAMiterStrokeRectIndexBuffer) { 446 fAAMiterStrokeRectIndexBuffer = 447 gpu->createIndexBuffer(sizeof(gMiterStrokeAARectIdx), false); 448 if (fAAMiterStrokeRectIndexBuffer) { 449 #ifdef SK_DEBUG 450 bool updated = 451 #endif 452 fAAMiterStrokeRectIndexBuffer->updateData(gMiterStrokeAARectIdx, 453 sizeof(gMiterStrokeAARectIdx)); 454 GR_DEBUGASSERT(updated); 455 } 456 } 457 return fAAMiterStrokeRectIndexBuffer; 458 } else { 459 if (NULL == fAABevelStrokeRectIndexBuffer) { 460 fAABevelStrokeRectIndexBuffer = 461 gpu->createIndexBuffer(sizeof(gBevelStrokeAARectIdx), false); 462 if (fAABevelStrokeRectIndexBuffer) { 463 #ifdef SK_DEBUG 464 bool updated = 465 #endif 466 fAABevelStrokeRectIndexBuffer->updateData(gBevelStrokeAARectIdx, 467 sizeof(gBevelStrokeAARectIdx)); 468 GR_DEBUGASSERT(updated); 469 } 470 } 471 return fAABevelStrokeRectIndexBuffer; 472 } 473 } 474 475 void GrAARectRenderer::geometryFillAARect(GrGpu* gpu, 476 GrDrawTarget* target, 477 const SkRect& rect, 478 const SkMatrix& combinedMatrix, 479 const SkRect& devRect) { 480 GrDrawState* drawState = target->drawState(); 481 482 GrColor color = drawState->getColor(); 483 484 CoverageAttribType covAttribType = set_rect_attribs(drawState); 485 if (kUseCoverage_CoverageAttribType == covAttribType && GrColorIsOpaque(color)) { 486 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); 487 } 488 489 GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0); 490 if (!geo.succeeded()) { 491 GrPrintf("Failed to get space for vertices!\n"); 492 return; 493 } 494 495 GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu); 496 if (NULL == indexBuffer) { 497 GrPrintf("Failed to create index buffer!\n"); 498 return; 499 } 500 501 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); 502 size_t vstride = drawState->getVertexStride(); 503 504 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); 505 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vstride); 506 507 SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); 508 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); 509 510 if (combinedMatrix.rectStaysRect()) { 511 // Temporarily #if'ed out. We don't want to pass in the devRect but 512 // right now it is computed in GrContext::apply_aa_to_rect and we don't 513 // want to throw away the work 514 #if 0 515 SkRect devRect; 516 combinedMatrix.mapRect(&devRect, rect); 517 #endif 518 519 set_inset_fan(fan0Pos, vstride, devRect, -SK_ScalarHalf, -SK_ScalarHalf); 520 set_inset_fan(fan1Pos, vstride, devRect, inset, inset); 521 } else { 522 // compute transformed (1, 0) and (0, 1) vectors 523 SkVector vec[2] = { 524 { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, 525 { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } 526 }; 527 528 vec[0].normalize(); 529 vec[0].scale(SK_ScalarHalf); 530 vec[1].normalize(); 531 vec[1].scale(SK_ScalarHalf); 532 533 // create the rotated rect 534 fan0Pos->setRectFan(rect.fLeft, rect.fTop, 535 rect.fRight, rect.fBottom, vstride); 536 combinedMatrix.mapPointsWithStride(fan0Pos, vstride, 4); 537 538 // Now create the inset points and then outset the original 539 // rotated points 540 541 // TL 542 *((SkPoint*)((intptr_t)fan1Pos + 0 * vstride)) = 543 *((SkPoint*)((intptr_t)fan0Pos + 0 * vstride)) + vec[0] + vec[1]; 544 *((SkPoint*)((intptr_t)fan0Pos + 0 * vstride)) -= vec[0] + vec[1]; 545 // BL 546 *((SkPoint*)((intptr_t)fan1Pos + 1 * vstride)) = 547 *((SkPoint*)((intptr_t)fan0Pos + 1 * vstride)) + vec[0] - vec[1]; 548 *((SkPoint*)((intptr_t)fan0Pos + 1 * vstride)) -= vec[0] - vec[1]; 549 // BR 550 *((SkPoint*)((intptr_t)fan1Pos + 2 * vstride)) = 551 *((SkPoint*)((intptr_t)fan0Pos + 2 * vstride)) - vec[0] - vec[1]; 552 *((SkPoint*)((intptr_t)fan0Pos + 2 * vstride)) += vec[0] + vec[1]; 553 // TR 554 *((SkPoint*)((intptr_t)fan1Pos + 3 * vstride)) = 555 *((SkPoint*)((intptr_t)fan0Pos + 3 * vstride)) - vec[0] + vec[1]; 556 *((SkPoint*)((intptr_t)fan0Pos + 3 * vstride)) += vec[0] - vec[1]; 557 } 558 559 // Make verts point to vertex color and then set all the color and coverage vertex attrs values. 560 verts += sizeof(SkPoint); 561 for (int i = 0; i < 4; ++i) { 562 if (kUseCoverage_CoverageAttribType == covAttribType) { 563 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; 564 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0; 565 } else { 566 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; 567 } 568 } 569 570 int scale; 571 if (inset < SK_ScalarHalf) { 572 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); 573 SkASSERT(scale >= 0 && scale <= 255); 574 } else { 575 scale = 0xff; 576 } 577 578 GrColor innerCoverage; 579 if (kUseCoverage_CoverageAttribType == covAttribType) { 580 innerCoverage = GrColorPackRGBA(scale, scale, scale, scale); 581 } else { 582 innerCoverage = (0xff == scale) ? color : SkAlphaMulQ(color, scale); 583 } 584 verts += 4 * vstride; 585 for (int i = 0; i < 4; ++i) { 586 if (kUseCoverage_CoverageAttribType == covAttribType) { 587 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; 588 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage; 589 } else { 590 *reinterpret_cast<GrColor*>(verts + i * vstride) = innerCoverage; 591 } 592 } 593 594 target->setIndexSourceToBuffer(indexBuffer); 595 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 596 kVertsPerAAFillRect, 597 kIndicesPerAAFillRect); 598 target->resetIndexSource(); 599 } 600 601 namespace { 602 603 // Rotated 604 struct RectVertex { 605 SkPoint fPos; 606 SkPoint fCenter; 607 SkPoint fDir; 608 SkPoint fWidthHeight; 609 }; 610 611 // Rotated 612 extern const GrVertexAttrib gAARectVertexAttribs[] = { 613 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, 614 { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }, 615 { kVec2f_GrVertexAttribType, 3*sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding } 616 }; 617 618 // Axis Aligned 619 struct AARectVertex { 620 SkPoint fPos; 621 SkPoint fOffset; 622 SkPoint fWidthHeight; 623 }; 624 625 // Axis Aligned 626 extern const GrVertexAttrib gAAAARectVertexAttribs[] = { 627 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, 628 { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }, 629 }; 630 631 }; 632 633 void GrAARectRenderer::shaderFillAARect(GrGpu* gpu, 634 GrDrawTarget* target, 635 const SkRect& rect, 636 const SkMatrix& combinedMatrix) { 637 GrDrawState* drawState = target->drawState(); 638 639 SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY()); 640 combinedMatrix.mapPoints(¢er, 1); 641 642 // compute transformed (0, 1) vector 643 SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] }; 644 dir.normalize(); 645 646 // compute transformed (width, 0) and (0, height) vectors 647 SkVector vec[2] = { 648 { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, 649 { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } 650 }; 651 652 SkScalar newWidth = SkScalarHalf(rect.width() * vec[0].length()) + SK_ScalarHalf; 653 SkScalar newHeight = SkScalarHalf(rect.height() * vec[1].length()) + SK_ScalarHalf; 654 drawState->setVertexAttribs<gAARectVertexAttribs>(SK_ARRAY_COUNT(gAARectVertexAttribs), 655 sizeof(RectVertex)); 656 657 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 658 if (!geo.succeeded()) { 659 GrPrintf("Failed to get space for vertices!\n"); 660 return; 661 } 662 663 RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices()); 664 665 GrGeometryProcessor* gp = GrRectEffect::Create(); 666 drawState->setGeometryProcessor(gp)->unref(); 667 668 for (int i = 0; i < 4; ++i) { 669 verts[i].fCenter = center; 670 verts[i].fDir = dir; 671 verts[i].fWidthHeight.fX = newWidth; 672 verts[i].fWidthHeight.fY = newHeight; 673 } 674 675 SkRect devRect; 676 combinedMatrix.mapRect(&devRect, rect); 677 678 SkRect devBounds = { 679 devRect.fLeft - SK_ScalarHalf, 680 devRect.fTop - SK_ScalarHalf, 681 devRect.fRight + SK_ScalarHalf, 682 devRect.fBottom + SK_ScalarHalf 683 }; 684 685 verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); 686 verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); 687 verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); 688 verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); 689 690 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); 691 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); 692 target->resetIndexSource(); 693 } 694 695 void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu, 696 GrDrawTarget* target, 697 const SkRect& rect, 698 const SkMatrix& combinedMatrix) { 699 GrDrawState* drawState = target->drawState(); 700 SkASSERT(combinedMatrix.rectStaysRect()); 701 702 drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs), 703 sizeof(AARectVertex)); 704 705 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 706 if (!geo.succeeded()) { 707 GrPrintf("Failed to get space for vertices!\n"); 708 return; 709 } 710 711 AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices()); 712 713 GrGeometryProcessor* gp = GrAlignedRectEffect::Create(); 714 drawState->setGeometryProcessor(gp)->unref(); 715 716 SkRect devRect; 717 combinedMatrix.mapRect(&devRect, rect); 718 719 SkRect devBounds = { 720 devRect.fLeft - SK_ScalarHalf, 721 devRect.fTop - SK_ScalarHalf, 722 devRect.fRight + SK_ScalarHalf, 723 devRect.fBottom + SK_ScalarHalf 724 }; 725 726 SkPoint widthHeight = { 727 SkScalarHalf(devRect.width()) + SK_ScalarHalf, 728 SkScalarHalf(devRect.height()) + SK_ScalarHalf 729 }; 730 731 verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); 732 verts[0].fOffset = SkPoint::Make(-widthHeight.fX, -widthHeight.fY); 733 verts[0].fWidthHeight = widthHeight; 734 735 verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); 736 verts[1].fOffset = SkPoint::Make(-widthHeight.fX, widthHeight.fY); 737 verts[1].fWidthHeight = widthHeight; 738 739 verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); 740 verts[2].fOffset = widthHeight; 741 verts[2].fWidthHeight = widthHeight; 742 743 verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); 744 verts[3].fOffset = SkPoint::Make(widthHeight.fX, -widthHeight.fY); 745 verts[3].fWidthHeight = widthHeight; 746 747 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); 748 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); 749 target->resetIndexSource(); 750 } 751 752 void GrAARectRenderer::strokeAARect(GrGpu* gpu, 753 GrDrawTarget* target, 754 const SkRect& rect, 755 const SkMatrix& combinedMatrix, 756 const SkRect& devRect, 757 const SkStrokeRec& stroke) { 758 SkVector devStrokeSize; 759 SkScalar width = stroke.getWidth(); 760 if (width > 0) { 761 devStrokeSize.set(width, width); 762 combinedMatrix.mapVectors(&devStrokeSize, 1); 763 devStrokeSize.setAbs(devStrokeSize); 764 } else { 765 devStrokeSize.set(SK_Scalar1, SK_Scalar1); 766 } 767 768 const SkScalar dx = devStrokeSize.fX; 769 const SkScalar dy = devStrokeSize.fY; 770 const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); 771 const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf); 772 773 // Temporarily #if'ed out. We don't want to pass in the devRect but 774 // right now it is computed in GrContext::apply_aa_to_rect and we don't 775 // want to throw away the work 776 #if 0 777 SkRect devRect; 778 combinedMatrix.mapRect(&devRect, rect); 779 #endif 780 781 SkScalar spare; 782 { 783 SkScalar w = devRect.width() - dx; 784 SkScalar h = devRect.height() - dy; 785 spare = SkTMin(w, h); 786 } 787 788 SkRect devOutside(devRect); 789 devOutside.outset(rx, ry); 790 791 bool miterStroke = true; 792 // For hairlines, make bevel and round joins appear the same as mitered ones. 793 // small miter limit means right angles show bevel... 794 if ((width > 0) && (stroke.getJoin() != SkPaint::kMiter_Join || 795 stroke.getMiter() < SK_ScalarSqrt2)) { 796 miterStroke = false; 797 } 798 799 if (spare <= 0 && miterStroke) { 800 this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside); 801 return; 802 } 803 804 SkRect devInside(devRect); 805 devInside.inset(rx, ry); 806 807 SkRect devOutsideAssist(devRect); 808 809 // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist) 810 // to draw the outer of the rect. Because there are 8 vertices on the outer 811 // edge, while vertex number of inner edge is 4, the same as miter-stroke. 812 if (!miterStroke) { 813 devOutside.inset(0, ry); 814 devOutsideAssist.outset(0, ry); 815 } 816 817 this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, miterStroke); 818 } 819 820 void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu, 821 GrDrawTarget* target, 822 const SkRect& devOutside, 823 const SkRect& devOutsideAssist, 824 const SkRect& devInside, 825 bool miterStroke) { 826 GrDrawState* drawState = target->drawState(); 827 828 CoverageAttribType covAttribType = set_rect_attribs(drawState); 829 830 GrColor color = drawState->getColor(); 831 if (kUseCoverage_CoverageAttribType == covAttribType && GrColorIsOpaque(color)) { 832 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); 833 } 834 835 int innerVertexNum = 4; 836 int outerVertexNum = miterStroke ? 4 : 8; 837 int totalVertexNum = (outerVertexNum + innerVertexNum) * 2; 838 839 GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, 0); 840 if (!geo.succeeded()) { 841 GrPrintf("Failed to get space for vertices!\n"); 842 return; 843 } 844 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu, miterStroke); 845 if (NULL == indexBuffer) { 846 GrPrintf("Failed to create index buffer!\n"); 847 return; 848 } 849 850 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); 851 size_t vstride = drawState->getVertexStride(); 852 853 // We create vertices for four nested rectangles. There are two ramps from 0 to full 854 // coverage, one on the exterior of the stroke and the other on the interior. 855 // The following pointers refer to the four rects, from outermost to innermost. 856 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); 857 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstride); 858 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vstride); 859 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride); 860 861 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX 862 // TODO: this only really works if the X & Y margins are the same all around 863 // the rect 864 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight); 865 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft); 866 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop); 867 if (miterStroke) { 868 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom); 869 } else { 870 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom); 871 } 872 SkASSERT(inset >= 0); 873 #else 874 SkScalar inset = SK_ScalarHalf; 875 #endif 876 877 if (miterStroke) { 878 // outermost 879 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); 880 // inner two 881 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); 882 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); 883 // innermost 884 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf); 885 } else { 886 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vstride); 887 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vstride); 888 // outermost 889 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); 890 set_inset_fan(fan0AssistPos, vstride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf); 891 // outer one of the inner two 892 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset); 893 set_inset_fan(fan1AssistPos, vstride, devOutsideAssist, inset, inset); 894 // inner one of the inner two 895 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset); 896 // innermost 897 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf); 898 } 899 900 // Make verts point to vertex color and then set all the color and coverage vertex attrs values. 901 // The outermost rect has 0 coverage 902 verts += sizeof(SkPoint); 903 for (int i = 0; i < outerVertexNum; ++i) { 904 if (kUseCoverage_CoverageAttribType == covAttribType) { 905 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; 906 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0; 907 } else { 908 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; 909 } 910 } 911 912 // scale is the coverage for the the inner two rects. 913 int scale; 914 if (inset < SK_ScalarHalf) { 915 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); 916 SkASSERT(scale >= 0 && scale <= 255); 917 } else { 918 scale = 0xff; 919 } 920 921 verts += outerVertexNum * vstride; 922 GrColor innerCoverage; 923 if (kUseCoverage_CoverageAttribType == covAttribType) { 924 innerCoverage = GrColorPackRGBA(scale, scale, scale, scale); 925 } else { 926 innerCoverage = (0xff == scale) ? color : SkAlphaMulQ(color, scale); 927 } 928 929 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { 930 if (kUseCoverage_CoverageAttribType == covAttribType) { 931 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; 932 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage; 933 } else { 934 *reinterpret_cast<GrColor*>(verts + i * vstride) = innerCoverage; 935 } 936 } 937 938 // The innermost rect has 0 coverage 939 verts += (outerVertexNum + innerVertexNum) * vstride; 940 for (int i = 0; i < innerVertexNum; ++i) { 941 if (kUseCoverage_CoverageAttribType == covAttribType) { 942 *reinterpret_cast<GrColor*>(verts + i * vstride) = color; 943 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0; 944 } else { 945 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0; 946 } 947 } 948 949 target->setIndexSourceToBuffer(indexBuffer); 950 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 951 totalVertexNum, aaStrokeRectIndexCount(miterStroke)); 952 } 953 954 void GrAARectRenderer::fillAANestedRects(GrGpu* gpu, 955 GrDrawTarget* target, 956 const SkRect rects[2], 957 const SkMatrix& combinedMatrix) { 958 SkASSERT(combinedMatrix.rectStaysRect()); 959 SkASSERT(!rects[1].isEmpty()); 960 961 SkRect devOutside, devOutsideAssist, devInside; 962 combinedMatrix.mapRect(&devOutside, rects[0]); 963 // can't call mapRect for devInside since it calls sort 964 combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2); 965 966 if (devInside.isEmpty()) { 967 this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside); 968 return; 969 } 970 971 this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, true); 972 } 973