diff options
Diffstat (limited to 'vendor/golang.org/x/exp/shiny/driver/x11driver')
10 files changed, 157 insertions, 11 deletions
diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/buffer.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/buffer.go index c479639..a905928 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/buffer.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/buffer.go @@ -16,10 +16,13 @@ import ( "github.com/BurntSushi/xgb/render" "github.com/BurntSushi/xgb/shm" "github.com/BurntSushi/xgb/xproto" - "golang.org/x/exp/shiny/driver/internal/swizzle" ) +type bufferUploader interface { + upload(xd xproto.Drawable, xg xproto.Gcontext, depth uint8, dp image.Point, sr image.Rectangle) +} + type bufferImpl struct { s *screenImpl diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/buffer_fallback.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/buffer_fallback.go new file mode 100644 index 0000000..bfdd9c7 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/buffer_fallback.go @@ -0,0 +1,123 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x11driver + +import ( + "image" + "sync" + + "github.com/BurntSushi/xgb" + "github.com/BurntSushi/xgb/xproto" + "golang.org/x/exp/shiny/driver/internal/swizzle" +) + +const ( + xPutImageReqSizeMax = (1 << 16) * 4 + xPutImageReqSizeFixed = 28 + xPutImageReqDataSize = xPutImageReqSizeMax - xPutImageReqSizeFixed +) + +type bufferFallbackImpl struct { + xc *xgb.Conn + + buf []byte + rgba image.RGBA + size image.Point + + mu sync.Mutex + nUpload uint32 + released bool +} + +func (b *bufferFallbackImpl) Size() image.Point { return b.size } +func (b *bufferFallbackImpl) Bounds() image.Rectangle { return image.Rectangle{Max: b.size} } +func (b *bufferFallbackImpl) RGBA() *image.RGBA { return &b.rgba } + +func (b *bufferFallbackImpl) preUpload() { + // Check that the program hasn't tried to modify the rgba field via the + // pointer returned by the bufferFallbackImpl.RGBA method. This check doesn't catch + // 100% of all cases; it simply tries to detect some invalid uses of a + // screen.Buffer such as: + // *buffer.RGBA() = anotherImageRGBA + if len(b.buf) != 0 && len(b.rgba.Pix) != 0 && &b.buf[0] != &b.rgba.Pix[0] { + panic("x11driver: invalid Buffer.RGBA modification") + } + + b.mu.Lock() + defer b.mu.Unlock() + + if b.released { + panic("x11driver: Buffer.Upload called after Buffer.Release") + } + if b.nUpload == 0 { + swizzle.BGRA(b.buf) + } + b.nUpload++ +} + +func (b *bufferFallbackImpl) postUpload() { + b.mu.Lock() + defer b.mu.Unlock() + + b.nUpload-- + if b.nUpload != 0 { + return + } + + if !b.released { + swizzle.BGRA(b.buf) + } +} + +func (b *bufferFallbackImpl) Release() { + b.mu.Lock() + defer b.mu.Unlock() + + b.released = true +} + +func (b *bufferFallbackImpl) upload(xd xproto.Drawable, xg xproto.Gcontext, depth uint8, dp image.Point, sr image.Rectangle) { + originalSRMin := sr.Min + sr = sr.Intersect(b.Bounds()) + if sr.Empty() { + return + } + dp = dp.Add(sr.Min.Sub(originalSRMin)) + b.preUpload() + + b.putImage(xd, xg, depth, dp, sr) + + b.postUpload() +} + +// putImage issues xproto.PutImage requests in batches. +func (b *bufferFallbackImpl) putImage(xd xproto.Drawable, xg xproto.Gcontext, depth uint8, dp image.Point, sr image.Rectangle) { + widthPerReq := b.size.X + rowPerReq := xPutImageReqDataSize / (widthPerReq * 4) + dataPerReq := rowPerReq * widthPerReq * 4 + dstX := dp.X + dstY := dp.Y + start := 0 + end := 0 + + for end < len(b.buf) { + end = start + dataPerReq + if end > len(b.buf) { + end = len(b.buf) + } + + data := b.buf[start:end] + heightPerReq := len(data) / (widthPerReq * 4) + + xproto.PutImage( + b.xc, xproto.ImageFormatZPixmap, xd, xg, + uint16(widthPerReq), uint16(heightPerReq), + int16(dstX), int16(dstY), + 0, depth, data) + + start = end + dstY += rowPerReq + } +} diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/screen.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/screen.go index 7e0d3bb..0d0374b 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/screen.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/screen.go @@ -51,6 +51,7 @@ type screenImpl struct { // opaqueP is a fully opaque, solid fill picture. opaqueP render.Picture + useShm bool uniformMu sync.Mutex uniformC render.Color @@ -64,13 +65,14 @@ type screenImpl struct { completionKeys []uint16 } -func newScreenImpl(xc *xgb.Conn) (*screenImpl, error) { +func newScreenImpl(xc *xgb.Conn, useShm bool) (*screenImpl, error) { s := &screenImpl{ xc: xc, xsi: xproto.Setup(xc).DefaultScreen(xc), buffers: map[shm.Seg]*bufferImpl{}, uploads: map[uint16]chan struct{}{}, windows: map[xproto.Window]*windowImpl{}, + useShm: useShm, } if err := s.initAtoms(); err != nil { return nil, err @@ -282,14 +284,28 @@ const ( ) func (s *screenImpl) NewBuffer(size image.Point) (retBuf screen.Buffer, retErr error) { - // TODO: detect if the X11 server or connection cannot support SHM pixmaps, - // and fall back to regular pixmaps. w, h := int64(size.X), int64(size.Y) if w < 0 || maxShmSide < w || h < 0 || maxShmSide < h || maxShmSize < 4*w*h { return nil, fmt.Errorf("x11driver: invalid buffer size %v", size) } + // If the X11 server or connection cannot support SHM pixmaps, + // fall back to regular pixmaps. + if !s.useShm { + b := &bufferFallbackImpl{ + xc: s.xc, + size: size, + rgba: image.RGBA{ + Stride: 4 * size.X, + Rect: image.Rectangle{Max: size}, + Pix: make([]uint8, 4*size.X*size.Y), + }, + } + b.buf = b.rgba.Pix + return b, nil + } + b := &bufferImpl{ s: s, rgba: image.RGBA{ diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_linux_ipc.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_linux_ipc.go index 025f3ff..23fe9a4 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_linux_ipc.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_linux_ipc.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (386 || ppc64 || ppc64le || s390x) // +build linux // +build 386 ppc64 ppc64le s390x diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_openbsd_syscall.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_openbsd_syscall.go index 573c78b..d42cb4c 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_openbsd_syscall.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_openbsd_syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build openbsd && (i386 || amd64) // +build openbsd // +build i386 amd64 diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_other.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_other.go index d09994f..fa071c3 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_other.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_other.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !linux -// +build !dragonfly -// +build !openbsd +//go:build !linux && !dragonfly && !openbsd +// +build !linux,!dragonfly,!openbsd package x11driver diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_shmopen_syscall.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_shmopen_syscall.go index 23f9026..45d7373 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_shmopen_syscall.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/shm_shmopen_syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (linux || dragonfly) && (amd64 || arm || arm64 || mips64 || mips64le) // +build linux dragonfly // +build amd64 arm arm64 mips64 mips64le diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/texture.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/texture.go index da6fc86..8ca4759 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/texture.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/texture.go @@ -59,7 +59,7 @@ func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectang if t.degenerate() { return } - src.(*bufferImpl).upload(xproto.Drawable(t.xm), t.s.gcontext32, textureDepth, dp, sr) + src.(bufferUploader).upload(xproto.Drawable(t.xm), t.s.gcontext32, textureDepth, dp, sr) } func (t *textureImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) { diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/window.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/window.go index 5ebdbcd..f77b876 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/window.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/window.go @@ -67,7 +67,7 @@ func (w *windowImpl) Release() { } func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { - src.(*bufferImpl).upload(xproto.Drawable(w.xw), w.xg, w.s.xsi.RootDepth, dp, sr) + src.(bufferUploader).upload(xproto.Drawable(w.xw), w.xg, w.s.xsi.RootDepth, dp, sr) } func (w *windowImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) { diff --git a/vendor/golang.org/x/exp/shiny/driver/x11driver/x11driver.go b/vendor/golang.org/x/exp/shiny/driver/x11driver/x11driver.go index 29d2b0d..1ba227e 100644 --- a/vendor/golang.org/x/exp/shiny/driver/x11driver/x11driver.go +++ b/vendor/golang.org/x/exp/shiny/driver/x11driver/x11driver.go @@ -47,11 +47,13 @@ func main(f func(screen.Screen)) (retErr error) { if err := render.Init(xc); err != nil { return fmt.Errorf("x11driver: render.Init failed: %v", err) } + + useShm := true if err := shm.Init(xc); err != nil { - return fmt.Errorf("x11driver: shm.Init failed: %v", err) + useShm = false } - s, err := newScreenImpl(xc) + s, err := newScreenImpl(xc, useShm) if err != nil { return err } |