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:
Nigel Tao 2016-05-22 09:13:42 +10:00
Родитель c2f815647a
Коммит 7576772392
2 изменённых файлов: 46 добавлений и 54 удалений

Просмотреть файл

@ -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[:])
}