CPU generator

This commit is contained in:
Dmitry Sergeev
2026-09-17 23:27:38 +03:00
parent fa787b5ef1
commit b85293b5d2
2 changed files with 184 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
package generator
import (
"encoding/binary"
"fmt"
)
type YCbCr10 struct {
Y uint32
Cb uint32
Cr uint32
}
type PixelSampler func(x, y, width, height, frameIndex int) YCbCr10
type CPUGenerator struct {
width int
height int
sampler PixelSampler
}
func NewCPUGenerator(
width, height uint,
sampler PixelSampler,
) (*CPUGenerator, error) {
if width == 0 || height == 0 {
return nil, fmt.Errorf(
"width and height must be greater than 0, got: %dx%d",
width,
height,
)
}
if width%6 != 0 {
return nil, fmt.Errorf(
"width must be divisible by 6, got: %d",
width,
)
}
if sampler == nil {
return nil, fmt.Errorf("pixel sampler is nil")
}
return &CPUGenerator{
width: int(width),
height: int(height),
sampler: sampler,
}, nil
}
func (g *CPUGenerator) GenerateFrame(dest []byte, frameIndex int) error {
frameSize := (g.width / 6) * g.height * 16
if len(dest) < frameSize {
return fmt.Errorf(
"cpu: destination is too small: got %d bytes, need %d",
len(dest),
frameSize,
)
}
const componentMask uint32 = 0x3ff
offset := 0
for y := 0; y < g.height; y++ {
for x := 0; x < g.width; x += 6 {
var pixels [6]YCbCr10
for i := range pixels {
pixels[i] = g.sampler(x+i, y, g.width, g.height, frameIndex)
}
word0 := pixels[0].Cb&componentMask |
(pixels[0].Y&componentMask)<<10 |
(pixels[0].Cr&componentMask)<<20
word1 := pixels[1].Y&componentMask |
(pixels[2].Cb&componentMask)<<10 |
(pixels[2].Y&componentMask)<<20
word2 := pixels[2].Cr&componentMask |
(pixels[3].Y&componentMask)<<10 |
(pixels[4].Cb&componentMask)<<20
word3 := pixels[4].Y&componentMask |
(pixels[4].Cr&componentMask)<<10 |
(pixels[5].Y&componentMask)<<20
binary.LittleEndian.PutUint32(dest[offset:], word0)
binary.LittleEndian.PutUint32(dest[offset+4:], word1)
binary.LittleEndian.PutUint32(dest[offset+8:], word2)
binary.LittleEndian.PutUint32(dest[offset+12:], word3)
offset += 16
}
}
return nil
}
func (g *CPUGenerator) Close() error { return nil }