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