draw: substitute Src for Over when the source image is completely opaque.
The two Ops are equivalent, but Src is faster. Change-Id: I2c73a13755047c224c71fb5af786875f02681de9 Reviewed-on: https://go-review.googlesource.com/8640 Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
65a798f031
commit
67c770d218
54
draw/gen.go
54
draw/gen.go
|
@ -55,6 +55,7 @@ var (
|
|||
// should be the fallback pair ("Image", "image.Image").
|
||||
//
|
||||
// TODO: add *image.CMYK src type after Go 1.5 is released.
|
||||
// An *image.CMYK is also alwaysOpaque.
|
||||
dsTypes = []struct{ dType, sType string }{
|
||||
{"*image.RGBA", "*image.Gray"},
|
||||
{"*image.RGBA", "*image.NRGBA"},
|
||||
|
@ -72,6 +73,13 @@ var (
|
|||
"440",
|
||||
}
|
||||
ops = []string{"Over", "Src"}
|
||||
// alwaysOpaque are those image.Image implementations that are always
|
||||
// opaque. For these types, Over is equivalent to the faster Src, in the
|
||||
// absence of a source mask.
|
||||
alwaysOpaque = map[string]bool{
|
||||
"*image.Gray": true,
|
||||
"*image.YCbCr": true,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -104,6 +112,9 @@ func gen(w *bytes.Buffer, receiver string, codes ...string) {
|
|||
for _, code := range codes {
|
||||
for _, t := range dsTypes {
|
||||
for _, op := range ops {
|
||||
if op == "Over" && alwaysOpaque[t.sType] {
|
||||
continue
|
||||
}
|
||||
expn(w, code, &data{
|
||||
dType: t.dType,
|
||||
sType: t.sType,
|
||||
|
@ -132,6 +143,9 @@ func genKernel(w *bytes.Buffer) {
|
|||
}
|
||||
for _, t := range dsTypes {
|
||||
for _, op := range ops {
|
||||
if op == "Over" && alwaysOpaque[t.sType] {
|
||||
continue
|
||||
}
|
||||
expn(w, codeKernelTransformLeaf, &data{
|
||||
dType: t.dType,
|
||||
sType: t.sType,
|
||||
|
@ -585,7 +599,7 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
|||
|
||||
func expnSwitch(op, dType string, expandBoth bool, template string) string {
|
||||
if op == "" && dType != "anyDType" {
|
||||
lines := []string{"switch opts.op() {"}
|
||||
lines := []string{"switch op {"}
|
||||
for _, op = range ops {
|
||||
lines = append(lines,
|
||||
fmt.Sprintf("case %s:", op),
|
||||
|
@ -607,6 +621,14 @@ func expnSwitch(op, dType string, expandBoth bool, template string) string {
|
|||
fallback, values = "image.Image", sTypesForDType[dType]
|
||||
}
|
||||
for _, v := range values {
|
||||
if dType != "" {
|
||||
// v is the sType. Skip those always-opaque sTypes, where Over is
|
||||
// equivalent to Src.
|
||||
if op == "Over" && alwaysOpaque[v] {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if v == fallback {
|
||||
lines = append(lines, "default:")
|
||||
} else {
|
||||
|
@ -745,18 +767,22 @@ const (
|
|||
if adr.Empty() || sr.Empty() {
|
||||
return
|
||||
}
|
||||
op := opts.op()
|
||||
if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
|
||||
op = Src
|
||||
}
|
||||
// sr is the source pixels. If it extends beyond the src bounds,
|
||||
// we cannot use the type-specific fast paths, as they access
|
||||
// the Pix fields directly without bounds checking.
|
||||
if !sr.In(src.Bounds()) {
|
||||
switch opts.op() {
|
||||
switch op {
|
||||
case Over:
|
||||
z.scale_Image_Image_Over(dst, dr, adr, src, sr)
|
||||
case Src:
|
||||
z.scale_Image_Image_Src(dst, dr, adr, src, sr)
|
||||
}
|
||||
} else if _, ok := src.(*image.Uniform); ok {
|
||||
Draw(dst, dr, src, src.Bounds().Min, opts.op())
|
||||
Draw(dst, dr, src, src.Bounds().Min, op)
|
||||
} else {
|
||||
$switch z.scale_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, src, sr)
|
||||
}
|
||||
|
@ -769,6 +795,10 @@ const (
|
|||
if adr.Empty() || sr.Empty() {
|
||||
return
|
||||
}
|
||||
op := opts.op()
|
||||
if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
|
||||
op = Src
|
||||
}
|
||||
d2s := invert(s2d)
|
||||
// bias is a translation of the mapping from dst co-ordinates to
|
||||
// src co-ordinates such that the latter temporarily have
|
||||
|
@ -788,14 +818,14 @@ const (
|
|||
// we cannot use the type-specific fast paths, as they access
|
||||
// the Pix fields directly without bounds checking.
|
||||
if !sr.In(src.Bounds()) {
|
||||
switch opts.op() {
|
||||
switch op {
|
||||
case Over:
|
||||
z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
|
||||
case Src:
|
||||
z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias)
|
||||
}
|
||||
} else if u, ok := src.(*image.Uniform); ok {
|
||||
transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, opts.op())
|
||||
transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
|
||||
} else {
|
||||
$switch z.transform_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, &d2s, src, sr, bias)
|
||||
}
|
||||
|
@ -961,9 +991,13 @@ const (
|
|||
if adr.Empty() || sr.Empty() {
|
||||
return
|
||||
}
|
||||
op := opts.op()
|
||||
if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
|
||||
op = Src
|
||||
}
|
||||
|
||||
if _, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
|
||||
Draw(dst, dr, src, src.Bounds().Min, opts.op())
|
||||
Draw(dst, dr, src, src.Bounds().Min, op)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -998,6 +1032,10 @@ const (
|
|||
if adr.Empty() || sr.Empty() {
|
||||
return
|
||||
}
|
||||
op := opts.op()
|
||||
if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
|
||||
op = Src
|
||||
}
|
||||
d2s := invert(s2d)
|
||||
// bias is a translation of the mapping from dst co-ordinates to
|
||||
// src co-ordinates such that the latter temporarily have
|
||||
|
@ -1015,7 +1053,7 @@ const (
|
|||
adr = adr.Sub(dr.Min)
|
||||
|
||||
if u, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
|
||||
transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, opts.op())
|
||||
transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1032,7 +1070,7 @@ const (
|
|||
// we cannot use the type-specific fast paths, as they access
|
||||
// the Pix fields directly without bounds checking.
|
||||
if !sr.In(src.Bounds()) {
|
||||
switch opts.op() {
|
||||
switch op {
|
||||
case Over:
|
||||
q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
|
||||
case Src:
|
||||
|
|
2626
draw/impl.go
2626
draw/impl.go
File diff suppressed because it is too large
Load Diff
|
@ -431,3 +431,10 @@ func transform_Uniform(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src *i
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func opaque(m image.Image) bool {
|
||||
o, ok := m.(interface {
|
||||
Opaque() bool
|
||||
})
|
||||
return ok && o.Opaque()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user