Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 2bd36b640477eaf1b14a60003436553b9a344b0f..51145c89883e99836fc4c50b30fa8095bbd4755d 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -233,7 +233,7 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context) |
fPathRendering.reset(new GrGLPathRendering(this)); |
} |
- this->createCopyProgram(); |
+ this->createCopyPrograms(); |
} |
GrGLGpu::~GrGLGpu() { |
@@ -253,12 +253,13 @@ GrGLGpu::~GrGLGpu() { |
GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID)); |
} |
- if (0 != fCopyProgram.fArrayBuffer) { |
- GL_CALL(DeleteBuffers(1, &fCopyProgram.fArrayBuffer)); |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) { |
+ if (0 != fCopyPrograms[i].fProgram) { |
+ GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram)); |
+ } |
} |
- |
- if (0 != fCopyProgram.fProgram) { |
- GL_CALL(DeleteProgram(fCopyProgram.fProgram)); |
+ if (0 != fCopyProgramArrayBuffer) { |
+ GL_CALL(DeleteBuffers(1, &fCopyProgramArrayBuffer)); |
} |
delete fProgramCache; |
@@ -271,8 +272,10 @@ void GrGLGpu::contextAbandoned() { |
fTempSrcFBOID = 0; |
fTempDstFBOID = 0; |
fStencilClearFBOID = 0; |
- fCopyProgram.fArrayBuffer = 0; |
- fCopyProgram.fProgram = 0; |
+ fCopyProgramArrayBuffer = 0; |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) { |
+ fCopyPrograms[i].fProgram = 0; |
+ } |
if (this->glCaps().shaderCaps()->pathRenderingSupport()) { |
this->glPathRendering()->abandonGpuResources(); |
} |
@@ -429,6 +432,9 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, |
return nullptr; |
} |
+ // next line relies on GrBackendTextureDesc's flags matching GrTexture's |
+ bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag); |
+ |
GrGLTexture::IDDesc idDesc; |
GrSurfaceDesc surfDesc; |
@@ -439,6 +445,15 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, |
#else |
idDesc.fInfo = *info; |
#endif |
+ if (GR_GL_TEXTURE_EXTERNAL == idDesc.fInfo.fTarget) { |
+ if (renderTarget) { |
+ // This combination is not supported. |
+ return nullptr; |
+ } |
+ if (!this->glCaps().externalTextureSupport()) { |
+ return nullptr; |
+ } |
+ } |
switch (ownership) { |
case kAdopt_GrWrapOwnership: |
@@ -449,13 +464,11 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, |
break; |
} |
- // next line relies on GrBackendTextureDesc's flags matching GrTexture's |
surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags; |
surfDesc.fWidth = desc.fWidth; |
surfDesc.fHeight = desc.fHeight; |
surfDesc.fConfig = desc.fConfig; |
surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()); |
- bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag); |
// FIXME: this should be calling resolve_origin(), but Chrome code is currently |
// assuming the old behaviour, which is that backend textures are always |
// BottomLeft, even for non-RT's. Once Chrome is fixed, change this to: |
@@ -524,6 +537,12 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, |
// into it. We could use glDrawPixels on GLs that have it, but we don't today. |
if (!dstSurface->asTexture()) { |
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
+ } else { |
+ GrGLTexture* texture = static_cast<GrGLTexture*>(dstSurface->asTexture()); |
+ if (GR_GL_TEXTURE_2D != texture->target()) { |
+ // We don't currently support writing pixels to non-TEXTURE_2D textures. |
+ return false; |
+ } |
} |
if (GrPixelConfigIsSRGB(dstSurface->config()) != GrPixelConfigIsSRGB(srcConfig)) { |
@@ -585,6 +604,11 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, |
return false; |
} |
+ // Write pixels is only implemented for TEXTURE_2D textures |
+ if (GR_GL_TEXTURE_2D != glTex->target()) { |
+ return false; |
+ } |
+ |
this->setScratchTextureUnit(); |
GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
@@ -2752,11 +2776,10 @@ void GrGLGpu::setScratchTextureUnit() { |
fHWBoundTextureUniqueIDs[lastUnitIdx] = SK_InvalidUniqueID; |
} |
-namespace { |
// Determines whether glBlitFramebuffer could be used between src and dst. |
-inline bool can_blit_framebuffer(const GrSurface* dst, |
- const GrSurface* src, |
- const GrGLGpu* gpu) { |
+static inline bool can_blit_framebuffer(const GrSurface* dst, |
+ const GrSurface* src, |
+ const GrGLGpu* gpu) { |
if (gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) && |
gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) && |
gpu->glCaps().usesMSAARenderBuffers()) { |
@@ -2766,15 +2789,23 @@ inline bool can_blit_framebuffer(const GrSurface* dst, |
(src->desc().fSampleCnt > 0 || src->config() != dst->config())) { |
return false; |
} |
+ const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture()); |
+ if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) { |
+ return false; |
+ } |
+ const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(dst->asTexture()); |
+ if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) { |
+ return false; |
+ } |
return true; |
} else { |
return false; |
} |
} |
-inline bool can_copy_texsubimage(const GrSurface* dst, |
- const GrSurface* src, |
- const GrGLGpu* gpu) { |
+static inline bool can_copy_texsubimage(const GrSurface* dst, |
+ const GrSurface* src, |
+ const GrGLGpu* gpu) { |
// Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage |
// and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps |
// many drivers would allow it to work, but ANGLE does not. |
@@ -2794,18 +2825,29 @@ inline bool can_copy_texsubimage(const GrSurface* dst, |
if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) { |
return false; |
} |
+ |
+ const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture()); |
+ // CopyTex(Sub)Image writes to a texture and we have no way of dynamically wrapping a RT in a |
+ // texture. |
+ if (!dstTex) { |
+ return false; |
+ } |
+ |
+ const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture()); |
+ |
+ // Check that we could wrap the source in an FBO, that the dst is TEXTURE_2D, that no mirroring |
+ // is required. |
if (gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) && |
- dst->asTexture() && |
- dst->origin() == src->origin() && |
- !GrPixelConfigIsCompressed(src->config())) { |
+ !GrPixelConfigIsCompressed(src->config()) && |
+ (!srcTex || srcTex->target() == GR_GL_TEXTURE_2D) && |
+ dstTex->target() == GR_GL_TEXTURE_2D && |
+ dst->origin() == src->origin()) { |
return true; |
} else { |
return false; |
} |
} |
-} |
- |
// If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is |
// relative to is output. |
void GrGLGpu::bindSurfaceFBOForCopy(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport, |
@@ -2863,6 +2905,12 @@ bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) |
return true; |
} |
+ const GrGLTexture* srcTexture = static_cast<const GrGLTexture*>(src->asTexture()); |
+ if (srcTexture && srcTexture->target() != GR_GL_TEXTURE_2D) { |
+ // Not supported for FBO blit or CopyTexSubImage |
+ return false; |
+ } |
+ |
// We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are |
// possible and we return false to fallback to creating a render target dst for render-to- |
// texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo |
@@ -2927,92 +2975,109 @@ bool GrGLGpu::onCopySurface(GrSurface* dst, |
} |
-void GrGLGpu::createCopyProgram() { |
+void GrGLGpu::createCopyPrograms() { |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) { |
+ fCopyPrograms[i].fProgram = 0; |
+ } |
const char* version = this->glCaps().glslCaps()->versionDeclString(); |
- |
- GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier); |
- GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType, |
+ static const GrSLType kSamplerTypes[2] = { kSampler2D_GrSLType, kSamplerExternal_GrSLType }; |
+ SkASSERT(2 == SK_ARRAY_COUNT(fCopyPrograms)); |
+ int programCount = this->glCaps().externalTextureSupport() ? 2 : 1; |
+ for (int i = 0; i < programCount; ++i) { |
+ GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier); |
+ GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType, |
+ GrShaderVar::kUniform_TypeModifier); |
+ GrGLSLShaderVar uPosXform("u_posXform", kVec4f_GrSLType, |
+ GrShaderVar::kUniform_TypeModifier); |
+ GrGLSLShaderVar uTexture("u_texture", kSamplerTypes[i], |
GrShaderVar::kUniform_TypeModifier); |
- GrGLSLShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier); |
- GrGLSLShaderVar uTexture("u_texture", kSampler2D_GrSLType, GrShaderVar::kUniform_TypeModifier); |
- GrGLSLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier); |
- GrGLSLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier); |
+ GrGLSLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, |
+ GrShaderVar::kVaryingOut_TypeModifier); |
+ GrGLSLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, |
+ GrShaderVar::kOut_TypeModifier); |
- SkString vshaderTxt(version); |
- aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
- vshaderTxt.append(";"); |
- uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
- vshaderTxt.append(";"); |
- uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
- vshaderTxt.append(";"); |
- vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
- vshaderTxt.append(";"); |
+ SkString vshaderTxt(version); |
+ aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
+ vshaderTxt.append(";"); |
+ uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
+ vshaderTxt.append(";"); |
+ uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
+ vshaderTxt.append(";"); |
+ vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
+ vshaderTxt.append(";"); |
- vshaderTxt.append( |
- "// Copy Program VS\n" |
- "void main() {" |
- " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;" |
- " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;" |
- " gl_Position.zw = vec2(0, 1);" |
- "}" |
- ); |
- |
- SkString fshaderTxt(version); |
- GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, |
- *this->glCaps().glslCaps(), |
- &fshaderTxt); |
- vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); |
- vTexCoord.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); |
- fshaderTxt.append(";"); |
- uTexture.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); |
- fshaderTxt.append(";"); |
- const char* fsOutName; |
- if (this->glCaps().glslCaps()->mustDeclareFragmentShaderOutput()) { |
- oFragColor.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); |
+ vshaderTxt.append( |
+ "// Copy Program VS\n" |
+ "void main() {" |
+ " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;" |
+ " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;" |
+ " gl_Position.zw = vec2(0, 1);" |
+ "}" |
+ ); |
+ |
+ SkString fshaderTxt(version); |
+ if (kSamplerTypes[i] == kSamplerExternal_GrSLType) { |
+ fshaderTxt.appendf("#extension %s : require\n", |
+ this->glCaps().glslCaps()->externalTextureExtensionString()); |
+ } |
+ GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, |
+ *this->glCaps().glslCaps(), |
+ &fshaderTxt); |
+ vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); |
+ vTexCoord.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); |
fshaderTxt.append(";"); |
- fsOutName = oFragColor.c_str(); |
- } else { |
- fsOutName = "gl_FragColor"; |
- } |
- fshaderTxt.appendf( |
- "// Copy Program FS\n" |
- "void main() {" |
- " %s = %s(u_texture, v_texCoord);" |
- "}", |
- fsOutName, |
- GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration()) |
- ); |
+ uTexture.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); |
+ fshaderTxt.append(";"); |
+ const char* fsOutName; |
+ if (this->glCaps().glslCaps()->mustDeclareFragmentShaderOutput()) { |
+ oFragColor.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); |
+ fshaderTxt.append(";"); |
+ fsOutName = oFragColor.c_str(); |
+ } else { |
+ fsOutName = "gl_FragColor"; |
+ } |
+ fshaderTxt.appendf( |
+ "// Copy Program FS\n" |
+ "void main() {" |
+ " %s = %s(u_texture, v_texCoord);" |
+ "}", |
+ fsOutName, |
+ GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration()) |
+ ); |
- GL_CALL_RET(fCopyProgram.fProgram, CreateProgram()); |
- const char* str; |
- GrGLint length; |
+ GL_CALL_RET(fCopyPrograms[i].fProgram, CreateProgram()); |
+ const char* str; |
+ GrGLint length; |
- str = vshaderTxt.c_str(); |
- length = SkToInt(vshaderTxt.size()); |
- GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyProgram.fProgram, |
- GR_GL_VERTEX_SHADER, &str, &length, 1, &fStats); |
+ str = vshaderTxt.c_str(); |
+ length = SkToInt(vshaderTxt.size()); |
+ GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[i].fProgram, |
+ GR_GL_VERTEX_SHADER, &str, &length, 1, |
+ &fStats); |
- str = fshaderTxt.c_str(); |
- length = SkToInt(fshaderTxt.size()); |
- GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyProgram.fProgram, |
- GR_GL_FRAGMENT_SHADER, &str, &length, 1, &fStats); |
+ str = fshaderTxt.c_str(); |
+ length = SkToInt(fshaderTxt.size()); |
+ GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[i].fProgram, |
+ GR_GL_FRAGMENT_SHADER, &str, &length, 1, |
+ &fStats); |
- GL_CALL(LinkProgram(fCopyProgram.fProgram)); |
+ GL_CALL(LinkProgram(fCopyPrograms[i].fProgram)); |
- GL_CALL_RET(fCopyProgram.fTextureUniform, GetUniformLocation(fCopyProgram.fProgram, |
- "u_texture")); |
- GL_CALL_RET(fCopyProgram.fPosXformUniform, GetUniformLocation(fCopyProgram.fProgram, |
- "u_posXform")); |
- GL_CALL_RET(fCopyProgram.fTexCoordXformUniform, GetUniformLocation(fCopyProgram.fProgram, |
- "u_texCoordXform")); |
+ GL_CALL_RET(fCopyPrograms[i].fTextureUniform, |
+ GetUniformLocation(fCopyPrograms[i].fProgram, "u_texture")); |
+ GL_CALL_RET(fCopyPrograms[i].fPosXformUniform, |
+ GetUniformLocation(fCopyPrograms[i].fProgram, "u_posXform")); |
+ GL_CALL_RET(fCopyPrograms[i].fTexCoordXformUniform, |
+ GetUniformLocation(fCopyPrograms[i].fProgram, "u_texCoordXform")); |
- GL_CALL(BindAttribLocation(fCopyProgram.fProgram, 0, "a_vertex")); |
+ GL_CALL(BindAttribLocation(fCopyPrograms[i].fProgram, 0, "a_vertex")); |
- GL_CALL(DeleteShader(vshader)); |
- GL_CALL(DeleteShader(fshader)); |
+ GL_CALL(DeleteShader(vshader)); |
+ GL_CALL(DeleteShader(fshader)); |
+ } |
- GL_CALL(GenBuffers(1, &fCopyProgram.fArrayBuffer)); |
- fHWGeometryState.setVertexBufferID(this, fCopyProgram.fArrayBuffer); |
+ GL_CALL(GenBuffers(1, &fCopyProgramArrayBuffer)); |
+ fHWGeometryState.setVertexBufferID(this, fCopyProgramArrayBuffer); |
static const GrGLfloat vdata[] = { |
0, 0, |
0, 1, |
@@ -3041,14 +3106,16 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst, |
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h); |
this->flushRenderTarget(dstRT, &dstRect); |
- GL_CALL(UseProgram(fCopyProgram.fProgram)); |
- fHWProgramID = fCopyProgram.fProgram; |
+ int progIdx = TextureTargetToCopyProgramIdx(srcTex->target()); |
+ |
+ GL_CALL(UseProgram(fCopyPrograms[progIdx].fProgram)); |
+ fHWProgramID = fCopyPrograms[progIdx].fProgram; |
fHWGeometryState.setVertexArrayID(this, 0); |
GrGLAttribArrayState* attribs = |
- fHWGeometryState.bindArrayAndBufferToDraw(this, fCopyProgram.fArrayBuffer); |
- attribs->set(this, 0, fCopyProgram.fArrayBuffer, 2, GR_GL_FLOAT, false, |
+ fHWGeometryState.bindArrayAndBufferToDraw(this, fCopyProgramArrayBuffer); |
+ attribs->set(this, 0, fCopyProgramArrayBuffer, 2, GR_GL_FLOAT, false, |
2 * sizeof(GrGLfloat), 0); |
attribs->disableUnusedArrays(this, 0x1); |
@@ -3076,9 +3143,10 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst, |
sy1 = 1.f - sy1; |
} |
- GL_CALL(Uniform4f(fCopyProgram.fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0)); |
- GL_CALL(Uniform4f(fCopyProgram.fTexCoordXformUniform, sx1 - sx0, sy1 - sy0, sx0, sy0)); |
- GL_CALL(Uniform1i(fCopyProgram.fTextureUniform, 0)); |
+ GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0)); |
+ GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform, |
+ sx1 - sx0, sy1 - sy0, sx0, sy0)); |
+ GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0)); |
GrXferProcessor::BlendInfo blendInfo; |
blendInfo.reset(); |