I'm really grateful for your answer.
To answer your questions:
I am taking matrix transformation into account, but to exclude the SkRegion I switched to a SkRect and just did clipRect instead which caused the same problem for me.
I haven't been able to produce an example app but will continue to try.
I am running an OpenGL backend.
I have however been able to find a way for the clipping to behave, iGrContext->asDirectContext()->resetContext(GrGLBackendState::kView_GrGLBackendState) seems to do the trick for me, if called before every time I fetch the surface.
Looking at the source code it looks like some glScissor states being reset when resetContext() is called, but I'm not that fluid in reading Skia source code so I'm not drawing any conclusions.
I'm quite sure we don't modify the glState at all, these are the only calls we do after GrContext is created.
glViewport() when size changes
makeCurrentContext & clearCurrentContext before we start drawing and after flush
flushBuffer after flushAndSubmit() on SkSurface.
The app does not do anything fancy, works something like this:
surfaceOne = MakeFromBackendRenderTarget()
surfaceTwo = MakeRenderTarget().
We clip surfaceTwo.clipRect(dirtyRect)
....
Walks through the view hierarchy and draws all views intersecting dirtyRect (canvas gets clipped to view bounds before drawing)
....
Then surfaceTwo.draw(surfaceOne.getCanvas(), 0, 0);
surfaceOne.flushAndSubmit();
I do monitor save count so it isn't any mismatches of save()/restore().