1 /* 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 #ifndef GrDeferredUpload_DEFINED 9 #define GrDeferredUpload_DEFINED 10 11 #include <functional> 12 #include "GrTypes.h" 13 #include "GrTypesPriv.h" 14 15 class GrTextureProxy; 16 17 /** 18 * A word about deferred uploads and tokens: Ops should usually schedule their uploads to occur at 19 * the beginning of a frame whenever possible. These are called ASAP uploads. Of course, this 20 * requires that there are no draws that have yet to be flushed that rely on the old texture 21 * contents. In that case the ASAP upload would happen prior to the draw and therefore the draw 22 * would read the new (wrong) texture data. When this read-before-write data hazard exists they 23 * should schedule an inline upload. 24 * 25 * Ops, in conjunction with helpers such as GrDrawOpAtlas, use upload tokens to know what the most 26 * recent draw was that referenced a resource (or portion of a resource). Each draw is assigned a 27 * token. A resource (or portion thereof) can be tagged with the most recent reading draw's token. 28 * The deferred uploads target provides a facility for testing whether the draw corresponding to the 29 * token has been flushed. If it has not been flushed then the op must perform an inline upload 30 * instead so that the upload occurs after the draw depending on the old contents and before the 31 * draw depending on the updated contents. When scheduling an inline upload the op provides the 32 * token of the draw that the upload must occur before. 33 */ 34 35 /** 36 * GrDeferredUploadToken is used to sequence the uploads relative to each other and to draws. 37 */ 38 class GrDeferredUploadToken { 39 public: 40 static GrDeferredUploadToken AlreadyFlushedToken() { return GrDeferredUploadToken(0); } 41 42 GrDeferredUploadToken(const GrDeferredUploadToken&) = default; 43 GrDeferredUploadToken& operator=(const GrDeferredUploadToken&) = default; 44 45 bool operator==(const GrDeferredUploadToken& that) const { 46 return fSequenceNumber == that.fSequenceNumber; 47 } 48 bool operator!=(const GrDeferredUploadToken& that) const { return !(*this == that); } 49 bool operator<(const GrDeferredUploadToken that) const { 50 return fSequenceNumber < that.fSequenceNumber; 51 } 52 bool operator<=(const GrDeferredUploadToken that) const { 53 return fSequenceNumber <= that.fSequenceNumber; 54 } 55 bool operator>(const GrDeferredUploadToken that) const { 56 return fSequenceNumber > that.fSequenceNumber; 57 } 58 bool operator>=(const GrDeferredUploadToken that) const { 59 return fSequenceNumber >= that.fSequenceNumber; 60 } 61 62 GrDeferredUploadToken& operator++() { 63 ++fSequenceNumber; 64 return *this; 65 } 66 GrDeferredUploadToken operator++(int) { 67 auto old = fSequenceNumber; 68 ++fSequenceNumber; 69 return GrDeferredUploadToken(old); 70 } 71 72 GrDeferredUploadToken next() const { return GrDeferredUploadToken(fSequenceNumber + 1); } 73 74 /** Is this token in the [start, end] inclusive interval? */ 75 bool inInterval(const GrDeferredUploadToken& start, const GrDeferredUploadToken& end) { 76 return *this >= start && *this <= end; 77 } 78 79 private: 80 GrDeferredUploadToken() = delete; 81 explicit GrDeferredUploadToken(uint64_t sequenceNumber) : fSequenceNumber(sequenceNumber) {} 82 uint64_t fSequenceNumber; 83 }; 84 85 /* 86 * The GrTokenTracker encapsulates the incrementing and distribution of tokens. 87 */ 88 class GrTokenTracker { 89 public: 90 /** Gets the token one beyond the last token that has been flushed. */ 91 GrDeferredUploadToken nextTokenToFlush() const { return fLastFlushedToken.next(); } 92 93 /** Gets the next draw token that will be issued by this target. This can be used by an op 94 to record that the next draw it issues will use a resource (e.g. texture) while preparing 95 that draw. */ 96 GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); } 97 98 private: 99 // Only these three classes get to increment the token counters 100 friend class SkInternalAtlasTextContext; 101 friend class GrOpFlushState; 102 friend class TestingUploadTarget; 103 104 /** Issues the next token for a draw. */ 105 GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; } 106 107 /** Advances the last flushed token by one. */ 108 GrDeferredUploadToken flushToken() { return ++fLastFlushedToken; } 109 110 GrDeferredUploadToken fLastIssuedToken = GrDeferredUploadToken::AlreadyFlushedToken(); 111 GrDeferredUploadToken fLastFlushedToken = GrDeferredUploadToken::AlreadyFlushedToken(); 112 }; 113 114 /** 115 * Passed to a deferred upload when it is executed, this method allows the deferred upload to 116 * actually write its pixel data into a texture. 117 */ 118 using GrDeferredTextureUploadWritePixelsFn = 119 std::function<bool(GrTextureProxy*, int left, int top, int width, int height, 120 GrColorType colorType, const void* buffer, size_t rowBytes)>; 121 122 /** 123 * A deferred texture upload is simply a std::function that takes a 124 * GrDeferredTextureUploadWritePixelsFn as a parameter. It is called when it should perform its 125 * upload as the draw/upload sequence is executed. 126 */ 127 using GrDeferredTextureUploadFn = std::function<void(GrDeferredTextureUploadWritePixelsFn&)>; 128 129 /** 130 * An interface for scheduling deferred uploads. It accepts asap and deferred inline uploads. 131 */ 132 class GrDeferredUploadTarget { 133 public: 134 virtual ~GrDeferredUploadTarget() {} 135 136 virtual const GrTokenTracker* tokenTracker() = 0; 137 138 /** Returns the token of the draw that this upload will occur before. */ 139 virtual GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) = 0; 140 141 /** Returns the token of the draw that this upload will occur before. Since ASAP uploads 142 are done first during a flush, this will be the first token since the most recent 143 flush. */ 144 virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) = 0; 145 }; 146 147 #endif 148