• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "GrGLTestInterface.h"
9 #include "GrNonAtomicRef.h"
10 #include "SkMutex.h"
11 #include "SkTDArray.h"
12 #include "SkTo.h"
13 #include "gl/GrGLInterface.h"
14 
15 #include <type_traits>
16 
17 // added to suppress 'no previous prototype' warning and because this code is duplicated in
18 // SkNullGLContext.cpp
19 namespace {
20 
21 class GLObject : public GrNonAtomicRef<GLObject> {
22 public:
GLObject(GrGLuint id)23     GLObject(GrGLuint id) : fID(id) {}
~GLObject()24     virtual ~GLObject() {}
25 
id() const26     GrGLuint id() const { return fID; }
27 
28 private:
29     GrGLuint fID;
30 };
31 
32 // This class maintains a sparsely populated array of object pointers.
33 template<typename T> class TGLObjectManager {
34    static_assert(std::is_convertible<T*, GLObject*>::value, "T must be a subclass of GLObject");
35 
36 public:
TGLObjectManager()37     TGLObjectManager() : fFreeListHead(kFreeListEnd) {
38         *fGLObjects.append() = nullptr; // 0 is not a valid GL object id.
39     }
40 
~TGLObjectManager()41     ~TGLObjectManager() {
42         // nullptr out the entries that are really free list links rather than ptrs before deleting.
43         intptr_t curr = fFreeListHead;
44         while (kFreeListEnd != curr) {
45             intptr_t next = reinterpret_cast<intptr_t>(fGLObjects[SkToS32(curr)]);
46             fGLObjects[SkToS32(curr)] = nullptr;
47             curr = next;
48         }
49 
50         fGLObjects.safeUnrefAll();
51     }
52 
lookUp(GrGLuint id)53     T* lookUp(GrGLuint id) {
54         T* object = fGLObjects[id];
55         SkASSERT(object && object->id() == id);
56         return object;
57     }
58 
create()59     T* create() {
60         GrGLuint id;
61         T* object;
62 
63         if (kFreeListEnd == fFreeListHead) {
64             // no free slots - create a new one
65             id = fGLObjects.count();
66             object = new T(id);
67             *fGLObjects.append() = object;
68         } else {
69             // grab the head of the free list and advance the head to the next free slot.
70             id = static_cast<GrGLuint>(fFreeListHead);
71             fFreeListHead = reinterpret_cast<intptr_t>(fGLObjects[id]);
72 
73             object = new T(id);
74             fGLObjects[id] = object;
75         }
76 
77         return object;
78     }
79 
free(T * object)80     void free(T* object) {
81         SkASSERT(object);
82         SkASSERT(fGLObjects.count() > 0);
83 
84         GrGLuint id = object->id();
85         object->unref();
86 
87         fGLObjects[id] = reinterpret_cast<T*>(fFreeListHead);
88         fFreeListHead = id;
89     }
90 
91 private:
92     static const intptr_t kFreeListEnd = -1;
93     // Index of the first entry of fGLObjects in the free list. Free slots in fGLObjects are indices
94     // to the next free slot. The last free slot has a value of kFreeListEnd.
95     intptr_t        fFreeListHead;
96     SkTDArray<T*>   fGLObjects;
97 };
98 
99 class Buffer : public GLObject {
100 public:
Buffer(GrGLuint id)101     Buffer(GrGLuint id) : INHERITED(id), fDataPtr(nullptr), fSize(0), fMapped(false) {}
~Buffer()102     ~Buffer() { delete[] fDataPtr; }
103 
allocate(GrGLsizeiptr size,const GrGLchar * dataPtr)104     void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) {
105         if (fDataPtr) {
106             SkASSERT(0 != fSize);
107             delete[] fDataPtr;
108         }
109 
110         fSize = size;
111         fDataPtr = new char[size];
112     }
113 
dataPtr()114     GrGLchar* dataPtr()          { return fDataPtr; }
size() const115     GrGLsizeiptr size() const    { return fSize; }
116 
setMapped(bool mapped)117     void setMapped(bool mapped)  { fMapped = mapped; }
mapped() const118     bool mapped() const          { return fMapped; }
119 
120 private:
121     GrGLchar*    fDataPtr;
122     GrGLsizeiptr fSize;         // size in bytes
123     bool         fMapped;
124 
125     typedef GLObject INHERITED;
126 };
127 
128 class FramebufferAttachment : public GLObject {
129 public:
numSamples() const130     int numSamples() const { return fNumSamples; }
131 
132 protected:
FramebufferAttachment(int id)133     FramebufferAttachment(int id) : INHERITED(id), fNumSamples(1) {}
134 
135     int fNumSamples;
136 
137     typedef GLObject INHERITED;
138 };
139 
140 class Renderbuffer : public FramebufferAttachment {
141 public:
Renderbuffer(int id)142     Renderbuffer(int id) : INHERITED(id) {}
setNumSamples(int numSamples)143     void setNumSamples(int numSamples) { fNumSamples = numSamples; }
144 
145 private:
146     typedef FramebufferAttachment INHERITED;
147 };
148 
149 class Texture : public FramebufferAttachment {
150 public:
Texture()151     Texture() : INHERITED(1) {}
152 
153 private:
154     typedef FramebufferAttachment INHERITED;
155 };
156 
157 class Framebuffer : public GLObject {
158 public:
Framebuffer(int id)159     Framebuffer(int id) : INHERITED(id) {}
160 
setAttachment(GrGLenum attachmentPoint,const FramebufferAttachment * attachment)161     void setAttachment(GrGLenum attachmentPoint, const FramebufferAttachment* attachment) {
162         switch (attachmentPoint) {
163             default:
164                 SK_ABORT("Invalid framebuffer attachment.");
165                 break;
166             case GR_GL_STENCIL_ATTACHMENT:
167                 fAttachments[(int)AttachmentPoint::kStencil].reset(SkRef(attachment));
168                 break;
169             case GR_GL_DEPTH_ATTACHMENT:
170                 fAttachments[(int)AttachmentPoint::kDepth].reset(SkRef(attachment));
171                 break;
172             case GR_GL_COLOR_ATTACHMENT0:
173                 fAttachments[(int)AttachmentPoint::kColor].reset(SkRef(attachment));
174                 break;
175         }
176     }
177 
notifyAttachmentDeleteWhileBound(const FramebufferAttachment * deleted)178     void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) {
179         for (auto& attachment : fAttachments) {
180             if (attachment.get() == deleted) {
181                 attachment.reset(nullptr);
182             }
183         }
184     }
185 
numSamples() const186     int numSamples() const {
187         int numSamples = 0;
188         for (auto& attachment : fAttachments) {
189             if (!attachment) {
190                 continue;
191             }
192             if (numSamples) {
193                 GrAlwaysAssert(attachment->numSamples() == numSamples);
194                 continue;
195             }
196             numSamples = attachment->numSamples();
197         }
198         GrAlwaysAssert(numSamples);
199         return numSamples;
200     }
201 
202 private:
203     enum AttachmentPoint {
204         kStencil,
205         kDepth,
206         kColor
207     };
208     constexpr int static kNumAttachmentPoints = 1 + (int)AttachmentPoint::kColor;
209 
210     sk_sp<const FramebufferAttachment> fAttachments[kNumAttachmentPoints];
211 
212     typedef GLObject INHERITED;
213 };
214 
215 /** Null interface implementation */
216 class NullInterface : public GrGLTestInterface {
217 public:
NullInterface(bool enableNVPR)218     NullInterface(bool enableNVPR)
219         : fCurrDrawFramebuffer(0)
220         , fCurrReadFramebuffer(0)
221         , fCurrRenderbuffer(0)
222         , fCurrProgramID(0)
223         , fCurrShaderID(0)
224         , fCurrGenericID(0)
225         , fCurrUniformLocation(0)
226         , fCurrPathID(0) {
227         memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
228         fAdvertisedExtensions.push_back("GL_ARB_framebuffer_object");
229         fAdvertisedExtensions.push_back("GL_ARB_blend_func_extended");
230         fAdvertisedExtensions.push_back("GL_ARB_timer_query");
231         fAdvertisedExtensions.push_back("GL_ARB_draw_buffers");
232         fAdvertisedExtensions.push_back("GL_ARB_occlusion_query");
233         fAdvertisedExtensions.push_back("GL_EXT_stencil_wrap");
234         if (enableNVPR) {
235             fAdvertisedExtensions.push_back("GL_NV_path_rendering");
236             fAdvertisedExtensions.push_back("GL_ARB_program_interface_query");
237         }
238         fAdvertisedExtensions.push_back(nullptr);
239 
240         this->init(kGL_GrGLStandard);
241     }
242 
checkFramebufferStatus(GrGLenum target)243     GrGLenum checkFramebufferStatus(GrGLenum target) override {
244         return GR_GL_FRAMEBUFFER_COMPLETE;
245     }
246 
genBuffers(GrGLsizei n,GrGLuint * ids)247     GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override {
248         for (int i = 0; i < n; ++i) {
249             Buffer* buffer = fBufferManager.create();
250             ids[i] = buffer->id();
251         }
252     }
253 
bufferData(GrGLenum target,GrGLsizeiptr size,const GrGLvoid * data,GrGLenum usage)254     GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
255                         GrGLenum usage) override {
256         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
257         if (id > 0) {
258             Buffer* buffer = fBufferManager.lookUp(id);
259             buffer->allocate(size, (const GrGLchar*) data);
260         }
261     }
262 
createProgram()263     GrGLuint createProgram() override {
264         return ++fCurrProgramID;
265     }
266 
createShader(GrGLenum type)267     GrGLuint createShader(GrGLenum type) override {
268         return ++fCurrShaderID;
269     }
270 
bindBuffer(GrGLenum target,GrGLuint buffer)271     GrGLvoid bindBuffer(GrGLenum target, GrGLuint buffer) override {
272         fBoundBuffers[GetBufferIndex(target)] = buffer;
273     }
274 
275    // deleting a bound buffer has the side effect of binding 0
deleteBuffers(GrGLsizei n,const GrGLuint * ids)276    GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* ids) override {
277         // First potentially unbind the buffers.
278         for (int buffIdx = 0; buffIdx < kNumBufferTargets; ++buffIdx) {
279             if (!fBoundBuffers[buffIdx]) {
280                 continue;
281             }
282             for (int i = 0; i < n; ++i) {
283                 if (ids[i] == fBoundBuffers[buffIdx]) {
284                     fBoundBuffers[buffIdx] = 0;
285                     break;
286                 }
287             }
288         }
289 
290         // Then actually "delete" the buffers.
291         for (int i = 0; i < n; ++i) {
292             if (ids[i] > 0) {
293                 Buffer* buffer = fBufferManager.lookUp(ids[i]);
294                 fBufferManager.free(buffer);
295             }
296         }
297     }
298 
genFramebuffers(GrGLsizei n,GrGLuint * framebuffers)299     GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override {
300         for (int i = 0; i < n; ++i) {
301             Framebuffer* framebuffer = fFramebufferManager.create();
302             framebuffers[i] = framebuffer->id();
303         }
304     }
305 
bindFramebuffer(GrGLenum target,GrGLuint framebuffer)306     GrGLvoid bindFramebuffer(GrGLenum target, GrGLuint framebuffer) override {
307         SkASSERT(GR_GL_FRAMEBUFFER == target || GR_GL_DRAW_FRAMEBUFFER == target ||
308                  GR_GL_READ_FRAMEBUFFER == target);
309         if (GR_GL_READ_FRAMEBUFFER != target) {
310             fCurrDrawFramebuffer = framebuffer;
311         }
312         if (GR_GL_DRAW_FRAMEBUFFER != target) {
313             fCurrReadFramebuffer = framebuffer;
314         }
315     }
316 
deleteFramebuffers(GrGLsizei n,const GrGLuint * ids)317     GrGLvoid deleteFramebuffers(GrGLsizei n, const GrGLuint* ids) override {
318         for (int i = 0; i < n; ++i) {
319             if (ids[i] == fCurrDrawFramebuffer) {
320                 fCurrDrawFramebuffer = 0;
321             }
322             if (ids[i] == fCurrReadFramebuffer) {
323                 fCurrReadFramebuffer = 0;
324             }
325 
326             if (ids[i] > 0) {
327                 Framebuffer* framebuffer = fFramebufferManager.lookUp(ids[i]);
328                 fFramebufferManager.free(framebuffer);
329             }
330         }
331     }
332 
genQueries(GrGLsizei n,GrGLuint * ids)333     GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
334 
genRenderbuffers(GrGLsizei n,GrGLuint * renderbuffers)335     GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override {
336         for (int i = 0; i < n; ++i) {
337             Renderbuffer* renderbuffer = fRenderbufferManager.create();
338             renderbuffers[i] = renderbuffer->id();
339         }
340     }
341 
bindRenderbuffer(GrGLenum target,GrGLuint renderbuffer)342     GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) override {
343         SkASSERT(GR_GL_RENDERBUFFER == target);
344         fCurrRenderbuffer = renderbuffer;
345     }
346 
deleteRenderbuffers(GrGLsizei n,const GrGLuint * ids)347     GrGLvoid deleteRenderbuffers(GrGLsizei n, const GrGLuint* ids) override {
348         for (int i = 0; i < n; ++i) {
349             if (ids[i] <= 0) {
350                 continue;
351             }
352             if (ids[i] == fCurrRenderbuffer) {
353                 fCurrRenderbuffer = 0;
354             }
355             Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(ids[i]);
356 
357             if (fCurrDrawFramebuffer) {
358                 Framebuffer* drawFramebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
359                 drawFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer);
360             }
361             if (fCurrReadFramebuffer) {
362                 Framebuffer* readFramebuffer = fFramebufferManager.lookUp(fCurrReadFramebuffer);
363                 readFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer);
364             }
365 
366             fRenderbufferManager.free(renderbuffer);
367         }
368     }
369 
renderbufferStorage(GrGLenum target,GrGLenum internalformat,GrGLsizei width,GrGLsizei height)370     GrGLvoid renderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width,
371                                  GrGLsizei height) override {
372         GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
373         GrAlwaysAssert(fCurrRenderbuffer);
374         Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
375         renderbuffer->setNumSamples(1);
376     }
377 
renderbufferStorageMultisample(GrGLenum target,GrGLsizei samples,GrGLenum internalformat,GrGLsizei width,GrGLsizei height)378     GrGLvoid renderbufferStorageMultisample(GrGLenum target, GrGLsizei samples,
379                                             GrGLenum internalformat, GrGLsizei width,
380                                             GrGLsizei height) override {
381         GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
382         GrAlwaysAssert(samples > 0);
383         GrAlwaysAssert(fCurrRenderbuffer);
384         Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
385         renderbuffer->setNumSamples(samples);
386     }
387 
namedRenderbufferStorage(GrGLuint renderbuffer,GrGLenum GrGLinternalformat,GrGLsizei width,GrGLsizei height)388     GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat,
389                                       GrGLsizei width, GrGLsizei height) override {
390         SK_ABORT("Not implemented");
391     }
392 
namedRenderbufferStorageMultisample(GrGLuint renderbuffer,GrGLsizei samples,GrGLenum GrGLinternalformat,GrGLsizei width,GrGLsizei height)393     GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples,
394                                                  GrGLenum GrGLinternalformat, GrGLsizei width,
395                                                  GrGLsizei height) override {
396         SK_ABORT("Not implemented");
397     }
398 
framebufferRenderbuffer(GrGLenum target,GrGLenum attachment,GrGLenum renderbuffertarget,GrGLuint renderBufferID)399     GrGLvoid framebufferRenderbuffer(GrGLenum target, GrGLenum attachment,
400                                      GrGLenum renderbuffertarget,
401                                      GrGLuint renderBufferID) override {
402         GrGLuint id = this->getBoundFramebufferID(target);
403         GrAlwaysAssert(id);
404         Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
405 
406         GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget);
407         if (!renderBufferID && !fCurrRenderbuffer) {
408            return;
409         }
410         GrAlwaysAssert(fCurrRenderbuffer);
411         Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
412 
413         framebuffer->setAttachment(attachment, renderbuffer);
414     }
415 
namedFramebufferRenderbuffer(GrGLuint framebuffer,GrGLenum attachment,GrGLenum renderbuffertarget,GrGLuint renderbuffer)416     GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
417                                           GrGLenum renderbuffertarget,
418                                           GrGLuint renderbuffer) override {
419         SK_ABORT("Not implemented");
420     }
421 
genSamplers(GrGLsizei n,GrGLuint * samplers)422     GrGLvoid genSamplers(GrGLsizei n, GrGLuint* samplers) override {
423         this->genGenericIds(n, samplers);
424     }
425 
genTextures(GrGLsizei n,GrGLuint * textures)426     GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override {
427         this->genGenericIds(n, textures);
428     }
429 
framebufferTexture2D(GrGLenum target,GrGLenum attachment,GrGLenum textarget,GrGLuint textureID,GrGLint level)430     GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget,
431                                   GrGLuint textureID, GrGLint level) override {
432         GrGLuint id = this->getBoundFramebufferID(target);
433         GrAlwaysAssert(id);
434         Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
435         framebuffer->setAttachment(attachment, this->getSingleTextureObject());
436     }
437 
framebufferTexture2DMultisample(GrGLenum target,GrGLenum attachment,GrGLenum textarget,GrGLuint texture,GrGLint level,GrGLsizei samples)438     GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment,
439                                              GrGLenum textarget, GrGLuint texture, GrGLint level,
440                                              GrGLsizei samples) override {
441         SK_ABORT("Not implemented");
442     }
443 
namedFramebufferTexture1D(GrGLuint framebuffer,GrGLenum attachment,GrGLenum textarget,GrGLuint texture,GrGLint level)444     GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
445                                        GrGLenum textarget, GrGLuint texture,
446                                        GrGLint level) override {
447         SK_ABORT("Not implemented");
448     }
449 
namedFramebufferTexture2D(GrGLuint framebuffer,GrGLenum attachment,GrGLenum textarget,GrGLuint texture,GrGLint level)450     GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
451                                        GrGLenum textarget, GrGLuint texture,
452                                        GrGLint level) override {
453         SK_ABORT("Not implemented");
454     }
455 
namedFramebufferTexture3D(GrGLuint framebuffer,GrGLenum attachment,GrGLenum textarget,GrGLuint texture,GrGLint level,GrGLint zoffset)456     GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment,
457                                        GrGLenum textarget, GrGLuint texture, GrGLint level,
458                                        GrGLint zoffset) override {
459         SK_ABORT("Not implemented");
460     }
461 
genVertexArrays(GrGLsizei n,GrGLuint * arrays)462     GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override {
463         this->genGenericIds(n, arrays);
464     }
465 
getError()466     GrGLenum getError() override { return GR_GL_NO_ERROR; }
467 
getIntegerv(GrGLenum pname,GrGLint * params)468     GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override {
469         // TODO: remove from Ganesh the #defines for gets we don't use.
470         // We would like to minimize gets overall due to performance issues
471         switch (pname) {
472             case GR_GL_CONTEXT_PROFILE_MASK:
473                 *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
474                 break;
475             case GR_GL_STENCIL_BITS:
476                 *params = 8;
477                 break;
478             case GR_GL_SAMPLES: {
479                 GrAlwaysAssert(fCurrDrawFramebuffer);
480                 Framebuffer* framebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
481                 *params = framebuffer->numSamples();
482                 break;
483             }
484             case GR_GL_FRAMEBUFFER_BINDING:
485                 *params = 0;
486                 break;
487             case GR_GL_VIEWPORT:
488                 params[0] = 0;
489                 params[1] = 0;
490                 params[2] = 800;
491                 params[3] = 600;
492                 break;
493             case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
494             case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
495             case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
496             case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
497                 *params = 8;
498                 break;
499             case GR_GL_MAX_TEXTURE_COORDS:
500                 *params = 8;
501                 break;
502             case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
503                 *params = kDefaultMaxVertexUniformVectors;
504                 break;
505             case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
506                 *params = kDefaultMaxFragmentUniformVectors;
507                 break;
508             case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
509                 *params = 16 * 4;
510                 break;
511             case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
512                 *params = 0;
513                 break;
514             case GR_GL_COMPRESSED_TEXTURE_FORMATS:
515                 break;
516             case GR_GL_MAX_TEXTURE_SIZE:
517                 *params = 8192;
518                 break;
519             case GR_GL_MAX_RENDERBUFFER_SIZE:
520                 *params = 8192;
521                 break;
522             case GR_GL_MAX_SAMPLES:
523                 *params = 32;
524                 break;
525             case GR_GL_MAX_VERTEX_ATTRIBS:
526                 *params = kDefaultMaxVertexAttribs;
527                 break;
528             case GR_GL_MAX_VARYING_VECTORS:
529                 *params = kDefaultMaxVaryingVectors;
530                 break;
531             case GR_GL_NUM_EXTENSIONS: {
532                 GrGLint i = 0;
533                 while (fAdvertisedExtensions[i++]);
534                 *params = i;
535                 break;
536             }
537             default:
538                 SK_ABORT("Unexpected pname to GetIntegerv");
539         }
540     }
541 
getProgramiv(GrGLuint program,GrGLenum pname,GrGLint * params)542     GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
543         this->getShaderOrProgramiv(program, pname, params);
544     }
545 
getProgramInfoLog(GrGLuint program,GrGLsizei bufsize,GrGLsizei * length,char * infolog)546     GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
547                                char* infolog) override {
548         this->getInfoLog(program, bufsize, length, infolog);
549     }
550 
getMultisamplefv(GrGLenum pname,GrGLuint index,GrGLfloat * val)551     GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
552         val[0] = val[1] = 0.5f;
553     }
554 
getQueryiv(GrGLenum GLtarget,GrGLenum pname,GrGLint * params)555     GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override {
556         switch (pname) {
557             case GR_GL_CURRENT_QUERY:
558                 *params = 0;
559                 break;
560             case GR_GL_QUERY_COUNTER_BITS:
561                 *params = 32;
562                 break;
563             default:
564                 SK_ABORT("Unexpected pname passed GetQueryiv.");
565         }
566     }
567 
getQueryObjecti64v(GrGLuint id,GrGLenum pname,GrGLint64 * params)568     GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
569         this->queryResult(id, pname, params);
570     }
571 
getQueryObjectiv(GrGLuint id,GrGLenum pname,GrGLint * params)572     GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
573         this->queryResult(id, pname, params);
574     }
575 
getQueryObjectui64v(GrGLuint id,GrGLenum pname,GrGLuint64 * params)576     GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
577         this->queryResult(id, pname, params);
578     }
579 
getQueryObjectuiv(GrGLuint id,GrGLenum pname,GrGLuint * params)580     GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
581         this->queryResult(id, pname, params);
582     }
583 
getShaderiv(GrGLuint shader,GrGLenum pname,GrGLint * params)584     GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
585         this->getShaderOrProgramiv(shader, pname, params);
586     }
587 
getShaderInfoLog(GrGLuint shader,GrGLsizei bufsize,GrGLsizei * length,char * infolog)588     GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
589                               char* infolog) override {
590         this->getInfoLog(shader, bufsize, length, infolog);
591     }
592 
getString(GrGLenum name)593     const GrGLubyte* getString(GrGLenum name) override {
594         switch (name) {
595             case GR_GL_EXTENSIONS:
596                 return CombinedExtensionString();
597             case GR_GL_VERSION:
598                 return (const GrGLubyte*)"4.0 Null GL";
599             case GR_GL_SHADING_LANGUAGE_VERSION:
600                 return (const GrGLubyte*)"4.20.8 Null GLSL";
601             case GR_GL_VENDOR:
602                 return (const GrGLubyte*)"Null Vendor";
603             case GR_GL_RENDERER:
604                 return (const GrGLubyte*)"The Null (Non-)Renderer";
605             default:
606                 SK_ABORT("Unexpected name passed to GetString");
607                 return nullptr;
608         }
609     }
610 
getStringi(GrGLenum name,GrGLuint i)611     const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override {
612         switch (name) {
613             case GR_GL_EXTENSIONS: {
614                 GrGLint count;
615                 this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count);
616                 if ((GrGLint)i <= count) {
617                     return (const GrGLubyte*) fAdvertisedExtensions[i];
618                 } else {
619                     return nullptr;
620                 }
621             }
622             default:
623                 SK_ABORT("Unexpected name passed to GetStringi");
624                 return nullptr;
625         }
626     }
627 
getUniformLocation(GrGLuint program,const char * name)628     GrGLint getUniformLocation(GrGLuint program, const char* name) override {
629         return ++fCurrUniformLocation;
630     }
631 
mapBufferRange(GrGLenum target,GrGLintptr offset,GrGLsizeiptr length,GrGLbitfield access)632     GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length,
633                              GrGLbitfield access) override {
634         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
635         if (id > 0) {
636             // We just ignore the offset and length here.
637             Buffer* buffer = fBufferManager.lookUp(id);
638             SkASSERT(!buffer->mapped());
639             buffer->setMapped(true);
640             return buffer->dataPtr();
641         }
642         return nullptr;
643     }
644 
mapBuffer(GrGLenum target,GrGLenum access)645     GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override {
646         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
647         if (id > 0) {
648             Buffer* buffer = fBufferManager.lookUp(id);
649             SkASSERT(!buffer->mapped());
650             buffer->setMapped(true);
651             return buffer->dataPtr();
652         }
653 
654         SkASSERT(false);
655         return nullptr;            // no buffer bound to target
656     }
657 
unmapBuffer(GrGLenum target)658     GrGLboolean unmapBuffer(GrGLenum target) override {
659         GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
660         if (id > 0) {
661             Buffer* buffer = fBufferManager.lookUp(id);
662             SkASSERT(buffer->mapped());
663             buffer->setMapped(false);
664             return GR_GL_TRUE;
665         }
666 
667         GrAlwaysAssert(false);
668         return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
669     }
670 
getBufferParameteriv(GrGLenum target,GrGLenum pname,GrGLint * params)671     GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) override {
672         switch (pname) {
673             case GR_GL_BUFFER_MAPPED: {
674                 *params = GR_GL_FALSE;
675                 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
676                 if (id > 0) {
677                     Buffer* buffer = fBufferManager.lookUp(id);
678                     if (buffer->mapped()) {
679                         *params = GR_GL_TRUE;
680                     }
681                 }
682                 break; }
683             default:
684                 SK_ABORT("Unexpected pname to GetBufferParamateriv");
685                 break;
686         }
687     }
688 
689     // NV_path_rendering
genPaths(GrGLsizei range)690     GrGLuint genPaths(GrGLsizei range) override {
691         return ++fCurrPathID;
692     }
693 
694 
695 private:
GetBufferIndex(GrGLenum glTarget)696     inline int static GetBufferIndex(GrGLenum glTarget) {
697         switch (glTarget) {
698             default:                           SK_ABORT("Unexpected GL target to GetBufferIndex");
699             case GR_GL_ARRAY_BUFFER:           return 0;
700             case GR_GL_ELEMENT_ARRAY_BUFFER:   return 1;
701             case GR_GL_TEXTURE_BUFFER:         return 2;
702             case GR_GL_DRAW_INDIRECT_BUFFER:   return 3;
703             case GR_GL_PIXEL_PACK_BUFFER:      return 4;
704             case GR_GL_PIXEL_UNPACK_BUFFER:    return 5;
705         }
706     }
707     constexpr int static kNumBufferTargets = 6;
708 
709     TGLObjectManager<Buffer>         fBufferManager;
710     GrGLuint                         fBoundBuffers[kNumBufferTargets];
711     TGLObjectManager<Framebuffer>    fFramebufferManager;
712     GrGLuint                         fCurrDrawFramebuffer;
713     GrGLuint                         fCurrReadFramebuffer;
714     TGLObjectManager<Renderbuffer>   fRenderbufferManager;
715     GrGLuint                         fCurrRenderbuffer;
716     GrGLuint                         fCurrProgramID;
717     GrGLuint                         fCurrShaderID;
718     GrGLuint                         fCurrGenericID;
719     GrGLuint                         fCurrUniformLocation;
720     GrGLuint                         fCurrPathID;
721     sk_sp<const Texture>             fSingleTextureObject;
722     SkTArray<const char*>            fAdvertisedExtensions;
723 
724     // the OpenGLES 2.0 spec says this must be >= 128
725     static const GrGLint kDefaultMaxVertexUniformVectors = 128;
726 
727     // the OpenGLES 2.0 spec says this must be >=16
728     static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
729 
730     // the OpenGLES 2.0 spec says this must be >= 8
731     static const GrGLint kDefaultMaxVertexAttribs = 8;
732 
733     // the OpenGLES 2.0 spec says this must be >= 8
734     static const GrGLint kDefaultMaxVaryingVectors = 8;
735 
getBoundFramebufferID(GrGLenum target)736     GrGLuint getBoundFramebufferID(GrGLenum target) {
737         switch (target) {
738             case GR_GL_FRAMEBUFFER:
739             case GR_GL_DRAW_FRAMEBUFFER:
740                 return fCurrDrawFramebuffer;
741             case GR_GL_READ_FRAMEBUFFER:
742                 return fCurrReadFramebuffer;
743             default:
744                 SK_ABORT("Invalid framebuffer target.");
745                 return 0;
746         }
747     }
748 
getSingleTextureObject()749     const Texture* getSingleTextureObject() {
750         // We currently only use FramebufferAttachment objects for a sample count, and all textures
751         // in Skia have one sample, so there is no need as of yet to track individual textures. This
752         // also works around a bug in chromium's cc_unittests where they send us texture IDs that
753         // were generated by cc::TestGLES2Interface.
754         if (!fSingleTextureObject) {
755             fSingleTextureObject.reset(new Texture);
756         }
757         return fSingleTextureObject.get();
758     }
759 
CombinedExtensionString()760     const GrGLubyte* CombinedExtensionString() {
761         static SkString gExtString;
762         static SkMutex gMutex;
763         gMutex.acquire();
764         if (0 == gExtString.size()) {
765             int i = 0;
766             while (fAdvertisedExtensions[i]) {
767                 if (i > 0) {
768                     gExtString.append(" ");
769                 }
770                 gExtString.append(fAdvertisedExtensions[i]);
771                 ++i;
772             }
773         }
774         gMutex.release();
775         return (const GrGLubyte*) gExtString.c_str();
776     }
777 
genGenericIds(GrGLsizei n,GrGLuint * ids)778     GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
779         for (int i = 0; i < n; ++i) {
780             ids[i] = ++fCurrGenericID;
781         }
782     }
783 
getInfoLog(GrGLuint object,GrGLsizei bufsize,GrGLsizei * length,char * infolog)784     GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length,
785                         char* infolog) {
786         if (length) {
787             *length = 0;
788         }
789         if (bufsize > 0) {
790             *infolog = 0;
791         }
792     }
793 
getShaderOrProgramiv(GrGLuint object,GrGLenum pname,GrGLint * params)794     GrGLvoid getShaderOrProgramiv(GrGLuint object,  GrGLenum pname, GrGLint* params) {
795         switch (pname) {
796             case GR_GL_LINK_STATUS:  // fallthru
797             case GR_GL_COMPILE_STATUS:
798                 *params = GR_GL_TRUE;
799                 break;
800             case GR_GL_INFO_LOG_LENGTH: // fallthru
801             case GL_PROGRAM_BINARY_LENGTH:
802                 *params = 0;
803                 break;
804                 // we don't expect any other pnames
805             default:
806                 SK_ABORT("Unexpected pname to GetProgramiv");
807                 break;
808         }
809     }
810 
811     template <typename T>
queryResult(GrGLenum GLtarget,GrGLenum pname,T * params)812     void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
813         switch (pname) {
814             case GR_GL_QUERY_RESULT_AVAILABLE:
815                 *params = GR_GL_TRUE;
816                 break;
817             case GR_GL_QUERY_RESULT:
818                 *params = 0;
819                 break;
820             default:
821                 SK_ABORT("Unexpected pname passed to GetQueryObject.");
822                 break;
823         }
824     }
825 
826     typedef GrGLTestInterface INHERITED;
827 };
828 
829 }  // anonymous namespace
830 
GrGLCreateNullInterface(bool enableNVPR)831 const GrGLInterface* GrGLCreateNullInterface(bool enableNVPR) { return new NullInterface(enableNVPR); }
832