func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender) { // TODO: adjust if dp is outside dst bounds, or sr is outside src bounds. gl.BindTexture(gl.TEXTURE_2D, t.id) m := src.RGBA().SubImage(sr).(*image.RGBA) b := m.Bounds() // TODO check m bounds smaller than t.size gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, b.Dx(), b.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, m.Pix) // TODO: send a screen.UploadedEvent. }
func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { t.w.glctxMu.Lock() defer t.w.glctxMu.Unlock() // TODO: adjust if dp is outside dst bounds, or r is outside src bounds. t.w.glctx.BindTexture(gl.TEXTURE_2D, t.id) m := src.RGBA().SubImage(sr).(*image.RGBA) b := m.Bounds() // TODO check m bounds smaller than t.size t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, b.Dx(), b.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, m.Pix) }
func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { originalSRMin := sr.Min sr = sr.Intersect(src.Bounds()) if sr.Empty() { return } dp = dp.Add(sr.Min.Sub(originalSRMin)) // TODO: keep a texture around for this purpose? t, err := w.s.NewTexture(sr.Size()) if err != nil { panic(err) } t.Upload(image.Point{}, src, sr) w.Draw(f64.Aff3{ 1, 0, float64(dp.X), 0, 1, float64(dp.Y), }, t, t.Bounds(), draw.Src, nil) t.Release() }
func main() { flag.Parse() rand.Seed(int64(time.Now().Nanosecond())) board := NewBoard(9, *scale) driver.Main(func(s screen.Screen) { w, err := s.NewWindow(nil) if err != nil { log.Fatal(err) } defer w.Release() var b screen.Buffer defer func() { if b != nil { b.Release() } }() for e := range w.Events() { switch e := e.(type) { case mouse.Event: if e.Direction == mouse.DirRelease && e.Button != 0 { board.click(b.RGBA(), int(e.X), int(e.Y), int(e.Button)) w.Send(paint.Event{}) } case key.Event: if e.Code == key.CodeEscape { return } case paint.Event: w.Upload(image.Point{}, b, b.Bounds()) w.Publish() case size.Event: // TODO: Set board size. if b != nil { b.Release() } b, err = s.NewBuffer(e.Size()) if err != nil { log.Fatal(err) } render(b.RGBA(), board) case error: log.Print(e) } } }) }
func main() { log.SetFlags(0) log.SetPrefix("preview: ") flag.Usage = func() { log.Print("Usage: preview [options] file") flag.PrintDefaults() } flag.Parse() if flag.NArg() != 1 { flag.Usage() os.Exit(1) } if *prof != "" { log.Print("profile mode: will write out CPU profile after 5 seconds") f, err := os.Create(*prof) if err != nil { log.Fatal(err) } err = pprof.StartCPUProfile(f) if err != nil { log.Fatal(err) } go func() { time.Sleep(5 * time.Second) pprof.StopCPUProfile() log.Print("done writing CPU profile") }() } f, err := os.Open(flag.Arg(0)) if err != nil { log.Fatal(err) } log.Print("parsing STL...") t := time.Now() stl, err := slice.Parse(f) if err != nil { log.Fatal(err) } f.Close() log.Printf("parsing took %v", time.Now().Sub(t)) if err := sliceSTL(stl); err != nil { log.Fatal(err) } imgs, err := drawLayers(stl) if err != nil { log.Fatal(err) } r := imgs[0].Bounds() log.Print("Launching UI...") driver.Main(func(s screen.Screen) { w, err := s.NewWindow(&screen.NewWindowOptions{ Width: r.Dx(), Height: r.Dy(), }) if err != nil { log.Fatal(err) } defer w.Release() r := image.Rect(int(stl.Min.X), int(stl.Min.Y), int(stl.Max.X)+1, int(stl.Max.Y)+1) winSize := r.Size() var b screen.Buffer defer func() { if b != nil { b.Release() } }() var sz size.Event var lastClick mouse.Event var layer int redraw := func() { draw.Draw(b.RGBA(), b.RGBA().Bounds(), imgs[layer], imgs[layer].Bounds().Min, draw.Src) drawLayerNumber(b.RGBA(), layer) w.Send(paint.Event{}) } for e := range w.Events() { switch e := e.(type) { default: case mouse.Event: if e.Button == mouse.ButtonLeft { if e.Y > lastClick.Y && layer < len(imgs)-1 { layer++ redraw() } else if e.Y < lastClick.Y && layer > 0 { layer-- redraw() } lastClick = e } case key.Event: log.Printf("key: %v", e) if e.Code == key.CodeEscape { log.Print("quitting") return } case paint.Event: w.Upload(image.Point{}, b, b.Bounds(), w) w.Publish() case screen.UploadedEvent: // No-op. case size.Event: sz = e if b != nil { b.Release() } winSize = image.Point{sz.WidthPx, sz.HeightPx} b, err = s.NewBuffer(winSize) if err != nil { log.Fatal(err) } redraw() case error: log.Printf("error: %v", e) } } }) }
func main() { flag.Parse() rand.Seed(int64(time.Now().Nanosecond())) board := NewBoard(9, *scale) driver.Main(func(s screen.Screen) { w, err := s.NewWindow(nil) if err != nil { log.Fatal(err) } defer w.Release() var b screen.Buffer defer func() { if b != nil { b.Release() } }() for e := range w.Events() { switch e := e.(type) { case mouse.Event: if e.Direction == mouse.DirRelease && e.Button != 0 { board.click(b.RGBA(), int(e.X), int(e.Y), int(e.Button)) dirty = true } case key.Event: if e.Code == key.CodeEscape { return } case paint.Event: // TODO: we shouldn't rely on the library sending us a constant // stream of paint events. If we're dirty, we should just draw // on the window and then call w.Publish. // // TODO: This check should save CPU time but causes flicker on Darwin. //if dirty && !uploading { w.Upload(image.Point{}, b, b.Bounds(), w) // TODO: On Darwin always writes to 0,0, ignoring first arg. dirty = false uploading = true //} w.Publish() case screen.UploadedEvent: // No-op. uploading = false case size.Event: // TODO: Set board size. if b != nil { b.Release() } b, err = s.NewBuffer(e.Size()) if err != nil { log.Fatal(err) } render(b.RGBA(), board) case error: log.Print(e) } } }) }