diff options
author | csmartdalton <csmartdalton@google.com> | 2016-06-23 13:42:13 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-23 13:42:13 -0700 |
commit | b593a76749c6c7e12bf86aeaa06e1e52708e9bdf (patch) | |
tree | f830d0739fe1710765fa019bf8335a8b01923317 /src | |
parent | 425c27fab9d82d19b0bce7c091533d546465bbae (diff) |
Support GL_SAMPLES queries in null contexts
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2085043002
Committed: https://skia.googlesource.com/skia/+/64b92a59294a2f73448b3fa8f36f39079f032521
Committed: https://skia.googlesource.com/skia/+/57e98530c113066c4c2d9c64505c52dc25e66c00
Review-Url: https://codereview.chromium.org/2085043002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/gl/GrGLCreateNullInterface.cpp | 428 |
1 files changed, 354 insertions, 74 deletions
diff --git a/src/gpu/gl/GrGLCreateNullInterface.cpp b/src/gpu/gl/GrGLCreateNullInterface.cpp index efdea2b47f..b70ca44cb0 100644 --- a/src/gpu/gl/GrGLCreateNullInterface.cpp +++ b/src/gpu/gl/GrGLCreateNullInterface.cpp @@ -6,114 +6,219 @@ */ +#include "GrNonAtomicRef.h" #include "gl/GrGLInterface.h" #include "GrGLTestInterface.h" #include "SkMutex.h" #include "SkTDArray.h" +#include <type_traits> // added to suppress 'no previous prototype' warning and because this code is duplicated in // SkNullGLContext.cpp namespace { -class BufferObj { +class GLObject : public GrNonAtomicRef<GLObject> { public: - BufferObj(GrGLuint id) : fID(id), fDataPtr(nullptr), fSize(0), fMapped(false) {} - ~BufferObj() { delete[] fDataPtr; } + GLObject(GrGLuint id) : fID(id) {} + virtual ~GLObject() {} - void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) { - if (fDataPtr) { - SkASSERT(0 != fSize); - delete[] fDataPtr; - } - - fSize = size; - fDataPtr = new char[size]; - } - - GrGLuint id() const { return fID; } - GrGLchar* dataPtr() { return fDataPtr; } - GrGLsizeiptr size() const { return fSize; } - - void setMapped(bool mapped) { fMapped = mapped; } - bool mapped() const { return fMapped; } + GrGLuint id() const { return fID; } private: - GrGLuint fID; - GrGLchar* fDataPtr; - GrGLsizeiptr fSize; // size in bytes - bool fMapped; + GrGLuint fID; }; -// This class maintains a sparsely populated array of buffer pointers. -class BufferManager { +// This class maintains a sparsely populated array of object pointers. +template<typename T> class TGLObjectManager { + static_assert(std::is_convertible<T*, GLObject*>::value, "T must be a subclass of GLObject"); + public: - BufferManager() : fFreeListHead(kFreeListEnd) { - *fBuffers.append() = nullptr; // 0 is not a valid GL buffer id. + TGLObjectManager() : fFreeListHead(kFreeListEnd) { + *fGLObjects.append() = nullptr; // 0 is not a valid GL object id. } - ~BufferManager() { + ~TGLObjectManager() { // nullptr out the entries that are really free list links rather than ptrs before deleting. intptr_t curr = fFreeListHead; while (kFreeListEnd != curr) { - intptr_t next = reinterpret_cast<intptr_t>(fBuffers[SkToS32(curr)]); - fBuffers[SkToS32(curr)] = nullptr; + intptr_t next = reinterpret_cast<intptr_t>(fGLObjects[SkToS32(curr)]); + fGLObjects[SkToS32(curr)] = nullptr; curr = next; } - fBuffers.deleteAll(); + fGLObjects.safeUnrefAll(); } - BufferObj* lookUp(GrGLuint id) { - BufferObj* buffer = fBuffers[id]; - SkASSERT(buffer && buffer->id() == id); - return buffer; + T* lookUp(GrGLuint id) { + T* object = fGLObjects[id]; + SkASSERT(object && object->id() == id); + return object; } - BufferObj* create() { + T* create() { GrGLuint id; - BufferObj* buffer; + T* object; if (kFreeListEnd == fFreeListHead) { // no free slots - create a new one - id = fBuffers.count(); - buffer = new BufferObj(id); - *fBuffers.append() = buffer; + id = fGLObjects.count(); + object = new T(id); + *fGLObjects.append() = object; } else { // grab the head of the free list and advance the head to the next free slot. id = static_cast<GrGLuint>(fFreeListHead); - fFreeListHead = reinterpret_cast<intptr_t>(fBuffers[id]); + fFreeListHead = reinterpret_cast<intptr_t>(fGLObjects[id]); - buffer = new BufferObj(id); - fBuffers[id] = buffer; + object = new T(id); + fGLObjects[id] = object; } - return buffer; + return object; } - void free(BufferObj* buffer) { - SkASSERT(buffer); - SkASSERT(fBuffers.count() > 0); + void free(T* object) { + SkASSERT(object); + SkASSERT(fGLObjects.count() > 0); - GrGLuint id = buffer->id(); - delete buffer; + GrGLuint id = object->id(); + object->unref(); - fBuffers[id] = reinterpret_cast<BufferObj*>(fFreeListHead); + fGLObjects[id] = reinterpret_cast<T*>(fFreeListHead); fFreeListHead = id; } private: static const intptr_t kFreeListEnd = -1; - // Index of the first entry of fBuffers in the free list. Free slots in fBuffers are indices to - // the next free slot. The last free slot has a value of kFreeListEnd. - intptr_t fFreeListHead; - SkTDArray<BufferObj*> fBuffers; + // Index of the first entry of fGLObjects in the free list. Free slots in fGLObjects are indices + // to the next free slot. The last free slot has a value of kFreeListEnd. + intptr_t fFreeListHead; + SkTDArray<T*> fGLObjects; +}; + +class Buffer : public GLObject { +public: + Buffer(GrGLuint id) : INHERITED(id), fDataPtr(nullptr), fSize(0), fMapped(false) {} + ~Buffer() { delete[] fDataPtr; } + + void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) { + if (fDataPtr) { + SkASSERT(0 != fSize); + delete[] fDataPtr; + } + + fSize = size; + fDataPtr = new char[size]; + } + + GrGLchar* dataPtr() { return fDataPtr; } + GrGLsizeiptr size() const { return fSize; } + + void setMapped(bool mapped) { fMapped = mapped; } + bool mapped() const { return fMapped; } + +private: + GrGLchar* fDataPtr; + GrGLsizeiptr fSize; // size in bytes + bool fMapped; + + typedef GLObject INHERITED; +}; + +class FramebufferAttachment : public GLObject { +public: + int numSamples() const { return fNumSamples; } + +protected: + FramebufferAttachment(int id) : INHERITED(id), fNumSamples(1) {} + + int fNumSamples; + + typedef GLObject INHERITED; +}; + +class Renderbuffer : public FramebufferAttachment { +public: + Renderbuffer(int id) : INHERITED(id) {} + void setNumSamples(int numSamples) { fNumSamples = numSamples; } + +private: + typedef FramebufferAttachment INHERITED; +}; + +class Texture : public FramebufferAttachment { +public: + Texture() : INHERITED(1) {} + +private: + typedef FramebufferAttachment INHERITED; +}; + +class Framebuffer : public GLObject { +public: + Framebuffer(int id) : INHERITED(id) {} + + void setAttachment(GrGLenum attachmentPoint, const FramebufferAttachment* attachment) { + switch (attachmentPoint) { + default: + SK_ABORT("Invalid framebuffer attachment."); + break; + case GR_GL_STENCIL_ATTACHMENT: + fAttachments[(int)AttachmentPoint::kStencil].reset(SkRef(attachment)); + break; + case GR_GL_DEPTH_ATTACHMENT: + fAttachments[(int)AttachmentPoint::kDepth].reset(SkRef(attachment)); + break; + case GR_GL_COLOR_ATTACHMENT0: + fAttachments[(int)AttachmentPoint::kColor].reset(SkRef(attachment)); + break; + } + } + + void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) { + for (auto& attachment : fAttachments) { + if (attachment == deleted) { + attachment.reset(nullptr); + } + } + } + + int numSamples() const { + int numSamples = 0; + for (auto& attachment : fAttachments) { + if (!attachment) { + continue; + } + if (numSamples) { + GrAlwaysAssert(attachment->numSamples() == numSamples); + continue; + } + numSamples = attachment->numSamples(); + } + GrAlwaysAssert(numSamples); + return numSamples; + } + +private: + enum AttachmentPoint { + kStencil, + kDepth, + kColor + }; + constexpr int static kNumAttachmentPoints = 1 + (int)AttachmentPoint::kColor; + + SkAutoTUnref<const FramebufferAttachment> fAttachments[kNumAttachmentPoints]; + + typedef GLObject INHERITED; }; /** Null interface implementation */ class NullInterface : public GrGLTestInterface { public: NullInterface(bool enableNVPR) - : fCurrProgramID(0) + : fCurrDrawFramebuffer(0) + , fCurrReadFramebuffer(0) + , fCurrRenderbuffer(0) + , fCurrProgramID(0) , fCurrShaderID(0) , fCurrGenericID(0) , fCurrUniformLocation(0) @@ -140,7 +245,7 @@ public: GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override { for (int i = 0; i < n; ++i) { - BufferObj* buffer = fBufferManager.create(); + Buffer* buffer = fBufferManager.create(); ids[i] = buffer->id(); } } @@ -149,7 +254,7 @@ public: GrGLenum usage) override { GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; if (id > 0) { - BufferObj* buffer = fBufferManager.lookUp(id); + Buffer* buffer = fBufferManager.lookUp(id); buffer->allocate(size, (const GrGLchar*) data); } } @@ -184,26 +289,168 @@ public: // Then actually "delete" the buffers. for (int i = 0; i < n; ++i) { if (ids[i] > 0) { - BufferObj* buffer = fBufferManager.lookUp(ids[i]); + Buffer* buffer = fBufferManager.lookUp(ids[i]); fBufferManager.free(buffer); } } } GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override { - this->genGenericIds(n, framebuffers); + for (int i = 0; i < n; ++i) { + Framebuffer* framebuffer = fFramebufferManager.create(); + framebuffers[i] = framebuffer->id(); + } + } + + GrGLvoid bindFramebuffer(GrGLenum target, GrGLuint framebuffer) override { + SkASSERT(GR_GL_FRAMEBUFFER == target || GR_GL_DRAW_FRAMEBUFFER == target || + GR_GL_READ_FRAMEBUFFER == target); + if (GR_GL_READ_FRAMEBUFFER != target) { + fCurrDrawFramebuffer = framebuffer; + } + if (GR_GL_DRAW_FRAMEBUFFER != target) { + fCurrReadFramebuffer = framebuffer; + } + } + + GrGLvoid deleteFramebuffers(GrGLsizei n, const GrGLuint* ids) override { + for (int i = 0; i < n; ++i) { + if (ids[i] == fCurrDrawFramebuffer) { + fCurrDrawFramebuffer = 0; + } + if (ids[i] == fCurrReadFramebuffer) { + fCurrReadFramebuffer = 0; + } + + if (ids[i] > 0) { + Framebuffer* framebuffer = fFramebufferManager.lookUp(ids[i]); + fFramebufferManager.free(framebuffer); + } + } } GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); } GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override { - this->genGenericIds(n, renderbuffers); + for (int i = 0; i < n; ++i) { + Renderbuffer* renderbuffer = fRenderbufferManager.create(); + renderbuffers[i] = renderbuffer->id(); + } + } + + GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) override { + SkASSERT(GR_GL_RENDERBUFFER == target); + fCurrRenderbuffer = renderbuffer; + } + + GrGLvoid deleteRenderbuffers(GrGLsizei n, const GrGLuint* ids) override { + for (int i = 0; i < n; ++i) { + if (ids[i] <= 0) { + continue; + } + if (ids[i] == fCurrRenderbuffer) { + fCurrRenderbuffer = 0; + } + Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(ids[i]); + + if (fCurrDrawFramebuffer) { + Framebuffer* drawFramebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer); + drawFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer); + } + if (fCurrReadFramebuffer) { + Framebuffer* readFramebuffer = fFramebufferManager.lookUp(fCurrReadFramebuffer); + readFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer); + } + + fRenderbufferManager.free(renderbuffer); + } + } + + GrGLvoid renderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width, + GrGLsizei height) override { + GrAlwaysAssert(GR_GL_RENDERBUFFER == target); + GrAlwaysAssert(fCurrRenderbuffer); + Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer); + renderbuffer->setNumSamples(1); + } + + GrGLvoid renderbufferStorageMultisample(GrGLenum target, GrGLsizei samples, + GrGLenum internalformat, GrGLsizei width, + GrGLsizei height) override { + GrAlwaysAssert(GR_GL_RENDERBUFFER == target); + GrAlwaysAssert(samples > 0); + GrAlwaysAssert(fCurrRenderbuffer); + Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer); + renderbuffer->setNumSamples(samples); + } + + GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat, + GrGLsizei width, GrGLsizei height) override { + SK_ABORT("Not implemented"); + } + + GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples, + GrGLenum GrGLinternalformat, GrGLsizei width, + GrGLsizei height) override { + SK_ABORT("Not implemented"); + } + + GrGLvoid framebufferRenderbuffer(GrGLenum target, GrGLenum attachment, + GrGLenum renderbuffertarget, + GrGLuint renderBufferID) override { + GrGLuint id = this->getBoundFramebufferID(target); + GrAlwaysAssert(id); + Framebuffer* framebuffer = fFramebufferManager.lookUp(id); + + GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget); + GrAlwaysAssert(fCurrRenderbuffer); + Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer); + + framebuffer->setAttachment(attachment, renderbuffer); + } + + GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment, + GrGLenum renderbuffertarget, + GrGLuint renderbuffer) override { + SK_ABORT("Not implemented"); } GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override { this->genGenericIds(n, textures); } + GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, + GrGLuint textureID, GrGLint level) override { + GrGLuint id = this->getBoundFramebufferID(target); + GrAlwaysAssert(id); + Framebuffer* framebuffer = fFramebufferManager.lookUp(id); + framebuffer->setAttachment(attachment, this->getSingleTextureObject()); + } + + GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment, + GrGLenum textarget, GrGLuint texture, GrGLint level, + GrGLsizei samples) override { + SK_ABORT("Not implemented"); + } + + GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment, + GrGLenum textarget, GrGLuint texture, + GrGLint level) override { + SK_ABORT("Not implemented"); + } + + GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment, + GrGLenum textarget, GrGLuint texture, + GrGLint level) override { + SK_ABORT("Not implemented"); + } + + GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment, + GrGLenum textarget, GrGLuint texture, GrGLint level, + GrGLint zoffset) override { + SK_ABORT("Not implemented"); + } + GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override { this->genGenericIds(n, arrays); } @@ -220,9 +467,12 @@ public: case GR_GL_STENCIL_BITS: *params = 8; break; - case GR_GL_SAMPLES: - *params = 1; + case GR_GL_SAMPLES: { + GrAlwaysAssert(fCurrDrawFramebuffer); + Framebuffer* framebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer); + *params = framebuffer->numSamples(); break; + } case GR_GL_FRAMEBUFFER_BINDING: *params = 0; break; @@ -376,7 +626,7 @@ public: GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; if (id > 0) { // We just ignore the offset and length here. - BufferObj* buffer = fBufferManager.lookUp(id); + Buffer* buffer = fBufferManager.lookUp(id); SkASSERT(!buffer->mapped()); buffer->setMapped(true); return buffer->dataPtr(); @@ -387,7 +637,7 @@ public: GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override { GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; if (id > 0) { - BufferObj* buffer = fBufferManager.lookUp(id); + Buffer* buffer = fBufferManager.lookUp(id); SkASSERT(!buffer->mapped()); buffer->setMapped(true); return buffer->dataPtr(); @@ -400,7 +650,7 @@ public: GrGLboolean unmapBuffer(GrGLenum target) override { GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; if (id > 0) { - BufferObj* buffer = fBufferManager.lookUp(id); + Buffer* buffer = fBufferManager.lookUp(id); SkASSERT(buffer->mapped()); buffer->setMapped(false); return GR_GL_TRUE; @@ -416,7 +666,7 @@ public: *params = GR_GL_FALSE; GrGLuint id = fBoundBuffers[GetBufferIndex(target)]; if (id > 0) { - BufferObj* buffer = fBufferManager.lookUp(id); + Buffer* buffer = fBufferManager.lookUp(id); if (buffer->mapped()) { *params = GR_GL_TRUE; } @@ -448,14 +698,20 @@ private: } constexpr int static kNumBufferTargets = 6; - BufferManager fBufferManager; - GrGLuint fBoundBuffers[kNumBufferTargets]; - GrGLuint fCurrProgramID; - GrGLuint fCurrShaderID; - GrGLuint fCurrGenericID; - GrGLuint fCurrUniformLocation; - GrGLuint fCurrPathID; - SkTArray<const char*> fExtensions; + TGLObjectManager<Buffer> fBufferManager; + GrGLuint fBoundBuffers[kNumBufferTargets]; + TGLObjectManager<Framebuffer> fFramebufferManager; + GrGLuint fCurrDrawFramebuffer; + GrGLuint fCurrReadFramebuffer; + TGLObjectManager<Renderbuffer> fRenderbufferManager; + GrGLuint fCurrRenderbuffer; + GrGLuint fCurrProgramID; + GrGLuint fCurrShaderID; + GrGLuint fCurrGenericID; + GrGLuint fCurrUniformLocation; + GrGLuint fCurrPathID; + SkAutoTUnref<const Texture> fSingleTextureObject; + SkTArray<const char*> fExtensions; // the OpenGLES 2.0 spec says this must be >= 128 static const GrGLint kDefaultMaxVertexUniformVectors = 128; @@ -469,6 +725,30 @@ private: // the OpenGLES 2.0 spec says this must be >= 8 static const GrGLint kDefaultMaxVaryingVectors = 8; + GrGLuint getBoundFramebufferID(GrGLenum target) { + switch (target) { + case GR_GL_FRAMEBUFFER: + case GR_GL_DRAW_FRAMEBUFFER: + return fCurrDrawFramebuffer; + case GR_GL_READ_FRAMEBUFFER: + return fCurrReadFramebuffer; + default: + SK_ABORT("Invalid framebuffer target."); + return 0; + } + } + + const Texture* getSingleTextureObject() { + // We currently only use FramebufferAttachment objects for a sample count, and all textures + // in Skia have one sample, so there is no need as of yet to track individual textures. This + // also works around a bug in chromium's cc_unittests where they send us texture IDs that + // were generated by cc::TestGLES2Interface. + if (!fSingleTextureObject) { + fSingleTextureObject.reset(new Texture); + } + return fSingleTextureObject; + } + const GrGLubyte* CombinedExtensionString() { static SkString gExtString; static SkMutex gMutex; |