github.com/as/shiny@v0.8.2/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  // +build darwin
     6  
     7  package gldriver
     8  
     9  import (
    10  	"fmt"
    11  	"image"
    12  	"sync"
    13  
    14  	"github.com/as/shiny/gl"
    15  	"github.com/as/shiny/screen"
    16  )
    17  
    18  var theScreen = &screenImpl{}
    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  	window *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  	w := s.window
    59  	if w == nil {
    60  		return nil, fmt.Errorf("gldriver: no window available")
    61  	}
    62  
    63  	w.glctxMu.Lock()
    64  	defer w.glctxMu.Unlock()
    65  	glctx := w.glctx
    66  	if glctx == nil {
    67  		return nil, fmt.Errorf("gldriver: no GL context available")
    68  	}
    69  
    70  	if !glctx.IsProgram(s.texture.program) {
    71  		p, err := compileProgram(glctx, textureVertexSrc, textureFragmentSrc)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		s.texture.program = p
    76  		s.texture.pos = glctx.GetAttribLocation(p, "pos")
    77  		s.texture.mvp = glctx.GetUniformLocation(p, "mvp")
    78  		s.texture.uvp = glctx.GetUniformLocation(p, "uvp")
    79  		s.texture.inUV = glctx.GetAttribLocation(p, "inUV")
    80  		s.texture.sample = glctx.GetUniformLocation(p, "sample")
    81  		s.texture.quad = glctx.CreateBuffer()
    82  
    83  		glctx.BindBuffer(gl.ARRAY_BUFFER, s.texture.quad)
    84  		glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW)
    85  	}
    86  
    87  	t := &textureImpl{
    88  		w:    w,
    89  		id:   glctx.CreateTexture(),
    90  		size: size,
    91  	}
    92  
    93  	glctx.BindTexture(gl.TEXTURE_2D, t.id)
    94  	glctx.TexImage2D(gl.TEXTURE_2D, 0, size.X, size.Y, gl.RGBA, gl.UNSIGNED_BYTE, nil)
    95  	glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
    96  	glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
    97  	glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
    98  	glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
    99  
   100  	return t, nil
   101  }
   102  
   103  func optsSize(opts *screen.NewWindowOptions) (width, height int) {
   104  	width, height = 1024, 768
   105  	if opts != nil {
   106  		if opts.Width > 0 {
   107  			width = opts.Width
   108  		}
   109  		if opts.Height > 0 {
   110  			height = opts.Height
   111  		}
   112  	}
   113  	return width, height
   114  }
   115  
   116  func (s *screenImpl) NewWindow(opts *screen.NewWindowOptions) (screen.Window, error) {
   117  	id, err := newWindow(opts)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	w := &windowImpl{
   122  		s:           s,
   123  		id:          id,
   124  		publish:     make(chan struct{}),
   125  		publishDone: make(chan screen.PublishResult),
   126  		drawDone:    make(chan struct{}),
   127  	}
   128  	initWindow(w)
   129  
   130  	if s.window != nil {
   131  		panic("newwindow")
   132  	}
   133  	s.window = w
   134  	showWindow(w)
   135  	return w, nil
   136  }