OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrInOrderDrawBuffer.h" | 8 #include "GrInOrderDrawBuffer.h" |
9 | 9 |
10 #include "GrBufferAllocPool.h" | 10 #include "GrBufferAllocPool.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 for (int i = 1; i < vertexCount; ++i) { | 71 for (int i = 1; i < vertexCount; ++i) { |
72 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + v
ertexSize); | 72 point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + v
ertexSize); |
73 bounds->growToInclude(point->fX, point->fY); | 73 bounds->growToInclude(point->fX, point->fY); |
74 } | 74 } |
75 } | 75 } |
76 } | 76 } |
77 | 77 |
78 | 78 |
79 namespace { | 79 namespace { |
80 | 80 |
81 extern const GrVertexAttrib kRectPosColorUVAttribs[] = { | 81 extern const GrVertexAttrib kRectAttribs[] = { |
82 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindin
g}, | 82 {kVec2f_GrVertexAttribType, 0, kPosition_GrVe
rtexAttribBinding}, |
83 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding}, | 83 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVerte
xAttribBinding}, |
84 {kVec2f_GrVertexAttribType, sizeof(SkPoint)+sizeof(GrColor), | 84 {kVec2f_GrVertexAttribType, sizeof(SkPoint)+sizeof(GrColor), kLocalCoord_Gr
VertexAttribBinding}, |
85 kLocalCoord_GrVertexAttribBind
ing}, | |
86 }; | 85 }; |
| 86 } |
87 | 87 |
88 extern const GrVertexAttrib kRectPosUVAttribs[] = { | 88 /** We always use per-vertex colors so that rects can be batched across color ch
anges. Sometimes we |
89 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, | 89 have explicit local coords and sometimes not. We *could* always provide expl
icit local coords |
90 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBindi
ng}, | 90 and just duplicate the positions when the caller hasn't provided a local coo
rd rect, but we |
91 }; | 91 haven't seen a use case which frequently switches between local rect and no
local rect draws. |
92 | 92 |
93 static void set_vertex_attributes(GrDrawState* drawState, | 93 The color param is used to determine whether the opaque hint can be set on t
he draw state. |
94 bool hasColor, bool hasUVs, | 94 The caller must populate the vertex colors itself. |
95 int* colorOffset, int* localOffset) { | |
96 *colorOffset = -1; | |
97 *localOffset = -1; | |
98 | 95 |
99 // Using per-vertex colors allows batching across colors. (A lot of rects in
a row differing | 96 The vertex attrib order is always pos, color, [local coords]. |
100 // only in color is a common occurrence in tables). However, having per-vert
ex colors disables | 97 */ |
101 // blending optimizations because we don't know if the color will be solid o
r not. These | 98 static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, G
rColor color) { |
102 // optimizations help determine whether coverage and color can be blended co
rrectly when | 99 if (hasLocalCoords) { |
103 // dual-source blending isn't available. This comes into play when there is
coverage. If colors | 100 drawState->setVertexAttribs<kRectAttribs>(3); |
104 // were a stage it could take a hint that every vertex's color will be opaqu
e. | |
105 if (hasColor && hasUVs) { | |
106 *colorOffset = sizeof(SkPoint); | |
107 *localOffset = sizeof(SkPoint) + sizeof(GrColor); | |
108 drawState->setVertexAttribs<kRectPosColorUVAttribs>(3); | |
109 } else if (hasColor) { | |
110 *colorOffset = sizeof(SkPoint); | |
111 drawState->setVertexAttribs<kRectPosColorUVAttribs>(2); | |
112 } else if (hasUVs) { | |
113 *localOffset = sizeof(SkPoint); | |
114 drawState->setVertexAttribs<kRectPosUVAttribs>(2); | |
115 } else { | 101 } else { |
116 drawState->setVertexAttribs<kRectPosUVAttribs>(1); | 102 drawState->setVertexAttribs<kRectAttribs>(2); |
| 103 } |
| 104 if (0xFF == GrColorUnpackA(color)) { |
| 105 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); |
117 } | 106 } |
118 } | 107 } |
119 | 108 |
120 }; | |
121 | |
122 enum { | 109 enum { |
123 kTraceCmdBit = 0x80, | 110 kTraceCmdBit = 0x80, |
124 kCmdMask = 0x7f, | 111 kCmdMask = 0x7f, |
125 }; | 112 }; |
126 | 113 |
127 static uint8_t add_trace_bit(uint8_t cmd) { | 114 static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; } |
128 return cmd | kTraceCmdBit; | |
129 } | |
130 | 115 |
131 static uint8_t strip_trace_bit(uint8_t cmd) { | 116 static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; } |
132 return cmd & kCmdMask; | |
133 } | |
134 | 117 |
135 static bool cmd_has_trace_marker(uint8_t cmd) { | 118 static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTr
aceCmdBit); } |
136 return SkToBool(cmd & kTraceCmdBit); | |
137 } | |
138 | 119 |
139 void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect, | 120 void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect, |
140 const SkRect* localRect, | 121 const SkRect* localRect, |
141 const SkMatrix* localMatrix) { | 122 const SkMatrix* localMatrix) { |
142 GrDrawState* drawState = this->drawState(); | 123 GrDrawState* drawState = this->drawState(); |
143 | 124 |
144 GrColor color = drawState->getColor(); | 125 GrColor color = drawState->getColor(); |
145 | 126 |
146 int colorOffset, localOffset; | 127 set_vertex_attributes(drawState, NULL != localRect, color); |
147 set_vertex_attributes(drawState, | |
148 this->caps()->dualSourceBlendingSupport() || drawState->hasSo
lidCoverage(), | |
149 NULL != localRect, | |
150 &colorOffset, &localOffset); | |
151 | 128 |
152 AutoReleaseGeometry geo(this, 4, 0); | 129 AutoReleaseGeometry geo(this, 4, 0); |
153 if (!geo.succeeded()) { | 130 if (!geo.succeeded()) { |
154 GrPrintf("Failed to get space for vertices!\n"); | 131 GrPrintf("Failed to get space for vertices!\n"); |
155 return; | 132 return; |
156 } | 133 } |
157 | 134 |
158 // Go to device coords to allow batching across matrix changes | 135 // Go to device coords to allow batching across matrix changes |
159 SkMatrix matrix = drawState->getViewMatrix(); | 136 SkMatrix matrix = drawState->getViewMatrix(); |
160 | 137 |
161 // When the caller has provided an explicit source rect for a stage then we
don't want to | 138 // When the caller has provided an explicit source rect for a stage then we
don't want to |
162 // modify that stage's matrix. Otherwise if the effect is generating its sou
rce rect from | 139 // modify that stage's matrix. Otherwise if the effect is generating its sou
rce rect from |
163 // the vertex positions then we have to account for the view matrix change. | 140 // the vertex positions then we have to account for the view matrix change. |
164 GrDrawState::AutoViewMatrixRestore avmr; | 141 GrDrawState::AutoViewMatrixRestore avmr; |
165 if (!avmr.setIdentity(drawState)) { | 142 if (!avmr.setIdentity(drawState)) { |
166 return; | 143 return; |
167 } | 144 } |
168 | 145 |
169 size_t vsize = drawState->getVertexSize(); | 146 size_t vsize = drawState->getVertexSize(); |
170 | 147 |
171 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom
, vsize); | 148 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom
, vsize); |
172 matrix.mapPointsWithStride(geo.positions(), vsize, 4); | 149 matrix.mapPointsWithStride(geo.positions(), vsize, 4); |
173 | 150 |
174 SkRect devBounds; | 151 SkRect devBounds; |
175 // since we already computed the dev verts, set the bounds hint. This will h
elp us avoid | 152 // since we already computed the dev verts, set the bounds hint. This will h
elp us avoid |
176 // unnecessary clipping in our onDraw(). | 153 // unnecessary clipping in our onDraw(). |
177 get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds); | 154 get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds); |
178 | 155 |
179 if (localOffset >= 0) { | 156 if (NULL != localRect) { |
180 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) +
localOffset); | 157 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); |
| 158 SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) +
kLocalOffset); |
181 coords->setRectFan(localRect->fLeft, localRect->fTop, | 159 coords->setRectFan(localRect->fLeft, localRect->fTop, |
182 localRect->fRight, localRect->fBottom, | 160 localRect->fRight, localRect->fBottom, |
183 vsize); | 161 vsize); |
184 if (NULL != localMatrix) { | 162 if (NULL != localMatrix) { |
185 localMatrix->mapPointsWithStride(coords, vsize, 4); | 163 localMatrix->mapPointsWithStride(coords, vsize, 4); |
186 } | 164 } |
187 } | 165 } |
188 | 166 |
189 if (colorOffset >= 0) { | 167 static const int kColorOffset = sizeof(SkPoint); |
190 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices())
+ colorOffset); | 168 GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + k
ColorOffset); |
191 for (int i = 0; i < 4; ++i) { | 169 for (int i = 0; i < 4; ++i) { |
192 *vertColor = color; | 170 *vertColor = color; |
193 vertColor = (GrColor*) ((intptr_t) vertColor + vsize); | 171 vertColor = (GrColor*) ((intptr_t) vertColor + vsize); |
194 } | |
195 } | 172 } |
196 | 173 |
197 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer()); | 174 this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer()); |
198 this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds); | 175 this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds); |
199 | 176 |
200 // to ensure that stashing the drawState ptr is valid | 177 // to ensure that stashing the drawState ptr is valid |
201 SkASSERT(this->drawState() == drawState); | 178 SkASSERT(this->drawState() == drawState); |
202 } | 179 } |
203 | 180 |
204 bool GrInOrderDrawBuffer::quickInsideClip(const SkRect& devBounds) { | 181 bool GrInOrderDrawBuffer::quickInsideClip(const SkRect& devBounds) { |
(...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 } | 879 } |
903 | 880 |
904 void GrInOrderDrawBuffer::recordStateIfNecessary() { | 881 void GrInOrderDrawBuffer::recordStateIfNecessary() { |
905 if (fStates.empty()) { | 882 if (fStates.empty()) { |
906 fStates.push_back() = this->getDrawState(); | 883 fStates.push_back() = this->getDrawState(); |
907 this->addToCmdBuffer(kSetState_Cmd); | 884 this->addToCmdBuffer(kSetState_Cmd); |
908 return; | 885 return; |
909 } | 886 } |
910 const GrDrawState& curr = this->getDrawState(); | 887 const GrDrawState& curr = this->getDrawState(); |
911 GrDrawState& prev = fStates.back(); | 888 GrDrawState& prev = fStates.back(); |
912 switch (GrDrawState::CombineIfPossible(prev, curr)) { | 889 switch (GrDrawState::CombineIfPossible(prev, curr, *this->caps())) { |
913 case GrDrawState::kIncompatible_CombinedState: | 890 case GrDrawState::kIncompatible_CombinedState: |
914 fStates.push_back() = this->getDrawState(); | 891 fStates.push_back() = this->getDrawState(); |
915 this->addToCmdBuffer(kSetState_Cmd); | 892 this->addToCmdBuffer(kSetState_Cmd); |
916 break; | 893 break; |
917 case GrDrawState::kA_CombinedState: | 894 case GrDrawState::kA_CombinedState: |
918 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA. | 895 case GrDrawState::kAOrB_CombinedState: // Treat the same as kA. |
919 break; | 896 break; |
920 case GrDrawState::kB_CombinedState: | 897 case GrDrawState::kB_CombinedState: |
921 prev = curr; | 898 prev = curr; |
922 break; | 899 break; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface() { | 958 GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface() { |
982 this->addToCmdBuffer(kCopySurface_Cmd); | 959 this->addToCmdBuffer(kCopySurface_Cmd); |
983 return &fCopySurfaces.push_back(); | 960 return &fCopySurfaces.push_back(); |
984 } | 961 } |
985 | 962 |
986 void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) { | 963 void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) { |
987 INHERITED::clipWillBeSet(newClipData); | 964 INHERITED::clipWillBeSet(newClipData); |
988 fClipSet = true; | 965 fClipSet = true; |
989 fClipProxyState = kUnknown_ClipProxyState; | 966 fClipProxyState = kUnknown_ClipProxyState; |
990 } | 967 } |
OLD | NEW |