github.com/as/shiny@v0.8.2/driver/x11driver/buffer.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package x11driver
     6  
     7  import (
     8  	"image"
     9  	"image/color"
    10  	"image/draw"
    11  	"log"
    12  	"unsafe"
    13  
    14  	"github.com/BurntSushi/xgb"
    15  	"github.com/BurntSushi/xgb/render"
    16  	"github.com/BurntSushi/xgb/shm"
    17  	"github.com/BurntSushi/xgb/xproto"
    18  	//	"github.com/as/shiny/driver/internal/swizzle"
    19  )
    20  
    21  type bufferImpl struct {
    22  	s *screenImpl
    23  
    24  	addr unsafe.Pointer
    25  	buf  []byte
    26  	rgba image.RGBA
    27  	size image.Point
    28  	xs   shm.Seg
    29  
    30  	nUpload  uint32
    31  	released bool
    32  }
    33  
    34  func (b *bufferImpl) degenerate() bool        { return b.size.X == 0 || b.size.Y == 0 }
    35  func (b *bufferImpl) Size() image.Point       { return b.size }
    36  func (b *bufferImpl) Bounds() image.Rectangle { return image.Rectangle{Max: b.size} }
    37  func (b *bufferImpl) RGBA() *image.RGBA       { return &b.rgba }
    38  
    39  func (b *bufferImpl) Release() {
    40  	if !b.released && b.nUpload == 0 {
    41  		go b.cleanUp()
    42  	}
    43  	b.released = true
    44  }
    45  
    46  func (b *bufferImpl) cleanUp() {
    47  	b.s.mu.Lock()
    48  	delete(b.s.buffers, b.xs)
    49  	b.s.mu.Unlock()
    50  
    51  	if b.degenerate() {
    52  		return
    53  	}
    54  	shm.Detach(b.s.xc, b.xs)
    55  	if err := shmClose(b.addr); err != nil {
    56  		log.Printf("x11driver: shmClose: %v", err)
    57  	}
    58  }
    59  
    60  func (b *bufferImpl) upload(xd xproto.Drawable, xg xproto.Gcontext, depth uint8, dp image.Point, sr image.Rectangle) {
    61  	originalSRMin := sr.Min
    62  	sr = sr.Intersect(b.Bounds())
    63  	if sr.Empty() {
    64  		return
    65  	}
    66  	dp = dp.Add(sr.Min.Sub(originalSRMin))
    67  	shm.PutImage(
    68  		b.s.xc, xd, xg,
    69  		uint16(b.size.X), uint16(b.size.Y), // TotalWidth, TotalHeight,
    70  		uint16(sr.Min.X), uint16(sr.Min.Y), // SrcX, SrcY,
    71  		uint16(sr.Dx()), uint16(sr.Dy()), // SrcWidth, SrcHeight,
    72  		int16(dp.X), int16(dp.Y), // DstX, DstY,
    73  		depth, xproto.ImageFormatZPixmap,
    74  		1, b.xs, 0, // 1 means send a completion event, 0 means a zero offset.
    75  	)
    76  }
    77  
    78  func fill(xc *xgb.Conn, xp render.Picture, dr image.Rectangle, src color.Color, op draw.Op) {
    79  	r, g, b, a := src.RGBA()
    80  	c := render.Color{
    81  		Red:   uint16(r),
    82  		Green: uint16(g),
    83  		Blue:  uint16(b),
    84  		Alpha: uint16(a),
    85  	}
    86  	x, y := dr.Min.X, dr.Min.Y
    87  	if x < -0x8000 || 0x7fff < x || y < -0x8000 || 0x7fff < y {
    88  		return
    89  	}
    90  	dx, dy := dr.Dx(), dr.Dy()
    91  	if dx < 0 || 0xffff < dx || dy < 0 || 0xffff < dy {
    92  		return
    93  	}
    94  	render.FillRectangles(xc, renderOp(op), xp, c, []xproto.Rectangle{{
    95  		X:      int16(x),
    96  		Y:      int16(y),
    97  		Width:  uint16(dx),
    98  		Height: uint16(dy),
    99  	}})
   100  }