mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
ui/app/internal/gpu: introduce caps and context
Enables graceful fallback to OpenGL ES 2 and WebGL. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
package gpu
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"gioui.org/ui/app/internal/gl"
|
||||
)
|
||||
|
||||
type context struct {
|
||||
caps caps
|
||||
*gl.Functions
|
||||
}
|
||||
|
||||
type caps struct {
|
||||
EXT_disjoint_timer_query bool
|
||||
srgbMode srgbMode
|
||||
}
|
||||
|
||||
type srgbMode uint8
|
||||
|
||||
const (
|
||||
srgbES3 srgbMode = iota
|
||||
srgbEXT
|
||||
)
|
||||
|
||||
func newContext(glctx gl.Context) (*context, error) {
|
||||
ctx := &context{
|
||||
Functions: glctx.Functions(),
|
||||
}
|
||||
exts := ctx.GetString(gl.EXTENSIONS)
|
||||
glVer := ctx.GetString(gl.VERSION)
|
||||
ver, err := gl.ParseGLVersion(glVer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.caps = caps{
|
||||
EXT_disjoint_timer_query: strings.Contains(exts, "GL_EXT_disjoint_timer_query"),
|
||||
srgbMode: srgbModeFor(ver, exts),
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func srgbModeFor(ver [2]int, exts string) srgbMode {
|
||||
switch {
|
||||
case ver[0] >= 3:
|
||||
return srgbES3
|
||||
case strings.Contains(exts, "EXT_sRGB"):
|
||||
return srgbEXT
|
||||
default:
|
||||
panic("neither OpenGL ES 3 nor EXT_sRGB is supported")
|
||||
}
|
||||
}
|
||||
+44
-68
@@ -47,8 +47,7 @@ type frameResult struct {
|
||||
}
|
||||
|
||||
type renderer struct {
|
||||
ctx *gl.Functions
|
||||
srgbMode srgbMode
|
||||
ctx *context
|
||||
blitter *blitter
|
||||
pather *pather
|
||||
packer packer
|
||||
@@ -115,7 +114,7 @@ type resourceCache struct {
|
||||
}
|
||||
|
||||
type resource interface {
|
||||
release(ctx *gl.Functions)
|
||||
release(ctx *context)
|
||||
}
|
||||
|
||||
type texture struct {
|
||||
@@ -125,7 +124,7 @@ type texture struct {
|
||||
}
|
||||
|
||||
type blitter struct {
|
||||
ctx *gl.Functions
|
||||
ctx *context
|
||||
viewport image.Point
|
||||
prog [2]gl.Program
|
||||
vars [2]struct {
|
||||
@@ -138,12 +137,6 @@ type blitter struct {
|
||||
}
|
||||
|
||||
type materialType uint8
|
||||
type srgbMode uint8
|
||||
|
||||
const (
|
||||
srgbES3 srgbMode = iota
|
||||
srgbEXT
|
||||
)
|
||||
|
||||
const (
|
||||
clipTypeNone clipType = iota
|
||||
@@ -172,14 +165,13 @@ func NewGPU(ctx gl.Context) (*GPU, error) {
|
||||
stopped: make(chan struct{}),
|
||||
cache: newResourceCache(),
|
||||
}
|
||||
// Pretend the last error was nil.
|
||||
if err := g.renderLoop(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *GPU) renderLoop(ctx gl.Context) error {
|
||||
func (g *GPU) renderLoop(glctx gl.Context) error {
|
||||
// GL Operations must happen on a single OS thread, so
|
||||
// pass initialization result through a channel.
|
||||
initErr := make(chan error)
|
||||
@@ -187,35 +179,31 @@ func (g *GPU) renderLoop(ctx gl.Context) error {
|
||||
runtime.LockOSThread()
|
||||
// Don't UnlockOSThread to avoid reuse by the Go runtime.
|
||||
defer close(g.stopped)
|
||||
defer ctx.Release()
|
||||
defer glctx.Release()
|
||||
|
||||
if err := ctx.MakeCurrent(); err != nil {
|
||||
if err := glctx.MakeCurrent(); err != nil {
|
||||
initErr <- err
|
||||
return
|
||||
}
|
||||
funcs := ctx.Functions()
|
||||
defer g.cache.release(funcs)
|
||||
exts := funcs.GetString(gl.EXTENSIONS)
|
||||
glVer := funcs.GetString(gl.VERSION)
|
||||
ver, err := gl.ParseGLVersion(glVer)
|
||||
ctx, err := newContext(glctx)
|
||||
if err != nil {
|
||||
initErr <- err
|
||||
return
|
||||
}
|
||||
r := newRenderer(funcs, srgbModeFor(ver, exts))
|
||||
defer g.cache.release(ctx)
|
||||
r := newRenderer(ctx)
|
||||
defer r.release()
|
||||
var timers *timers
|
||||
var zopsTimer, stencilTimer, coverTimer, cleanupTimer *timer
|
||||
hasTimers := strings.Contains(exts, "GL_EXT_disjoint_timer_query")
|
||||
initErr <- nil
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-g.refresh:
|
||||
g.refreshErr <- ctx.MakeCurrent()
|
||||
g.refreshErr <- glctx.MakeCurrent()
|
||||
case frame := <-g.frames:
|
||||
if frame.collectStats && timers == nil && hasTimers {
|
||||
timers = newTimers(funcs, exts)
|
||||
if frame.collectStats && timers == nil && ctx.caps.EXT_disjoint_timer_query {
|
||||
timers = newTimers(ctx)
|
||||
zopsTimer = timers.newTimer()
|
||||
stencilTimer = timers.newTimer()
|
||||
coverTimer = timers.newTimer()
|
||||
@@ -231,29 +219,29 @@ func (g *GPU) renderLoop(ctx gl.Context) error {
|
||||
if frame.collectStats {
|
||||
zopsTimer.begin()
|
||||
}
|
||||
funcs.DepthFunc(gl.GREATER)
|
||||
funcs.ClearColor(ops.clearColor[0], ops.clearColor[1], ops.clearColor[2], 1.0)
|
||||
funcs.ClearDepthf(0.0)
|
||||
funcs.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
funcs.Viewport(0, 0, frame.viewport.X, frame.viewport.Y)
|
||||
ctx.DepthFunc(gl.GREATER)
|
||||
ctx.ClearColor(ops.clearColor[0], ops.clearColor[1], ops.clearColor[2], 1.0)
|
||||
ctx.ClearDepthf(0.0)
|
||||
ctx.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
ctx.Viewport(0, 0, frame.viewport.X, frame.viewport.Y)
|
||||
r.drawZOps(ops.zimageOps)
|
||||
zopsTimer.end()
|
||||
stencilTimer.begin()
|
||||
funcs.Enable(gl.BLEND)
|
||||
ctx.Enable(gl.BLEND)
|
||||
r.packStencils(&ops.pathOps)
|
||||
r.stencilClips(g.cache, ops.pathOps)
|
||||
r.packIntersections(ops.imageOps)
|
||||
r.intersect(ops.imageOps)
|
||||
stencilTimer.end()
|
||||
coverTimer.begin()
|
||||
funcs.Viewport(0, 0, frame.viewport.X, frame.viewport.Y)
|
||||
ctx.Viewport(0, 0, frame.viewport.X, frame.viewport.Y)
|
||||
r.drawOps(ops.imageOps)
|
||||
funcs.Disable(gl.BLEND)
|
||||
ctx.Disable(gl.BLEND)
|
||||
r.pather.stenciler.invalidateFBO()
|
||||
coverTimer.end()
|
||||
err := ctx.Present()
|
||||
err := glctx.Present()
|
||||
cleanupTimer.begin()
|
||||
g.cache.frame(funcs)
|
||||
g.cache.frame(ctx)
|
||||
cleanupTimer.end()
|
||||
var res frameResult
|
||||
if frame.collectStats && timers.ready() {
|
||||
@@ -335,18 +323,17 @@ func (r *renderer) texHandle(t *texture) gl.Texture {
|
||||
return t.id
|
||||
}
|
||||
|
||||
func (t *texture) release(ctx *gl.Functions) {
|
||||
func (t *texture) release(ctx *context) {
|
||||
if t.id != (gl.Texture{}) {
|
||||
ctx.DeleteTexture(t.id)
|
||||
}
|
||||
}
|
||||
|
||||
func newRenderer(ctx *gl.Functions, mode srgbMode) *renderer {
|
||||
func newRenderer(ctx *context) *renderer {
|
||||
r := &renderer{
|
||||
ctx: ctx,
|
||||
srgbMode: mode,
|
||||
blitter: newBlitter(ctx),
|
||||
pather: newPather(ctx),
|
||||
ctx: ctx,
|
||||
blitter: newBlitter(ctx),
|
||||
pather: newPather(ctx),
|
||||
}
|
||||
r.packer.maxDim = ctx.GetInteger(gl.MAX_TEXTURE_SIZE)
|
||||
r.intersections.maxDim = r.packer.maxDim
|
||||
@@ -381,7 +368,7 @@ func (r *resourceCache) put(key interface{}, val resource) {
|
||||
r.newRes[key] = val
|
||||
}
|
||||
|
||||
func (r *resourceCache) frame(ctx *gl.Functions) {
|
||||
func (r *resourceCache) frame(ctx *context) {
|
||||
for k, v := range r.res {
|
||||
if _, exists := r.newRes[k]; !exists {
|
||||
delete(r.res, k)
|
||||
@@ -394,7 +381,7 @@ func (r *resourceCache) frame(ctx *gl.Functions) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resourceCache) release(ctx *gl.Functions) {
|
||||
func (r *resourceCache) release(ctx *context) {
|
||||
for _, v := range r.newRes {
|
||||
v.release(ctx)
|
||||
}
|
||||
@@ -402,7 +389,7 @@ func (r *resourceCache) release(ctx *gl.Functions) {
|
||||
r.res = nil
|
||||
}
|
||||
|
||||
func newBlitter(ctx *gl.Functions) *blitter {
|
||||
func newBlitter(ctx *context) *blitter {
|
||||
prog, err := createColorPrograms(ctx, blitVSrc, blitFSrc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -426,16 +413,16 @@ func newBlitter(ctx *gl.Functions) *blitter {
|
||||
ctx.UseProgram(prog)
|
||||
switch materialType(i) {
|
||||
case materialTexture:
|
||||
uTex := gl.GetUniformLocation(ctx, prog, "tex")
|
||||
uTex := gl.GetUniformLocation(ctx.Functions, prog, "tex")
|
||||
ctx.Uniform1i(uTex, 0)
|
||||
b.vars[i].uUVScale = gl.GetUniformLocation(ctx, prog, "uvScale")
|
||||
b.vars[i].uUVOffset = gl.GetUniformLocation(ctx, prog, "uvOffset")
|
||||
b.vars[i].uUVScale = gl.GetUniformLocation(ctx.Functions, prog, "uvScale")
|
||||
b.vars[i].uUVOffset = gl.GetUniformLocation(ctx.Functions, prog, "uvOffset")
|
||||
case materialColor:
|
||||
b.vars[i].uColor = gl.GetUniformLocation(ctx, prog, "color")
|
||||
b.vars[i].uColor = gl.GetUniformLocation(ctx.Functions, prog, "color")
|
||||
}
|
||||
b.vars[i].z = gl.GetUniformLocation(ctx, prog, "z")
|
||||
b.vars[i].uScale = gl.GetUniformLocation(ctx, prog, "scale")
|
||||
b.vars[i].uOffset = gl.GetUniformLocation(ctx, prog, "offset")
|
||||
b.vars[i].z = gl.GetUniformLocation(ctx.Functions, prog, "z")
|
||||
b.vars[i].uScale = gl.GetUniformLocation(ctx.Functions, prog, "scale")
|
||||
b.vars[i].uOffset = gl.GetUniformLocation(ctx.Functions, prog, "offset")
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -447,7 +434,7 @@ func (b *blitter) release() {
|
||||
}
|
||||
}
|
||||
|
||||
func createColorPrograms(ctx *gl.Functions, vsSrc, fsSrc string) ([2]gl.Program, error) {
|
||||
func createColorPrograms(ctx *context, vsSrc, fsSrc string) ([2]gl.Program, error) {
|
||||
var prog [2]gl.Program
|
||||
frep := strings.NewReplacer(
|
||||
"HEADER", `
|
||||
@@ -457,7 +444,7 @@ uniform sampler2D tex;
|
||||
)
|
||||
fsSrcTex := frep.Replace(fsSrc)
|
||||
var err error
|
||||
prog[materialTexture], err = gl.CreateProgram(ctx, vsSrc, fsSrcTex, blitAttribs)
|
||||
prog[materialTexture], err = gl.CreateProgram(ctx.Functions, vsSrc, fsSrcTex, blitAttribs)
|
||||
if err != nil {
|
||||
return prog, err
|
||||
}
|
||||
@@ -468,7 +455,7 @@ uniform vec4 color;
|
||||
"GET_COLOR", `color`,
|
||||
)
|
||||
fsSrcCol := frep.Replace(fsSrc)
|
||||
prog[materialColor], err = gl.CreateProgram(ctx, vsSrc, fsSrcCol, blitAttribs)
|
||||
prog[materialColor], err = gl.CreateProgram(ctx.Functions, vsSrc, fsSrcCol, blitAttribs)
|
||||
if err != nil {
|
||||
ctx.DeleteProgram(prog[materialTexture])
|
||||
return prog, err
|
||||
@@ -886,7 +873,7 @@ func (r *renderer) uploadTexture(img image.Image, opaque bool) {
|
||||
r.ctx.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
|
||||
var internal int
|
||||
var format gl.Enum
|
||||
switch r.srgbMode {
|
||||
switch r.ctx.caps.srgbMode {
|
||||
case srgbES3:
|
||||
internal, format = gl.SRGB8, gl.RGB
|
||||
case srgbEXT:
|
||||
@@ -897,7 +884,7 @@ func (r *renderer) uploadTexture(img image.Image, opaque bool) {
|
||||
} else {
|
||||
var internal int
|
||||
var format gl.Enum
|
||||
switch r.srgbMode {
|
||||
switch r.ctx.caps.srgbMode {
|
||||
case srgbES3:
|
||||
internal, format = gl.SRGB8_ALPHA8, gl.RGBA
|
||||
case srgbEXT:
|
||||
@@ -970,14 +957,14 @@ func clipSpaceTransform(r image.Rectangle, viewport image.Point) (f32.Point, f32
|
||||
return scale, offset
|
||||
}
|
||||
|
||||
func bindFramebuffer(ctx *gl.Functions, fbo gl.Framebuffer) {
|
||||
func bindFramebuffer(ctx *context, fbo gl.Framebuffer) {
|
||||
ctx.BindFramebuffer(gl.FRAMEBUFFER, fbo)
|
||||
if st := ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE {
|
||||
panic(fmt.Errorf("AA FBO not complete; status = 0x%x, err = %d", st, ctx.GetError()))
|
||||
}
|
||||
}
|
||||
|
||||
func createTexture(ctx *gl.Functions) gl.Texture {
|
||||
func createTexture(ctx *context) gl.Texture {
|
||||
tex := ctx.CreateTexture()
|
||||
ctx.BindTexture(gl.TEXTURE_2D, tex)
|
||||
ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||
@@ -993,17 +980,6 @@ func copyImage(img image.Image, r image.Rectangle) *image.RGBA {
|
||||
return tmp
|
||||
}
|
||||
|
||||
func srgbModeFor(ver [2]int, exts string) srgbMode {
|
||||
switch {
|
||||
case ver[0] >= 3:
|
||||
return srgbES3
|
||||
case strings.Contains(exts, "EXT_sRGB"):
|
||||
return srgbEXT
|
||||
default:
|
||||
panic("neither OpenGL ES 3 nor EXT_sRGB is supported")
|
||||
}
|
||||
}
|
||||
|
||||
const blitVSrc = `
|
||||
#version 100
|
||||
|
||||
|
||||
+31
-31
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
type pather struct {
|
||||
ctx *gl.Functions
|
||||
ctx *context
|
||||
|
||||
viewport image.Point
|
||||
|
||||
@@ -24,7 +24,7 @@ type pather struct {
|
||||
}
|
||||
|
||||
type coverer struct {
|
||||
ctx *gl.Functions
|
||||
ctx *context
|
||||
prog [2]gl.Program
|
||||
vars [2]struct {
|
||||
z gl.Uniform
|
||||
@@ -36,7 +36,7 @@ type coverer struct {
|
||||
}
|
||||
|
||||
type stenciler struct {
|
||||
ctx *gl.Functions
|
||||
ctx *context
|
||||
defFBO gl.Framebuffer
|
||||
indexBufQuads int
|
||||
prog gl.Program
|
||||
@@ -77,7 +77,7 @@ var (
|
||||
intersectAttribs = []string{"pos", "uv"}
|
||||
)
|
||||
|
||||
func newPather(ctx *gl.Functions) *pather {
|
||||
func newPather(ctx *context) *pather {
|
||||
return &pather{
|
||||
ctx: ctx,
|
||||
stenciler: newStenciler(ctx),
|
||||
@@ -85,7 +85,7 @@ func newPather(ctx *gl.Functions) *pather {
|
||||
}
|
||||
}
|
||||
|
||||
func newCoverer(ctx *gl.Functions) *coverer {
|
||||
func newCoverer(ctx *context) *coverer {
|
||||
prog, err := createColorPrograms(ctx, coverVSrc, coverFSrc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -98,42 +98,42 @@ func newCoverer(ctx *gl.Functions) *coverer {
|
||||
ctx.UseProgram(prog)
|
||||
switch materialType(i) {
|
||||
case materialTexture:
|
||||
uTex := gl.GetUniformLocation(ctx, prog, "tex")
|
||||
uTex := gl.GetUniformLocation(ctx.Functions, prog, "tex")
|
||||
ctx.Uniform1i(uTex, 0)
|
||||
c.vars[i].uUVScale = gl.GetUniformLocation(ctx, prog, "uvScale")
|
||||
c.vars[i].uUVOffset = gl.GetUniformLocation(ctx, prog, "uvOffset")
|
||||
c.vars[i].uUVScale = gl.GetUniformLocation(ctx.Functions, prog, "uvScale")
|
||||
c.vars[i].uUVOffset = gl.GetUniformLocation(ctx.Functions, prog, "uvOffset")
|
||||
case materialColor:
|
||||
c.vars[i].uColor = gl.GetUniformLocation(ctx, prog, "color")
|
||||
c.vars[i].uColor = gl.GetUniformLocation(ctx.Functions, prog, "color")
|
||||
}
|
||||
uCover := gl.GetUniformLocation(ctx, prog, "cover")
|
||||
uCover := gl.GetUniformLocation(ctx.Functions, prog, "cover")
|
||||
ctx.Uniform1i(uCover, 1)
|
||||
c.vars[i].z = gl.GetUniformLocation(ctx, prog, "z")
|
||||
c.vars[i].uScale = gl.GetUniformLocation(ctx, prog, "scale")
|
||||
c.vars[i].uOffset = gl.GetUniformLocation(ctx, prog, "offset")
|
||||
c.vars[i].uCoverUVScale = gl.GetUniformLocation(ctx, prog, "uvCoverScale")
|
||||
c.vars[i].uCoverUVOffset = gl.GetUniformLocation(ctx, prog, "uvCoverOffset")
|
||||
c.vars[i].z = gl.GetUniformLocation(ctx.Functions, prog, "z")
|
||||
c.vars[i].uScale = gl.GetUniformLocation(ctx.Functions, prog, "scale")
|
||||
c.vars[i].uOffset = gl.GetUniformLocation(ctx.Functions, prog, "offset")
|
||||
c.vars[i].uCoverUVScale = gl.GetUniformLocation(ctx.Functions, prog, "uvCoverScale")
|
||||
c.vars[i].uCoverUVOffset = gl.GetUniformLocation(ctx.Functions, prog, "uvCoverOffset")
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func newStenciler(ctx *gl.Functions) *stenciler {
|
||||
func newStenciler(ctx *context) *stenciler {
|
||||
defFBO := gl.Framebuffer(ctx.GetBinding(gl.FRAMEBUFFER_BINDING))
|
||||
prog, err := gl.CreateProgram(ctx, stencilVSrc, stencilFSrc, pathAttribs)
|
||||
prog, err := gl.CreateProgram(ctx.Functions, stencilVSrc, stencilFSrc, pathAttribs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
uAreaLUT := gl.GetUniformLocation(ctx, prog, "areaLUT")
|
||||
uAreaLUT := gl.GetUniformLocation(ctx.Functions, prog, "areaLUT")
|
||||
ctx.UseProgram(prog)
|
||||
ctx.Uniform1i(uAreaLUT, 0)
|
||||
areaLUT, err := loadLUT(ctx, genAreaLUT(256, 256))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
iprog, err := gl.CreateProgram(ctx, intersectVSrc, intersectFSrc, intersectAttribs)
|
||||
iprog, err := gl.CreateProgram(ctx.Functions, intersectVSrc, intersectFSrc, intersectAttribs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
coverLoc := gl.GetUniformLocation(ctx, iprog, "cover")
|
||||
coverLoc := gl.GetUniformLocation(ctx.Functions, iprog, "cover")
|
||||
ctx.UseProgram(iprog)
|
||||
ctx.Uniform1i(coverLoc, 0)
|
||||
return &stenciler{
|
||||
@@ -142,16 +142,16 @@ func newStenciler(ctx *gl.Functions) *stenciler {
|
||||
prog: prog,
|
||||
iprog: iprog,
|
||||
areaLUT: areaLUT,
|
||||
uScale: gl.GetUniformLocation(ctx, prog, "scale"),
|
||||
uOffset: gl.GetUniformLocation(ctx, prog, "offset"),
|
||||
uPathOffset: gl.GetUniformLocation(ctx, prog, "pathOffset"),
|
||||
uIntersectUVScale: gl.GetUniformLocation(ctx, iprog, "uvScale"),
|
||||
uIntersectUVOffset: gl.GetUniformLocation(ctx, iprog, "uvOffset"),
|
||||
uScale: gl.GetUniformLocation(ctx.Functions, prog, "scale"),
|
||||
uOffset: gl.GetUniformLocation(ctx.Functions, prog, "offset"),
|
||||
uPathOffset: gl.GetUniformLocation(ctx.Functions, prog, "pathOffset"),
|
||||
uIntersectUVScale: gl.GetUniformLocation(ctx.Functions, iprog, "uvScale"),
|
||||
uIntersectUVOffset: gl.GetUniformLocation(ctx.Functions, iprog, "uvOffset"),
|
||||
indexBuf: ctx.CreateBuffer(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *fboSet) resize(ctx *gl.Functions, sizes []image.Point, internalFormat int, format, ty gl.Enum) {
|
||||
func (s *fboSet) resize(ctx *context, sizes []image.Point, internalFormat int, format, ty gl.Enum) {
|
||||
// Add fbos.
|
||||
for i := len(s.fbos); i < len(sizes); i++ {
|
||||
tex := ctx.CreateTexture()
|
||||
@@ -186,14 +186,14 @@ func (s *fboSet) resize(ctx *gl.Functions, sizes []image.Point, internalFormat i
|
||||
s.delete(ctx, len(sizes))
|
||||
}
|
||||
|
||||
func (s *fboSet) invalidate(ctx *gl.Functions) {
|
||||
func (s *fboSet) invalidate(ctx *context) {
|
||||
for _, f := range s.fbos {
|
||||
ctx.BindFramebuffer(gl.FRAMEBUFFER, f.fbo)
|
||||
ctx.InvalidateFramebuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *fboSet) delete(ctx *gl.Functions, idx int) {
|
||||
func (s *fboSet) delete(ctx *context, idx int) {
|
||||
for i := idx; i < len(s.fbos); i++ {
|
||||
f := s.fbos[i]
|
||||
ctx.DeleteFramebuffer(f.fbo)
|
||||
@@ -220,7 +220,7 @@ func (c *coverer) release() {
|
||||
}
|
||||
}
|
||||
|
||||
func buildPath(ctx *gl.Functions, p *path.Path) *pathData {
|
||||
func buildPath(ctx *context, p *path.Path) *pathData {
|
||||
buf := ctx.CreateBuffer()
|
||||
ctx.BindBuffer(gl.ARRAY_BUFFER, buf)
|
||||
ctx.BufferData(gl.ARRAY_BUFFER, gl.BytesView(p.Vertices), gl.STATIC_DRAW)
|
||||
@@ -230,7 +230,7 @@ func buildPath(ctx *gl.Functions, p *path.Path) *pathData {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pathData) release(ctx *gl.Functions) {
|
||||
func (p *pathData) release(ctx *context) {
|
||||
ctx.DeleteBuffer(p.data)
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ func (c *coverer) cover(z float32, mat materialType, col [4]float32, scale, off,
|
||||
c.ctx.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
|
||||
}
|
||||
|
||||
func loadLUT(ctx *gl.Functions, lut *image.Gray) (gl.Texture, error) {
|
||||
func loadLUT(ctx *context, lut *image.Gray) (gl.Texture, error) {
|
||||
tex := ctx.CreateTexture()
|
||||
ctx.BindTexture(gl.TEXTURE_2D, tex)
|
||||
ctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
||||
|
||||
@@ -9,13 +9,13 @@ import (
|
||||
)
|
||||
|
||||
type timers struct {
|
||||
ctx *gl.Functions
|
||||
ctx *context
|
||||
timers []*timer
|
||||
}
|
||||
|
||||
type timer struct {
|
||||
Elapsed time.Duration
|
||||
ctx *gl.Functions
|
||||
ctx *context
|
||||
obj gl.Query
|
||||
state timerState
|
||||
}
|
||||
@@ -28,7 +28,7 @@ const (
|
||||
timerWaiting
|
||||
)
|
||||
|
||||
func newTimers(ctx *gl.Functions, exts string) *timers {
|
||||
func newTimers(ctx *context) *timers {
|
||||
return &timers{
|
||||
ctx: ctx,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user