| Index: src/gpu/gl/GrGLGpu.cpp | 
| diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp | 
| index 8bd06638521db4b9c204381d8276d277cb64a588..fc9675fdda30478cf3d2a03048658a73932f34fc 100644 | 
| --- a/src/gpu/gl/GrGLGpu.cpp | 
| +++ b/src/gpu/gl/GrGLGpu.cpp | 
| @@ -1492,11 +1492,11 @@ bool GrGLGpu::flushGLState(const DrawArgs& args) { | 
| GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget()); | 
| this->flushStencil(pipeline.getStencil()); | 
| this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin()); | 
| -    this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled()); | 
| +    this->flushHWAAState(glRT, pipeline.isHWAntialiasState()); | 
|  | 
| // This must come after textures are flushed because a texture may need | 
| // to be msaa-resolved (which will modify bound FBO state). | 
| -    this->flushRenderTarget(glRT, nullptr); | 
| +    this->flushRenderTarget(glRT, nullptr, pipeline.hasCoCenteredSamples()); | 
|  | 
| return true; | 
| } | 
| @@ -2026,33 +2026,10 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, | 
| return true; | 
| } | 
|  | 
| -void GrGLGpu::setColocatedSampleLocations(GrRenderTarget* rt, bool useColocatedSampleLocations) { | 
| -    GrGLRenderTarget* target = static_cast<GrGLRenderTarget*>(rt->asRenderTarget()); | 
| -    SkASSERT(0 != target->renderFBOID()); | 
| - | 
| -    if (!rt->isStencilBufferMultisampled() || | 
| -        useColocatedSampleLocations == target->usesColocatedSampleLocations()) { | 
| -        return; | 
| -    } | 
| - | 
| -    if (kGL_GrGLStandard == this->glStandard() && this->glVersion() >= GR_GL_VER(4,5)) { | 
| -        GL_CALL(NamedFramebufferParameteri(target->renderFBOID(), | 
| -                                           GR_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS, | 
| -                                           useColocatedSampleLocations)); | 
| -    } else { | 
| -        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, target->renderFBOID())); | 
| -        GL_CALL(FramebufferParameteri(GR_GL_FRAMEBUFFER, | 
| -                                      GR_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS, | 
| -                                      useColocatedSampleLocations)); | 
| -        fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; | 
| -    } | 
| - | 
| -    target->flagAsUsingColocatedSampleLocations(useColocatedSampleLocations); | 
| -} | 
| - | 
| -void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) { | 
| - | 
| +void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound, | 
| +                                bool coCenterSamples) { | 
| SkASSERT(target); | 
| +    SkASSERT(!coCenterSamples || this->caps()->programmableSampleLocationsSupport()); | 
|  | 
| uint32_t rtID = target->getUniqueID(); | 
| if (fHWBoundRenderTargetUniqueID != rtID) { | 
| @@ -2096,6 +2073,19 @@ void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) | 
| if (texture) { | 
| texture->texturePriv().dirtyMipMaps(true); | 
| } | 
| + | 
| +    if (this->caps()->programmableSampleLocationsSupport()) { | 
| +        ResetTimestamp timestamp; | 
| +        bool hasCoCenteredSamples = target->getCachedCoCenteredSamplesState(×tamp); | 
| +        if (timestamp < this->getResetTimestamp() || hasCoCenteredSamples != coCenterSamples) { | 
| +            // The default state for programmable sample locations is already at pixel center, so we | 
| +            // don't assign them. This assumes the client does not modify them outside of Skia. | 
| +            GL_CALL(FramebufferParameteri(GR_GL_FRAMEBUFFER, | 
| +                                          GR_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS, | 
| +                                          coCenterSamples)); | 
| +            target->setCachedCoCenteredSamplesState(coCenterSamples, this->getResetTimestamp()); | 
| +        } | 
| +    } | 
| } | 
|  | 
| GrGLenum gPrimitiveType2GLMode[] = { | 
| @@ -2297,20 +2287,10 @@ void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) { | 
| } | 
| } | 
|  | 
| -void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled) { | 
| +void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA) { | 
| SkASSERT(!useHWAA || rt->isStencilBufferMultisampled()); | 
|  | 
| -    if (rt->hasMixedSamples() && stencilEnabled && | 
| -        this->glCaps().glslCaps()->programmableSampleLocationsSupport()) { | 
| -        if (useHWAA) { | 
| -            this->setColocatedSampleLocations(rt, false); | 
| -        } else { | 
| -            this->setColocatedSampleLocations(rt, true); | 
| -        } | 
| -        useHWAA = true; | 
| -    } | 
| - | 
| -    if (this->glCaps().multisampleDisableSupport()) { | 
| +    if (this->caps()->multisampleDisableSupport()) { | 
| if (useHWAA) { | 
| if (kYes_TriState != fMSAAEnabled) { | 
| GL_CALL(Enable(GR_GL_MULTISAMPLE)); | 
| @@ -3111,7 +3091,7 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst, | 
| this->flushBlend(blendInfo); | 
| this->flushColorWrite(true); | 
| this->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace); | 
| -    this->flushHWAAState(dstRT, false, false); | 
| +    this->flushHWAAState(dstRT, false); | 
| this->disableScissor(); | 
| GrStencilSettings stencil; | 
| stencil.setDisabled(); | 
|  |