zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

screen.go (3478B)


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