gl_js.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 package wm
4
5 import (
6 "errors"
7 "syscall/js"
8
9 "github.com/p9c/p9/pkg/gel/gio/gpu"
10 "github.com/p9c/p9/pkg/gel/gio/internal/gl"
11 "github.com/p9c/p9/pkg/gel/gio/internal/srgb"
12 )
13
14 type context struct {
15 ctx js.Value
16 cnv js.Value
17 srgbFBO *srgb.FBO
18 }
19
20 func newContext(w *window) (*context, error) {
21 args := map[string]interface{}{
22 // Enable low latency rendering.
23 // See https://developers.google.com/web/updates/2019/05/desynchronized.
24 "desynchronized": true,
25 "preserveDrawingBuffer": true,
26 }
27 ctx := w.cnv.Call("getContext", "webgl2", args)
28 if ctx.IsNull() {
29 ctx = w.cnv.Call("getContext", "webgl", args)
30 }
31 if ctx.IsNull() {
32 return nil, errors.New("app: webgl is not supported")
33 }
34 c := &context{
35 ctx: ctx,
36 cnv: w.cnv,
37 }
38 return c, nil
39 }
40
41 func (c *context) API() gpu.API {
42 return gpu.OpenGL{Context: gl.Context(c.ctx)}
43 }
44
45 func (c *context) Release() {
46 if c.srgbFBO != nil {
47 c.srgbFBO.Release()
48 c.srgbFBO = nil
49 }
50 }
51
52 func (c *context) Present() error {
53 if c.srgbFBO != nil {
54 c.srgbFBO.Blit()
55 }
56 if c.srgbFBO != nil {
57 c.srgbFBO.AfterPresent()
58 }
59 if c.ctx.Call("isContextLost").Bool() {
60 return errors.New("context lost")
61 }
62 return nil
63 }
64
65 func (c *context) Lock() {}
66
67 func (c *context) Unlock() {}
68
69 func (c *context) MakeCurrent() error {
70 if c.srgbFBO == nil {
71 var err error
72 c.srgbFBO, err = srgb.New(gl.Context(c.ctx))
73 if err != nil {
74 c.Release()
75 c.srgbFBO = nil
76 return err
77 }
78 }
79 w, h := c.cnv.Get("width").Int(), c.cnv.Get("height").Int()
80 if err := c.srgbFBO.Refresh(w, h); err != nil {
81 c.Release()
82 return err
83 }
84 return nil
85 }
86
87 func (w *window) NewContext() (Context, error) {
88 return newContext(w)
89 }
90