github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/shiny/driver/gldriver/screen.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 gldriver 6 7 import ( 8 "fmt" 9 "image" 10 "sync" 11 12 "golang.org/x/exp/shiny/driver/internal/pump" 13 "golang.org/x/exp/shiny/screen" 14 "golang.org/x/mobile/gl" 15 ) 16 17 var theScreen = &screenImpl{ 18 windows: make(map[uintptr]*windowImpl), 19 } 20 21 type screenImpl struct { 22 texture struct { 23 program gl.Program 24 pos gl.Attrib 25 mvp gl.Uniform 26 uvp gl.Uniform 27 inUV gl.Attrib 28 sample gl.Uniform 29 quad gl.Buffer 30 } 31 fill struct { 32 program gl.Program 33 pos gl.Attrib 34 mvp gl.Uniform 35 color gl.Uniform 36 quad gl.Buffer 37 } 38 39 mu sync.Mutex 40 windows map[uintptr]*windowImpl 41 } 42 43 func (s *screenImpl) NewBuffer(size image.Point) (retBuf screen.Buffer, retErr error) { 44 return &bufferImpl{ 45 rgba: image.NewRGBA(image.Rectangle{Max: size}), 46 size: size, 47 }, nil 48 } 49 50 func (s *screenImpl) NewTexture(size image.Point) (screen.Texture, error) { 51 // TODO: can we compile these programs eagerly instead of lazily? 52 53 // Find a GL context for this texture. 54 // TODO: this might be correct. Some GL objects can be shared 55 // across contexts. But this needs a review of the spec to make 56 // sure it's correct, and some testing would be nice. 57 var w *windowImpl 58 59 s.mu.Lock() 60 for _, window := range s.windows { 61 w = window 62 break 63 } 64 s.mu.Unlock() 65 66 if w == nil { 67 return nil, fmt.Errorf("gldriver: no window available") 68 } 69 70 w.glctxMu.Lock() 71 defer w.glctxMu.Unlock() 72 glctx := w.glctx 73 if glctx == nil { 74 return nil, fmt.Errorf("gldriver: no GL context available") 75 } 76 77 if !glctx.IsProgram(s.texture.program) { 78 p, err := compileProgram(glctx, textureVertexSrc, textureFragmentSrc) 79 if err != nil { 80 return nil, err 81 } 82 s.texture.program = p 83 s.texture.pos = glctx.GetAttribLocation(p, "pos") 84 s.texture.mvp = glctx.GetUniformLocation(p, "mvp") 85 s.texture.uvp = glctx.GetUniformLocation(p, "uvp") 86 s.texture.inUV = glctx.GetAttribLocation(p, "inUV") 87 s.texture.sample = glctx.GetUniformLocation(p, "sample") 88 s.texture.quad = glctx.CreateBuffer() 89 90 glctx.BindBuffer(gl.ARRAY_BUFFER, s.texture.quad) 91 glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW) 92 } 93 94 t := &textureImpl{ 95 w: w, 96 id: glctx.CreateTexture(), 97 size: size, 98 } 99 100 glctx.BindTexture(gl.TEXTURE_2D, t.id) 101 glctx.TexImage2D(gl.TEXTURE_2D, 0, size.X, size.Y, gl.RGBA, gl.UNSIGNED_BYTE, nil) 102 glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) 103 glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) 104 glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) 105 glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) 106 107 return t, nil 108 } 109 110 func (s *screenImpl) NewWindow(opts *screen.NewWindowOptions) (screen.Window, error) { 111 width, height := 1024, 768 112 if opts != nil { 113 if opts.Width > 0 { 114 width = opts.Width 115 } 116 if opts.Height > 0 { 117 height = opts.Height 118 } 119 } 120 121 id := newWindow(int32(width), int32(height)) 122 w := &windowImpl{ 123 s: s, 124 id: id, 125 pump: pump.Make(), 126 publish: make(chan struct{}), 127 publishDone: make(chan screen.PublishResult), 128 drawDone: make(chan struct{}), 129 } 130 131 s.mu.Lock() 132 s.windows[id] = w 133 s.mu.Unlock() 134 135 showWindow(w) 136 137 return w, nil 138 }