blob: 057a8c9412955c1ad9678609929dace19f132415 [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"
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000024#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000025
26///////////////////////////////////////////////////////////////////////////////
27
28size_t GrTexture::BytesPerPixel(PixelConfig config) {
29 switch (config) {
30 case kAlpha_8_PixelConfig:
31 case kIndex_8_PixelConfig:
32 return 1;
33 case kRGB_565_PixelConfig:
34 case kRGBA_4444_PixelConfig:
35 return 2;
36 case kRGBA_8888_PixelConfig:
37 case kRGBX_8888_PixelConfig:
38 return 4;
39 default:
40 return 0;
41 }
42}
43
44bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
45 switch (config) {
46 case GrTexture::kRGB_565_PixelConfig:
47 case GrTexture::kRGBX_8888_PixelConfig:
48 return true;
49 default:
50 return false;
51 }
52}
53
54
55///////////////////////////////////////////////////////////////////////////////
56
57extern void gr_run_unittests();
58
59GrGpu::GrGpu() : f8bitPaletteSupport(false),
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000060 fQuadIndexBuffer(NULL),
61 fUnitSquareVertexBuffer(NULL) {
reed@google.comac10a2d2010-12-22 21:39:39 +000062#if GR_DEBUG
63// gr_run_unittests();
64#endif
65 resetStats();
66}
67
68GrGpu::~GrGpu() {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000069 GrSafeUnref(fQuadIndexBuffer);
70 GrSafeUnref(fUnitSquareVertexBuffer);
reed@google.comac10a2d2010-12-22 21:39:39 +000071}
72
73void GrGpu::resetContext() {
74}
75
76void GrGpu::unimpl(const char msg[]) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +000077#if GR_DEBUG
78 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
79#endif
reed@google.comac10a2d2010-12-22 21:39:39 +000080}
81
82///////////////////////////////////////////////////////////////////////////////
83
84bool GrGpu::canDisableBlend() const {
85 if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
86 (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
87 return true;
88 }
89
90 // If we have vertex color without alpha then we can't force blend off
91 if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
92 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
93 return false;
94 }
95
96 // If the src coef will always be 1...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000097 if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
98 kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
99 return false;
100 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000101
102 // ...and the dst coef is always 0...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000103 if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
104 kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
105 return false;
106 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000107
108 // ...and there isn't a texture with an alpha channel...
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000109 for (int s = 0; s < kNumStages; ++s) {
110 if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
111 GrAssert(NULL != fCurrDrawState.fTextures[s]);
112 GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000113
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000114 if (GrTexture::kRGB_565_PixelConfig != config &&
115 GrTexture::kRGBX_8888_PixelConfig != config) {
116 return false;
117 }
118 }
119 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000120
121 // ...then we disable blend.
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000122 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000123}
124
125///////////////////////////////////////////////////////////////////////////////
126
127static const int MAX_QUADS = 512; // max possible: (1 << 14) - 1;
128
reed@google.com8195f672011-01-12 18:14:28 +0000129GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +0000130
131static inline void fillIndices(uint16_t* indices, int quadCount) {
132 for (int i = 0; i < quadCount; ++i) {
133 indices[6 * i + 0] = 4 * i + 0;
134 indices[6 * i + 1] = 4 * i + 1;
135 indices[6 * i + 2] = 4 * i + 2;
136 indices[6 * i + 3] = 4 * i + 0;
137 indices[6 * i + 4] = 4 * i + 2;
138 indices[6 * i + 5] = 4 * i + 3;
139 }
140}
141
142const GrIndexBuffer* GrGpu::quadIndexBuffer() const {
143 if (NULL == fQuadIndexBuffer) {
144 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
145 GrGpu* me = const_cast<GrGpu*>(this);
146 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
147 if (NULL != fQuadIndexBuffer) {
148 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
149 if (NULL != indices) {
150 fillIndices(indices, MAX_QUADS);
151 fQuadIndexBuffer->unlock();
152 } else {
153 indices = (uint16_t*)GrMalloc(SIZE);
154 fillIndices(indices, MAX_QUADS);
155 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
156 fQuadIndexBuffer->unref();
157 fQuadIndexBuffer = NULL;
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000158 GrCrash("Can't get indices into buffer!");
reed@google.comac10a2d2010-12-22 21:39:39 +0000159 }
160 GrFree(indices);
161 }
162 }
163 }
164
165 return fQuadIndexBuffer;
166}
167
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000168const GrVertexBuffer* GrGpu::unitSquareVertexBuffer() const {
169 if (NULL == fUnitSquareVertexBuffer) {
170
171 static const GrPoint DATA[] = {
172 GrPoint(0, 0),
173 GrPoint(GR_Scalar1,0),
174 GrPoint(GR_Scalar1,GR_Scalar1),
175 GrPoint(0, GR_Scalar1)
176 };
177 static const size_t SIZE = sizeof(DATA);
178
179 GrGpu* me = const_cast<GrGpu*>(this);
180 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
181 if (NULL != fUnitSquareVertexBuffer) {
182 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
183 fUnitSquareVertexBuffer->unref();
184 fUnitSquareVertexBuffer = NULL;
185 GrCrash("Can't get vertices into buffer!");
186 }
187 }
188 }
189
190 return fUnitSquareVertexBuffer;
191}
192
reed@google.comac10a2d2010-12-22 21:39:39 +0000193int GrGpu::maxQuadsInIndexBuffer() const {
194 return (NULL == this->quadIndexBuffer()) ? 0 : MAX_QUADS;
195}
196
197///////////////////////////////////////////////////////////////////////////////
198
199void GrGpu::clipWillChange(const GrClip& clip) {
200 if (clip != fClip) {
201 fClipState.fClipIsDirty = true;
202 }
203}
204
205bool GrGpu::setupClipAndFlushState(PrimitiveType type) {
206 const GrIRect* r = NULL;
207
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000208 // we check this early because we need a valid
209 // render target to setup stencil clipping
210 // before even going into flushGraphicsState
211 if (NULL == fCurrDrawState.fRenderTarget) {
212 GrAssert(!"No render target bound.");
213 return false;
214 }
215
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
217 fClipState.fClipInStencil = fClip.countRects() > 1;
218
219 if (fClipState.fClipInStencil &&
220 (fClipState.fClipIsDirty ||
221 fClipState.fStencilClipTarget != fCurrDrawState.fRenderTarget)) {
222
223 AutoStateRestore asr(this);
224 AutoGeometrySrcRestore agsr(this);
225 this->disableState(kClip_StateBit);
226 eraseStencilClip();
227
228 int rectTotal = fClip.countRects();
229 static const int PtsPerRect = 4;
230 // this may be called while geometry is already reserved by the
231 // client. So we use our own vertex array where we avoid malloc
232 // if we have 4 or fewer rects.
233 GrAutoSTMalloc<PtsPerRect * 4, GrPoint> vertices(PtsPerRect *
234 rectTotal);
235 this->setVertexSourceToArray(vertices.get(), 0);
236 int currRect = 0;
237 while (currRect < rectTotal) {
238 int rectCount = GrMin(this->maxQuadsInIndexBuffer(),
239 rectTotal - currRect);
240
241 GrPoint* verts = (GrPoint*)vertices +
242 (currRect * PtsPerRect);
243
244 for (int i = 0; i < rectCount; i++) {
245 GrRect r(fClip.getRects()[i + currRect]);
246 verts = r.setRectFan(verts);
247 }
248 this->setIndexSourceToBuffer(quadIndexBuffer());
249
250 this->setViewMatrix(GrMatrix::I());
251 this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass);
252 this->drawIndexed(GrGpu::kTriangles_PrimitiveType,
253 currRect * PtsPerRect, 0,
254 rectCount * PtsPerRect, rectCount * 6);
255
256 currRect += rectCount;
257 }
258 fClipState.fStencilClipTarget = fCurrDrawState.fRenderTarget;
259 }
260 fClipState.fClipIsDirty = false;
261 if (!fClipState.fClipInStencil) {
262 r = &fClip.getBounds();
263 }
264 }
265 // Must flush the scissor after graphics state
266 if (!flushGraphicsState(type)) {
267 return false;
268 }
269 flushScissor(r);
270 return true;
271}
272
273
274///////////////////////////////////////////////////////////////////////////////
275
276void GrGpu::drawIndexed(PrimitiveType type,
277 uint32_t startVertex,
278 uint32_t startIndex,
279 uint32_t vertexCount,
280 uint32_t indexCount) {
281 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
282 fReservedGeometry.fLocked);
283 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
284 fReservedGeometry.fLocked);
285
286 if (!setupClipAndFlushState(type)) {
287 return;
288 }
289
290#if GR_COLLECT_STATS
291 fStats.fVertexCnt += vertexCount;
292 fStats.fIndexCnt += indexCount;
293 fStats.fDrawCnt += 1;
294#endif
295
296 setupGeometry(startVertex, startIndex, vertexCount, indexCount);
297
298 drawIndexedHelper(type, startVertex, startIndex,
299 vertexCount, indexCount);
300}
301
302void GrGpu::drawNonIndexed(PrimitiveType type,
303 uint32_t startVertex,
304 uint32_t vertexCount) {
305 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
306 fReservedGeometry.fLocked);
307
308 if (!setupClipAndFlushState(type)) {
309 return;
310 }
311#if GR_COLLECT_STATS
312 fStats.fVertexCnt += vertexCount;
313 fStats.fDrawCnt += 1;
314#endif
315
316 setupGeometry(startVertex, 0, vertexCount, 0);
317
318 drawNonIndexedHelper(type, startVertex, vertexCount);
319}
320
321bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
322 void** vertices,
323 void** indices) {
324 GrAssert((fReservedGeometry.fVertexCount == 0) ||
325 (NULL != vertices));
326 if (NULL != vertices) {
327 *vertices = fVertices.realloc(VertexSize(vertexLayout) *
328 fReservedGeometry.fVertexCount);
329 if (!*vertices && fReservedGeometry.fVertexCount) {
330 return false;
331 }
332 }
333 GrAssert((fReservedGeometry.fIndexCount == 0) ||
334 (NULL != indices));
335 if (NULL != indices) {
336 *indices = fIndices.realloc(sizeof(uint16_t) *
337 fReservedGeometry.fIndexCount);
338 if (!*indices && fReservedGeometry.fIndexCount) {
339 return false;
340 }
341 }
342 return true;
343}
344
345void GrGpu::releaseGeometryHelper() {
346 return;
347}
348
349///////////////////////////////////////////////////////////////////////////////
350
351const GrGpu::Stats& GrGpu::getStats() const {
352 return fStats;
353}
354
355void GrGpu::resetStats() {
356 memset(&fStats, 0, sizeof(fStats));
357}
358
359void GrGpu::printStats() const {
360 if (GR_COLLECT_STATS) {
361 GrPrintf(
362 "-v-------------------------GPU STATS----------------------------v-\n"
363 "Stats collection is: %s\n"
364 "Draws: %04d, Verts: %04d, Indices: %04d\n"
365 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
366 "TexCreates: %04d, RTCreates:%04d\n"
367 "-^--------------------------------------------------------------^-\n",
368 (GR_COLLECT_STATS ? "ON" : "OFF"),
369 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
370 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
371 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
372 }
373}
374
375////////////////////////////////////////////////////////////////////////////////
376
377GrTexture::~GrTexture() {
378 // use this to set a break-point if needed
379// Gr_clz(3);
380}
381
382const GrSamplerState GrSamplerState::gClampNoFilter(
383 GrSamplerState::kClamp_WrapMode,
384 GrSamplerState::kClamp_WrapMode,
385 GrSamplerState::kNormal_SampleMode,
386 false);
387
388
389
390