OLD | NEW |
| (Empty) |
1 /* | |
2 * 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. | |
6 */ | |
7 | |
8 #ifndef GrGpuGL_DEFINED | |
9 #define GrGpuGL_DEFINED | |
10 | |
11 #include "GrDrawState.h" | |
12 #include "GrGLContext.h" | |
13 #include "GrGLIRect.h" | |
14 #include "GrGLIndexBuffer.h" | |
15 #include "GrGLPathRendering.h" | |
16 #include "GrGLProgram.h" | |
17 #include "GrGLRenderTarget.h" | |
18 #include "GrGLStencilBuffer.h" | |
19 #include "GrGLTexture.h" | |
20 #include "GrGLVertexArray.h" | |
21 #include "GrGLVertexBuffer.h" | |
22 #include "GrGpu.h" | |
23 #include "GrOptDrawState.h" | |
24 #include "GrXferProcessor.h" | |
25 #include "SkTypes.h" | |
26 | |
27 #ifdef SK_DEVELOPER | |
28 #define PROGRAM_CACHE_STATS | |
29 #endif | |
30 | |
31 class GrGLGpu : public GrGpu { | |
32 public: | |
33 GrGLGpu(const GrGLContext& ctx, GrContext* context); | |
34 ~GrGLGpu() SK_OVERRIDE; | |
35 | |
36 void contextAbandoned() SK_OVERRIDE; | |
37 | |
38 const GrGLContext& glContext() const { return fGLContext; } | |
39 | |
40 const GrGLInterface* glInterface() const { return fGLContext.interface(); } | |
41 const GrGLContextInfo& ctxInfo() const { return fGLContext; } | |
42 GrGLStandard glStandard() const { return fGLContext.standard(); } | |
43 GrGLVersion glVersion() const { return fGLContext.version(); } | |
44 GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration()
; } | |
45 const GrGLCaps& glCaps() const { return *fGLContext.caps(); } | |
46 | |
47 GrGLPathRendering* glPathRendering() { | |
48 SkASSERT(glCaps().pathRenderingSupport()); | |
49 return static_cast<GrGLPathRendering*>(pathRendering()); | |
50 } | |
51 | |
52 void discard(GrRenderTarget*) SK_OVERRIDE; | |
53 | |
54 // Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL | |
55 // state. | |
56 void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* te
xture); | |
57 | |
58 // GrGpu overrides | |
59 GrPixelConfig preferredReadPixelsConfig(GrPixelConfig readConfig, | |
60 GrPixelConfig surfaceConfig) const S
K_OVERRIDE; | |
61 GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig, | |
62 GrPixelConfig surfaceConfig) const
SK_OVERRIDE; | |
63 bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const
SK_OVERRIDE; | |
64 bool readPixelsWillPayForYFlip(GrRenderTarget* renderTarget, | |
65 int left, int top, | |
66 int width, int height, | |
67 GrPixelConfig config, | |
68 size_t rowBytes) const SK_OVERRIDE; | |
69 bool fullReadPixelsIsFasterThanPartial() const SK_OVERRIDE; | |
70 | |
71 bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) SK_OV
ERRIDE; | |
72 | |
73 // These functions should be used to bind GL objects. They track the GL stat
e and skip redundant | |
74 // bindings. Making the equivalent glBind calls directly will confuse the st
ate tracking. | |
75 void bindVertexArray(GrGLuint id) { | |
76 fHWGeometryState.setVertexArrayID(this, id); | |
77 } | |
78 void bindIndexBufferAndDefaultVertexArray(GrGLuint id) { | |
79 fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id); | |
80 } | |
81 void bindVertexBuffer(GrGLuint id) { | |
82 fHWGeometryState.setVertexBufferID(this, id); | |
83 } | |
84 | |
85 // These callbacks update state tracking when GL objects are deleted. They a
re called from | |
86 // GrGLResource onRelease functions. | |
87 void notifyVertexArrayDelete(GrGLuint id) { | |
88 fHWGeometryState.notifyVertexArrayDelete(id); | |
89 } | |
90 void notifyVertexBufferDelete(GrGLuint id) { | |
91 fHWGeometryState.notifyVertexBufferDelete(id); | |
92 } | |
93 void notifyIndexBufferDelete(GrGLuint id) { | |
94 fHWGeometryState.notifyIndexBufferDelete(id); | |
95 } | |
96 | |
97 bool copySurface(GrSurface* dst, | |
98 GrSurface* src, | |
99 const SkIRect& srcRect, | |
100 const SkIPoint& dstPoint) SK_OVERRIDE; | |
101 | |
102 bool canCopySurface(const GrSurface* dst, | |
103 const GrSurface* src, | |
104 const SkIRect& srcRect, | |
105 const SkIPoint& dstPoint) SK_OVERRIDE; | |
106 | |
107 protected: | |
108 void buildProgramDesc(const GrOptDrawState&, | |
109 const GrProgramDesc::DescInfo&, | |
110 GrGpu::DrawType, | |
111 GrProgramDesc*) SK_OVERRIDE; | |
112 | |
113 private: | |
114 // GrGpu overrides | |
115 void onResetContext(uint32_t resetBits) SK_OVERRIDE; | |
116 | |
117 GrTexture* onCreateTexture(const GrSurfaceDesc& desc, | |
118 const void* srcData, | |
119 size_t rowBytes) SK_OVERRIDE; | |
120 GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, | |
121 const void* srcData) SK_OVERRIDE; | |
122 GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) SK_OVERRIDE; | |
123 GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE; | |
124 GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) SK_OVERRIDE; | |
125 GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&)
SK_OVERRIDE; | |
126 bool createStencilBufferForRenderTarget(GrRenderTarget* rt, | |
127 int width, int height) SK_OVERRIDE; | |
128 bool attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget*
rt) SK_OVERRIDE; | |
129 | |
130 void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color, | |
131 bool canIgnoreRect) SK_OVERRIDE; | |
132 | |
133 void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideCli
p) SK_OVERRIDE; | |
134 | |
135 bool onReadPixels(GrRenderTarget* target, | |
136 int left, int top, | |
137 int width, int height, | |
138 GrPixelConfig, | |
139 void* buffer, | |
140 size_t rowBytes) SK_OVERRIDE; | |
141 | |
142 bool onWriteTexturePixels(GrTexture* texture, | |
143 int left, int top, int width, int height, | |
144 GrPixelConfig config, const void* buffer, | |
145 size_t rowBytes) SK_OVERRIDE; | |
146 | |
147 void onResolveRenderTarget(GrRenderTarget* target) SK_OVERRIDE; | |
148 | |
149 void onDraw(const GrOptDrawState&, const GrDrawTarget::DrawInfo&) SK_OVERRID
E; | |
150 void onStencilPath(const GrPath*, const StencilPathState&) SK_OVERRIDE; | |
151 void onDrawPath(const GrOptDrawState&, const GrPath*, const GrStencilSetting
s&) SK_OVERRIDE; | |
152 void onDrawPaths(const GrOptDrawState&, | |
153 const GrPathRange*, | |
154 const void* indices, | |
155 GrDrawTarget::PathIndexType, | |
156 const float transformValues[], | |
157 GrDrawTarget::PathTransformType, | |
158 int count, | |
159 const GrStencilSettings&) SK_OVERRIDE; | |
160 | |
161 void clearStencil(GrRenderTarget*) SK_OVERRIDE; | |
162 | |
163 // GrDrawTarget overrides | |
164 void didAddGpuTraceMarker() SK_OVERRIDE; | |
165 void didRemoveGpuTraceMarker() SK_OVERRIDE; | |
166 | |
167 // binds texture unit in GL | |
168 void setTextureUnit(int unitIdx); | |
169 | |
170 // Flushes state from GrOptDrawState to GL. Returns false if the state could
n't be set. | |
171 bool flushGLState(const GrOptDrawState&); | |
172 | |
173 // Sets up vertex attribute pointers and strides. On return indexOffsetInByt
es gives the offset | |
174 // an into the index buffer. It does not account for drawInfo.startIndex() b
ut rather the start | |
175 // index is relative to the returned offset. | |
176 void setupGeometry(const GrOptDrawState&, | |
177 const GrDrawTarget::DrawInfo& info, | |
178 size_t* indexOffsetInBytes); | |
179 | |
180 // Subclasses should call this to flush the blend state. | |
181 void flushBlend(const GrXferProcessor::BlendInfo& blendInfo); | |
182 | |
183 bool hasExtension(const char* ext) const { return fGLContext.hasExtension(ex
t); } | |
184 | |
185 static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff); | |
186 | |
187 class ProgramCache : public ::SkNoncopyable { | |
188 public: | |
189 ProgramCache(GrGLGpu* gpu); | |
190 ~ProgramCache(); | |
191 | |
192 void abandon(); | |
193 GrGLProgram* getProgram(const GrOptDrawState&); | |
194 | |
195 private: | |
196 enum { | |
197 // We may actually have kMaxEntries+1 shaders in the GL context beca
use we create a new | |
198 // shader before evicting from the cache. | |
199 kMaxEntries = 128, | |
200 kHashBits = 6, | |
201 }; | |
202 | |
203 struct Entry; | |
204 | |
205 struct ProgDescLess; | |
206 | |
207 // binary search for entry matching desc. returns index into fEntries th
at matches desc or ~ | |
208 // of the index of where it should be inserted. | |
209 int search(const GrProgramDesc& desc) const; | |
210 | |
211 // sorted array of all the entries | |
212 Entry* fEntries[kMaxEntries]; | |
213 // hash table based on lowest kHashBits bits of the program key. Used to
avoid binary | |
214 // searching fEntries. | |
215 Entry* fHashTable[1 << kHashBits]; | |
216 | |
217 int fCount; | |
218 unsigned int fCurrLRUStamp; | |
219 GrGLGpu* fGpu; | |
220 #ifdef PROGRAM_CACHE_STATS | |
221 int fTotalRequests; | |
222 int fCacheMisses; | |
223 int fHashMisses; // cache hit but hash table mis
sed | |
224 #endif | |
225 }; | |
226 | |
227 void flushDither(bool dither); | |
228 void flushColorWrite(bool writeColor); | |
229 void flushDrawFace(GrDrawState::DrawFace face); | |
230 | |
231 // flushes the scissor. see the note on flushBoundTextureAndParams about | |
232 // flushing the scissor after that function is called. | |
233 void flushScissor(const GrScissorState&, | |
234 const GrGLIRect& rtViewport, | |
235 GrSurfaceOrigin rtOrigin); | |
236 | |
237 // disables the scissor | |
238 void disableScissor(); | |
239 | |
240 void initFSAASupport(); | |
241 | |
242 // determines valid stencil formats | |
243 void initStencilFormats(); | |
244 | |
245 // sets a texture unit to use for texture operations other than binding a te
xture to a program. | |
246 // ensures that such operations don't negatively interact with tracking boun
d textures. | |
247 void setScratchTextureUnit(); | |
248 | |
249 // bounds is region that may be modified and therefore has to be resolved. | |
250 // NULL means whole target. Can be an empty rect. | |
251 void flushRenderTarget(GrGLRenderTarget*, const SkIRect* bounds); | |
252 | |
253 void flushStencil(const GrStencilSettings&); | |
254 void flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool isLineDraw); | |
255 | |
256 bool configToGLFormats(GrPixelConfig config, | |
257 bool getSizedInternal, | |
258 GrGLenum* internalFormat, | |
259 GrGLenum* externalFormat, | |
260 GrGLenum* externalType); | |
261 // helper for onCreateTexture and writeTexturePixels | |
262 bool uploadTexData(const GrSurfaceDesc& desc, | |
263 bool isNewTexture, | |
264 int left, int top, int width, int height, | |
265 GrPixelConfig dataConfig, | |
266 const void* data, | |
267 size_t rowBytes); | |
268 | |
269 // helper for onCreateCompressedTexture. If width and height are | |
270 // set to -1, then this function will use desc.fWidth and desc.fHeight | |
271 // for the size of the data. The isNewTexture flag should be set to true | |
272 // whenever a new texture needs to be created. Otherwise, we assume that | |
273 // the texture is already in GPU memory and that it's going to be updated | |
274 // with new data. | |
275 bool uploadCompressedTexData(const GrSurfaceDesc& desc, | |
276 const void* data, | |
277 bool isNewTexture = true, | |
278 int left = 0, int top = 0, | |
279 int width = -1, int height = -1); | |
280 | |
281 bool createRenderTargetObjects(const GrSurfaceDesc&, GrGLuint texID, GrGLRen
derTarget::IDDesc*); | |
282 | |
283 GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect*
viewport); | |
284 | |
285 GrGLContext fGLContext; | |
286 | |
287 // GL program-related state | |
288 ProgramCache* fProgramCache; | |
289 SkAutoTUnref<GrGLProgram> fCurrentProgram; | |
290 | |
291 /////////////////////////////////////////////////////////////////////////// | |
292 ///@name Caching of GL State | |
293 ///@{ | |
294 int fHWActiveTextureUnitIdx; | |
295 GrGLuint fHWProgramID; | |
296 | |
297 enum TriState { | |
298 kNo_TriState, | |
299 kYes_TriState, | |
300 kUnknown_TriState | |
301 }; | |
302 | |
303 // last scissor / viewport scissor state seen by the GL. | |
304 struct { | |
305 TriState fEnabled; | |
306 GrGLIRect fRect; | |
307 void invalidate() { | |
308 fEnabled = kUnknown_TriState; | |
309 fRect.invalidate(); | |
310 } | |
311 } fHWScissorSettings; | |
312 | |
313 GrGLIRect fHWViewport; | |
314 | |
315 /** | |
316 * Tracks bound vertex and index buffers and vertex attrib array state. | |
317 */ | |
318 class HWGeometryState { | |
319 public: | |
320 HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); } | |
321 | |
322 ~HWGeometryState() { SkSafeUnref(fVBOVertexArray); } | |
323 | |
324 void invalidate() { | |
325 fBoundVertexArrayIDIsValid = false; | |
326 fBoundVertexBufferIDIsValid = false; | |
327 fDefaultVertexArrayBoundIndexBufferID = false; | |
328 fDefaultVertexArrayBoundIndexBufferIDIsValid = false; | |
329 fDefaultVertexArrayAttribState.invalidate(); | |
330 if (fVBOVertexArray) { | |
331 fVBOVertexArray->invalidateCachedState(); | |
332 } | |
333 } | |
334 | |
335 void notifyVertexArrayDelete(GrGLuint id) { | |
336 if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) { | |
337 // Does implicit bind to 0 | |
338 fBoundVertexArrayID = 0; | |
339 } | |
340 } | |
341 | |
342 void setVertexArrayID(GrGLGpu* gpu, GrGLuint arrayID) { | |
343 if (!gpu->glCaps().vertexArrayObjectSupport()) { | |
344 SkASSERT(0 == arrayID); | |
345 return; | |
346 } | |
347 if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) { | |
348 GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID)); | |
349 fBoundVertexArrayIDIsValid = true; | |
350 fBoundVertexArrayID = arrayID; | |
351 } | |
352 } | |
353 | |
354 void notifyVertexBufferDelete(GrGLuint id) { | |
355 if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) { | |
356 fBoundVertexBufferID = 0; | |
357 } | |
358 if (fVBOVertexArray) { | |
359 fVBOVertexArray->notifyVertexBufferDelete(id); | |
360 } | |
361 fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id); | |
362 } | |
363 | |
364 void notifyIndexBufferDelete(GrGLuint id) { | |
365 if (fDefaultVertexArrayBoundIndexBufferIDIsValid && | |
366 id == fDefaultVertexArrayBoundIndexBufferID) { | |
367 fDefaultVertexArrayBoundIndexBufferID = 0; | |
368 } | |
369 if (fVBOVertexArray) { | |
370 fVBOVertexArray->notifyIndexBufferDelete(id); | |
371 } | |
372 } | |
373 | |
374 void setVertexBufferID(GrGLGpu* gpu, GrGLuint id) { | |
375 if (!fBoundVertexBufferIDIsValid || id != fBoundVertexBufferID) { | |
376 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ARRAY_BUFFER, id
)); | |
377 fBoundVertexBufferIDIsValid = true; | |
378 fBoundVertexBufferID = id; | |
379 } | |
380 } | |
381 | |
382 /** | |
383 * Binds the default vertex array and binds the index buffer. This is us
ed when binding | |
384 * an index buffer in order to update it. | |
385 */ | |
386 void setIndexBufferIDOnDefaultVertexArray(GrGLGpu* gpu, GrGLuint id) { | |
387 this->setVertexArrayID(gpu, 0); | |
388 if (!fDefaultVertexArrayBoundIndexBufferIDIsValid || | |
389 id != fDefaultVertexArrayBoundIndexBufferID) { | |
390 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BU
FFER, id)); | |
391 fDefaultVertexArrayBoundIndexBufferIDIsValid = true; | |
392 fDefaultVertexArrayBoundIndexBufferID = id; | |
393 } | |
394 } | |
395 | |
396 /** | |
397 * Binds the vertex array object that should be used to render from the
vertex buffer. | |
398 * The vertex array is bound and its attrib array state object is return
ed. The vertex | |
399 * buffer is bound. The index buffer (if non-NULL) is bound to the verte
x array. The | |
400 * returned GrGLAttribArrayState should be used to set vertex attribute
arrays. | |
401 */ | |
402 GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGLGpu* gpu, | |
403 const GrGLVertexBuffer*
vbuffer, | |
404 const GrGLIndexBuffer* i
buffer); | |
405 | |
406 private: | |
407 GrGLuint fBoundVertexArrayID; | |
408 GrGLuint fBoundVertexBufferID; | |
409 bool fBoundVertexArrayIDIsValid; | |
410 bool fBoundVertexBufferIDIsValid; | |
411 | |
412 GrGLuint fDefaultVertexArrayBoundIndexBufferID; | |
413 bool fDefaultVertexArrayBoundIndexBufferIDIsValid; | |
414 // We return a non-const pointer to this from bindArrayAndBuffersToDraw
when vertex array 0 | |
415 // is bound. However, this class is internal to GrGpuGL and this object
never leaks out of | |
416 // GrGpuGL. | |
417 GrGLAttribArrayState fDefaultVertexArrayAttribState; | |
418 | |
419 // This is used when we're using a core profile and the vertices are in
a VBO. | |
420 GrGLVertexArray* fVBOVertexArray; | |
421 } fHWGeometryState; | |
422 | |
423 struct { | |
424 GrBlendCoeff fSrcCoeff; | |
425 GrBlendCoeff fDstCoeff; | |
426 GrColor fConstColor; | |
427 bool fConstColorValid; | |
428 TriState fEnabled; | |
429 | |
430 void invalidate() { | |
431 fSrcCoeff = kInvalid_GrBlendCoeff; | |
432 fDstCoeff = kInvalid_GrBlendCoeff; | |
433 fConstColorValid = false; | |
434 fEnabled = kUnknown_TriState; | |
435 } | |
436 } fHWBlendState; | |
437 | |
438 TriState fMSAAEnabled; | |
439 | |
440 GrStencilSettings fHWStencilSettings; | |
441 TriState fHWStencilTestEnabled; | |
442 | |
443 | |
444 GrDrawState::DrawFace fHWDrawFace; | |
445 TriState fHWWriteToColor; | |
446 TriState fHWDitherEnabled; | |
447 uint32_t fHWBoundRenderTargetUniqueID; | |
448 SkTArray<uint32_t, true> fHWBoundTextureUniqueIDs; | |
449 | |
450 ///@} | |
451 | |
452 // we record what stencil format worked last time to hopefully exit early | |
453 // from our loop that tries stencil formats and calls check fb status. | |
454 int fLastSuccessfulStencilFmtIdx; | |
455 | |
456 typedef GrGpu INHERITED; | |
457 friend class GrGLPathRendering; // For accessing setTextureUnit. | |
458 }; | |
459 | |
460 #endif | |
OLD | NEW |