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