blob: 9df22659dd183c2e351570619002236bf363a3ca [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
Hal Canary2a2f6752018-06-11 21:44:01 -04009#include "GrNonAtomicRef.h"
Hal Canaryfdcfb8b2018-06-13 09:42:32 -040010#include "gl/GrGLInterface.h"
11#include "GrGLTestInterface.h"
bsalomonb5a94e32016-03-18 12:07:24 -070012#include "SkMutex.h"
bsalomon@google.com21cbec42013-01-07 17:23:00 +000013#include "SkTDArray.h"
csmartdaltonb593a762016-06-23 13:42:13 -070014#include <type_traits>
bsalomon7e340072015-02-11 12:07:31 -080015
16// added to suppress 'no previous prototype' warning and because this code is duplicated in
17// SkNullGLContext.cpp
halcanary9d524f22016-03-29 09:03:52 -070018namespace {
bsalomon7e340072015-02-11 12:07:31 -080019
csmartdaltonb593a762016-06-23 13:42:13 -070020class GLObject : public GrNonAtomicRef<GLObject> {
robertphillips@google.comd6543e52013-07-18 17:39:14 +000021public:
csmartdaltonb593a762016-06-23 13:42:13 -070022 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; }
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000102
robertphillips@google.comae6b7772013-07-18 18:07:39 +0000103 void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) {
bsalomon49f085d2014-09-05 13:34:00 -0700104 if (fDataPtr) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000105 SkASSERT(0 != fSize);
halcanary385fe4d2015-08-26 13:07:48 -0700106 delete[] fDataPtr;
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000107 }
108
109 fSize = size;
halcanary385fe4d2015-08-26 13:07:48 -0700110 fDataPtr = new char[size];
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000111 }
112
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000113 GrGLchar* dataPtr() { return fDataPtr; }
robertphillips@google.comae6b7772013-07-18 18:07:39 +0000114 GrGLsizeiptr size() const { return fSize; }
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000115
116 void setMapped(bool mapped) { fMapped = mapped; }
117 bool mapped() const { return fMapped; }
118
119private:
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000120 GrGLchar* fDataPtr;
robertphillips@google.comae6b7772013-07-18 18:07:39 +0000121 GrGLsizeiptr fSize; // size in bytes
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000122 bool fMapped;
csmartdaltonb593a762016-06-23 13:42:13 -0700123
124 typedef GLObject INHERITED;
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000125};
126
csmartdaltonb593a762016-06-23 13:42:13 -0700127class FramebufferAttachment : public GLObject {
bsalomon776d3552014-08-14 08:13:27 -0700128public:
csmartdaltonb593a762016-06-23 13:42:13 -0700129 int numSamples() const { return fNumSamples; }
robertphillips@google.comd6543e52013-07-18 17:39:14 +0000130
csmartdaltonb593a762016-06-23 13:42:13 -0700131protected:
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;
bsalomon776d3552014-08-14 08:13:27 -0700174 }
brianosman37feccb2016-06-23 06:11:51 -0700175 }
176
csmartdaltonb593a762016-06-23 13:42:13 -0700177 void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) {
178 for (auto& attachment : fAttachments) {
Hal Canary144caf52016-11-07 17:57:18 -0500179 if (attachment.get() == deleted) {
csmartdaltonb593a762016-06-23 13:42:13 -0700180 attachment.reset(nullptr);
181 }
brianosman37feccb2016-06-23 06:11:51 -0700182 }
brianosman37feccb2016-06-23 06:11:51 -0700183 }
184
csmartdaltonb593a762016-06-23 13:42:13 -0700185 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;
bsalomon776d3552014-08-14 08:13:27 -0700199 }
200
201private:
csmartdaltonb593a762016-06-23 13:42:13 -0700202 enum AttachmentPoint {
203 kStencil,
204 kDepth,
205 kColor
206 };
207 constexpr int static kNumAttachmentPoints = 1 + (int)AttachmentPoint::kColor;
208
Hal Canary144caf52016-11-07 17:57:18 -0500209 sk_sp<const FramebufferAttachment> fAttachments[kNumAttachmentPoints];
csmartdaltonb593a762016-06-23 13:42:13 -0700210
211 typedef GLObject INHERITED;
bsalomon776d3552014-08-14 08:13:27 -0700212};
213
bsalomonb5a94e32016-03-18 12:07:24 -0700214/** Null interface implementation */
215class NullInterface : public GrGLTestInterface {
bsalomon776d3552014-08-14 08:13:27 -0700216public:
svaisanenb988ecf2016-04-20 00:36:53 -0700217 NullInterface(bool enableNVPR)
csmartdaltonb593a762016-06-23 13:42:13 -0700218 : fCurrDrawFramebuffer(0)
219 , fCurrReadFramebuffer(0)
220 , fCurrRenderbuffer(0)
221 , fCurrProgramID(0)
bsalomonb5a94e32016-03-18 12:07:24 -0700222 , fCurrShaderID(0)
223 , fCurrGenericID(0)
svaisanenb988ecf2016-04-20 00:36:53 -0700224 , fCurrUniformLocation(0)
225 , fCurrPathID(0) {
csmartdalton9b972c42016-06-21 07:55:17 -0700226 memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500227 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");
svaisanenb988ecf2016-04-20 00:36:53 -0700233 if (enableNVPR) {
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500234 fAdvertisedExtensions.push_back("GL_NV_path_rendering");
235 fAdvertisedExtensions.push_back("GL_ARB_program_interface_query");
svaisanenb988ecf2016-04-20 00:36:53 -0700236 }
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500237 fAdvertisedExtensions.push_back(nullptr);
svaisanenb988ecf2016-04-20 00:36:53 -0700238
bsalomonb5a94e32016-03-18 12:07:24 -0700239 this->init(kGL_GrGLStandard);
240 }
bsalomon776d3552014-08-14 08:13:27 -0700241
bsalomonb5a94e32016-03-18 12:07:24 -0700242 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) {
csmartdaltonb593a762016-06-23 13:42:13 -0700248 Buffer* buffer = fBufferManager.create();
bsalomonb5a94e32016-03-18 12:07:24 -0700249 ids[i] = buffer->id();
250 }
251 }
252
253 GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
254 GrGLenum usage) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700255 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700256 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700257 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700258 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 {
csmartdalton9b972c42016-06-21 07:55:17 -0700271 fBoundBuffers[GetBufferIndex(target)] = buffer;
bsalomonb5a94e32016-03-18 12:07:24 -0700272 }
273
274 // deleting a bound buffer has the side effect of binding 0
csmartdalton9b972c42016-06-21 07:55:17 -0700275 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;
bsalomonb5a94e32016-03-18 12:07:24 -0700280 }
csmartdalton9b972c42016-06-21 07:55:17 -0700281 for (int i = 0; i < n; ++i) {
282 if (ids[i] == fBoundBuffers[buffIdx]) {
283 fBoundBuffers[buffIdx] = 0;
284 break;
285 }
bsalomonb5a94e32016-03-18 12:07:24 -0700286 }
csmartdalton9b972c42016-06-21 07:55:17 -0700287 }
bsalomonb5a94e32016-03-18 12:07:24 -0700288
csmartdalton9b972c42016-06-21 07:55:17 -0700289 // Then actually "delete" the buffers.
290 for (int i = 0; i < n; ++i) {
cdaltona957b8a2016-04-06 13:36:38 -0700291 if (ids[i] > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700292 Buffer* buffer = fBufferManager.lookUp(ids[i]);
cdaltona957b8a2016-04-06 13:36:38 -0700293 fBufferManager.free(buffer);
294 }
bsalomonb5a94e32016-03-18 12:07:24 -0700295 }
296 }
297
298 GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override {
csmartdaltonb593a762016-06-23 13:42:13 -0700299 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 }
bsalomonb5a94e32016-03-18 12:07:24 -0700330 }
331
332 GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
333
334 GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override {
csmartdaltonb593a762016-06-23 13:42:13 -0700335 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);
Adrienne Walker3a69c742018-05-21 11:05:48 -0700406 if (!renderBufferID && !fCurrRenderbuffer) {
407 return;
408 }
csmartdaltonb593a762016-06-23 13:42:13 -0700409 GrAlwaysAssert(fCurrRenderbuffer);
410 Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
411
412 framebuffer->setAttachment(attachment, renderbuffer);
413 }
414
415 GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
416 GrGLenum renderbuffertarget,
417 GrGLuint renderbuffer) override {
418 SK_ABORT("Not implemented");
bsalomonb5a94e32016-03-18 12:07:24 -0700419 }
420
421 GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override {
brianosmane6865a02016-06-22 05:57:17 -0700422 this->genGenericIds(n, textures);
bsalomonb5a94e32016-03-18 12:07:24 -0700423 }
424
csmartdaltonb593a762016-06-23 13:42:13 -0700425 GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget,
426 GrGLuint textureID, GrGLint level) override {
427 GrGLuint id = this->getBoundFramebufferID(target);
428 GrAlwaysAssert(id);
429 Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
430 framebuffer->setAttachment(attachment, this->getSingleTextureObject());
431 }
432
433 GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment,
434 GrGLenum textarget, GrGLuint texture, GrGLint level,
435 GrGLsizei samples) override {
436 SK_ABORT("Not implemented");
437 }
438
439 GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
440 GrGLenum textarget, GrGLuint texture,
441 GrGLint level) override {
442 SK_ABORT("Not implemented");
443 }
444
445 GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
446 GrGLenum textarget, GrGLuint texture,
447 GrGLint level) override {
448 SK_ABORT("Not implemented");
449 }
450
451 GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment,
452 GrGLenum textarget, GrGLuint texture, GrGLint level,
453 GrGLint zoffset) override {
454 SK_ABORT("Not implemented");
455 }
456
bsalomonb5a94e32016-03-18 12:07:24 -0700457 GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override {
458 this->genGenericIds(n, arrays);
459 }
460
461 GrGLenum getError() override { return GR_GL_NO_ERROR; }
462
463 GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override {
464 // TODO: remove from Ganesh the #defines for gets we don't use.
465 // We would like to minimize gets overall due to performance issues
466 switch (pname) {
467 case GR_GL_CONTEXT_PROFILE_MASK:
468 *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
469 break;
470 case GR_GL_STENCIL_BITS:
471 *params = 8;
472 break;
csmartdaltonb593a762016-06-23 13:42:13 -0700473 case GR_GL_SAMPLES: {
474 GrAlwaysAssert(fCurrDrawFramebuffer);
475 Framebuffer* framebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
476 *params = framebuffer->numSamples();
bsalomonb5a94e32016-03-18 12:07:24 -0700477 break;
csmartdaltonb593a762016-06-23 13:42:13 -0700478 }
bsalomonb5a94e32016-03-18 12:07:24 -0700479 case GR_GL_FRAMEBUFFER_BINDING:
480 *params = 0;
481 break;
482 case GR_GL_VIEWPORT:
483 params[0] = 0;
484 params[1] = 0;
485 params[2] = 800;
486 params[3] = 600;
487 break;
488 case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
489 case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
490 case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
491 case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
492 *params = 8;
493 break;
494 case GR_GL_MAX_TEXTURE_COORDS:
495 *params = 8;
496 break;
497 case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
498 *params = kDefaultMaxVertexUniformVectors;
499 break;
500 case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
501 *params = kDefaultMaxFragmentUniformVectors;
502 break;
503 case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
504 *params = 16 * 4;
505 break;
506 case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
507 *params = 0;
508 break;
509 case GR_GL_COMPRESSED_TEXTURE_FORMATS:
510 break;
511 case GR_GL_MAX_TEXTURE_SIZE:
512 *params = 8192;
513 break;
514 case GR_GL_MAX_RENDERBUFFER_SIZE:
515 *params = 8192;
516 break;
517 case GR_GL_MAX_SAMPLES:
518 *params = 32;
519 break;
520 case GR_GL_MAX_VERTEX_ATTRIBS:
521 *params = kDefaultMaxVertexAttribs;
522 break;
523 case GR_GL_MAX_VARYING_VECTORS:
524 *params = kDefaultMaxVaryingVectors;
525 break;
526 case GR_GL_NUM_EXTENSIONS: {
527 GrGLint i = 0;
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500528 while (fAdvertisedExtensions[i++]);
bsalomonb5a94e32016-03-18 12:07:24 -0700529 *params = i;
530 break;
531 }
532 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400533 SK_ABORT("Unexpected pname to GetIntegerv");
bsalomonb5a94e32016-03-18 12:07:24 -0700534 }
535 }
536
537 GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
538 this->getShaderOrProgramiv(program, pname, params);
539 }
540
541 GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
542 char* infolog) override {
543 this->getInfoLog(program, bufsize, length, infolog);
544 }
545
546 GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
547 val[0] = val[1] = 0.5f;
548 }
549
550 GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override {
551 switch (pname) {
552 case GR_GL_CURRENT_QUERY:
553 *params = 0;
554 break;
555 case GR_GL_QUERY_COUNTER_BITS:
556 *params = 32;
557 break;
558 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400559 SK_ABORT("Unexpected pname passed GetQueryiv.");
bsalomonb5a94e32016-03-18 12:07:24 -0700560 }
561 }
562
563 GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700564 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700565 }
566
567 GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700568 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700569 }
570
571 GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700572 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700573 }
574
575 GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
bsalomon3c481002016-03-21 09:04:26 -0700576 this->queryResult(id, pname, params);
bsalomonb5a94e32016-03-18 12:07:24 -0700577 }
578
579 GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
580 this->getShaderOrProgramiv(shader, pname, params);
581 }
582
583 GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
584 char* infolog) override {
585 this->getInfoLog(shader, bufsize, length, infolog);
586 }
587
588 const GrGLubyte* getString(GrGLenum name) override {
589 switch (name) {
590 case GR_GL_EXTENSIONS:
591 return CombinedExtensionString();
592 case GR_GL_VERSION:
bsalomon3c481002016-03-21 09:04:26 -0700593 return (const GrGLubyte*)"4.0 Null GL";
bsalomonb5a94e32016-03-18 12:07:24 -0700594 case GR_GL_SHADING_LANGUAGE_VERSION:
bsalomon3c481002016-03-21 09:04:26 -0700595 return (const GrGLubyte*)"4.20.8 Null GLSL";
bsalomonb5a94e32016-03-18 12:07:24 -0700596 case GR_GL_VENDOR:
bsalomon3c481002016-03-21 09:04:26 -0700597 return (const GrGLubyte*)"Null Vendor";
bsalomonb5a94e32016-03-18 12:07:24 -0700598 case GR_GL_RENDERER:
bsalomon3c481002016-03-21 09:04:26 -0700599 return (const GrGLubyte*)"The Null (Non-)Renderer";
bsalomonb5a94e32016-03-18 12:07:24 -0700600 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400601 SK_ABORT("Unexpected name passed to GetString");
bsalomonb5a94e32016-03-18 12:07:24 -0700602 return nullptr;
603 }
604 }
605
606 const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override {
607 switch (name) {
608 case GR_GL_EXTENSIONS: {
609 GrGLint count;
610 this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count);
611 if ((GrGLint)i <= count) {
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500612 return (const GrGLubyte*) fAdvertisedExtensions[i];
bsalomonb5a94e32016-03-18 12:07:24 -0700613 } else {
614 return nullptr;
615 }
616 }
617 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400618 SK_ABORT("Unexpected name passed to GetStringi");
bsalomonb5a94e32016-03-18 12:07:24 -0700619 return nullptr;
620 }
621 }
622
bsalomonb5a94e32016-03-18 12:07:24 -0700623 GrGLint getUniformLocation(GrGLuint program, const char* name) override {
624 return ++fCurrUniformLocation;
625 }
626
627 GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length,
628 GrGLbitfield access) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700629 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700630 if (id > 0) {
631 // We just ignore the offset and length here.
csmartdaltonb593a762016-06-23 13:42:13 -0700632 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700633 SkASSERT(!buffer->mapped());
634 buffer->setMapped(true);
635 return buffer->dataPtr();
636 }
637 return nullptr;
638 }
639
640 GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700641 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700642 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700643 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700644 SkASSERT(!buffer->mapped());
645 buffer->setMapped(true);
646 return buffer->dataPtr();
647 }
648
649 SkASSERT(false);
650 return nullptr; // no buffer bound to target
651 }
652
653 GrGLboolean unmapBuffer(GrGLenum target) override {
csmartdalton9b972c42016-06-21 07:55:17 -0700654 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700655 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700656 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700657 SkASSERT(buffer->mapped());
658 buffer->setMapped(false);
659 return GR_GL_TRUE;
660 }
661
662 GrAlwaysAssert(false);
663 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
664 }
665
666 GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) override {
667 switch (pname) {
668 case GR_GL_BUFFER_MAPPED: {
669 *params = GR_GL_FALSE;
csmartdalton9b972c42016-06-21 07:55:17 -0700670 GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
bsalomonb5a94e32016-03-18 12:07:24 -0700671 if (id > 0) {
csmartdaltonb593a762016-06-23 13:42:13 -0700672 Buffer* buffer = fBufferManager.lookUp(id);
bsalomonb5a94e32016-03-18 12:07:24 -0700673 if (buffer->mapped()) {
674 *params = GR_GL_TRUE;
675 }
676 }
677 break; }
678 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400679 SK_ABORT("Unexpected pname to GetBufferParamateriv");
bsalomonb5a94e32016-03-18 12:07:24 -0700680 break;
681 }
Mike Kleinfc6c37b2016-09-27 09:34:10 -0400682 }
bsalomonb5a94e32016-03-18 12:07:24 -0700683
svaisanenb988ecf2016-04-20 00:36:53 -0700684 // NV_path_rendering
685 GrGLuint genPaths(GrGLsizei range) override {
686 return ++fCurrPathID;
687 }
688
689
bsalomonb5a94e32016-03-18 12:07:24 -0700690private:
csmartdalton9b972c42016-06-21 07:55:17 -0700691 inline int static GetBufferIndex(GrGLenum glTarget) {
692 switch (glTarget) {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400693 default: SK_ABORT("Unexpected GL target to GetBufferIndex");
csmartdalton9b972c42016-06-21 07:55:17 -0700694 case GR_GL_ARRAY_BUFFER: return 0;
695 case GR_GL_ELEMENT_ARRAY_BUFFER: return 1;
696 case GR_GL_TEXTURE_BUFFER: return 2;
697 case GR_GL_DRAW_INDIRECT_BUFFER: return 3;
698 case GR_GL_PIXEL_PACK_BUFFER: return 4;
699 case GR_GL_PIXEL_UNPACK_BUFFER: return 5;
700 }
701 }
702 constexpr int static kNumBufferTargets = 6;
703
csmartdaltonb593a762016-06-23 13:42:13 -0700704 TGLObjectManager<Buffer> fBufferManager;
705 GrGLuint fBoundBuffers[kNumBufferTargets];
706 TGLObjectManager<Framebuffer> fFramebufferManager;
707 GrGLuint fCurrDrawFramebuffer;
708 GrGLuint fCurrReadFramebuffer;
709 TGLObjectManager<Renderbuffer> fRenderbufferManager;
710 GrGLuint fCurrRenderbuffer;
711 GrGLuint fCurrProgramID;
712 GrGLuint fCurrShaderID;
713 GrGLuint fCurrGenericID;
714 GrGLuint fCurrUniformLocation;
715 GrGLuint fCurrPathID;
Hal Canary144caf52016-11-07 17:57:18 -0500716 sk_sp<const Texture> fSingleTextureObject;
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500717 SkTArray<const char*> fAdvertisedExtensions;
bsalomon776d3552014-08-14 08:13:27 -0700718
bsalomonb5a94e32016-03-18 12:07:24 -0700719 // the OpenGLES 2.0 spec says this must be >= 128
720 static const GrGLint kDefaultMaxVertexUniformVectors = 128;
bsalomon776d3552014-08-14 08:13:27 -0700721
bsalomonb5a94e32016-03-18 12:07:24 -0700722 // the OpenGLES 2.0 spec says this must be >=16
723 static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
bsalomon776d3552014-08-14 08:13:27 -0700724
bsalomonb5a94e32016-03-18 12:07:24 -0700725 // the OpenGLES 2.0 spec says this must be >= 8
726 static const GrGLint kDefaultMaxVertexAttribs = 8;
bsalomon776d3552014-08-14 08:13:27 -0700727
bsalomonb5a94e32016-03-18 12:07:24 -0700728 // the OpenGLES 2.0 spec says this must be >= 8
729 static const GrGLint kDefaultMaxVaryingVectors = 8;
bsalomon776d3552014-08-14 08:13:27 -0700730
csmartdaltonb593a762016-06-23 13:42:13 -0700731 GrGLuint getBoundFramebufferID(GrGLenum target) {
732 switch (target) {
733 case GR_GL_FRAMEBUFFER:
734 case GR_GL_DRAW_FRAMEBUFFER:
735 return fCurrDrawFramebuffer;
736 case GR_GL_READ_FRAMEBUFFER:
737 return fCurrReadFramebuffer;
738 default:
739 SK_ABORT("Invalid framebuffer target.");
740 return 0;
741 }
742 }
743
744 const Texture* getSingleTextureObject() {
745 // We currently only use FramebufferAttachment objects for a sample count, and all textures
746 // in Skia have one sample, so there is no need as of yet to track individual textures. This
747 // also works around a bug in chromium's cc_unittests where they send us texture IDs that
748 // were generated by cc::TestGLES2Interface.
749 if (!fSingleTextureObject) {
750 fSingleTextureObject.reset(new Texture);
751 }
Hal Canary144caf52016-11-07 17:57:18 -0500752 return fSingleTextureObject.get();
csmartdaltonb593a762016-06-23 13:42:13 -0700753 }
754
svaisanenb988ecf2016-04-20 00:36:53 -0700755 const GrGLubyte* CombinedExtensionString() {
bsalomonb5a94e32016-03-18 12:07:24 -0700756 static SkString gExtString;
757 static SkMutex gMutex;
758 gMutex.acquire();
759 if (0 == gExtString.size()) {
760 int i = 0;
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500761 while (fAdvertisedExtensions[i]) {
bsalomonb5a94e32016-03-18 12:07:24 -0700762 if (i > 0) {
763 gExtString.append(" ");
bsalomon@google.com74913722011-10-27 20:44:19 +0000764 }
Brian Salomon7fc4a2d2017-02-17 20:43:43 -0500765 gExtString.append(fAdvertisedExtensions[i]);
bsalomonb5a94e32016-03-18 12:07:24 -0700766 ++i;
bsalomon@google.com74913722011-10-27 20:44:19 +0000767 }
bsalomonb5a94e32016-03-18 12:07:24 -0700768 }
769 gMutex.release();
770 return (const GrGLubyte*) gExtString.c_str();
771 }
772
773 GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
774 for (int i = 0; i < n; ++i) {
775 ids[i] = ++fCurrGenericID;
776 }
777 }
778
779 GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length,
780 char* infolog) {
781 if (length) {
782 *length = 0;
783 }
784 if (bufsize > 0) {
785 *infolog = 0;
786 }
787 }
788
789 GrGLvoid getShaderOrProgramiv(GrGLuint object, GrGLenum pname, GrGLint* params) {
790 switch (pname) {
791 case GR_GL_LINK_STATUS: // fallthru
792 case GR_GL_COMPILE_STATUS:
793 *params = GR_GL_TRUE;
794 break;
Ethan Nicholasd1b2eec2017-11-01 15:45:43 -0400795 case GR_GL_INFO_LOG_LENGTH: // fallthru
796 case GL_PROGRAM_BINARY_LENGTH:
bsalomonb5a94e32016-03-18 12:07:24 -0700797 *params = 0;
798 break;
799 // we don't expect any other pnames
800 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400801 SK_ABORT("Unexpected pname to GetProgramiv");
bsalomonb5a94e32016-03-18 12:07:24 -0700802 break;
803 }
804 }
805
806 template <typename T>
807 void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
808 switch (pname) {
809 case GR_GL_QUERY_RESULT_AVAILABLE:
810 *params = GR_GL_TRUE;
811 break;
812 case GR_GL_QUERY_RESULT:
813 *params = 0;
814 break;
815 default:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400816 SK_ABORT("Unexpected pname passed to GetQueryObject.");
bsalomonb5a94e32016-03-18 12:07:24 -0700817 break;
818 }
bsalomon@google.com74913722011-10-27 20:44:19 +0000819 }
bsalomon3c481002016-03-21 09:04:26 -0700820
821 typedef GrGLTestInterface INHERITED;
bsalomon@google.com74913722011-10-27 20:44:19 +0000822};
823
bsalomonb5a94e32016-03-18 12:07:24 -0700824} // anonymous namespace
commit-bot@chromium.orgc72425a2014-01-21 16:09:18 +0000825
svaisanenb988ecf2016-04-20 00:36:53 -0700826const GrGLInterface* GrGLCreateNullInterface(bool enableNVPR) { return new NullInterface(enableNVPR); }