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
18namespace {
19
20class GLObject : public GrNonAtomicRef<GLObject> {
21public:
22    GLObject(GrGLuint id) : fID(id) {}
23    virtual ~GLObject() {}
24
25    GrGLuint id() const { return fID; }
26
27private:
28    GrGLuint fID;
29};
30
31// This class maintains a sparsely populated array of object pointers.
32template<typename T> class TGLObjectManager {
33   static_assert(std::is_convertible<T*, GLObject*>::value, "T must be a subclass of GLObject");
34
35public:
36    TGLObjectManager() : fFreeListHead(kFreeListEnd) {
37        *fGLObjects.append() = nullptr; // 0 is not a valid GL object id.
38    }
39
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
52    T* lookUp(GrGLuint id) {
53        T* object = fGLObjects[id];
54        SkASSERT(object && object->id() == id);
55        return object;
56    }
57
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
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
90private:
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
98class Buffer : public GLObject {
99public:
100    Buffer(GrGLuint id) : INHERITED(id), fDataPtr(nullptr), fSize(0), fMapped(false) {}
101    ~Buffer() { delete[] fDataPtr; }
102
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
113    GrGLchar* dataPtr()          { return fDataPtr; }
114    GrGLsizeiptr size() const    { return fSize; }
115
116    void setMapped(bool mapped)  { fMapped = mapped; }
117    bool mapped() const          { return fMapped; }
118
119private:
120    GrGLchar*    fDataPtr;
121    GrGLsizeiptr fSize;         // size in bytes
122    bool         fMapped;
123
124    typedef GLObject INHERITED;
125};
126
127class FramebufferAttachment : public GLObject {
128public:
129    int numSamples() const { return fNumSamples; }
130
131protected:
132    FramebufferAttachment(int id) : INHERITED(id), fNumSamples(1) {}
133
134    int fNumSamples;
135
136    typedef GLObject INHERITED;
137};
138
139class Renderbuffer : public FramebufferAttachment {
140public:
141    Renderbuffer(int id) : INHERITED(id) {}
142    void setNumSamples(int numSamples) { fNumSamples = numSamples; }
143
144private:
145    typedef FramebufferAttachment INHERITED;
146};
147
148class Texture : public FramebufferAttachment {
149public:
150    Texture() : INHERITED(1) {}
151
152private:
153    typedef FramebufferAttachment INHERITED;
154};
155
156class Framebuffer : public GLObject {
157public:
158    Framebuffer(int id) : INHERITED(id) {}
159
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
177    void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) {
178        for (auto& attachment : fAttachments) {
179            if (attachment.get() == deleted) {
180                attachment.reset(nullptr);
181            }
182        }
183    }
184
185    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
201private:
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 */
215class NullInterface : public GrGLTestInterface {
216public:
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
242    GrGLenum checkFramebufferStatus(GrGLenum target) override {
243        return GR_GL_FRAMEBUFFER_COMPLETE;
244    }
245
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
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
262    GrGLuint createProgram() override {
263        return ++fCurrProgramID;
264    }
265
266    GrGLuint createShader(GrGLenum type) override {
267        return ++fCurrShaderID;
268    }
269
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
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
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
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
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
332    GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
333
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
341    GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) override {
342        SkASSERT(GR_GL_RENDERBUFFER == target);
343        fCurrRenderbuffer = renderbuffer;
344    }
345
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
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
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
387    GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat,
388                                      GrGLsizei width, GrGLsizei height) override {
389        SK_ABORT("Not implemented");
390    }
391
392    GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples,
393                                                 GrGLenum GrGLinternalformat, GrGLsizei width,
394                                                 GrGLsizei height) override {
395        SK_ABORT("Not implemented");
396    }
397
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
412    GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
413                                          GrGLenum renderbuffertarget,
414                                          GrGLuint renderbuffer) override {
415        SK_ABORT("Not implemented");
416    }
417
418    GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override {
419        this->genGenericIds(n, textures);
420    }
421
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
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
436    GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
437                                       GrGLenum textarget, GrGLuint texture,
438                                       GrGLint level) override {
439        SK_ABORT("Not implemented");
440    }
441
442    GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
443                                       GrGLenum textarget, GrGLuint texture,
444                                       GrGLint level) override {
445        SK_ABORT("Not implemented");
446    }
447
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
454    GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override {
455        this->genGenericIds(n, arrays);
456    }
457
458    GrGLenum getError() override { return GR_GL_NO_ERROR; }
459
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                SK_ABORT("Unexpected pname to GetIntegerv");
531        }
532    }
533
534    GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
535        this->getShaderOrProgramiv(program, pname, params);
536    }
537
538    GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
539                               char* infolog) override {
540        this->getInfoLog(program, bufsize, length, infolog);
541    }
542
543    GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
544        val[0] = val[1] = 0.5f;
545    }
546
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                SK_ABORT("Unexpected pname passed GetQueryiv.");
557        }
558    }
559
560    GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
561        this->queryResult(id, pname, params);
562    }
563
564    GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
565        this->queryResult(id, pname, params);
566    }
567
568    GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
569        this->queryResult(id, pname, params);
570    }
571
572    GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
573        this->queryResult(id, pname, params);
574    }
575
576    GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
577        this->getShaderOrProgramiv(shader, pname, params);
578    }
579
580    GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
581                              char* infolog) override {
582        this->getInfoLog(shader, bufsize, length, infolog);
583    }
584
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                SK_ABORT("Unexpected name passed to GetString");
599                return nullptr;
600        }
601    }
602
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                SK_ABORT("Unexpected name passed to GetStringi");
616                return nullptr;
617        }
618    }
619
620    GrGLint getUniformLocation(GrGLuint program, const char* name) override {
621        return ++fCurrUniformLocation;
622    }
623
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
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
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
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                SK_ABORT("Unexpected pname to GetBufferParamateriv");
677                break;
678        }
679    }
680
681    // NV_path_rendering
682    GrGLuint genPaths(GrGLsizei range) override {
683        return ++fCurrPathID;
684    }
685
686
687private:
688    inline int static GetBufferIndex(GrGLenum glTarget) {
689        switch (glTarget) {
690            default:                           SK_ABORT("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
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
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
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
770    GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
771        for (int i = 0; i < n; ++i) {
772            ids[i] = ++fCurrGenericID;
773        }
774    }
775
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
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: // fallthru
793            case GL_PROGRAM_BINARY_LENGTH:
794                *params = 0;
795                break;
796                // we don't expect any other pnames
797            default:
798                SK_ABORT("Unexpected pname to GetProgramiv");
799                break;
800        }
801    }
802
803    template <typename T>
804    void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
805        switch (pname) {
806            case GR_GL_QUERY_RESULT_AVAILABLE:
807                *params = GR_GL_TRUE;
808                break;
809            case GR_GL_QUERY_RESULT:
810                *params = 0;
811                break;
812            default:
813                SK_ABORT("Unexpected pname passed to GetQueryObject.");
814                break;
815        }
816    }
817
818    typedef GrGLTestInterface INHERITED;
819};
820
821}  // anonymous namespace
822
823const GrGLInterface* GrGLCreateNullInterface(bool enableNVPR) { return new NullInterface(enableNVPR); }
824