blob: c65f0b69576347b34d73ae24cce7d98258e19d66 [file] [log] [blame]
junov@google.comf93e7172011-03-31 21:26:24 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
junov@google.comf93e7172011-03-31 21:26:24 +00006 */
7
bsalomon@google.com5739d2c2012-05-31 15:07:19 +00008#include "GrGpuGL.h"
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
bsalomon@google.coma469c282012-10-24 18:28:34 +000010#include "GrEffect.h"
bsalomon@google.comd698f772012-10-25 13:22:00 +000011#include "GrGLEffect.h"
junov@google.comf93e7172011-03-31 21:26:24 +000012
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000013typedef GrGLUniformManager::UniformHandle UniformHandle;
14static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
15
junov@google.comf93e7172011-03-31 21:26:24 +000016#define SKIP_CACHE_CHECK true
17#define GR_UINT32_MAX static_cast<uint32_t>(-1)
18
robertphillips@google.com6177e692013-02-28 20:16:25 +000019GrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl)
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000020 : fCount(0)
21 , fCurrLRUStamp(0)
22 , fGL(gl) {
23}
junov@google.comf93e7172011-03-31 21:26:24 +000024
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000025void GrGpuGL::ProgramCache::abandon() {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000026 for (int i = 0; i < fCount; ++i) {
27 GrAssert(NULL != fEntries[i].fProgram.get());
28 fEntries[i].fProgram->abandon();
29 fEntries[i].fProgram.reset(NULL);
30 }
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000031 fCount = 0;
32}
33
bsalomon@google.com91207482013-02-12 21:45:24 +000034GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgram::Desc& desc,
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000035 const GrEffectStage* stages[]) {
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000036 Entry newEntry;
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +000037 newEntry.fKey.setKeyData(desc.asKey());
38
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000039 Entry* entry = fHashCache.find(newEntry.fKey);
40 if (NULL == entry) {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000041 newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages));
42 if (NULL == newEntry.fProgram.get()) {
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000043 return NULL;
44 }
45 if (fCount < kMaxEntries) {
46 entry = fEntries + fCount;
47 ++fCount;
48 } else {
49 GrAssert(kMaxEntries == fCount);
50 entry = fEntries;
51 for (int i = 1; i < kMaxEntries; ++i) {
52 if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
53 entry = fEntries + i;
junov@google.comf93e7172011-03-31 21:26:24 +000054 }
junov@google.comf93e7172011-03-31 21:26:24 +000055 }
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000056 fHashCache.remove(entry->fKey, entry);
junov@google.comf93e7172011-03-31 21:26:24 +000057 }
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +000058 *entry = newEntry;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000059 fHashCache.insert(entry->fKey, entry);
junov@google.comf93e7172011-03-31 21:26:24 +000060 }
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000061
62 entry->fLRUStamp = fCurrLRUStamp;
63 if (GR_UINT32_MAX == fCurrLRUStamp) {
64 // wrap around! just trash our LRU, one time hit.
65 for (int i = 0; i < fCount; ++i) {
66 fEntries[i].fLRUStamp = 0;
67 }
68 }
69 ++fCurrLRUStamp;
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +000070 return entry->fProgram;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +000071}
junov@google.comf93e7172011-03-31 21:26:24 +000072
bsalomon@google.com1e257a52011-07-06 19:52:16 +000073////////////////////////////////////////////////////////////////////////////////
74
bsalomon@google.com5739d2c2012-05-31 15:07:19 +000075void GrGpuGL::abandonResources(){
76 INHERITED::abandonResources();
77 fProgramCache->abandon();
78 fHWProgramID = 0;
79}
80
81////////////////////////////////////////////////////////////////////////////////
82
bsalomon@google.com0b77d682011-08-19 13:28:54 +000083#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
84
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +000085void GrGpuGL::flushPathStencilMatrix() {
86 const SkMatrix& viewMatrix = this->getDrawState().getViewMatrix();
87 const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
88 SkISize size;
89 size.set(rt->width(), rt->height());
bsalomon@google.comb9086a02012-11-01 18:02:54 +000090 const SkMatrix& vm = this->getDrawState().getViewMatrix();
bsalomon@google.com4c883782012-06-04 19:05:11 +000091
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +000092 if (fHWPathStencilMatrixState.fRenderTargetOrigin != rt->origin() ||
93 fHWPathStencilMatrixState.fViewMatrix.cheapEqualTo(viewMatrix) ||
94 fHWPathStencilMatrixState.fRenderTargetSize!= size) {
95 // rescale the coords from skia's "device" coords to GL's normalized coords,
96 // and perform a y-flip if required.
bsalomon@google.comb9086a02012-11-01 18:02:54 +000097 SkMatrix m;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +000098 if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +000099 m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height());
100 m.postTranslate(-SK_Scalar1, SK_Scalar1);
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000101 } else {
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000102 m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(2) / rt->height());
103 m.postTranslate(-SK_Scalar1, -SK_Scalar1);
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000104 }
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000105 m.preConcat(vm);
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000106
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000107 // GL wants a column-major 4x4.
108 GrGLfloat mv[] = {
109 // col 0
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000110 SkScalarToFloat(m[SkMatrix::kMScaleX]),
111 SkScalarToFloat(m[SkMatrix::kMSkewY]),
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000112 0,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000113 SkScalarToFloat(m[SkMatrix::kMPersp0]),
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000114
115 // col 1
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000116 SkScalarToFloat(m[SkMatrix::kMSkewX]),
117 SkScalarToFloat(m[SkMatrix::kMScaleY]),
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000118 0,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000119 SkScalarToFloat(m[SkMatrix::kMPersp1]),
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000120
121 // col 2
122 0, 0, 0, 0,
123
124 // col3
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000125 SkScalarToFloat(m[SkMatrix::kMTransX]),
126 SkScalarToFloat(m[SkMatrix::kMTransY]),
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000127 0.0f,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000128 SkScalarToFloat(m[SkMatrix::kMPersp2])
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000129 };
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000130 GL_CALL(MatrixMode(GR_GL_PROJECTION));
131 GL_CALL(LoadMatrixf(mv));
132 fHWPathStencilMatrixState.fViewMatrix = vm;
133 fHWPathStencilMatrixState.fRenderTargetSize = size;
134 fHWPathStencilMatrixState.fRenderTargetOrigin = rt->origin();
bsalomon@google.com91961302011-05-09 18:39:58 +0000135 }
junov@google.comf93e7172011-03-31 21:26:24 +0000136}
137
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000138bool GrGpuGL::flushGraphicsState(DrawType type) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000139 const GrDrawState& drawState = this->getDrawState();
140
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000141 // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +0000142 GrAssert(NULL != drawState.getRenderTarget());
143
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000144 if (kStencilPath_DrawType == type) {
145 this->flushPathStencilMatrix();
146 } else {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000147 this->flushMiscFixedFunctionState();
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +0000148
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000149 GrBlendCoeff srcCoeff;
150 GrBlendCoeff dstCoeff;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000151 GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff);
152 if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000153 return false;
154 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000155
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000156 const GrEffectStage* stages[GrDrawState::kNumStages];
157 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
158 stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL;
159 }
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000160 GrGLProgram::Desc desc;
bsalomon@google.com91207482013-02-12 21:45:24 +0000161 GrGLProgram::BuildDesc(this->getDrawState(),
162 kDrawPoints_DrawType == type,
163 blendOpts,
164 srcCoeff,
165 dstCoeff,
166 this,
167 &desc);
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000168
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000169 fCurrentProgram.reset(fProgramCache->getProgram(desc, stages));
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000170 if (NULL == fCurrentProgram.get()) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000171 GrAssert(!"Failed to create program!");
172 return false;
173 }
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000174 fCurrentProgram.get()->ref();
junov@google.comf93e7172011-03-31 21:26:24 +0000175
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000176 GrGLuint programID = fCurrentProgram->programID();
177 if (fHWProgramID != programID) {
178 GL_CALL(UseProgram(programID));
179 fHWProgramID = programID;
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000180 }
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000181
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000182 fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000183 this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
junov@google.comf93e7172011-03-31 21:26:24 +0000184
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000185 GrColor color;
186 GrColor coverage;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000187 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000188 color = 0;
189 coverage = 0;
bsalomon@google.com2b446732013-02-12 16:47:41 +0000190 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000191 color = 0xffffffff;
192 coverage = drawState.getCoverage();
193 } else {
194 color = drawState.getColor();
195 coverage = drawState.getCoverage();
196 }
bsalomon@google.com91207482013-02-12 21:45:24 +0000197 fCurrentProgram->setData(this, color, coverage, &fSharedGLProgramState);
junov@google.comf93e7172011-03-31 21:26:24 +0000198 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000199 this->flushStencil(type);
bsalomon@google.coma3201942012-06-21 19:58:20 +0000200 this->flushScissor();
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000201 this->flushAAState(type);
bsalomon@google.com4c883782012-06-04 19:05:11 +0000202
robertphillips@google.com7b112892012-07-31 15:18:21 +0000203 GrIRect* devRect = NULL;
204 GrIRect devClipBounds;
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +0000205 if (drawState.isClipState()) {
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000206 this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds);
robertphillips@google.com7b112892012-07-31 15:18:21 +0000207 devRect = &devClipBounds;
bsalomon@google.com4c883782012-06-04 19:05:11 +0000208 }
209 // This must come after textures are flushed because a texture may need
210 // to be msaa-resolved (which will modify bound FBO state).
robertphillips@google.com7b112892012-07-31 15:18:21 +0000211 this->flushRenderTarget(devRect);
bsalomon@google.com4c883782012-06-04 19:05:11 +0000212
junov@google.comf93e7172011-03-31 21:26:24 +0000213 return true;
214}
215
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000216void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
junov@google.comf93e7172011-03-31 21:26:24 +0000217
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000218 GrGLsizei stride = this->getDrawState().getVertexSize();
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000219
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000220 size_t vertexOffset;
221 GrGLVertexBuffer* vb= this->setBuffers(info.isIndexed(), &vertexOffset, indexOffsetInBytes);
222 vertexOffset += stride * info.startVertex();
junov@google.comf93e7172011-03-31 21:26:24 +0000223
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000224 uint32_t usedAttribArraysMask = 0;
225 const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
226 int vertexAttribCount = this->getDrawState().getVertexAttribCount();
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000227 for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000228 ++vertexAttribIndex, ++vertexAttrib) {
robertphillips@google.comaf3a3b92013-02-28 23:08:28 +0000229
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000230 usedAttribArraysMask |= (1 << vertexAttribIndex);
231 GrVertexAttribType attribType = vertexAttrib->fType;
robertphillips@google.comaf3a3b92013-02-28 23:08:28 +0000232 fHWGeometryState.setAttribArray(this,
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000233 vertexAttribIndex,
robertphillips@google.comaf3a3b92013-02-28 23:08:28 +0000234 vb,
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000235 GrGLProgram::kAttribLayouts[attribType].fCount,
236 GrGLProgram::kAttribLayouts[attribType].fType,
237 GrGLProgram::kAttribLayouts[attribType].fNormalized,
robertphillips@google.comaf3a3b92013-02-28 23:08:28 +0000238 stride,
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000239 reinterpret_cast<GrGLvoid*>(
240 vertexOffset + vertexAttrib->fOffset));
241 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000242
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000243 fHWGeometryState.disableUnusedAttribArrays(this, usedAttribArraysMask);
junov@google.comf93e7172011-03-31 21:26:24 +0000244}