github.com/racerxdl/gonx@v0.0.0-20210103083128-c5afc43bcbd2/services/display/frame.go (about) 1 package display 2 3 import ( 4 "github.com/racerxdl/gonx/font" 5 "github.com/racerxdl/gonx/nx/nxtypes" 6 "github.com/racerxdl/gonx/svc" 7 "image" 8 "image/color" 9 "time" 10 "unsafe" 11 ) 12 13 const minScreenFps = 30 // 30 fps 14 const vsyncTimeout = time.Second / minScreenFps 15 16 type Frame struct { 17 surface *Surface 18 buff []byte // Local Image Buffer 19 surfaceBuff []byte // GPU Remote Buffer 20 bounds image.Rectangle 21 } 22 23 func (f *Frame) Convert(c color.Color) color.Color { 24 return c 25 } 26 27 // ColorModel returns the Image's color model. 28 func (f *Frame) ColorModel() color.Model { 29 return f 30 } 31 32 // Bounds returns the domain for which At can return non-zero color. 33 // The bounds do not necessarily contain the point (0, 0). 34 func (f *Frame) Bounds() image.Rectangle { 35 return f.bounds 36 } 37 38 // At returns the color of the pixel at (x, y). 39 // At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid. 40 // At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one. 41 func (f *Frame) At(x, y int) color.Color { 42 w := f.bounds.Size().X 43 off := (y*w + x) * 4 44 _ = f.buff[off+3] 45 return color.RGBA{ 46 R: f.buff[off+0], 47 G: f.buff[off+1], 48 B: f.buff[off+2], 49 A: f.buff[off+3], 50 } 51 } 52 53 func (f *Frame) Size() (x, y int16) { 54 return int16(f.Bounds().Size().X), int16(f.Bounds().Size().Y) 55 } 56 57 func (f *Frame) SetPixel(x, y int16, c color.RGBA) { 58 w := f.bounds.Size().X 59 off := (int(y)*w + int(x)) * 4 60 _ = f.buff[off+3] 61 f.buff[off+0] = c.R 62 f.buff[off+1] = c.G 63 f.buff[off+2] = c.B 64 f.buff[off+3] = c.A 65 } 66 67 //go:nobounds 68 func (f *Frame) Clear(c color.RGBA) { 69 u32color := (uint32(c.A) << 24) + (uint32(c.B) << 16) + (uint32(c.G) << 8) + uint32(c.R) 70 u32len := len(f.buff) / 4 71 72 for i := 0; i < u32len; i++ { 73 *(*uint32)(unsafe.Pointer(&f.buff[i*4])) = u32color 74 } 75 } 76 77 func (f *Frame) DrawStringAt(x, y int, data string, c color.RGBA, font *font.Data) { 78 cx := x 79 cy := y 80 for _, v := range data { 81 if v == '\n' { 82 cy += font.CharHeight 83 cx = x 84 continue 85 } 86 if v == '\r' { 87 continue 88 } 89 g := font.GetGlyph(uint32(v)) 90 g.DrawAt(cx, cy, c, f.buff, f.bounds.Size().X) 91 cx += font.CharWidth 92 } 93 } 94 95 func (f *Frame) Display() error { 96 s := f.bounds.Size() 97 GFXSlowSwizzlingBlit(f.surfaceBuff, f.buff, s.X, s.Y, 0, 0) 98 err := f.surface.QueueBuffer() 99 if err != nil { 100 return err 101 } 102 103 return f.surface.refreshFrame(f) 104 } 105 106 func (f *Frame) WaitVSync() error { 107 vsync, err := GetVSyncEvent() 108 if err != nil { 109 return err 110 } 111 112 return svc.WaitSynchronizationSingle(nxtypes.Handle(vsync), vsyncTimeout) 113 } 114 115 func (f *Frame) Destroy() error { 116 if f.surface.State == SURFACE_STATE_DEQUEUED { 117 return f.surface.QueueBuffer() 118 } 119 return nil 120 }