diff options
Diffstat (limited to 'src/gpu/gl/GrGLGpu.cpp')
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 272 |
1 files changed, 170 insertions, 102 deletions
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 2bd36b6404..51145c8988 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(); |