aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLBuffer.cpp4
-rw-r--r--src/gpu/gl/GrGLBuffer.h13
-rw-r--r--src/gpu/gl/GrGLCaps.cpp18
-rw-r--r--src/gpu/gl/GrGLCaps.h9
-rw-r--r--src/gpu/gl/GrGLGpu.cpp124
-rw-r--r--src/gpu/gl/GrGLGpu.h24
-rw-r--r--src/gpu/gl/GrGLProgram.cpp42
-rw-r--r--src/gpu/gl/GrGLProgram.h15
-rw-r--r--src/gpu/gl/GrGLProgramDataManager.cpp3
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp29
10 files changed, 218 insertions, 63 deletions
diff --git a/src/gpu/gl/GrGLBuffer.cpp b/src/gpu/gl/GrGLBuffer.cpp
index 6e1ce58588..24fd59267d 100644
--- a/src/gpu/gl/GrGLBuffer.cpp
+++ b/src/gpu/gl/GrGLBuffer.cpp
@@ -96,7 +96,8 @@ GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrBufferType intendedType,
fBufferID(0),
fSizeInBytes(size),
fUsage(gr_to_gl_access_pattern(intendedType, accessPattern)),
- fGLSizeInBytes(0) {
+ fGLSizeInBytes(0),
+ fHasAttachedToTexture(false) {
if (this->isCPUBacked()) {
// Core profile uses vertex array objects, which disallow client side arrays.
SkASSERT(!gpu->glCaps().isCoreProfile());
@@ -151,6 +152,7 @@ void GrGLBuffer::onRelease() {
GL_CALL(DeleteBuffers(1, &fBufferID));
fBufferID = 0;
fGLSizeInBytes = 0;
+ this->glGpu()->notifyBufferReleased(this);
}
fMapPtr = nullptr;
VALIDATE();
diff --git a/src/gpu/gl/GrGLBuffer.h b/src/gpu/gl/GrGLBuffer.h
index b3b4feb002..84d05be382 100644
--- a/src/gpu/gl/GrGLBuffer.h
+++ b/src/gpu/gl/GrGLBuffer.h
@@ -27,6 +27,15 @@ public:
GrGLuint bufferID() const { return fBufferID; }
size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); }
+ /**
+ * Returns the actual size of the underlying GL buffer object. In certain cases we may make this
+ * smaller than the size reported by GrBuffer.
+ */
+ size_t glSizeInBytes() const { return fGLSizeInBytes; }
+
+ void setHasAttachedToTexture() { fHasAttachedToTexture = true; }
+ bool hasAttachedToTexture() const { return fHasAttachedToTexture; }
+
protected:
GrGLBuffer(GrGLGpu*, size_t size, GrBufferType intendedType, GrAccessPattern, bool cpuBacked,
const void* data);
@@ -53,8 +62,8 @@ private:
GrGLuint fBufferID;
size_t fSizeInBytes;
GrGLenum fUsage;
- size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object
- // smaller or larger than the size in fDesc.
+ size_t fGLSizeInBytes;
+ bool fHasAttachedToTexture;
typedef GrBuffer INHERITED;
};
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 0322a0f57c..f3e494acb9 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1382,6 +1382,8 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
texStorageSupported = false;
}
+ bool texelBufferSupport = this->shaderCaps()->texelBufferSupport();
+
fConfigTable[kUnknown_GrPixelConfig].fFormats.fBaseInternalFormat = 0;
fConfigTable[kUnknown_GrPixelConfig].fFormats.fSizedInternalFormat = 0;
fConfigTable[kUnknown_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] = 0;
@@ -1408,6 +1410,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
if (texStorageSupported) {
fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
}
+ if (texelBufferSupport) {
+ fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
fConfigTable[kRGBA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] =
@@ -1567,6 +1572,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kAlpha_8_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] =
GR_GL_RED;
fConfigTable[kAlpha_8_GrPixelConfig].fSwizzle = GrSwizzle::RRRR();
+ if (texelBufferSupport) {
+ fConfigTable[kAlpha_8_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
} else {
fConfigTable[kAlpha_8_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_ALPHA;
fConfigTable[kAlpha_8_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_ALPHA8;
@@ -1635,6 +1643,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
if (texStorageSupported) {
fConfigTable[kRGBA_float_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
}
+ if (texelBufferSupport) {
+ fConfigTable[kRGBA_float_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
fConfigTable[kRGBA_float_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
if (this->textureRedSupport()) {
@@ -1643,6 +1654,10 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kAlpha_half_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage]
= GR_GL_RED;
fConfigTable[kAlpha_half_GrPixelConfig].fSwizzle = GrSwizzle::RRRR();
+ if (texelBufferSupport) {
+ fConfigTable[kAlpha_half_GrPixelConfig].fFlags |=
+ ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
} else {
fConfigTable[kAlpha_half_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_ALPHA;
fConfigTable[kAlpha_half_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_ALPHA16F;
@@ -1691,6 +1706,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
if (texStorageSupported) {
fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
}
+ if (texelBufferSupport) {
+ fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseWithTexelBuffer_Flag;
+ }
fConfigTable[kRGBA_half_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
// Compressed texture support
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index e2bc100cae..1602a0f63d 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -135,11 +135,19 @@ public:
return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseTexStorage_Flag);
}
+ bool canUseConfigWithTexelBuffer(GrPixelConfig config) const {
+ return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseWithTexelBuffer_Flag);
+ }
+
/** Returns the mapping between GrPixelConfig components and GL internal format components. */
const GrSwizzle& configSwizzle(GrPixelConfig config) const {
return fConfigTable[config].fSwizzle;
}
+ GrGLenum configSizedInternalFormat(GrPixelConfig config) const {
+ return fConfigTable[config].fFormats.fSizedInternalFormat;
+ }
+
bool getTexImageFormats(GrPixelConfig surfaceConfig, GrPixelConfig externalConfig,
GrGLenum* internalFormat, GrGLenum* externalFormat,
GrGLenum* externalType) const;
@@ -468,6 +476,7 @@ private:
kRenderable_Flag = 0x4,
kRenderableWithMSAA_Flag = 0x8,
kCanUseTexStorage_Flag = 0x10,
+ kCanUseWithTexelBuffer_Flag = 0x20,
};
uint32_t fFlags;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index e8b5755849..af5955014a 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -194,6 +194,7 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
, fTempSrcFBOID(0)
, fTempDstFBOID(0)
, fStencilClearFBOID(0)
+ , fHWMaxUsedBufferTextureUnit(-1)
, fHWPLSEnabled(false)
, fPLSHasBeenUsed(false)
, fHWMinSampleShading(0.0) {
@@ -223,6 +224,10 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
}
GR_STATIC_ASSERT(6 == SK_ARRAY_COUNT(fHWBufferState));
+ if (this->caps()->shaderCaps()->texelBufferSupport()) {
+ fHWBufferTextures.reset(this->glCaps().glslCaps()->maxCombinedSamplers());
+ }
+
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
fPathRendering.reset(new GrGLPathRendering(this));
}
@@ -522,6 +527,10 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
for (int s = 0; s < fHWBoundTextureUniqueIDs.count(); ++s) {
fHWBoundTextureUniqueIDs[s] = SK_InvalidUniqueID;
}
+ for (int b = 0; b < fHWBufferTextures.count(); ++b) {
+ SkASSERT(this->caps()->shaderCaps()->texelBufferSupport());
+ fHWBufferTextures[b].fKnownBound = false;
+ }
}
if (resetBits & kBlend_GrGLBackendState) {
@@ -2052,14 +2061,7 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso
this->flushBlend(blendInfo, swizzle);
}
- SkSTArray<8, const GrTextureAccess*> textureAccesses;
- program->setData(primProc, pipeline, &textureAccesses);
-
- int numTextureAccesses = textureAccesses.count();
- for (int i = 0; i < numTextureAccesses; i++) {
- this->bindTexture(i, textureAccesses[i]->getParams(), pipeline.getAllowSRGBInputs(),
- static_cast<GrGLTexture*>(textureAccesses[i]->getTexture()));
- }
+ program->setData(primProc, pipeline);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
this->flushStencil(pipeline.getStencil());
@@ -2147,6 +2149,31 @@ GrGLenum GrGLGpu::bindBuffer(GrBufferType type, const GrGLBuffer* buffer) {
return bufferState.fGLTarget;
}
+void GrGLGpu::notifyBufferReleased(const GrGLBuffer* buffer) {
+ if (buffer->hasAttachedToTexture()) {
+ // Detach this buffer from any textures to ensure the underlying memory is freed.
+ uint32_t uniqueID = buffer->getUniqueID();
+ for (int i = fHWMaxUsedBufferTextureUnit; i >= 0; --i) {
+ auto& buffTex = fHWBufferTextures[i];
+ if (uniqueID != buffTex.fAttachedBufferUniqueID) {
+ continue;
+ }
+ if (i == fHWMaxUsedBufferTextureUnit) {
+ --fHWMaxUsedBufferTextureUnit;
+ }
+
+ this->setTextureUnit(i);
+ if (!buffTex.fKnownBound) {
+ SkASSERT(buffTex.fTextureID);
+ GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
+ buffTex.fKnownBound = true;
+ }
+ GL_CALL(TexBuffer(GR_GL_TEXTURE_BUFFER,
+ this->glCaps().configSizedInternalFormat(buffTex.fTexelConfig), 0));
+ }
+ }
+}
+
void GrGLGpu::disableScissor() {
if (kNo_TriState != fHWScissorSettings.fEnabled) {
GL_CALL(Disable(GR_GL_SCISSOR_TEST));
@@ -3264,21 +3291,78 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, bool dstCo
(setAll || memcmp(newTexParams.fSwizzleRGBA,
oldTexParams.fSwizzleRGBA,
sizeof(newTexParams.fSwizzleRGBA)))) {
+ this->setTextureSwizzle(unitIdx, target, newTexParams.fSwizzleRGBA);
+ }
+ texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
+}
+
+void GrGLGpu::bindTexelBuffer(int unitIdx, intptr_t offsetInBytes, GrPixelConfig texelConfig,
+ GrGLBuffer* buffer) {
+ SkASSERT(this->glCaps().canUseConfigWithTexelBuffer(texelConfig));
+ SkASSERT(unitIdx >= 0 && unitIdx < fHWBufferTextures.count());
+ SkASSERT(offsetInBytes >= 0 && offsetInBytes < (intptr_t) buffer->glSizeInBytes());
+
+ BufferTexture& buffTex = fHWBufferTextures[unitIdx];
+
+ if (!buffTex.fKnownBound) {
+ if (!buffTex.fTextureID) {
+ GL_CALL(GenTextures(1, &buffTex.fTextureID));
+ if (!buffTex.fTextureID) {
+ return;
+ }
+ }
+
this->setTextureUnit(unitIdx);
- if (this->glStandard() == kGLES_GrGLStandard) {
- // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
- const GrGLenum* swizzle = newTexParams.fSwizzleRGBA;
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
- GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
- } else {
- GR_STATIC_ASSERT(sizeof(newTexParams.fSwizzleRGBA[0]) == sizeof(GrGLint));
- const GrGLint* swizzle = reinterpret_cast<const GrGLint*>(newTexParams.fSwizzleRGBA);
- GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA, swizzle));
+ GL_CALL(BindTexture(GR_GL_TEXTURE_BUFFER, buffTex.fTextureID));
+
+ buffTex.fKnownBound = true;
+ }
+
+ if (buffer->getUniqueID() != buffTex.fAttachedBufferUniqueID ||
+ buffTex.fOffsetInBytes != offsetInBytes ||
+ buffTex.fTexelConfig != texelConfig ||
+ buffTex.fAttachedSizeInBytes != buffer->glSizeInBytes() - offsetInBytes) {
+
+ size_t attachmentSizeInBytes = buffer->glSizeInBytes() - offsetInBytes;
+
+ this->setTextureUnit(unitIdx);
+ GL_CALL(TexBufferRange(GR_GL_TEXTURE_BUFFER,
+ this->glCaps().configSizedInternalFormat(texelConfig),
+ buffer->bufferID(),
+ offsetInBytes,
+ attachmentSizeInBytes));
+
+ buffTex.fOffsetInBytes = offsetInBytes;
+ buffTex.fTexelConfig = texelConfig;
+ buffTex.fAttachedSizeInBytes = attachmentSizeInBytes;
+ buffTex.fAttachedBufferUniqueID = buffer->getUniqueID();
+
+ if (this->glCaps().textureSwizzleSupport() &&
+ this->glCaps().configSwizzle(texelConfig) != buffTex.fSwizzle) {
+ GrGLenum glSwizzle[4];
+ get_tex_param_swizzle(texelConfig, this->glCaps(), glSwizzle);
+ this->setTextureSwizzle(unitIdx, GR_GL_TEXTURE_BUFFER, glSwizzle);
+ buffTex.fSwizzle = this->glCaps().configSwizzle(texelConfig);
}
+
+ buffer->setHasAttachedToTexture();
+ fHWMaxUsedBufferTextureUnit = SkTMax(unitIdx, fHWMaxUsedBufferTextureUnit);
+ }
+}
+
+void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]) {
+ this->setTextureUnit(unitIdx);
+ if (this->glStandard() == kGLES_GrGLStandard) {
+ // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
+ } else {
+ GR_STATIC_ASSERT(sizeof(swizzle[0]) == sizeof(GrGLint));
+ GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
+ reinterpret_cast<const GrGLint*>(swizzle)));
}
- texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
}
void GrGLGpu::flushColorWrite(bool writeColor) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index c2dda0a222..c8b5d70f1b 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -60,6 +60,8 @@ public:
void bindTexture(int unitIdx, const GrTextureParams& params, bool dstConfigAllowsSRGB,
GrGLTexture* texture);
+ void bindTexelBuffer(int unitIdx, intptr_t offsetInBytes, GrPixelConfig, GrGLBuffer*);
+
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
GrPixelConfig readConfig, DrawPreference*,
ReadPixelTempDrawInfo*) override;
@@ -88,6 +90,9 @@ public:
// If the caller wishes to bind an index buffer to a specific VAO, it can call glBind directly.
GrGLenum bindBuffer(GrBufferType type, const GrGLBuffer*);
+ // Called by GrGLBuffer after its buffer object has been destroyed.
+ void notifyBufferReleased(const GrGLBuffer*);
+
const GrGLContext* glContextForTesting() const override {
return &this->glContext();
}
@@ -206,6 +211,8 @@ private:
// binds texture unit in GL
void setTextureUnit(int unitIdx);
+ void setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]);
+
// Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
bool flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc);
@@ -498,6 +505,23 @@ private:
TriState fHWSRGBFramebuffer;
SkTArray<uint32_t, true> fHWBoundTextureUniqueIDs;
+ struct BufferTexture {
+ BufferTexture() : fTextureID(0), fKnownBound(false),
+ fAttachedBufferUniqueID(SK_InvalidUniqueID),
+ fSwizzle(GrSwizzle::RGBA()) {}
+
+ GrGLuint fTextureID;
+ bool fKnownBound;
+ intptr_t fOffsetInBytes;
+ GrPixelConfig fTexelConfig;
+ size_t fAttachedSizeInBytes;
+ uint32_t fAttachedBufferUniqueID;
+ GrSwizzle fSwizzle;
+ };
+
+ SkTArray<BufferTexture, true> fHWBufferTextures;
+ int fHWMaxUsedBufferTextureUnit;
+
// EXT_raster_multisample.
TriState fHWRasterMultisampleEnabled;
int fHWNumRasterSamples;
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index aa828a24c4..6a433e17c5 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -11,6 +11,7 @@
#include "GrProcessor.h"
#include "GrCoordTransform.h"
#include "GrGLGpu.h"
+#include "GrGLBuffer.h"
#include "GrGLPathRendering.h"
#include "GrPathProcessor.h"
#include "GrPipeline.h"
@@ -66,46 +67,34 @@ void GrGLProgram::abandon() {
///////////////////////////////////////////////////////////////////////////////
-static void append_texture_bindings(const GrProcessor& processor,
- SkTArray<const GrTextureAccess*>* textureBindings) {
- if (int numTextures = processor.numTextures()) {
- const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures);
- int i = 0;
- do {
- bindings[i] = &processor.textureAccess(i);
- } while (++i < numTextures);
- }
-}
-
-void GrGLProgram::setData(const GrPrimitiveProcessor& primProc,
- const GrPipeline& pipeline,
- SkTArray<const GrTextureAccess*>* textureBindings) {
+void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) {
this->setRenderTargetState(primProc, pipeline);
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
+ int nextSamplerIdx = 0;
fGeometryProcessor->setData(fProgramDataManager, primProc);
- append_texture_bindings(primProc, textureBindings);
+ this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
- this->setFragmentData(primProc, pipeline, textureBindings);
+ this->setFragmentData(primProc, pipeline, &nextSamplerIdx);
if (primProc.getPixelLocalStorageState() !=
GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
const GrXferProcessor& xp = pipeline.getXferProcessor();
fXferProcessor->setData(fProgramDataManager, xp);
- append_texture_bindings(xp, textureBindings);
+ this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
}
}
void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
- SkTArray<const GrTextureAccess*>* textureBindings) {
+ int* nextSamplerIdx) {
int numProcessors = fFragmentProcessors.count();
for (int i = 0; i < numProcessors; ++i) {
const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
fFragmentProcessors[i]->setData(fProgramDataManager, processor);
this->setTransformData(primProc, processor, i);
- append_texture_bindings(processor, textureBindings);
+ this->bindTextures(processor, pipeline.getAllowSRGBInputs(), nextSamplerIdx);
}
}
void GrGLProgram::setTransformData(const GrPrimitiveProcessor& primProc,
@@ -145,3 +134,18 @@ void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
size, rt->origin());
}
}
+
+void GrGLProgram::bindTextures(const GrProcessor& processor,
+ bool allowSRGBInputs,
+ int* nextSamplerIdx) {
+ for (int i = 0; i < processor.numTextures(); ++i) {
+ const GrTextureAccess& access = processor.textureAccess(i);
+ fGpu->bindTexture((*nextSamplerIdx)++, access.getParams(),
+ allowSRGBInputs, static_cast<GrGLTexture*>(access.getTexture()));
+ }
+ for (int i = 0; i < processor.numBuffers(); ++i) {
+ const GrBufferAccess& access = processor.bufferAccess(i);
+ fGpu->bindTexelBuffer((*nextSamplerIdx)++, access.offsetInBytes(), access.texelConfig(),
+ static_cast<GrGLBuffer*>(access.buffer()));
+ }
+}
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 22678cb6a3..c70b1bd0e2 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -94,8 +94,7 @@ public:
* the program is bound before calling, and to bind the outgoing textures to their respective
* units upon return. (Each index in the array corresponds to its matching GL texture unit.)
*/
- void setData(const GrPrimitiveProcessor&, const GrPipeline&,
- SkTArray<const GrTextureAccess*>* textureBindings);
+ void setData(const GrPrimitiveProcessor&, const GrPipeline&);
protected:
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
@@ -113,16 +112,16 @@ protected:
const GrGLSLFragProcs& fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms);
- // A templated helper to loop over effects, set the transforms(via subclass) and bind textures
- void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&,
- SkTArray<const GrTextureAccess*>* textureBindings);
- void setTransformData(const GrPrimitiveProcessor&,
- const GrFragmentProcessor&,
- int index);
+ // A helper to loop over effects, set the transforms (via subclass) and bind textures
+ void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&, int* nextSamplerIdx);
+ void setTransformData(const GrPrimitiveProcessor&, const GrFragmentProcessor&, int index);
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setRenderTargetState(const GrPrimitiveProcessor&, const GrPipeline&);
+ // Helper for setData() that binds textures and texel buffers to the appropriate texture units
+ void bindTextures(const GrProcessor&, bool allowSRGBInputs, int* nextSamplerIdx);
+
// these reflect the current values of uniforms (GL uniform values travel with program)
RenderTargetState fRenderTargetState;
BuiltinUniformHandles fBuiltinUniformHandles;
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index d5b48f7061..6b2e1118cb 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -63,8 +63,7 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, GrGLuint programID,
void GrGLProgramDataManager::setSampler(UniformHandle u, int texUnit) const {
const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kSampler2D_GrSLType || uni.fType == kSamplerExternal_GrSLType ||
- uni.fType == kSampler2DRect_GrSLType);
+ SkASSERT(GrSLTypeIsSamplerType(uni.fType));
SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
// FIXME: We still insert a single sampler uniform for every stage. If the shader does not
// reference the sampler then the compiler may have optimized it out. Uncomment this assert
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 5e9fe5fcc6..801224c9b6 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -17,11 +17,11 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLCaps.h"
-static uint16_t texture_key(GrSLType samplerType, GrPixelConfig config, GrShaderFlags visibility,
+static uint16_t sampler_key(GrSLType samplerType, GrPixelConfig config, GrShaderFlags visibility,
const GrGLSLCaps& caps) {
enum {
kFirstSamplerType = kSampler2D_GrSLType,
- kLastSamplerType = kSampler2DRect_GrSLType,
+ kLastSamplerType = kSamplerBuffer_GrSLType,
kSamplerTypeKeyBits = 4
};
GR_STATIC_ASSERT(kLastSamplerType - kFirstSamplerType < (1 << kSamplerTypeKeyBits));
@@ -34,23 +34,30 @@ static uint16_t texture_key(GrSLType samplerType, GrPixelConfig config, GrShader
(caps.samplerPrecision(config, visibility) << (8 + kSamplerTypeKeyBits)));
}
-static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
- const GrGLSLCaps& caps) {
+static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrProcessor& proc,
+ const GrGLSLCaps& caps) {
int numTextures = proc.numTextures();
+ int numSamplers = numTextures + proc.numBuffers();
// Need two bytes per key (swizzle, sampler type, and precision).
- int word32Count = (proc.numTextures() + 1) / 2;
+ int word32Count = (numSamplers + 1) / 2;
if (0 == word32Count) {
return;
}
uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
- for (int i = 0; i < numTextures; ++i) {
+ int i = 0;
+ for (; i < numTextures; ++i) {
const GrTextureAccess& access = proc.textureAccess(i);
const GrTexture* tex = access.getTexture();
- k16[i] = texture_key(tex->samplerType(), tex->config(), access.getVisibility(), caps);
+ k16[i] = sampler_key(tex->samplerType(), tex->config(), access.getVisibility(), caps);
+ }
+ for (; i < numSamplers; ++i) {
+ const GrBufferAccess& access = proc.bufferAccess(i - numTextures);
+ k16[i] = sampler_key(kSamplerBuffer_GrSLType, access.texelConfig(), access.visibility(),
+ caps);
}
- // zero the last 16 bits if the number of textures is odd.
- if (numTextures & 0x1) {
- k16[numTextures] = 0;
+ // zero the last 16 bits if the number of samplers is odd.
+ if (numSamplers & 0x1) {
+ k16[numSamplers] = 0;
}
}
@@ -76,7 +83,7 @@ static bool gen_meta_key(const GrProcessor& proc,
return false;
}
- add_texture_key(b, proc, glslCaps);
+ add_sampler_keys(b, proc, glslCaps);
uint32_t* key = b->add32n(2);
key[0] = (classID << 16) | SkToU32(processorKeySize);