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// +build windows 6 7package windriver 8 9import ( 10 "image" 11 "image/draw" 12 "sync" 13 "syscall" 14 15 "golang.org/x/exp/shiny/driver/internal/swizzle" 16) 17 18type bufferImpl struct { 19 hbitmap syscall.Handle 20 buf []byte 21 rgba image.RGBA 22 size image.Point 23 24 mu sync.Mutex 25 nUpload uint32 26 released bool 27 cleanedUp bool 28} 29 30func (b *bufferImpl) Size() image.Point { return b.size } 31func (b *bufferImpl) Bounds() image.Rectangle { return image.Rectangle{Max: b.size} } 32func (b *bufferImpl) RGBA() *image.RGBA { return &b.rgba } 33 34func (b *bufferImpl) preUpload() { 35 // Check that the program hasn't tried to modify the rgba field via the 36 // pointer returned by the bufferImpl.RGBA method. This check doesn't catch 37 // 100% of all cases; it simply tries to detect some invalid uses of a 38 // screen.Buffer such as: 39 // *buffer.RGBA() = anotherImageRGBA 40 if len(b.buf) != 0 && len(b.rgba.Pix) != 0 && &b.buf[0] != &b.rgba.Pix[0] { 41 panic("windriver: invalid Buffer.RGBA modification") 42 } 43 44 b.mu.Lock() 45 defer b.mu.Unlock() 46 47 if b.released { 48 panic("windriver: Buffer.Upload called after Buffer.Release") 49 } 50 if b.nUpload == 0 { 51 swizzle.BGRA(b.buf) 52 } 53 b.nUpload++ 54} 55 56func (b *bufferImpl) postUpload() { 57 b.mu.Lock() 58 defer b.mu.Unlock() 59 60 b.nUpload-- 61 if b.nUpload != 0 { 62 return 63 } 64 65 if b.released { 66 go b.cleanUp() 67 } else { 68 swizzle.BGRA(b.buf) 69 } 70} 71 72func (b *bufferImpl) Release() { 73 b.mu.Lock() 74 defer b.mu.Unlock() 75 76 if !b.released && b.nUpload == 0 { 77 go b.cleanUp() 78 } 79 b.released = true 80} 81 82func (b *bufferImpl) cleanUp() { 83 b.mu.Lock() 84 if b.cleanedUp { 85 b.mu.Unlock() 86 panic("windriver: Buffer clean-up occurred twice") 87 } 88 b.cleanedUp = true 89 b.mu.Unlock() 90 91 b.rgba.Pix = nil 92 _DeleteObject(b.hbitmap) 93} 94 95func (b *bufferImpl) blitToDC(dc syscall.Handle, dp image.Point, sr image.Rectangle) error { 96 b.preUpload() 97 defer b.postUpload() 98 99 dr := sr.Add(dp.Sub(sr.Min)) 100 return copyBitmapToDC(dc, dr, b.hbitmap, sr, draw.Src) 101} 102