shiny/driver/x11driver: make the mask per-texture instead of per-screen.
Change-Id: I13face3a82cd825663d84423e8beda2801cc700a Reviewed-on: https://go-review.googlesource.com/23330 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Родитель
c2f815647a
Коммит
7576772392
|
@ -44,16 +44,6 @@ type screenImpl struct {
|
|||
gcontext32 xproto.Gcontext
|
||||
window32 xproto.Window
|
||||
|
||||
// opaque is a cached, fully opaque mask picture.
|
||||
//
|
||||
// Note that there is a lock ordering here. The textureImpl.draw method can
|
||||
// hold textureImpl.renderMu when acquiring screenImpl.opaqueMu.
|
||||
//
|
||||
// TODO: should this be per-texture instead of per-screen?
|
||||
opaqueMu sync.Mutex
|
||||
opaqueM xproto.Pixmap
|
||||
opaqueP render.Picture
|
||||
|
||||
mu sync.Mutex
|
||||
buffers map[shm.Seg]*bufferImpl
|
||||
uploads map[uint16]chan struct{}
|
||||
|
@ -323,15 +313,25 @@ func (s *screenImpl) NewTexture(size image.Point) (screen.Texture, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("x11driver: xproto.NewPictureId failed: %v", err)
|
||||
}
|
||||
opaqueM, err := xproto.NewPixmapId(s.xc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("x11driver: xproto.NewPixmapId failed: %v", err)
|
||||
}
|
||||
opaqueP, err := render.NewPictureId(s.xc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("x11driver: xproto.NewPictureId failed: %v", err)
|
||||
}
|
||||
xproto.CreatePixmap(s.xc, textureDepth, xm, xproto.Drawable(s.window32), uint16(w), uint16(h))
|
||||
render.CreatePicture(s.xc, xp, xproto.Drawable(xm), s.pictformat32, 0, nil)
|
||||
render.SetPictureFilter(s.xc, xp, uint16(len("bilinear")), "bilinear", nil)
|
||||
|
||||
return &textureImpl{
|
||||
s: s,
|
||||
size: size,
|
||||
xm: xm,
|
||||
xp: xp,
|
||||
s: s,
|
||||
size: size,
|
||||
xm: xm,
|
||||
xp: xp,
|
||||
opaqueM: opaqueM,
|
||||
opaqueP: opaqueP,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -523,38 +523,6 @@ func (s *screenImpl) initWindow32() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *screenImpl) useOpaque(f func(render.Picture)) {
|
||||
s.opaqueMu.Lock()
|
||||
defer s.opaqueMu.Unlock()
|
||||
|
||||
if s.opaqueM == 0 || s.opaqueP == 0 {
|
||||
var err error
|
||||
s.opaqueM, err = xproto.NewPixmapId(s.xc)
|
||||
if err != nil {
|
||||
log.Printf("x11driver: xproto.NewPixmapId failed: %v", err)
|
||||
return
|
||||
}
|
||||
s.opaqueP, err = render.NewPictureId(s.xc)
|
||||
if err != nil {
|
||||
log.Printf("x11driver: xproto.NewPictureId failed: %v", err)
|
||||
return
|
||||
}
|
||||
xproto.CreatePixmap(s.xc, textureDepth, s.opaqueM, xproto.Drawable(s.window32), 1, 1)
|
||||
render.CreatePicture(s.xc, s.opaqueP, xproto.Drawable(s.opaqueM), s.pictformat32, 0, nil)
|
||||
render.FillRectangles(s.xc, render.PictOpSrc, s.opaqueP, render.Color{
|
||||
Red: 0xffff,
|
||||
Green: 0xffff,
|
||||
Blue: 0xffff,
|
||||
Alpha: 0xffff,
|
||||
}, []xproto.Rectangle{{
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}})
|
||||
}
|
||||
|
||||
f(s.opaqueP)
|
||||
}
|
||||
|
||||
func findVisual(xsi *xproto.ScreenInfo, depth byte) (xproto.Visualid, error) {
|
||||
for _, d := range xsi.AllowedDepths {
|
||||
if d.Depth != depth {
|
||||
|
|
|
@ -32,7 +32,13 @@ type textureImpl struct {
|
|||
// multiple X11/Render calls. X11/Render is a stateful API, so interleaving
|
||||
// X11/Render calls from separate higher-level operations causes
|
||||
// inconsistencies.
|
||||
renderMu sync.Mutex
|
||||
//
|
||||
// It also protects the opaqueXxx fields, which hold a lazily created,
|
||||
// fully opaque mask picture.
|
||||
renderMu sync.Mutex
|
||||
opaqueM xproto.Pixmap
|
||||
opaqueP render.Picture
|
||||
opaqueCreated bool
|
||||
|
||||
releasedMu sync.Mutex
|
||||
released bool
|
||||
|
@ -51,6 +57,10 @@ func (t *textureImpl) Release() {
|
|||
if released || t.degenerate() {
|
||||
return
|
||||
}
|
||||
if t.opaqueCreated {
|
||||
render.FreePicture(t.s.xc, t.opaqueP)
|
||||
xproto.FreePixmap(t.s.xc, t.opaqueM)
|
||||
}
|
||||
render.FreePicture(t.s.xc, t.xp)
|
||||
xproto.FreePixmap(t.s.xc, t.xm)
|
||||
}
|
||||
|
@ -161,6 +171,22 @@ func (t *textureImpl) draw(xp render.Picture, src2dst *f64.Aff3, sr image.Rectan
|
|||
}}
|
||||
|
||||
if op == draw.Src {
|
||||
// Lazily create the opaque mask picture.
|
||||
if !t.opaqueCreated {
|
||||
t.opaqueCreated = true
|
||||
xproto.CreatePixmap(t.s.xc, textureDepth, t.opaqueM, xproto.Drawable(t.s.window32), 1, 1)
|
||||
render.CreatePicture(t.s.xc, t.opaqueP, xproto.Drawable(t.opaqueM), t.s.pictformat32, 0, nil)
|
||||
render.FillRectangles(t.s.xc, render.PictOpSrc, t.opaqueP, render.Color{
|
||||
Red: 0xffff,
|
||||
Green: 0xffff,
|
||||
Blue: 0xffff,
|
||||
Alpha: 0xffff,
|
||||
}, []xproto.Rectangle{{
|
||||
Width: 1,
|
||||
Height: 1,
|
||||
}})
|
||||
}
|
||||
|
||||
// render.TriFan visits every dst-space pixel in the axis-aligned
|
||||
// bounding box (AABB) containing the transformation of the sr
|
||||
// rectangle in src-space to a quad in dst-space.
|
||||
|
@ -189,14 +215,12 @@ func (t *textureImpl) draw(xp render.Picture, src2dst *f64.Aff3, sr image.Rectan
|
|||
// TODO: is the picture transform right when sr.Min isn't (0, 0)?
|
||||
invW := 1 / float64(sr.Dx())
|
||||
invH := 1 / float64(sr.Dy())
|
||||
t.s.useOpaque(func(opaqueP render.Picture) {
|
||||
render.SetPictureTransform(t.s.xc, opaqueP, render.Transform{
|
||||
f64ToFixed(invW * dst2src[0]), f64ToFixed(invW * dst2src[1]), 0,
|
||||
f64ToFixed(invH * dst2src[3]), f64ToFixed(invH * dst2src[4]), 0,
|
||||
0, 0, 1 << 16,
|
||||
})
|
||||
render.TriFan(t.s.xc, render.PictOpOutReverse, opaqueP, xp, 0, 0, 0, points[:])
|
||||
render.SetPictureTransform(t.s.xc, t.opaqueP, render.Transform{
|
||||
f64ToFixed(invW * dst2src[0]), f64ToFixed(invW * dst2src[1]), 0,
|
||||
f64ToFixed(invH * dst2src[3]), f64ToFixed(invH * dst2src[4]), 0,
|
||||
0, 0, 1 << 16,
|
||||
})
|
||||
render.TriFan(t.s.xc, render.PictOpOutReverse, t.opaqueP, xp, 0, 0, 0, points[:])
|
||||
}
|
||||
render.TriFan(t.s.xc, render.PictOpOver, t.xp, xp, 0, 0, 0, points[:])
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче