Chromium Code Reviews| Index: src/gpu/gl/GrGLGpu.cpp |
| diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
| index 2bd36b640477eaf1b14a60003436553b9a344b0f..8b61deb218312aea564c60caa563ae44aadbdb00 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 (idDesc.fInfo.fTarget == GR_GL_TEXTURE_EXTERNAL) { |
| + 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,9 +2776,8 @@ 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, |
| +static inline bool can_blit_framebuffer(const GrSurface* dst, |
| const GrSurface* src, |
|
joshualitt
2015/11/20 21:58:39
\t
bsalomon
2015/11/20 22:43:55
Done.
|
| const GrGLGpu* gpu) { |
| if (gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) && |
| @@ -2766,13 +2789,21 @@ 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, |
| +static inline bool can_copy_texsubimage(const GrSurface* dst, |
| const GrSurface* src, |
|
joshualitt
2015/11/20 21:58:39
\t
bsalomon
2015/11/20 22:43:55
Done.
|
| const GrGLGpu* gpu) { |
| // Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage |
| @@ -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 and RT in a |
|
egdaniel
2015/11/20 21:57:43
and -> a
bsalomon
2015/11/20 22:43:55
Done.
|
| + // 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,107 @@ bool GrGLGpu::onCopySurface(GrSurface* dst, |
| } |
| -void GrGLGpu::createCopyProgram() { |
| +void GrGLGpu::createCopyPrograms() { |
| 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) { |
|
bsalomon
2015/11/20 19:04:25
the code inside the loop is exactly the old code,
joshualitt
2015/11/20 21:58:39
create_copy_program helper? feel free to ignore
bsalomon
2015/11/20 22:43:55
ok
|
| + 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 +3104,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 +3141,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(); |