blob: a14fc673513b2825bdc927e7c97ffc14566f3bd7 [file] [log] [blame]
bsalomon@google.com74913722011-10-27 20:44:19 +00001/*
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
Hal Canaryfdcfb8b2018-06-13 09:42:32 -04008#include "GrGLTestInterface.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -04009#include "GrNonAtomicRef.h"
bsalomonb5a94e32016-03-18 12:07:24 -070010#include "SkMutex.h"
bsalomon@google.com21cbec42013-01-07 17:23:00 +000011#include "SkTDArray.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040012#include "SkTo.h"
13#include "gl/GrGLInterface.h"
14
csmartdaltonb593a762016-06-23 13:42:13 -070015#include <type_traits>
bsalomon7e340072015-02-11 12:07:31 -080016
17// added to suppress 'no previous prototype' warning and because this code is duplicated in
18// SkNullGLContext.cpp
halcanary9d524f22016-03-29 09:03:52 -070019namespace {
bsalomon7e340072015-02-11 12:07:31 -080020
csmartdaltonb593a762016-06-23 13:42:13 -070021class GLObject : public GrNonAtomicRef<GLObject> {
robertphillips@google.comd6543e52013-07-18 17:39:14 +000022public:
csmartdaltonb593a762016-06-23 13:42:13 -070023 GLObject(GrGLuint id) : fID(id) {}
24 virtual ~GLObject() {}
25
26 GrGLuint id() const { return fID; }
27
28private:
29 GrGLuint fID;
30};
31
32// This class maintains a sparsely populated array of object pointers.
33template<typename T> class TGLObjectManager {
34 static_assert(std::is_convertible<T*, GLObject*>::value, "T must be a subclass of GLObject");
35
36public:
37 TGLObjectManager() : fFreeListHead(kFreeListEnd) {
38 *fGLObjects.append() = nullptr; // 0 is not a valid GL object id.
39 }
40
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
53 T* lookUp(GrGLuint id) {
54 T* object = fGLObjects[id];
55 SkASSERT(object && object->id() == id);
56 return object;
57 }
58
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
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
91private:
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
99class Buffer : public GLObject {
100public:
101 Buffer(GrGLuint id) : INHERITED(id), fDataPtr(nullptr), fSize(0), fMapped(false) {}
102 ~Buffer() { delete[] fDataPtr; }
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000103
robertphillips@google.comae6b7772013-07-18 18:07:39 +0000104 void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) {
bsalomon49f085d2014-09-05 13:34:00 -0700105 if (fDataPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000106 SkASSERT(0 != fSize);
halcanary385fe4d2015-08-26 13:07:48 -0700107 delete[] fDataPtr;
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000108 }
109
110 fSize = size;
halcanary385fe4d2015-08-26 13:07:48 -0700111 fDataPtr = new char[size];
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000112 }
113
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000114 GrGLchar* dataPtr() { return fDataPtr; }
robertphillips@google.comae6b7772013-07-18 18:07:39 +0000115 GrGLsizeiptr size() const { return fSize; }
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000116
117 void setMapped(bool mapped) { fMapped = mapped; }
118 bool mapped() const { return fMapped; }
119
120private:
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000121 GrGLchar* fDataPtr;
robertphillips@google.comae6b7772013-07-18 18:07:39 +0000122 GrGLsizeiptr fSize; // size in bytes
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000123 bool fMapped;
csmartdaltonb593a762016-06-23 13:42:13 -0700124
125 typedef GLObject INHERITED;
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000126};
127
csmartdaltonb593a762016-06-23 13:42:13 -0700128class FramebufferAttachment : public GLObject {
bsalomon776d3552014-08-14 08:13:27 -0700129public:
csmartdaltonb593a762016-06-23 13:42:13 -0700130 int numSamples() const { return fNumSamples; }
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000131
csmartdaltonb593a762016-06-23 13:42:13 -0700132protected:
133 FramebufferAttachment(int id) : INHERITED(id), fNumSamples(1) {}
134
135 int fNumSamples;
136
137 typedef GLObject INHERITED;
138};
139
140class Renderbuffer : public FramebufferAttachment {
141public:
142 Renderbuffer(int id) : INHERITED(id) {}
143 void setNumSamples(int numSamples) { fNumSamples = numSamples; }
144
145private:
146 typedef FramebufferAttachment INHERITED;
147};
148
149class Texture : public FramebufferAttachment {
150public:
151 Texture() : INHERITED(1) {}
152
153private:
154 typedef FramebufferAttachment INHERITED;
155};
156
157class Framebuffer : public GLObject {
158public:
159 Framebuffer(int id) : INHERITED(id) {}
160
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;
bsalomon776d3552014-08-14 08:13:27 -0700175 }
brianosman37feccb2016-06-23 06:11:51 -0700176 }
177
csmartdaltonb593a762016-06-23 13:42:13 -0700178 void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) {
179 for (auto& attachment : fAttachments) {
Hal Canary144caf52016-11-07 17:57:18 -0500180 if (attachment.get() == deleted) {
csmartdaltonb593a762016-06-23 13:42:13 -0700181 attachment.reset(nullptr);
182 }
brianosman37feccb2016-06-23 06:11:51 -0700183 }
brianosman37feccb2016-06-23 06:11:51 -0700184 }
185
csmartdaltonb593a762016-06-23 13:42:13 -0700186 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;
bsalomon776d3552014-08-14 08:13:27 -0700200 }
201
202private:
csmartdaltonb593a762016-06-23 13:42:13 -0700203 enum AttachmentPoint {
204 kStencil,
205 kDepth,
206 kColor
207 };
208 constexpr int static kNumAttachmentPoints = 1 + (int)AttachmentPoint::kColor;
209
Hal Canary144caf52016-11-07 17:57:18 -0500210 sk_sp<const FramebufferAttachment> fAttachments[kNumAttachmentPoints];
csmartdaltonb593a762016-06-23 13:42:13 -0700211
212 typedef GLObject INHERITED;
bsalomon776d3552014-08-14 08:13:27 -0700213};
214
bsalomonb5a94e32016-03-18 12:07:24 -0700215/** Null interface implementation */
216class NullInterface : public GrGLTestInterface {
bsalomon776d3552014-08-14 08:13:27 -0700217public:
svaisanenb988ecf2016-04-20 00:36:53 -0700218 NullInterface(bool enableNVPR)
csmartdaltonb593a762016-06-23 13:42:13 -0700219 : fCurrDrawFramebuffer(0)
220 , fCurrReadFramebuffer(0)
221 , fCurrRenderbuffer(0)
222 , fCurrProgramID(0)
bsalomonb5a94e32016-03-18 12:07:24 -0700223 , fCurrShaderID(0)
224 , fCurrGenericID(0)
svaisanenb988ecf2016-04-20 00:36:53 -0700225 , fCurrUniformLocation(0)
226 , fCurrPathID(0) {
csmartdalton9b972c42016-06-21 07:55:17 -0700227 memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500228 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");
svaisanenb988ecf2016-04-20 00:36:53 -0700234 if (enableNVPR) {
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500235 fAdvertisedExtensions.push_back("GL_NV_path_rendering");
236 fAdvertisedExtensions.push_back("GL_ARB_program_interface_query");
svaisanenb988ecf2016-04-20 00:36:53 -0700237 }
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500238 fAdvertisedExtensions.push_back(nullptr);
svaisanenb988ecf2016-04-20 00:36:53 -0700239
bsalomonb5a94e32016-03-18 12:07:24 -0700240 this->init(kGL_GrGLStandard);
241 }
bsalomon776d3552014-08-14 08:13:27 -0700242
bsalomonb5a94e32016-03-18 12:07:24 -0700243 GrGLenum checkFramebufferStatus(GrGLenum target) override {
244 return GR_GL_FRAMEBUFFER_COMPLETE;
245 }
246
247 GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override {
248 for (int i = 0; i < n; ++i) {
csmartdaltonb593a762016-06-23 13:42:13 -0700249 Buffer* buffer = fBufferManager.create();
bsalomonb5a94e32016-03-18 12:07:24 -0700250 ids[i] = buffer->id();
251 }
252 }
253
254 GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
255 GrGLenum usage) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700256 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700257 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700258 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700259 buffer->allocate(size, (const GrGLchar*) data);
260 }
261 }
262
263 GrGLuint createProgram() override {
264 return ++fCurrProgramID;
265 }
266
267 GrGLuint createShader(GrGLenum type) override {
268 return ++fCurrShaderID;
269 }
270
271 GrGLvoid bindBuffer(GrGLenum target, GrGLuint buffer) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700272 fBoundBuffers[GetBufferIndex(target)] = buffer;
bsalomonb5a94e32016-03-18 12:07:24 -0700273 }
274
275 // deleting a bound buffer has the side effect of binding 0
csmartdalton9b972c42016-06-21 07:55:17 -0700276 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;
bsalomonb5a94e32016-03-18 12:07:24 -0700281 }
csmartdalton9b972c42016-06-21 07:55:17 -0700282 for (int i = 0; i < n; ++i) {
283 if (ids[i] == fBoundBuffers[buffIdx]) {
284 fBoundBuffers[buffIdx] = 0;
285 break;
286 }
bsalomonb5a94e32016-03-18 12:07:24 -0700287 }
csmartdalton9b972c42016-06-21 07:55:17 -0700288 }
bsalomonb5a94e32016-03-18 12:07:24 -0700289
csmartdalton9b972c42016-06-21 07:55:17 -0700290 // Then actually "delete" the buffers.
291 for (int i = 0; i < n; ++i) {
cdaltona957b8a2016-04-06 13:36:38 -0700292 if (ids[i] > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700293 Buffer* buffer = fBufferManager.lookUp(ids[i]);
cdaltona957b8a2016-04-06 13:36:38 -0700294 fBufferManager.free(buffer);
295 }
bsalomonb5a94e32016-03-18 12:07:24 -0700296 }
297 }
298
299 GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override {
csmartdaltonb593a762016-06-23 13:42:13 -0700300 for (int i = 0; i < n; ++i) {
301 Framebuffer* framebuffer = fFramebufferManager.create();
302 framebuffers[i] = framebuffer->id();
303 }
304 }
305
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
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 }
bsalomonb5a94e32016-03-18 12:07:24 -0700331 }
332
333 GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
334
335 GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override {
csmartdaltonb593a762016-06-23 13:42:13 -0700336 for (int i = 0; i < n; ++i) {
337 Renderbuffer* renderbuffer = fRenderbufferManager.create();
338 renderbuffers[i] = renderbuffer->id();
339 }
340 }
341
342 GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) override {
343 SkASSERT(GR_GL_RENDERBUFFER == target);
344 fCurrRenderbuffer = renderbuffer;
345 }
346
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
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
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
388 GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat,
389 GrGLsizei width, GrGLsizei height) override {
390 SK_ABORT("Not implemented");
391 }
392
393 GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples,
394 GrGLenum GrGLinternalformat, GrGLsizei width,
395 GrGLsizei height) override {
396 SK_ABORT("Not implemented");
397 }
398
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);
Adrienne Walker3a69c742018-05-21 11:05:48 -0700407 if (!renderBufferID && !fCurrRenderbuffer) {
408 return;
409 }
csmartdaltonb593a762016-06-23 13:42:13 -0700410 GrAlwaysAssert(fCurrRenderbuffer);
411 Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
412
413 framebuffer->setAttachment(attachment, renderbuffer);
414 }
415
416 GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
417 GrGLenum renderbuffertarget,
418 GrGLuint renderbuffer) override {
419 SK_ABORT("Not implemented");
bsalomonb5a94e32016-03-18 12:07:24 -0700420 }
421
422 GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override {
brianosmane6865a02016-06-22 05:57:17 -0700423 this->genGenericIds(n, textures);
bsalomonb5a94e32016-03-18 12:07:24 -0700424 }
425
csmartdaltonb593a762016-06-23 13:42:13 -0700426 GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget,
427 GrGLuint textureID, GrGLint level) override {
428 GrGLuint id = this->getBoundFramebufferID(target);
429 GrAlwaysAssert(id);
430 Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
431 framebuffer->setAttachment(attachment, this->getSingleTextureObject());
432 }
433
434 GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment,
435 GrGLenum textarget, GrGLuint texture, GrGLint level,
436 GrGLsizei samples) override {
437 SK_ABORT("Not implemented");
438 }
439
440 GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
441 GrGLenum textarget, GrGLuint texture,
442 GrGLint level) override {
443 SK_ABORT("Not implemented");
444 }
445
446 GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
447 GrGLenum textarget, GrGLuint texture,
448 GrGLint level) override {
449 SK_ABORT("Not implemented");
450 }
451
452 GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment,
453 GrGLenum textarget, GrGLuint texture, GrGLint level,
454 GrGLint zoffset) override {
455 SK_ABORT("Not implemented");
456 }
457
bsalomonb5a94e32016-03-18 12:07:24 -0700458 GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override {
459 this->genGenericIds(n, arrays);
460 }
461
462 GrGLenum getError() override { return GR_GL_NO_ERROR; }
463
464 GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override {
465 // TODO: remove from Ganesh the #defines for gets we don't use.
466 // We would like to minimize gets overall due to performance issues
467 switch (pname) {
468 case GR_GL_CONTEXT_PROFILE_MASK:
469 *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
470 break;
471 case GR_GL_STENCIL_BITS:
472 *params = 8;
473 break;
csmartdaltonb593a762016-06-23 13:42:13 -0700474 case GR_GL_SAMPLES: {
475 GrAlwaysAssert(fCurrDrawFramebuffer);
476 Framebuffer* framebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
477 *params = framebuffer->numSamples();
bsalomonb5a94e32016-03-18 12:07:24 -0700478 break;
csmartdaltonb593a762016-06-23 13:42:13 -0700479 }
bsalomonb5a94e32016-03-18 12:07:24 -0700480 case GR_GL_FRAMEBUFFER_BINDING:
481 *params = 0;
482 break;
483 case GR_GL_VIEWPORT:
484 params[0] = 0;
485 params[1] = 0;
486 params[2] = 800;
487 params[3] = 600;
488 break;
489 case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
490 case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
491 case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
492 case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
493 *params = 8;
494 break;
495 case GR_GL_MAX_TEXTURE_COORDS:
496 *params = 8;
497 break;
498 case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
499 *params = kDefaultMaxVertexUniformVectors;
500 break;
501 case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
502 *params = kDefaultMaxFragmentUniformVectors;
503 break;
504 case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
505 *params = 16 * 4;
506 break;
507 case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
508 *params = 0;
509 break;
510 case GR_GL_COMPRESSED_TEXTURE_FORMATS:
511 break;
512 case GR_GL_MAX_TEXTURE_SIZE:
513 *params = 8192;
514 break;
515 case GR_GL_MAX_RENDERBUFFER_SIZE:
516 *params = 8192;
517 break;
518 case GR_GL_MAX_SAMPLES:
519 *params = 32;
520 break;
521 case GR_GL_MAX_VERTEX_ATTRIBS:
522 *params = kDefaultMaxVertexAttribs;
523 break;
524 case GR_GL_MAX_VARYING_VECTORS:
525 *params = kDefaultMaxVaryingVectors;
526 break;
527 case GR_GL_NUM_EXTENSIONS: {
528 GrGLint i = 0;
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500529 while (fAdvertisedExtensions[i++]);
bsalomonb5a94e32016-03-18 12:07:24 -0700530 *params = i;
531 break;
532 }
533 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400534 SK_ABORT("Unexpected pname to GetIntegerv");
bsalomonb5a94e32016-03-18 12:07:24 -0700535 }
536 }
537
538 GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
539 this->getShaderOrProgramiv(program, pname, params);
540 }
541
542 GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
543 char* infolog) override {
544 this->getInfoLog(program, bufsize, length, infolog);
545 }
546
547 GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
548 val[0] = val[1] = 0.5f;
549 }
550
551 GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override {
552 switch (pname) {
553 case GR_GL_CURRENT_QUERY:
554 *params = 0;
555 break;
556 case GR_GL_QUERY_COUNTER_BITS:
557 *params = 32;
558 break;
559 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400560 SK_ABORT("Unexpected pname passed GetQueryiv.");
bsalomonb5a94e32016-03-18 12:07:24 -0700561 }
562 }
563
564 GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700565 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700566 }
567
568 GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700569 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700570 }
571
572 GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700573 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700574 }
575
576 GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700577 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700578 }
579
580 GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
581 this->getShaderOrProgramiv(shader, pname, params);
582 }
583
584 GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
585 char* infolog) override {
586 this->getInfoLog(shader, bufsize, length, infolog);
587 }
588
589 const GrGLubyte* getString(GrGLenum name) override {
590 switch (name) {
591 case GR_GL_EXTENSIONS:
592 return CombinedExtensionString();
593 case GR_GL_VERSION:
bsalomon3c481002016-03-21 09:04:26 -0700594 return (const GrGLubyte*)"4.0 Null GL";
bsalomonb5a94e32016-03-18 12:07:24 -0700595 case GR_GL_SHADING_LANGUAGE_VERSION:
bsalomon3c481002016-03-21 09:04:26 -0700596 return (const GrGLubyte*)"4.20.8 Null GLSL";
bsalomonb5a94e32016-03-18 12:07:24 -0700597 case GR_GL_VENDOR:
bsalomon3c481002016-03-21 09:04:26 -0700598 return (const GrGLubyte*)"Null Vendor";
bsalomonb5a94e32016-03-18 12:07:24 -0700599 case GR_GL_RENDERER:
bsalomon3c481002016-03-21 09:04:26 -0700600 return (const GrGLubyte*)"The Null (Non-)Renderer";
bsalomonb5a94e32016-03-18 12:07:24 -0700601 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400602 SK_ABORT("Unexpected name passed to GetString");
bsalomonb5a94e32016-03-18 12:07:24 -0700603 return nullptr;
604 }
605 }
606
607 const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override {
608 switch (name) {
609 case GR_GL_EXTENSIONS: {
610 GrGLint count;
611 this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count);
612 if ((GrGLint)i <= count) {
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500613 return (const GrGLubyte*) fAdvertisedExtensions[i];
bsalomonb5a94e32016-03-18 12:07:24 -0700614 } else {
615 return nullptr;
616 }
617 }
618 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400619 SK_ABORT("Unexpected name passed to GetStringi");
bsalomonb5a94e32016-03-18 12:07:24 -0700620 return nullptr;
621 }
622 }
623
bsalomonb5a94e32016-03-18 12:07:24 -0700624 GrGLint getUniformLocation(GrGLuint program, const char* name) override {
625 return ++fCurrUniformLocation;
626 }
627
628 GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length,
629 GrGLbitfield access) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700630 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700631 if (id > 0) {
632 // We just ignore the offset and length here.
csmartdaltonb593a762016-06-23 13:42:13 -0700633 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700634 SkASSERT(!buffer->mapped());
635 buffer->setMapped(true);
636 return buffer->dataPtr();
637 }
638 return nullptr;
639 }
640
641 GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700642 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700643 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700644 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700645 SkASSERT(!buffer->mapped());
646 buffer->setMapped(true);
647 return buffer->dataPtr();
648 }
649
650 SkASSERT(false);
651 return nullptr; // no buffer bound to target
652 }
653
654 GrGLboolean unmapBuffer(GrGLenum target) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700655 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700656 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700657 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700658 SkASSERT(buffer->mapped());
659 buffer->setMapped(false);
660 return GR_GL_TRUE;
661 }
662
663 GrAlwaysAssert(false);
664 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
665 }
666
667 GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) override {
668 switch (pname) {
669 case GR_GL_BUFFER_MAPPED: {
670 *params = GR_GL_FALSE;
csmartdalton9b972c42016-06-21 07:55:17 -0700671 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700672 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700673 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700674 if (buffer->mapped()) {
675 *params = GR_GL_TRUE;
676 }
677 }
678 break; }
679 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400680 SK_ABORT("Unexpected pname to GetBufferParamateriv");
bsalomonb5a94e32016-03-18 12:07:24 -0700681 break;
682 }
Mike Kleinfc6c37b2016-09-27 09:34:10 -0400683 }
bsalomonb5a94e32016-03-18 12:07:24 -0700684
svaisanenb988ecf2016-04-20 00:36:53 -0700685 // NV_path_rendering
686 GrGLuint genPaths(GrGLsizei range) override {
687 return ++fCurrPathID;
688 }
689
690
bsalomonb5a94e32016-03-18 12:07:24 -0700691private:
csmartdalton9b972c42016-06-21 07:55:17 -0700692 inline int static GetBufferIndex(GrGLenum glTarget) {
693 switch (glTarget) {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400694 default: SK_ABORT("Unexpected GL target to GetBufferIndex");
csmartdalton9b972c42016-06-21 07:55:17 -0700695 case GR_GL_ARRAY_BUFFER: return 0;
696 case GR_GL_ELEMENT_ARRAY_BUFFER: return 1;
697 case GR_GL_TEXTURE_BUFFER: return 2;
698 case GR_GL_DRAW_INDIRECT_BUFFER: return 3;
699 case GR_GL_PIXEL_PACK_BUFFER: return 4;
700 case GR_GL_PIXEL_UNPACK_BUFFER: return 5;
701 }
702 }
703 constexpr int static kNumBufferTargets = 6;
704
csmartdaltonb593a762016-06-23 13:42:13 -0700705 TGLObjectManager<Buffer> fBufferManager;
706 GrGLuint fBoundBuffers[kNumBufferTargets];
707 TGLObjectManager<Framebuffer> fFramebufferManager;
708 GrGLuint fCurrDrawFramebuffer;
709 GrGLuint fCurrReadFramebuffer;
710 TGLObjectManager<Renderbuffer> fRenderbufferManager;
711 GrGLuint fCurrRenderbuffer;
712 GrGLuint fCurrProgramID;
713 GrGLuint fCurrShaderID;
714 GrGLuint fCurrGenericID;
715 GrGLuint fCurrUniformLocation;
716 GrGLuint fCurrPathID;
Hal Canary144caf52016-11-07 17:57:18 -0500717 sk_sp<const Texture> fSingleTextureObject;
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500718 SkTArray<const char*> fAdvertisedExtensions;
bsalomon776d3552014-08-14 08:13:27 -0700719
bsalomonb5a94e32016-03-18 12:07:24 -0700720 // the OpenGLES 2.0 spec says this must be >= 128
721 static const GrGLint kDefaultMaxVertexUniformVectors = 128;
bsalomon776d3552014-08-14 08:13:27 -0700722
bsalomonb5a94e32016-03-18 12:07:24 -0700723 // the OpenGLES 2.0 spec says this must be >=16
724 static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
bsalomon776d3552014-08-14 08:13:27 -0700725
bsalomonb5a94e32016-03-18 12:07:24 -0700726 // the OpenGLES 2.0 spec says this must be >= 8
727 static const GrGLint kDefaultMaxVertexAttribs = 8;
bsalomon776d3552014-08-14 08:13:27 -0700728
bsalomonb5a94e32016-03-18 12:07:24 -0700729 // the OpenGLES 2.0 spec says this must be >= 8
730 static const GrGLint kDefaultMaxVaryingVectors = 8;
bsalomon776d3552014-08-14 08:13:27 -0700731
csmartdaltonb593a762016-06-23 13:42:13 -0700732 GrGLuint getBoundFramebufferID(GrGLenum target) {
733 switch (target) {
734 case GR_GL_FRAMEBUFFER:
735 case GR_GL_DRAW_FRAMEBUFFER:
736 return fCurrDrawFramebuffer;
737 case GR_GL_READ_FRAMEBUFFER:
738 return fCurrReadFramebuffer;
739 default:
740 SK_ABORT("Invalid framebuffer target.");
741 return 0;
742 }
743 }
744
745 const Texture* getSingleTextureObject() {
746 // We currently only use FramebufferAttachment objects for a sample count, and all textures
747 // in Skia have one sample, so there is no need as of yet to track individual textures. This
748 // also works around a bug in chromium's cc_unittests where they send us texture IDs that
749 // were generated by cc::TestGLES2Interface.
750 if (!fSingleTextureObject) {
751 fSingleTextureObject.reset(new Texture);
752 }
Hal Canary144caf52016-11-07 17:57:18 -0500753 return fSingleTextureObject.get();
csmartdaltonb593a762016-06-23 13:42:13 -0700754 }
755
svaisanenb988ecf2016-04-20 00:36:53 -0700756 const GrGLubyte* CombinedExtensionString() {
bsalomonb5a94e32016-03-18 12:07:24 -0700757 static SkString gExtString;
758 static SkMutex gMutex;
759 gMutex.acquire();
760 if (0 == gExtString.size()) {
761 int i = 0;
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500762 while (fAdvertisedExtensions[i]) {
bsalomonb5a94e32016-03-18 12:07:24 -0700763 if (i > 0) {
764 gExtString.append(" ");
bsalomon@google.com74913722011-10-27 20:44:19 +0000765 }
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500766 gExtString.append(fAdvertisedExtensions[i]);
bsalomonb5a94e32016-03-18 12:07:24 -0700767 ++i;
bsalomon@google.com74913722011-10-27 20:44:19 +0000768 }
bsalomonb5a94e32016-03-18 12:07:24 -0700769 }
770 gMutex.release();
771 return (const GrGLubyte*) gExtString.c_str();
772 }
773
774 GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
775 for (int i = 0; i < n; ++i) {
776 ids[i] = ++fCurrGenericID;
777 }
778 }
779
780 GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length,
781 char* infolog) {
782 if (length) {
783 *length = 0;
784 }
785 if (bufsize > 0) {
786 *infolog = 0;
787 }
788 }
789
790 GrGLvoid getShaderOrProgramiv(GrGLuint object, GrGLenum pname, GrGLint* params) {
791 switch (pname) {
792 case GR_GL_LINK_STATUS: // fallthru
793 case GR_GL_COMPILE_STATUS:
794 *params = GR_GL_TRUE;
795 break;
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400796 case GR_GL_INFO_LOG_LENGTH: // fallthru
797 case GL_PROGRAM_BINARY_LENGTH:
bsalomonb5a94e32016-03-18 12:07:24 -0700798 *params = 0;
799 break;
800 // we don't expect any other pnames
801 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400802 SK_ABORT("Unexpected pname to GetProgramiv");
bsalomonb5a94e32016-03-18 12:07:24 -0700803 break;
804 }
805 }
806
807 template <typename T>
808 void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
809 switch (pname) {
810 case GR_GL_QUERY_RESULT_AVAILABLE:
811 *params = GR_GL_TRUE;
812 break;
813 case GR_GL_QUERY_RESULT:
814 *params = 0;
815 break;
816 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400817 SK_ABORT("Unexpected pname passed to GetQueryObject.");
bsalomonb5a94e32016-03-18 12:07:24 -0700818 break;
819 }
bsalomon@google.com74913722011-10-27 20:44:19 +0000820 }
bsalomon3c481002016-03-21 09:04:26 -0700821
822 typedef GrGLTestInterface INHERITED;
bsalomon@google.com74913722011-10-27 20:44:19 +0000823};
824
bsalomonb5a94e32016-03-18 12:07:24 -0700825} // anonymous namespace
commit-bot@chromium.orgc72425a2014-01-21 16:09:18 +0000826
svaisanenb988ecf2016-04-20 00:36:53 -0700827const GrGLInterface* GrGLCreateNullInterface(bool enableNVPR) { return new NullInterface(enableNVPR); }