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