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