internal/ui: use BlendSourceOver at Fill when possible

Closes #2817
This commit is contained in:
Hajime Hoshi 2023-10-21 01:24:46 +09:00
parent 39688dd27d
commit c2ad36bdce

View File

@ -45,6 +45,9 @@ type Image struct {
dotsBuffer map[image.Point][4]byte dotsBuffer map[image.Point][4]byte
// lastBlend is the lastly-used blend for mipmap.Image.
lastBlend graphicsdriver.Blend
// bigOffscreenBuffer is a double-sized offscreen for anti-alias rendering. // bigOffscreenBuffer is a double-sized offscreen for anti-alias rendering.
bigOffscreenBuffer *bigOffscreenImage bigOffscreenBuffer *bigOffscreenImage
@ -62,6 +65,7 @@ func (u *UserInterface) NewImage(width, height int, imageType atlas.ImageType) *
width: width, width: width,
height: height, height: height,
imageType: imageType, imageType: imageType,
lastBlend: graphicsdriver.BlendSourceOver,
} }
} }
@ -84,6 +88,8 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
i.modifyCallback() i.modifyCallback()
} }
i.lastBlend = blend
if antialias { if antialias {
// Flush the other buffer to make the buffers exclusive. // Flush the other buffer to make the buffers exclusive.
i.flushDotsBufferIfNeeded() i.flushDotsBufferIfNeeded()
@ -249,7 +255,9 @@ func (i *Image) flushDotsBufferIfNeeded() {
srcs := [graphics.ShaderImageCount]*mipmap.Mipmap{i.ui.whiteImage.mipmap} srcs := [graphics.ShaderImageCount]*mipmap.Mipmap{i.ui.whiteImage.mipmap}
dr := image.Rect(0, 0, i.width, i.height) dr := image.Rect(0, 0, i.width, i.height)
i.mipmap.DrawTriangles(srcs, vs, is, graphicsdriver.BlendCopy, dr, [graphics.ShaderImageCount]image.Rectangle{}, NearestFilterShader.shader, nil, false, true) blend := graphicsdriver.BlendCopy
i.lastBlend = blend
i.mipmap.DrawTriangles(srcs, vs, is, blend, dr, [graphics.ShaderImageCount]image.Rectangle{}, NearestFilterShader.shader, nil, false, true)
} }
func (i *Image) flushBigOffscreenBufferIfNeeded() { func (i *Image) flushBigOffscreenBufferIfNeeded() {
@ -280,7 +288,13 @@ func (i *Image) Fill(r, g, b, a float32, region image.Rectangle) {
srcs := [graphics.ShaderImageCount]*Image{i.ui.whiteImage} srcs := [graphics.ShaderImageCount]*Image{i.ui.whiteImage}
i.DrawTriangles(srcs, i.tmpVerticesForFill, is, graphicsdriver.BlendCopy, region, [graphics.ShaderImageCount]image.Rectangle{}, NearestFilterShader, nil, false, true, false) blend := graphicsdriver.BlendCopy
// If possible, use BlendSourceOver to encourage batching (#2817).
if a == 1 && i.lastBlend == graphicsdriver.BlendSourceOver {
blend = graphicsdriver.BlendSourceOver
}
// i.lastBlend is updated in DrawTriangles.
i.DrawTriangles(srcs, i.tmpVerticesForFill, is, blend, region, [graphics.ShaderImageCount]image.Rectangle{}, NearestFilterShader, nil, false, true, false)
} }
type bigOffscreenImage struct { type bigOffscreenImage struct {