1 /* 2 * Copyright 2011 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 GrDrawState_DEFINED 9 #define GrDrawState_DEFINED 10 11 #include "GrBlend.h" 12 #include "GrDrawTargetCaps.h" 13 #include "GrGpuResourceRef.h" 14 #include "GrRODrawState.h" 15 #include "effects/GrSimpleTextureEffect.h" 16 17 class GrOptDrawState; 18 19 /** 20 * Modifiable subclass derived from GrRODrawState. The majority of the data that represents a draw 21 * state is stored in the parent class. GrDrawState contains methods for setting, adding to, etc. 22 * various data members of the draw state. This class is used to configure the state used when 23 * issuing draws via GrDrawTarget. 24 */ 25 class GrDrawState : public GrRODrawState { 26 public: 27 SK_DECLARE_INST_COUNT(GrDrawState) 28 29 GrDrawState() : fCachedOptState(NULL) { 30 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;) 31 this->reset(); 32 } 33 34 GrDrawState(const SkMatrix& initialViewMatrix) : fCachedOptState(NULL) { 35 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;) 36 this->reset(initialViewMatrix); 37 } 38 39 /** 40 * Copies another draw state. 41 **/ 42 GrDrawState(const GrDrawState& state) : INHERITED(), fCachedOptState(NULL) { 43 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;) 44 *this = state; 45 } 46 47 /** 48 * Copies another draw state with a preconcat to the view matrix. 49 **/ 50 GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix); 51 52 virtual ~GrDrawState(); 53 54 /** 55 * Resets to the default state. GrProcessors will be removed from all stages. 56 */ 57 void reset() { this->onReset(NULL); } 58 59 void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); } 60 61 /** 62 * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that 63 * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint 64 * equivalents are set to default values with the exception of vertex attribute state which 65 * is unmodified by this function and clipping which will be enabled. 66 */ 67 void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*); 68 69 /////////////////////////////////////////////////////////////////////////// 70 /// @name Vertex Attributes 71 //// 72 73 /** 74 * The format of vertices is represented as an array of GrVertexAttribs, with each representing 75 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in 76 * GrTypesPriv.h). 77 * 78 * The mapping of attributes with kEffect bindings to GrProcessor inputs is specified when 79 * setEffect is called. 80 */ 81 82 /** 83 * Sets vertex attributes for next draw. The object driving the templatization 84 * should be a global GrVertexAttrib array that is never changed. 85 * 86 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt. 87 * @param stride the number of bytes between successive vertex data. 88 */ 89 template <const GrVertexAttrib A[]> void setVertexAttribs(int count, size_t stride) { 90 this->internalSetVertexAttribs(A, count, stride); 91 } 92 93 /** 94 * Sets default vertex attributes for next draw. The default is a single attribute: 95 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType} 96 */ 97 void setDefaultVertexAttribs(); 98 99 /** 100 * Helper to save/restore vertex attribs 101 */ 102 class AutoVertexAttribRestore { 103 public: 104 AutoVertexAttribRestore(GrDrawState* drawState); 105 106 ~AutoVertexAttribRestore() { fDrawState->internalSetVertexAttribs(fVAPtr, fVACount, 107 fVAStride); } 108 109 private: 110 GrDrawState* fDrawState; 111 const GrVertexAttrib* fVAPtr; 112 int fVACount; 113 size_t fVAStride; 114 }; 115 116 /// @} 117 118 /** 119 * Depending on features available in the underlying 3D API and the color blend mode requested 120 * it may or may not be possible to correctly blend with fractional pixel coverage generated by 121 * the fragment shader. 122 * 123 * This function considers the current draw state and the draw target's capabilities to 124 * determine whether coverage can be handled correctly. This function assumes that the caller 125 * intends to specify fractional pixel coverage (via setCoverage(), through a coverage vertex 126 * attribute, or a coverage effect) but may not have specified it yet. 127 */ 128 bool couldApplyCoverage(const GrDrawTargetCaps& caps) const; 129 130 /// @} 131 132 /////////////////////////////////////////////////////////////////////////// 133 /// @name Color 134 //// 135 136 /** 137 * Sets color for next draw to a premultiplied-alpha color. 138 * 139 * @param color the color to set. 140 */ 141 void setColor(GrColor color) { 142 if (color != fColor) { 143 fColor = color; 144 this->invalidateOptState(); 145 } 146 } 147 148 /** 149 * Sets the color to be used for the next draw to be 150 * (r,g,b,a) = (alpha, alpha, alpha, alpha). 151 * 152 * @param alpha The alpha value to set as the color. 153 */ 154 void setAlpha(uint8_t a) { this->setColor((a << 24) | (a << 16) | (a << 8) | a); } 155 156 /// @} 157 158 /////////////////////////////////////////////////////////////////////////// 159 /// @name Coverage 160 //// 161 162 /** 163 * Sets a constant fractional coverage to be applied to the draw. The 164 * initial value (after construction or reset()) is 0xff. The constant 165 * coverage is ignored when per-vertex coverage is provided. 166 */ 167 void setCoverage(uint8_t coverage) { 168 if (coverage != fCoverage) { 169 fCoverage = coverage; 170 this->invalidateOptState(); 171 } 172 } 173 174 /// @} 175 176 /** 177 * The geometry processor is the sole element of the skia pipeline which can use the vertex, 178 * geometry, and tesselation shaders. The GP may also compute a coverage in its fragment shader 179 * but is never put in the color processing pipeline. 180 */ 181 182 const GrGeometryProcessor* setGeometryProcessor(const GrGeometryProcessor* geometryProcessor) { 183 SkASSERT(geometryProcessor); 184 SkASSERT(!this->hasGeometryProcessor()); 185 fGeometryProcessor.reset(new GrGeometryStage(geometryProcessor)); 186 this->invalidateOptState(); 187 return geometryProcessor; 188 } 189 190 /////////////////////////////////////////////////////////////////////////// 191 /// @name Effect Stages 192 /// Each stage hosts a GrProcessor. The effect produces an output color or coverage in the 193 /// fragment shader. Its inputs are the output from the previous stage as well as some variables 194 /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color, 195 /// the fragment position, local coordinates). 196 /// 197 /// The stages are divided into two sets, color-computing and coverage-computing. The final 198 /// color stage produces the final pixel color. The coverage-computing stages function exactly 199 /// as the color-computing but the output of the final coverage stage is treated as a fractional 200 /// pixel coverage rather than as input to the src/dst color blend step. 201 /// 202 /// The input color to the first color-stage is either the constant color or interpolated 203 /// per-vertex colors. The input to the first coverage stage is either a constant coverage 204 /// (usually full-coverage) or interpolated per-vertex coverage. 205 /// 206 /// See the documentation of kCoverageDrawing_StateBit for information about disabling the 207 /// the color / coverage distinction. 208 //// 209 210 const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) { 211 SkASSERT(effect); 212 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect)); 213 this->invalidateOptState(); 214 return effect; 215 } 216 217 const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* effect) { 218 SkASSERT(effect); 219 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (effect)); 220 this->invalidateOptState(); 221 return effect; 222 } 223 224 /** 225 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates. 226 */ 227 void addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) { 228 this->addColorProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref(); 229 } 230 231 void addCoverageTextureProcessor(GrTexture* texture, const SkMatrix& matrix) { 232 this->addCoverageProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref(); 233 } 234 235 void addColorTextureProcessor(GrTexture* texture, 236 const SkMatrix& matrix, 237 const GrTextureParams& params) { 238 this->addColorProcessor(GrSimpleTextureEffect::Create(texture, matrix, params))->unref(); 239 } 240 241 void addCoverageTextureProcessor(GrTexture* texture, 242 const SkMatrix& matrix, 243 const GrTextureParams& params) { 244 this->addCoverageProcessor(GrSimpleTextureEffect::Create(texture, matrix, params))->unref(); 245 } 246 247 /** 248 * When this object is destroyed it will remove any color/coverage effects from the draw state 249 * that were added after its constructor. 250 * 251 * This class has strange behavior around geometry processor. If there is a GP on the draw state 252 * it will assert that the GP is not modified until after the destructor of the ARE. If the 253 * draw state has a NULL GP when the ARE is constructed then it will reset it to null in the 254 * destructor. 255 * 256 * TODO: We'd prefer for the ARE to just save and restore the GP. However, this would add 257 * significant complexity to the multi-ref architecture for deferred drawing. Once GrDrawState 258 * and GrOptDrawState are fully separated then GrDrawState will never be in the deferred 259 * execution state and GrOptDrawState always will be (and will be immutable and therefore 260 * unable to have an ARE). At this point we can restore sanity and have the ARE save and restore 261 * the GP. 262 */ 263 class AutoRestoreEffects : public ::SkNoncopyable { 264 public: 265 AutoRestoreEffects() 266 : fDrawState(NULL) 267 , fOriginalGPID(SK_InvalidUniqueID) 268 , fColorEffectCnt(0) 269 , fCoverageEffectCnt(0) {} 270 271 AutoRestoreEffects(GrDrawState* ds) 272 : fDrawState(NULL) 273 , fOriginalGPID(SK_InvalidUniqueID) 274 , fColorEffectCnt(0) 275 , fCoverageEffectCnt(0) { 276 this->set(ds); 277 } 278 279 ~AutoRestoreEffects() { this->set(NULL); } 280 281 void set(GrDrawState* ds); 282 283 bool isSet() const { return SkToBool(fDrawState); } 284 285 private: 286 GrDrawState* fDrawState; 287 uint32_t fOriginalGPID; 288 int fColorEffectCnt; 289 int fCoverageEffectCnt; 290 }; 291 292 /// @} 293 294 /////////////////////////////////////////////////////////////////////////// 295 /// @name Blending 296 //// 297 298 /** 299 * Sets the blending function coefficients. 300 * 301 * The blend function will be: 302 * D' = sat(S*srcCoef + D*dstCoef) 303 * 304 * where D is the existing destination color, S is the incoming source 305 * color, and D' is the new destination color that will be written. sat() 306 * is the saturation function. 307 * 308 * @param srcCoef coefficient applied to the src color. 309 * @param dstCoef coefficient applied to the dst color. 310 */ 311 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 312 if (srcCoeff != fSrcBlend || dstCoeff != fDstBlend) { 313 fSrcBlend = srcCoeff; 314 fDstBlend = dstCoeff; 315 this->invalidateOptState(); 316 } 317 #ifdef SK_DEBUG 318 if (GrBlendCoeffRefsDst(dstCoeff)) { 319 GrPrintf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n"); 320 } 321 if (GrBlendCoeffRefsSrc(srcCoeff)) { 322 GrPrintf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n"); 323 } 324 #endif 325 } 326 327 /** 328 * Sets the blending function constant referenced by the following blending 329 * coefficients: 330 * kConstC_GrBlendCoeff 331 * kIConstC_GrBlendCoeff 332 * kConstA_GrBlendCoeff 333 * kIConstA_GrBlendCoeff 334 * 335 * @param constant the constant to set 336 */ 337 void setBlendConstant(GrColor constant) { 338 if (constant != fBlendConstant) { 339 fBlendConstant = constant; 340 this->invalidateOptState(); 341 } 342 } 343 344 /// @} 345 346 /////////////////////////////////////////////////////////////////////////// 347 /// @name View Matrix 348 //// 349 350 /** 351 * Sets the view matrix to identity and updates any installed effects to compensate for the 352 * coord system change. 353 */ 354 bool setIdentityViewMatrix(); 355 356 //////////////////////////////////////////////////////////////////////////// 357 358 /** 359 * Preconcats the current view matrix and restores the previous view matrix in the destructor. 360 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor. 361 */ 362 class AutoViewMatrixRestore : public ::SkNoncopyable { 363 public: 364 AutoViewMatrixRestore() : fDrawState(NULL) {} 365 366 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) { 367 fDrawState = NULL; 368 this->set(ds, preconcatMatrix); 369 } 370 371 ~AutoViewMatrixRestore() { this->restore(); } 372 373 /** 374 * Can be called prior to destructor to restore the original matrix. 375 */ 376 void restore(); 377 378 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix); 379 380 /** Sets the draw state's matrix to identity. This can fail because the current view matrix 381 is not invertible. */ 382 bool setIdentity(GrDrawState* drawState); 383 384 private: 385 void doEffectCoordChanges(const SkMatrix& coordChangeMatrix); 386 387 GrDrawState* fDrawState; 388 SkMatrix fViewMatrix; 389 int fNumColorStages; 390 bool fHasGeometryProcessor; 391 SkAutoSTArray<8, GrProcessorStage::SavedCoordChange> fSavedCoordChanges; 392 }; 393 394 /// @} 395 396 /////////////////////////////////////////////////////////////////////////// 397 /// @name Render Target 398 //// 399 400 /** 401 * Sets the render-target used at the next drawing call 402 * 403 * @param target The render target to set. 404 */ 405 void setRenderTarget(GrRenderTarget* target) { 406 fRenderTarget.set(SkSafeRef(target), GrIORef::kWrite_IOType); 407 this->invalidateOptState(); 408 } 409 410 /// @} 411 412 /////////////////////////////////////////////////////////////////////////// 413 /// @name Stencil 414 //// 415 416 /** 417 * Sets the stencil settings to use for the next draw. 418 * Changing the clip has the side-effect of possibly zeroing 419 * out the client settable stencil bits. So multipass algorithms 420 * using stencil should not change the clip between passes. 421 * @param settings the stencil settings to use. 422 */ 423 void setStencil(const GrStencilSettings& settings) { 424 if (settings != fStencilSettings) { 425 fStencilSettings = settings; 426 this->invalidateOptState(); 427 } 428 } 429 430 /** 431 * Shortcut to disable stencil testing and ops. 432 */ 433 void disableStencil() { 434 if (!fStencilSettings.isDisabled()) { 435 fStencilSettings.setDisabled(); 436 this->invalidateOptState(); 437 } 438 } 439 440 GrStencilSettings* stencil() { return &fStencilSettings; } 441 442 /// @} 443 444 /////////////////////////////////////////////////////////////////////////// 445 /// @name State Flags 446 //// 447 448 void resetStateFlags() { 449 if (0 != fFlagBits) { 450 fFlagBits = 0; 451 this->invalidateOptState(); 452 } 453 } 454 455 /** 456 * Enable render state settings. 457 * 458 * @param stateBits bitfield of StateBits specifying the states to enable 459 */ 460 void enableState(uint32_t stateBits) { 461 if (stateBits & ~fFlagBits) { 462 fFlagBits |= stateBits; 463 this->invalidateOptState(); 464 } 465 } 466 467 /** 468 * Disable render state settings. 469 * 470 * @param stateBits bitfield of StateBits specifying the states to disable 471 */ 472 void disableState(uint32_t stateBits) { 473 if (stateBits & fFlagBits) { 474 fFlagBits &= ~(stateBits); 475 this->invalidateOptState(); 476 } 477 } 478 479 /** 480 * Enable or disable stateBits based on a boolean. 481 * 482 * @param stateBits bitfield of StateBits to enable or disable 483 * @param enable if true enable stateBits, otherwise disable 484 */ 485 void setState(uint32_t stateBits, bool enable) { 486 if (enable) { 487 this->enableState(stateBits); 488 } else { 489 this->disableState(stateBits); 490 } 491 } 492 493 /// @} 494 495 /////////////////////////////////////////////////////////////////////////// 496 /// @name Face Culling 497 //// 498 499 /** 500 * Controls whether clockwise, counterclockwise, or both faces are drawn. 501 * @param face the face(s) to draw. 502 */ 503 void setDrawFace(DrawFace face) { 504 SkASSERT(kInvalid_DrawFace != face); 505 fDrawFace = face; 506 } 507 508 /// @} 509 510 /////////////////////////////////////////////////////////////////////////// 511 /// @name Hints 512 /// Hints that when provided can enable optimizations. 513 //// 514 515 void setHint(Hints hint, bool value) { fHints = value ? (fHints | hint) : (fHints & ~hint); } 516 517 /// @} 518 519 /////////////////////////////////////////////////////////////////////////// 520 521 /** Return type for CombineIfPossible. */ 522 enum CombinedState { 523 /** The GrDrawStates cannot be combined. */ 524 kIncompatible_CombinedState, 525 /** Either draw state can be used in place of the other. */ 526 kAOrB_CombinedState, 527 /** Use the first draw state. */ 528 kA_CombinedState, 529 /** Use the second draw state. */ 530 kB_CombinedState, 531 }; 532 533 /** This function determines whether the GrDrawStates used for two draws can be combined into 534 a single GrDrawState. This is used to avoid storing redundant GrDrawStates and to determine 535 if draws can be batched. The return value indicates whether combining is possible and, if 536 so, which of the two inputs should be used. */ 537 static CombinedState CombineIfPossible(const GrDrawState& a, const GrDrawState& b, 538 const GrDrawTargetCaps& caps); 539 540 GrDrawState& operator= (const GrDrawState& that); 541 542 /** 543 * Returns a snapshot of the current optimized state. If the current drawState has a valid 544 * cached optimiezed state it will simply return a pointer to it otherwise it will create a new 545 * GrOptDrawState. In all cases the GrOptDrawState is reffed and ownership is given to the 546 * caller. 547 */ 548 GrOptDrawState* createOptState(const GrDrawTargetCaps&) const; 549 550 private: 551 void invalidateOptState() const; 552 553 void onReset(const SkMatrix* initialViewMatrix); 554 555 // Some of the auto restore objects assume that no effects are removed during their lifetime. 556 // This is used to assert that this condition holds. 557 SkDEBUGCODE(int fBlockEffectRemovalCnt;) 558 559 void internalSetVertexAttribs(const GrVertexAttrib attribs[], int count, size_t stride); 560 561 mutable GrOptDrawState* fCachedOptState; 562 mutable uint32_t fCachedCapsID; 563 564 typedef GrRODrawState INHERITED; 565 }; 566 567 #endif 568