blob: fe6d0c37f7f088d7bc8239e889321f7b8a8a91e0 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrGpu.h"
19#include "GrMemory.h"
20#include "GrTextStrike.h"
21#include "GrTextureCache.h"
22#include "GrClipIterator.h"
23#include "GrIndexBuffer.h"
24
25///////////////////////////////////////////////////////////////////////////////
26
27size_t GrTexture::BytesPerPixel(PixelConfig config) {
28 switch (config) {
29 case kAlpha_8_PixelConfig:
30 case kIndex_8_PixelConfig:
31 return 1;
32 case kRGB_565_PixelConfig:
33 case kRGBA_4444_PixelConfig:
34 return 2;
35 case kRGBA_8888_PixelConfig:
36 case kRGBX_8888_PixelConfig:
37 return 4;
38 default:
39 return 0;
40 }
41}
42
43bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
44 switch (config) {
45 case GrTexture::kRGB_565_PixelConfig:
46 case GrTexture::kRGBX_8888_PixelConfig:
47 return true;
48 default:
49 return false;
50 }
51}
52
53
54///////////////////////////////////////////////////////////////////////////////
55
56extern void gr_run_unittests();
57
58GrGpu::GrGpu() : f8bitPaletteSupport(false),
59 fNPOTTextureSupport(kNone_NPOTTextureType),
60 fQuadIndexBuffer(NULL) {
61#if GR_DEBUG
62// gr_run_unittests();
63#endif
64 resetStats();
65}
66
67GrGpu::~GrGpu() {
68 if (NULL != fQuadIndexBuffer) {
69 fQuadIndexBuffer->unref();
70 }
71}
72
73void GrGpu::resetContext() {
74}
75
76void GrGpu::unimpl(const char msg[]) {
77// GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
78}
79
80///////////////////////////////////////////////////////////////////////////////
81
82bool GrGpu::canDisableBlend() const {
83 if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
84 (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
85 return true;
86 }
87
88 // If we have vertex color without alpha then we can't force blend off
89 if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
90 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
91 return false;
92 }
93
94 // If the src coef will always be 1...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000095 if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
96 kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
97 return false;
98 }
reed@google.comac10a2d2010-12-22 21:39:39 +000099
100 // ...and the dst coef is always 0...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000101 if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
102 kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
103 return false;
104 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000105
106 // ...and there isn't a texture with an alpha channel...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000107 for (int s = 0; s < kNumStages; ++s) {
108 if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
109 GrAssert(NULL != fCurrDrawState.fTextures[s]);
110 GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config();
111
112 if (GrTexture::kRGB_565_PixelConfig != config &&
113 GrTexture::kRGBX_8888_PixelConfig != config) {
114 return false;
115 }
116 }
117 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000118
119 // ...then we disable blend.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000120 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000121}
122
123///////////////////////////////////////////////////////////////////////////////
124
125static const int MAX_QUADS = 512; // max possible: (1 << 14) - 1;
126
reed@google.com8195f672011-01-12 18:14:28 +0000127GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +0000128
129static inline void fillIndices(uint16_t* indices, int quadCount) {
130 for (int i = 0; i < quadCount; ++i) {
131 indices[6 * i + 0] = 4 * i + 0;
132 indices[6 * i + 1] = 4 * i + 1;
133 indices[6 * i + 2] = 4 * i + 2;
134 indices[6 * i + 3] = 4 * i + 0;
135 indices[6 * i + 4] = 4 * i + 2;
136 indices[6 * i + 5] = 4 * i + 3;
137 }
138}
139
140const GrIndexBuffer* GrGpu::quadIndexBuffer() const {
141 if (NULL == fQuadIndexBuffer) {
142 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
143 GrGpu* me = const_cast<GrGpu*>(this);
144 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
145 if (NULL != fQuadIndexBuffer) {
146 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
147 if (NULL != indices) {
148 fillIndices(indices, MAX_QUADS);
149 fQuadIndexBuffer->unlock();
150 } else {
151 indices = (uint16_t*)GrMalloc(SIZE);
152 fillIndices(indices, MAX_QUADS);
153 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
154 fQuadIndexBuffer->unref();
155 fQuadIndexBuffer = NULL;
156 GrAssert(!"Can't get indices into buffer!");
157 }
158 GrFree(indices);
159 }
160 }
161 }
162
163 return fQuadIndexBuffer;
164}
165
166int GrGpu::maxQuadsInIndexBuffer() const {
167 return (NULL == this->quadIndexBuffer()) ? 0 : MAX_QUADS;
168}
169
170///////////////////////////////////////////////////////////////////////////////
171
172void GrGpu::clipWillChange(const GrClip& clip) {
173 if (clip != fClip) {
174 fClipState.fClipIsDirty = true;
175 }
176}
177
178bool GrGpu::setupClipAndFlushState(PrimitiveType type) {
179 const GrIRect* r = NULL;
180
181 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
182 fClipState.fClipInStencil = fClip.countRects() > 1;
183
184 if (fClipState.fClipInStencil &&
185 (fClipState.fClipIsDirty ||
186 fClipState.fStencilClipTarget != fCurrDrawState.fRenderTarget)) {
187
188 AutoStateRestore asr(this);
189 AutoGeometrySrcRestore agsr(this);
190 this->disableState(kClip_StateBit);
191 eraseStencilClip();
192
193 int rectTotal = fClip.countRects();
194 static const int PtsPerRect = 4;
195 // this may be called while geometry is already reserved by the
196 // client. So we use our own vertex array where we avoid malloc
197 // if we have 4 or fewer rects.
198 GrAutoSTMalloc<PtsPerRect * 4, GrPoint> vertices(PtsPerRect *
199 rectTotal);
200 this->setVertexSourceToArray(vertices.get(), 0);
201 int currRect = 0;
202 while (currRect < rectTotal) {
203 int rectCount = GrMin(this->maxQuadsInIndexBuffer(),
204 rectTotal - currRect);
205
206 GrPoint* verts = (GrPoint*)vertices +
207 (currRect * PtsPerRect);
208
209 for (int i = 0; i < rectCount; i++) {
210 GrRect r(fClip.getRects()[i + currRect]);
211 verts = r.setRectFan(verts);
212 }
213 this->setIndexSourceToBuffer(quadIndexBuffer());
214
215 this->setViewMatrix(GrMatrix::I());
216 this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass);
217 this->drawIndexed(GrGpu::kTriangles_PrimitiveType,
218 currRect * PtsPerRect, 0,
219 rectCount * PtsPerRect, rectCount * 6);
220
221 currRect += rectCount;
222 }
223 fClipState.fStencilClipTarget = fCurrDrawState.fRenderTarget;
224 }
225 fClipState.fClipIsDirty = false;
226 if (!fClipState.fClipInStencil) {
227 r = &fClip.getBounds();
228 }
229 }
230 // Must flush the scissor after graphics state
231 if (!flushGraphicsState(type)) {
232 return false;
233 }
234 flushScissor(r);
235 return true;
236}
237
238
239///////////////////////////////////////////////////////////////////////////////
240
241void GrGpu::drawIndexed(PrimitiveType type,
242 uint32_t startVertex,
243 uint32_t startIndex,
244 uint32_t vertexCount,
245 uint32_t indexCount) {
246 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
247 fReservedGeometry.fLocked);
248 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
249 fReservedGeometry.fLocked);
250
251 if (!setupClipAndFlushState(type)) {
252 return;
253 }
254
255#if GR_COLLECT_STATS
256 fStats.fVertexCnt += vertexCount;
257 fStats.fIndexCnt += indexCount;
258 fStats.fDrawCnt += 1;
259#endif
260
261 setupGeometry(startVertex, startIndex, vertexCount, indexCount);
262
263 drawIndexedHelper(type, startVertex, startIndex,
264 vertexCount, indexCount);
265}
266
267void GrGpu::drawNonIndexed(PrimitiveType type,
268 uint32_t startVertex,
269 uint32_t vertexCount) {
270 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
271 fReservedGeometry.fLocked);
272
273 if (!setupClipAndFlushState(type)) {
274 return;
275 }
276#if GR_COLLECT_STATS
277 fStats.fVertexCnt += vertexCount;
278 fStats.fDrawCnt += 1;
279#endif
280
281 setupGeometry(startVertex, 0, vertexCount, 0);
282
283 drawNonIndexedHelper(type, startVertex, vertexCount);
284}
285
286bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
287 void** vertices,
288 void** indices) {
289 GrAssert((fReservedGeometry.fVertexCount == 0) ||
290 (NULL != vertices));
291 if (NULL != vertices) {
292 *vertices = fVertices.realloc(VertexSize(vertexLayout) *
293 fReservedGeometry.fVertexCount);
294 if (!*vertices && fReservedGeometry.fVertexCount) {
295 return false;
296 }
297 }
298 GrAssert((fReservedGeometry.fIndexCount == 0) ||
299 (NULL != indices));
300 if (NULL != indices) {
301 *indices = fIndices.realloc(sizeof(uint16_t) *
302 fReservedGeometry.fIndexCount);
303 if (!*indices && fReservedGeometry.fIndexCount) {
304 return false;
305 }
306 }
307 return true;
308}
309
310void GrGpu::releaseGeometryHelper() {
311 return;
312}
313
314///////////////////////////////////////////////////////////////////////////////
315
316const GrGpu::Stats& GrGpu::getStats() const {
317 return fStats;
318}
319
320void GrGpu::resetStats() {
321 memset(&fStats, 0, sizeof(fStats));
322}
323
324void GrGpu::printStats() const {
325 if (GR_COLLECT_STATS) {
326 GrPrintf(
327 "-v-------------------------GPU STATS----------------------------v-\n"
328 "Stats collection is: %s\n"
329 "Draws: %04d, Verts: %04d, Indices: %04d\n"
330 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
331 "TexCreates: %04d, RTCreates:%04d\n"
332 "-^--------------------------------------------------------------^-\n",
333 (GR_COLLECT_STATS ? "ON" : "OFF"),
334 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
335 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
336 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
337 }
338}
339
340////////////////////////////////////////////////////////////////////////////////
341
342GrTexture::~GrTexture() {
343 // use this to set a break-point if needed
344// Gr_clz(3);
345}
346
347const GrSamplerState GrSamplerState::gClampNoFilter(
348 GrSamplerState::kClamp_WrapMode,
349 GrSamplerState::kClamp_WrapMode,
350 GrSamplerState::kNormal_SampleMode,
351 false);
352
353
354
355