draw: distinguish YCbCr fast paths by their chroma subsample ratios.

These code paths aren't actually fast yet. That will be a follow-up
change.

Change-Id: I814992573cc6af422e49d0ddf336003e662897a5
Reviewed-on: https://go-review.googlesource.com/7791
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Nigel Tao 2015-03-19 11:04:55 +11:00
parent 5afc4bbba5
commit ad68cd9759
2 changed files with 1080 additions and 25 deletions

View File

@ -64,8 +64,14 @@ var (
{"*image.RGBA", "image.Image"}, {"*image.RGBA", "image.Image"},
{"Image", "image.Image"}, {"Image", "image.Image"},
} }
dTypes, sTypes []string dTypes, sTypes []string
sTypesForDType = map[string][]string{} sTypesForDType = map[string][]string{}
subsampleRatios = []string{
"444",
"422",
"420",
"440",
}
) )
func init() { func init() {
@ -88,6 +94,7 @@ func init() {
type data struct { type data struct {
dType string dType string
sType string sType string
sratio string
receiver string receiver string
} }
@ -125,6 +132,15 @@ func genKernel(w *bytes.Buffer) {
} }
func expn(w *bytes.Buffer, code string, d *data) { func expn(w *bytes.Buffer, code string, d *data) {
if d.sType == "*image.YCbCr" && d.sratio == "" {
for _, sratio := range subsampleRatios {
e := *d
e.sratio = sratio
expn(w, code, &e)
}
return
}
for _, line := range strings.Split(code, "\n") { for _, line := range strings.Split(code, "\n") {
line = expnLine(line, d) line = expnLine(line, d)
if line == ";" { if line == ";" {
@ -169,6 +185,8 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
return prefix + d.dType + suffix return prefix + d.dType + suffix
case "dTypeRN": case "dTypeRN":
return prefix + relName(d.dType) + suffix return prefix + relName(d.dType) + suffix
case "sratio":
return prefix + d.sratio + suffix
case "sType": case "sType":
return prefix + d.sType + suffix return prefix + d.sType + suffix
case "sTypeRN": case "sTypeRN":
@ -482,7 +500,11 @@ func expnSwitch(dType string, expandBoth bool, template string) string {
} }
if dType != "" { if dType != "" {
lines = append(lines, expnLine(template, &data{dType: dType, sType: v})) if v == "*image.YCbCr" {
lines = append(lines, expnSwitchYCbCr(dType, template))
} else {
lines = append(lines, expnLine(template, &data{dType: dType, sType: v}))
}
} else if !expandBoth { } else if !expandBoth {
lines = append(lines, expnLine(template, &data{dType: v})) lines = append(lines, expnLine(template, &data{dType: v}))
} else { } else {
@ -494,6 +516,22 @@ func expnSwitch(dType string, expandBoth bool, template string) string {
return strings.Join(lines, "\n") return strings.Join(lines, "\n")
} }
func expnSwitchYCbCr(dType, template string) string {
lines := []string{
"switch src.SubsampleRatio {",
"default:",
expnLine(template, &data{dType: dType, sType: "image.Image"}),
}
for _, sratio := range subsampleRatios {
lines = append(lines,
fmt.Sprintf("case image.YCbCrSubsampleRatio%s:", sratio),
expnLine(template, &data{dType: dType, sType: "*image.YCbCr", sratio: sratio}),
)
}
lines = append(lines, "}")
return strings.Join(lines, "\n")
}
func split(s, sep string) (string, string) { func split(s, sep string) (string, string) {
if i := strings.Index(s, sep); i >= 0 { if i := strings.Index(s, sep); i >= 0 {
return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):]) return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
@ -551,7 +589,7 @@ const (
if !sr.In(src.Bounds()) { if !sr.In(src.Bounds()) {
z.scale_Image_Image(dst, dr, adr, src, sr) z.scale_Image_Image(dst, dr, adr, src, sr)
} else { } else {
$switch z.scale_$dTypeRN_$sTypeRN(dst, dr, adr, src, sr) $switch z.scale_$dTypeRN_$sTypeRN$sratio(dst, dr, adr, src, sr)
} }
} }
@ -569,13 +607,13 @@ const (
if !sr.In(src.Bounds()) { if !sr.In(src.Bounds()) {
z.transform_Image_Image(dst, dr, adr, &d2s, src, sr) z.transform_Image_Image(dst, dr, adr, &d2s, src, sr)
} else { } else {
$switch z.transform_$dTypeRN_$sTypeRN(dst, dr, adr, &d2s, src, sr) $switch z.transform_$dTypeRN_$sTypeRN$sratio(dst, dr, adr, &d2s, src, sr)
} }
} }
` `
codeNNScaleLeaf = ` codeNNScaleLeaf = `
func (nnInterpolator) scale_$dTypeRN_$sTypeRN(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle) { func (nnInterpolator) scale_$dTypeRN_$sTypeRN$sratio(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle) {
dw2 := uint64(dr.Dx()) * 2 dw2 := uint64(dr.Dx()) * 2
dh2 := uint64(dr.Dy()) * 2 dh2 := uint64(dr.Dy()) * 2
sw := uint64(sr.Dx()) sw := uint64(sr.Dx())
@ -594,7 +632,7 @@ const (
` `
codeNNTransformLeaf = ` codeNNTransformLeaf = `
func (nnInterpolator) transform_$dTypeRN_$sTypeRN(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle) { func (nnInterpolator) transform_$dTypeRN_$sTypeRN$sratio(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle) {
$preOuter $preOuter
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y + int(dy)) + 0.5 dyf := float64(dr.Min.Y + int(dy)) + 0.5
@ -615,7 +653,7 @@ const (
` `
codeABLScaleLeaf = ` codeABLScaleLeaf = `
func (ablInterpolator) scale_$dTypeRN_$sTypeRN(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle) { func (ablInterpolator) scale_$dTypeRN_$sTypeRN$sratio(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle) {
sw := int32(sr.Dx()) sw := int32(sr.Dx())
sh := int32(sr.Dy()) sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy()) yscale := float64(sh) / float64(dr.Dy())
@ -669,7 +707,7 @@ const (
` `
codeABLTransformLeaf = ` codeABLTransformLeaf = `
func (ablInterpolator) transform_$dTypeRN_$sTypeRN(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle) { func (ablInterpolator) transform_$dTypeRN_$sTypeRN$sratio(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle) {
$preOuter $preOuter
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y + int(dy)) + 0.5 dyf := float64(dr.Min.Y + int(dy)) + 0.5
@ -747,7 +785,7 @@ const (
if !sr.In(src.Bounds()) { if !sr.In(src.Bounds()) {
z.scaleX_Image(tmp, src, sr) z.scaleX_Image(tmp, src, sr)
} else { } else {
$switchS z.scaleX_$sTypeRN(tmp, src, sr) $switchS z.scaleX_$sTypeRN$sratio(tmp, src, sr)
} }
$switchD z.scaleY_$dTypeRN(dst, dr, adr, tmp) $switchD z.scaleY_$dTypeRN(dst, dr, adr, tmp)
@ -777,13 +815,13 @@ const (
if !sr.In(src.Bounds()) { if !sr.In(src.Bounds()) {
q.transform_Image_Image(dst, dr, adr, &d2s, src, sr, xscale, yscale) q.transform_Image_Image(dst, dr, adr, &d2s, src, sr, xscale, yscale)
} else { } else {
$switch q.transform_$dTypeRN_$sTypeRN(dst, dr, adr, &d2s, src, sr, xscale, yscale) $switch q.transform_$dTypeRN_$sTypeRN$sratio(dst, dr, adr, &d2s, src, sr, xscale, yscale)
} }
} }
` `
codeKernelScaleLeafX = ` codeKernelScaleLeafX = `
func (z *kernelScaler) scaleX_$sTypeRN(tmp [][4]float64, src $sType, sr image.Rectangle) { func (z *kernelScaler) scaleX_$sTypeRN$sratio(tmp [][4]float64, src $sType, sr image.Rectangle) {
t := 0 t := 0
for y := int32(0); y < z.sh; y++ { for y := int32(0); y < z.sh; y++ {
for _, s := range z.horizontal.sources { for _, s := range z.horizontal.sources {
@ -826,7 +864,7 @@ const (
` `
codeKernelTransformLeaf = ` codeKernelTransformLeaf = `
func (q *Kernel) transform_$dTypeRN_$sTypeRN(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, xscale, yscale float64) { func (q *Kernel) transform_$dTypeRN_$sTypeRN$sratio(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, xscale, yscale float64) {
// When shrinking, broaden the effective kernel support so that we still // When shrinking, broaden the effective kernel support so that we still
// visit every source pixel. // visit every source pixel.
xHalfWidth, xKernelArgScale := q.Support, 1.0 xHalfWidth, xKernelArgScale := q.Support, 1.0

File diff suppressed because it is too large Load Diff