1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9#include "GrNonAtomicRef.h" 10#include "gl/GrGLInterface.h" 11#include "GrGLTestInterface.h" 12#include "SkMutex.h" 13#include "SkTDArray.h" 14#include <type_traits> 15 16// added to suppress 'no previous prototype' warning and because this code is duplicated in 17// SkNullGLContext.cpp 18namespace { 19 20class GLObject : public GrNonAtomicRef<GLObject> { 21public: 22 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; } 102 103 void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) { 104 if (fDataPtr) { 105 SkASSERT(0 != fSize); 106 delete[] fDataPtr; 107 } 108 109 fSize = size; 110 fDataPtr = new char[size]; 111 } 112 113 GrGLchar* dataPtr() { return fDataPtr; } 114 GrGLsizeiptr size() const { return fSize; } 115 116 void setMapped(bool mapped) { fMapped = mapped; } 117 bool mapped() const { return fMapped; } 118 119private: 120 GrGLchar* fDataPtr; 121 GrGLsizeiptr fSize; // size in bytes 122 bool fMapped; 123 124 typedef GLObject INHERITED; 125}; 126 127class FramebufferAttachment : public GLObject { 128public: 129 int numSamples() const { return fNumSamples; } 130 131protected: 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; 174 } 175 } 176 177 void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) { 178 for (auto& attachment : fAttachments) { 179 if (attachment.get() == deleted) { 180 attachment.reset(nullptr); 181 } 182 } 183 } 184 185 int numSamples() const { 186 int numSamples = 0; 187 for (auto& attachment : fAttachments) { 188 if (!attachment) { 189 continue; 190 } 191 if (numSamples) { 192 GrAlwaysAssert(attachment->numSamples() == numSamples); 193 continue; 194 } 195 numSamples = attachment->numSamples(); 196 } 197 GrAlwaysAssert(numSamples); 198 return numSamples; 199 } 200 201private: 202 enum AttachmentPoint { 203 kStencil, 204 kDepth, 205 kColor 206 }; 207 constexpr int static kNumAttachmentPoints = 1 + (int)AttachmentPoint::kColor; 208 209 sk_sp<const FramebufferAttachment> fAttachments[kNumAttachmentPoints]; 210 211 typedef GLObject INHERITED; 212}; 213 214/** Null interface implementation */ 215class NullInterface : public GrGLTestInterface { 216public: 217 NullInterface(bool enableNVPR) 218 : fCurrDrawFramebuffer(0) 219 , fCurrReadFramebuffer(0) 220 , fCurrRenderbuffer(0) 221 , fCurrProgramID(0) 222 , fCurrShaderID(0) 223 , fCurrGenericID(0) 224 , fCurrUniformLocation(0) 225 , fCurrPathID(0) { 226 memset(fBoundBuffers, 0, sizeof(fBoundBuffers)); 227 fAdvertisedExtensions.push_back("GL_ARB_framebuffer_object"); 228 fAdvertisedExtensions.push_back("GL_ARB_blend_func_extended"); 229 fAdvertisedExtensions.push_back("GL_ARB_timer_query"); 230 fAdvertisedExtensions.push_back("GL_ARB_draw_buffers"); 231 fAdvertisedExtensions.push_back("GL_ARB_occlusion_query"); 232 fAdvertisedExtensions.push_back("GL_EXT_stencil_wrap"); 233 if (enableNVPR) { 234 fAdvertisedExtensions.push_back("GL_NV_path_rendering"); 235 fAdvertisedExtensions.push_back("GL_ARB_program_interface_query"); 236 } 237 fAdvertisedExtensions.push_back(nullptr); 238 239 this->init(kGL_GrGLStandard); 240 } 241 242 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) { 248 Buffer* buffer = fBufferManager.create(); 249 ids[i] = buffer->id(); 250 } 251 } 252 253 GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, 254 GrGLenum usage) override { 255 GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; 256 if (id > 0) { 257 Buffer* buffer = fBufferManager.lookUp(id); 258 buffer->allocate(size, (const GrGLchar*) data); 259 } 260 } 261 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 { 271 fBoundBuffers[GetBufferIndex(target)] = buffer; 272 } 273 274 // deleting a bound buffer has the side effect of binding 0 275 GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* ids) override { 276 // First potentially unbind the buffers. 277 for (int buffIdx = 0; buffIdx < kNumBufferTargets; ++buffIdx) { 278 if (!fBoundBuffers[buffIdx]) { 279 continue; 280 } 281 for (int i = 0; i < n; ++i) { 282 if (ids[i] == fBoundBuffers[buffIdx]) { 283 fBoundBuffers[buffIdx] = 0; 284 break; 285 } 286 } 287 } 288 289 // Then actually "delete" the buffers. 290 for (int i = 0; i < n; ++i) { 291 if (ids[i] > 0) { 292 Buffer* buffer = fBufferManager.lookUp(ids[i]); 293 fBufferManager.free(buffer); 294 } 295 } 296 } 297 298 GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override { 299 for (int i = 0; i < n; ++i) { 300 Framebuffer* framebuffer = fFramebufferManager.create(); 301 framebuffers[i] = framebuffer->id(); 302 } 303 } 304 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 } 330 } 331 332 GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); } 333 334 GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override { 335 for (int i = 0; i < n; ++i) { 336 Renderbuffer* renderbuffer = fRenderbufferManager.create(); 337 renderbuffers[i] = renderbuffer->id(); 338 } 339 } 340 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); 406 GrAlwaysAssert(fCurrRenderbuffer); 407 Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer); 408 409 framebuffer->setAttachment(attachment, renderbuffer); 410 } 411 412 GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment, 413 GrGLenum renderbuffertarget, 414 GrGLuint renderbuffer) override { 415 SK_ABORT("Not implemented"); 416 } 417 418 GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override { 419 this->genGenericIds(n, textures); 420 } 421 422 GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, 423 GrGLuint textureID, GrGLint level) override { 424 GrGLuint id = this->getBoundFramebufferID(target); 425 GrAlwaysAssert(id); 426 Framebuffer* framebuffer = fFramebufferManager.lookUp(id); 427 framebuffer->setAttachment(attachment, this->getSingleTextureObject()); 428 } 429 430 GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment, 431 GrGLenum textarget, GrGLuint texture, GrGLint level, 432 GrGLsizei samples) override { 433 SK_ABORT("Not implemented"); 434 } 435 436 GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment, 437 GrGLenum textarget, GrGLuint texture, 438 GrGLint level) override { 439 SK_ABORT("Not implemented"); 440 } 441 442 GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment, 443 GrGLenum textarget, GrGLuint texture, 444 GrGLint level) override { 445 SK_ABORT("Not implemented"); 446 } 447 448 GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment, 449 GrGLenum textarget, GrGLuint texture, GrGLint level, 450 GrGLint zoffset) override { 451 SK_ABORT("Not implemented"); 452 } 453 454 GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override { 455 this->genGenericIds(n, arrays); 456 } 457 458 GrGLenum getError() override { return GR_GL_NO_ERROR; } 459 460 GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override { 461 // TODO: remove from Ganesh the #defines for gets we don't use. 462 // We would like to minimize gets overall due to performance issues 463 switch (pname) { 464 case GR_GL_CONTEXT_PROFILE_MASK: 465 *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT; 466 break; 467 case GR_GL_STENCIL_BITS: 468 *params = 8; 469 break; 470 case GR_GL_SAMPLES: { 471 GrAlwaysAssert(fCurrDrawFramebuffer); 472 Framebuffer* framebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer); 473 *params = framebuffer->numSamples(); 474 break; 475 } 476 case GR_GL_FRAMEBUFFER_BINDING: 477 *params = 0; 478 break; 479 case GR_GL_VIEWPORT: 480 params[0] = 0; 481 params[1] = 0; 482 params[2] = 800; 483 params[3] = 600; 484 break; 485 case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: 486 case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS: 487 case GR_GL_MAX_TEXTURE_IMAGE_UNITS: 488 case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: 489 *params = 8; 490 break; 491 case GR_GL_MAX_TEXTURE_COORDS: 492 *params = 8; 493 break; 494 case GR_GL_MAX_VERTEX_UNIFORM_VECTORS: 495 *params = kDefaultMaxVertexUniformVectors; 496 break; 497 case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS: 498 *params = kDefaultMaxFragmentUniformVectors; 499 break; 500 case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: 501 *params = 16 * 4; 502 break; 503 case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS: 504 *params = 0; 505 break; 506 case GR_GL_COMPRESSED_TEXTURE_FORMATS: 507 break; 508 case GR_GL_MAX_TEXTURE_SIZE: 509 *params = 8192; 510 break; 511 case GR_GL_MAX_RENDERBUFFER_SIZE: 512 *params = 8192; 513 break; 514 case GR_GL_MAX_SAMPLES: 515 *params = 32; 516 break; 517 case GR_GL_MAX_VERTEX_ATTRIBS: 518 *params = kDefaultMaxVertexAttribs; 519 break; 520 case GR_GL_MAX_VARYING_VECTORS: 521 *params = kDefaultMaxVaryingVectors; 522 break; 523 case GR_GL_NUM_EXTENSIONS: { 524 GrGLint i = 0; 525 while (fAdvertisedExtensions[i++]); 526 *params = i; 527 break; 528 } 529 default: 530 SK_ABORT("Unexpected pname to GetIntegerv"); 531 } 532 } 533 534 GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override { 535 this->getShaderOrProgramiv(program, pname, params); 536 } 537 538 GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, 539 char* infolog) override { 540 this->getInfoLog(program, bufsize, length, infolog); 541 } 542 543 GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override { 544 val[0] = val[1] = 0.5f; 545 } 546 547 GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override { 548 switch (pname) { 549 case GR_GL_CURRENT_QUERY: 550 *params = 0; 551 break; 552 case GR_GL_QUERY_COUNTER_BITS: 553 *params = 32; 554 break; 555 default: 556 SK_ABORT("Unexpected pname passed GetQueryiv."); 557 } 558 } 559 560 GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override { 561 this->queryResult(id, pname, params); 562 } 563 564 GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override { 565 this->queryResult(id, pname, params); 566 } 567 568 GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override { 569 this->queryResult(id, pname, params); 570 } 571 572 GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override { 573 this->queryResult(id, pname, params); 574 } 575 576 GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override { 577 this->getShaderOrProgramiv(shader, pname, params); 578 } 579 580 GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length, 581 char* infolog) override { 582 this->getInfoLog(shader, bufsize, length, infolog); 583 } 584 585 const GrGLubyte* getString(GrGLenum name) override { 586 switch (name) { 587 case GR_GL_EXTENSIONS: 588 return CombinedExtensionString(); 589 case GR_GL_VERSION: 590 return (const GrGLubyte*)"4.0 Null GL"; 591 case GR_GL_SHADING_LANGUAGE_VERSION: 592 return (const GrGLubyte*)"4.20.8 Null GLSL"; 593 case GR_GL_VENDOR: 594 return (const GrGLubyte*)"Null Vendor"; 595 case GR_GL_RENDERER: 596 return (const GrGLubyte*)"The Null (Non-)Renderer"; 597 default: 598 SK_ABORT("Unexpected name passed to GetString"); 599 return nullptr; 600 } 601 } 602 603 const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override { 604 switch (name) { 605 case GR_GL_EXTENSIONS: { 606 GrGLint count; 607 this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count); 608 if ((GrGLint)i <= count) { 609 return (const GrGLubyte*) fAdvertisedExtensions[i]; 610 } else { 611 return nullptr; 612 } 613 } 614 default: 615 SK_ABORT("Unexpected name passed to GetStringi"); 616 return nullptr; 617 } 618 } 619 620 GrGLint getUniformLocation(GrGLuint program, const char* name) override { 621 return ++fCurrUniformLocation; 622 } 623 624 GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length, 625 GrGLbitfield access) override { 626 GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; 627 if (id > 0) { 628 // We just ignore the offset and length here. 629 Buffer* buffer = fBufferManager.lookUp(id); 630 SkASSERT(!buffer->mapped()); 631 buffer->setMapped(true); 632 return buffer->dataPtr(); 633 } 634 return nullptr; 635 } 636 637 GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override { 638 GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; 639 if (id > 0) { 640 Buffer* buffer = fBufferManager.lookUp(id); 641 SkASSERT(!buffer->mapped()); 642 buffer->setMapped(true); 643 return buffer->dataPtr(); 644 } 645 646 SkASSERT(false); 647 return nullptr; // no buffer bound to target 648 } 649 650 GrGLboolean unmapBuffer(GrGLenum target) override { 651 GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; 652 if (id > 0) { 653 Buffer* buffer = fBufferManager.lookUp(id); 654 SkASSERT(buffer->mapped()); 655 buffer->setMapped(false); 656 return GR_GL_TRUE; 657 } 658 659 GrAlwaysAssert(false); 660 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION; 661 } 662 663 GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) override { 664 switch (pname) { 665 case GR_GL_BUFFER_MAPPED: { 666 *params = GR_GL_FALSE; 667 GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; 668 if (id > 0) { 669 Buffer* buffer = fBufferManager.lookUp(id); 670 if (buffer->mapped()) { 671 *params = GR_GL_TRUE; 672 } 673 } 674 break; } 675 default: 676 SK_ABORT("Unexpected pname to GetBufferParamateriv"); 677 break; 678 } 679 } 680 681 // NV_path_rendering 682 GrGLuint genPaths(GrGLsizei range) override { 683 return ++fCurrPathID; 684 } 685 686 687private: 688 inline int static GetBufferIndex(GrGLenum glTarget) { 689 switch (glTarget) { 690 default: SK_ABORT("Unexpected GL target to GetBufferIndex"); 691 case GR_GL_ARRAY_BUFFER: return 0; 692 case GR_GL_ELEMENT_ARRAY_BUFFER: return 1; 693 case GR_GL_TEXTURE_BUFFER: return 2; 694 case GR_GL_DRAW_INDIRECT_BUFFER: return 3; 695 case GR_GL_PIXEL_PACK_BUFFER: return 4; 696 case GR_GL_PIXEL_UNPACK_BUFFER: return 5; 697 } 698 } 699 constexpr int static kNumBufferTargets = 6; 700 701 TGLObjectManager<Buffer> fBufferManager; 702 GrGLuint fBoundBuffers[kNumBufferTargets]; 703 TGLObjectManager<Framebuffer> fFramebufferManager; 704 GrGLuint fCurrDrawFramebuffer; 705 GrGLuint fCurrReadFramebuffer; 706 TGLObjectManager<Renderbuffer> fRenderbufferManager; 707 GrGLuint fCurrRenderbuffer; 708 GrGLuint fCurrProgramID; 709 GrGLuint fCurrShaderID; 710 GrGLuint fCurrGenericID; 711 GrGLuint fCurrUniformLocation; 712 GrGLuint fCurrPathID; 713 sk_sp<const Texture> fSingleTextureObject; 714 SkTArray<const char*> fAdvertisedExtensions; 715 716 // the OpenGLES 2.0 spec says this must be >= 128 717 static const GrGLint kDefaultMaxVertexUniformVectors = 128; 718 719 // the OpenGLES 2.0 spec says this must be >=16 720 static const GrGLint kDefaultMaxFragmentUniformVectors = 16; 721 722 // the OpenGLES 2.0 spec says this must be >= 8 723 static const GrGLint kDefaultMaxVertexAttribs = 8; 724 725 // the OpenGLES 2.0 spec says this must be >= 8 726 static const GrGLint kDefaultMaxVaryingVectors = 8; 727 728 GrGLuint getBoundFramebufferID(GrGLenum target) { 729 switch (target) { 730 case GR_GL_FRAMEBUFFER: 731 case GR_GL_DRAW_FRAMEBUFFER: 732 return fCurrDrawFramebuffer; 733 case GR_GL_READ_FRAMEBUFFER: 734 return fCurrReadFramebuffer; 735 default: 736 SK_ABORT("Invalid framebuffer target."); 737 return 0; 738 } 739 } 740 741 const Texture* getSingleTextureObject() { 742 // We currently only use FramebufferAttachment objects for a sample count, and all textures 743 // in Skia have one sample, so there is no need as of yet to track individual textures. This 744 // also works around a bug in chromium's cc_unittests where they send us texture IDs that 745 // were generated by cc::TestGLES2Interface. 746 if (!fSingleTextureObject) { 747 fSingleTextureObject.reset(new Texture); 748 } 749 return fSingleTextureObject.get(); 750 } 751 752 const GrGLubyte* CombinedExtensionString() { 753 static SkString gExtString; 754 static SkMutex gMutex; 755 gMutex.acquire(); 756 if (0 == gExtString.size()) { 757 int i = 0; 758 while (fAdvertisedExtensions[i]) { 759 if (i > 0) { 760 gExtString.append(" "); 761 } 762 gExtString.append(fAdvertisedExtensions[i]); 763 ++i; 764 } 765 } 766 gMutex.release(); 767 return (const GrGLubyte*) gExtString.c_str(); 768 } 769 770 GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) { 771 for (int i = 0; i < n; ++i) { 772 ids[i] = ++fCurrGenericID; 773 } 774 } 775 776 GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length, 777 char* infolog) { 778 if (length) { 779 *length = 0; 780 } 781 if (bufsize > 0) { 782 *infolog = 0; 783 } 784 } 785 786 GrGLvoid getShaderOrProgramiv(GrGLuint object, GrGLenum pname, GrGLint* params) { 787 switch (pname) { 788 case GR_GL_LINK_STATUS: // fallthru 789 case GR_GL_COMPILE_STATUS: 790 *params = GR_GL_TRUE; 791 break; 792 case GR_GL_INFO_LOG_LENGTH: // fallthru 793 case GL_PROGRAM_BINARY_LENGTH: 794 *params = 0; 795 break; 796 // we don't expect any other pnames 797 default: 798 SK_ABORT("Unexpected pname to GetProgramiv"); 799 break; 800 } 801 } 802 803 template <typename T> 804 void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) { 805 switch (pname) { 806 case GR_GL_QUERY_RESULT_AVAILABLE: 807 *params = GR_GL_TRUE; 808 break; 809 case GR_GL_QUERY_RESULT: 810 *params = 0; 811 break; 812 default: 813 SK_ABORT("Unexpected pname passed to GetQueryObject."); 814 break; 815 } 816 } 817 818 typedef GrGLTestInterface INHERITED; 819}; 820 821} // anonymous namespace 822 823const GrGLInterface* GrGLCreateNullInterface(bool enableNVPR) { return new NullInterface(enableNVPR); } 824