gioui.org/ui@v0.0.0-20190926171558-ce74bc0cbaea/app/internal/gl/gl_js.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package gl
     4  
     5  import (
     6  	"errors"
     7  	"strings"
     8  	"syscall/js"
     9  )
    10  
    11  type Functions struct {
    12  	Ctx                             js.Value
    13  	EXT_disjoint_timer_query        js.Value
    14  	EXT_disjoint_timer_query_webgl2 js.Value
    15  
    16  	// Cached JS arrays.
    17  	byteBuf  js.Value
    18  	int32Buf js.Value
    19  }
    20  
    21  func (f *Functions) Init(version int) error {
    22  	if version < 2 {
    23  		f.EXT_disjoint_timer_query = f.getExtension("EXT_disjoint_timer_query")
    24  		if f.getExtension("OES_texture_half_float") == js.Null() && f.getExtension("OES_texture_float") == js.Null() {
    25  			return errors.New("gl: no support for neither OES_texture_half_float nor OES_texture_float")
    26  		}
    27  		if f.getExtension("EXT_sRGB") == js.Null() {
    28  			return errors.New("gl: EXT_sRGB not supported")
    29  		}
    30  	} else {
    31  		// WebGL2 extensions.
    32  		f.EXT_disjoint_timer_query_webgl2 = f.getExtension("EXT_disjoint_timer_query_webgl2")
    33  		if f.getExtension("EXT_color_buffer_half_float") == js.Null() && f.getExtension("EXT_color_buffer_float") == js.Null() {
    34  			return errors.New("gl: no support for neither EXT_color_buffer_half_float nor EXT_color_buffer_float")
    35  		}
    36  	}
    37  	return nil
    38  }
    39  
    40  func (f *Functions) getExtension(name string) js.Value {
    41  	return f.Ctx.Call("getExtension", name)
    42  }
    43  
    44  func (f *Functions) ActiveTexture(t Enum) {
    45  	f.Ctx.Call("activeTexture", int(t))
    46  }
    47  func (f *Functions) AttachShader(p Program, s Shader) {
    48  	f.Ctx.Call("attachShader", js.Value(p), js.Value(s))
    49  }
    50  func (f *Functions) BeginQuery(target Enum, query Query) {
    51  	if f.EXT_disjoint_timer_query_webgl2 != js.Null() {
    52  		f.Ctx.Call("beginQuery", int(target), js.Value(query))
    53  	} else {
    54  		f.EXT_disjoint_timer_query.Call("beginQueryEXT", int(target), js.Value(query))
    55  	}
    56  }
    57  func (f *Functions) BindAttribLocation(p Program, a Attrib, name string) {
    58  	f.Ctx.Call("bindAttribLocation", js.Value(p), int(a), name)
    59  }
    60  func (f *Functions) BindBuffer(target Enum, b Buffer) {
    61  	f.Ctx.Call("bindBuffer", int(target), js.Value(b))
    62  }
    63  func (f *Functions) BindFramebuffer(target Enum, fb Framebuffer) {
    64  	f.Ctx.Call("bindFramebuffer", int(target), js.Value(fb))
    65  }
    66  func (f *Functions) BindRenderbuffer(target Enum, rb Renderbuffer) {
    67  	f.Ctx.Call("bindRenderbuffer", int(target), js.Value(rb))
    68  }
    69  func (f *Functions) BindTexture(target Enum, t Texture) {
    70  	f.Ctx.Call("bindTexture", int(target), js.Value(t))
    71  }
    72  func (f *Functions) BlendEquation(mode Enum) {
    73  	f.Ctx.Call("blendEquation", int(mode))
    74  }
    75  func (f *Functions) BlendFunc(sfactor, dfactor Enum) {
    76  	f.Ctx.Call("blendFunc", int(sfactor), int(dfactor))
    77  }
    78  func (f *Functions) BufferData(target Enum, src []byte, usage Enum) {
    79  	f.Ctx.Call("bufferData", int(target), f.byteArrayOf(src), int(usage))
    80  }
    81  func (f *Functions) CheckFramebufferStatus(target Enum) Enum {
    82  	return Enum(f.Ctx.Call("checkFramebufferStatus", int(target)).Int())
    83  }
    84  func (f *Functions) Clear(mask Enum) {
    85  	f.Ctx.Call("clear", int(mask))
    86  }
    87  func (f *Functions) ClearColor(red, green, blue, alpha float32) {
    88  	f.Ctx.Call("clearColor", red, green, blue, alpha)
    89  }
    90  func (f *Functions) ClearDepthf(d float32) {
    91  	f.Ctx.Call("clearDepth", d)
    92  }
    93  func (f *Functions) CompileShader(s Shader) {
    94  	f.Ctx.Call("compileShader", js.Value(s))
    95  }
    96  func (f *Functions) CreateBuffer() Buffer {
    97  	return Buffer(f.Ctx.Call("createBuffer"))
    98  }
    99  func (f *Functions) CreateFramebuffer() Framebuffer {
   100  	return Framebuffer(f.Ctx.Call("createFramebuffer"))
   101  }
   102  func (f *Functions) CreateProgram() Program {
   103  	return Program(f.Ctx.Call("createProgram"))
   104  }
   105  func (f *Functions) CreateQuery() Query {
   106  	return Query(f.Ctx.Call("createQuery"))
   107  }
   108  func (f *Functions) CreateRenderbuffer() Renderbuffer {
   109  	return Renderbuffer(f.Ctx.Call("createRenderbuffer"))
   110  }
   111  func (f *Functions) CreateShader(ty Enum) Shader {
   112  	return Shader(f.Ctx.Call("createShader", int(ty)))
   113  }
   114  func (f *Functions) CreateTexture() Texture {
   115  	return Texture(f.Ctx.Call("createTexture"))
   116  }
   117  func (f *Functions) DeleteBuffer(v Buffer) {
   118  	f.Ctx.Call("deleteBuffer", js.Value(v))
   119  }
   120  func (f *Functions) DeleteFramebuffer(v Framebuffer) {
   121  	f.Ctx.Call("deleteFramebuffer", js.Value(v))
   122  }
   123  func (f *Functions) DeleteProgram(p Program) {
   124  	f.Ctx.Call("deleteProgram", js.Value(p))
   125  }
   126  func (f *Functions) DeleteQuery(query Query) {
   127  	if f.EXT_disjoint_timer_query_webgl2 != js.Null() {
   128  		f.Ctx.Call("deleteQuery", js.Value(query))
   129  	} else {
   130  		f.EXT_disjoint_timer_query.Call("deleteQueryEXT", js.Value(query))
   131  	}
   132  }
   133  func (f *Functions) DeleteShader(s Shader) {
   134  	f.Ctx.Call("deleteShader", js.Value(s))
   135  }
   136  func (f *Functions) DeleteRenderbuffer(v Renderbuffer) {
   137  	f.Ctx.Call("deleteRenderbuffer", js.Value(v))
   138  }
   139  func (f *Functions) DeleteTexture(v Texture) {
   140  	f.Ctx.Call("deleteTexture", js.Value(v))
   141  }
   142  func (f *Functions) DepthFunc(fn Enum) {
   143  	f.Ctx.Call("depthFunc", int(fn))
   144  }
   145  func (f *Functions) DepthMask(mask bool) {
   146  	f.Ctx.Call("depthMask", mask)
   147  }
   148  func (f *Functions) DisableVertexAttribArray(a Attrib) {
   149  	f.Ctx.Call("disableVertexAttribArray", int(a))
   150  }
   151  func (f *Functions) Disable(cap Enum) {
   152  	f.Ctx.Call("disable", int(cap))
   153  }
   154  func (f *Functions) DrawArrays(mode Enum, first, count int) {
   155  	f.Ctx.Call("drawArrays", int(mode), first, count)
   156  }
   157  func (f *Functions) DrawElements(mode Enum, count int, ty Enum, offset int) {
   158  	f.Ctx.Call("drawElements", int(mode), count, int(ty), offset)
   159  }
   160  func (f *Functions) Enable(cap Enum) {
   161  	f.Ctx.Call("enable", int(cap))
   162  }
   163  func (f *Functions) EnableVertexAttribArray(a Attrib) {
   164  	f.Ctx.Call("enableVertexAttribArray", int(a))
   165  }
   166  func (f *Functions) EndQuery(target Enum) {
   167  	if f.EXT_disjoint_timer_query_webgl2 != js.Null() {
   168  		f.Ctx.Call("endQuery", int(target))
   169  	} else {
   170  		f.EXT_disjoint_timer_query.Call("endQueryEXT", int(target))
   171  	}
   172  }
   173  func (f *Functions) Finish() {
   174  	f.Ctx.Call("finish")
   175  }
   176  func (f *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) {
   177  	f.Ctx.Call("framebufferRenderbuffer", int(target), int(attachment), int(renderbuffertarget), js.Value(renderbuffer))
   178  }
   179  func (f *Functions) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) {
   180  	f.Ctx.Call("framebufferTexture2D", int(target), int(attachment), int(texTarget), js.Value(t), level)
   181  }
   182  func (f *Functions) GetError() Enum {
   183  	return Enum(f.Ctx.Call("getError").Int())
   184  }
   185  func (f *Functions) GetRenderbufferParameteri(target, pname Enum) int {
   186  	return paramVal(f.Ctx.Call("getRenderbufferParameteri", int(pname)))
   187  }
   188  func (f *Functions) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int {
   189  	return paramVal(f.Ctx.Call("getFramebufferAttachmentParameter", int(target), int(attachment), int(pname)))
   190  }
   191  func (f *Functions) GetBinding(pname Enum) Object {
   192  	return Object(f.Ctx.Call("getParameter", int(pname)))
   193  }
   194  func (f *Functions) GetInteger(pname Enum) int {
   195  	return paramVal(f.Ctx.Call("getParameter", int(pname)))
   196  }
   197  func (f *Functions) GetProgrami(p Program, pname Enum) int {
   198  	return paramVal(f.Ctx.Call("getProgramParameter", js.Value(p), int(pname)))
   199  }
   200  func (f *Functions) GetProgramInfoLog(p Program) string {
   201  	return f.Ctx.Call("getProgramInfoLog", js.Value(p)).String()
   202  }
   203  func (f *Functions) GetQueryObjectuiv(query Query, pname Enum) uint {
   204  	if f.EXT_disjoint_timer_query_webgl2 != js.Null() {
   205  		return uint(paramVal(f.Ctx.Call("getQueryParameter", js.Value(query), int(pname))))
   206  	} else {
   207  		return uint(paramVal(f.EXT_disjoint_timer_query.Call("getQueryObjectEXT", js.Value(query), int(pname))))
   208  	}
   209  }
   210  func (f *Functions) GetShaderi(s Shader, pname Enum) int {
   211  	return paramVal(f.Ctx.Call("getShaderParameter", js.Value(s), int(pname)))
   212  }
   213  func (f *Functions) GetShaderInfoLog(s Shader) string {
   214  	return f.Ctx.Call("getShaderInfoLog", js.Value(s)).String()
   215  }
   216  func (f *Functions) GetString(pname Enum) string {
   217  	switch pname {
   218  	case EXTENSIONS:
   219  		extsjs := f.Ctx.Call("getSupportedExtensions")
   220  		var exts []string
   221  		for i := 0; i < extsjs.Length(); i++ {
   222  			exts = append(exts, "GL_"+extsjs.Index(i).String())
   223  		}
   224  		return strings.Join(exts, " ")
   225  	default:
   226  		return f.Ctx.Call("getParameter", int(pname)).String()
   227  	}
   228  }
   229  func (f *Functions) GetUniformLocation(p Program, name string) Uniform {
   230  	return Uniform(f.Ctx.Call("getUniformLocation", js.Value(p), name))
   231  }
   232  func (f *Functions) InvalidateFramebuffer(target, attachment Enum) {
   233  	fn := f.Ctx.Get("invalidateFramebuffer")
   234  	if fn != js.Undefined() {
   235  		if f.int32Buf == (js.Value{}) {
   236  			f.int32Buf = js.Global().Get("Int32Array").New(1)
   237  		}
   238  		f.int32Buf.SetIndex(0, int32(attachment))
   239  		f.Ctx.Call("invalidateFramebuffer", int(target), f.int32Buf)
   240  	}
   241  }
   242  func (f *Functions) LinkProgram(p Program) {
   243  	f.Ctx.Call("linkProgram", js.Value(p))
   244  }
   245  func (f *Functions) PixelStorei(pname Enum, param int32) {
   246  	f.Ctx.Call("pixelStorei", int(pname), param)
   247  }
   248  func (f *Functions) RenderbufferStorage(target, internalformat Enum, width, height int) {
   249  	f.Ctx.Call("renderbufferStorage", int(target), int(internalformat), width, height)
   250  }
   251  func (f *Functions) ReadPixels(x, y, width, height int, format, ty Enum, data []byte) {
   252  	f.resizeByteBuffer(len(data))
   253  	f.Ctx.Call("readPixels", x, y, width, height, int(format), int(ty), f.byteBuf)
   254  	js.CopyBytesToGo(data, f.byteBuf)
   255  }
   256  func (f *Functions) Scissor(x, y, width, height int32) {
   257  	f.Ctx.Call("scissor", x, y, width, height)
   258  }
   259  func (f *Functions) ShaderSource(s Shader, src string) {
   260  	f.Ctx.Call("shaderSource", js.Value(s), src)
   261  }
   262  func (f *Functions) TexImage2D(target Enum, level int, internalFormat int, width, height int, format, ty Enum, data []byte) {
   263  	f.Ctx.Call("texImage2D", int(target), int(level), int(internalFormat), int(width), int(height), 0, int(format), int(ty), f.byteArrayOf(data))
   264  }
   265  func (f *Functions) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {
   266  	f.Ctx.Call("texSubImage2D", int(target), level, x, y, width, height, int(format), int(ty), f.byteArrayOf(data))
   267  }
   268  func (f *Functions) TexParameteri(target, pname Enum, param int) {
   269  	f.Ctx.Call("texParameteri", int(target), int(pname), int(param))
   270  }
   271  func (f *Functions) Uniform1f(dst Uniform, v float32) {
   272  	f.Ctx.Call("uniform1f", js.Value(dst), v)
   273  }
   274  func (f *Functions) Uniform1i(dst Uniform, v int) {
   275  	f.Ctx.Call("uniform1i", js.Value(dst), v)
   276  }
   277  func (f *Functions) Uniform2f(dst Uniform, v0, v1 float32) {
   278  	f.Ctx.Call("uniform2f", js.Value(dst), v0, v1)
   279  }
   280  func (f *Functions) Uniform3f(dst Uniform, v0, v1, v2 float32) {
   281  	f.Ctx.Call("uniform3f", js.Value(dst), v0, v1, v2)
   282  }
   283  func (f *Functions) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {
   284  	f.Ctx.Call("uniform4f", js.Value(dst), v0, v1, v2, v3)
   285  }
   286  func (f *Functions) UseProgram(p Program) {
   287  	f.Ctx.Call("useProgram", js.Value(p))
   288  }
   289  func (f *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {
   290  	f.Ctx.Call("vertexAttribPointer", int(dst), size, int(ty), normalized, stride, offset)
   291  }
   292  func (f *Functions) Viewport(x, y, width, height int) {
   293  	f.Ctx.Call("viewport", x, y, width, height)
   294  }
   295  
   296  func (f *Functions) byteArrayOf(data []byte) js.Value {
   297  	if len(data) == 0 {
   298  		return js.Null()
   299  	}
   300  	f.resizeByteBuffer(len(data))
   301  	js.CopyBytesToJS(f.byteBuf, data)
   302  	return f.byteBuf
   303  }
   304  
   305  func (f *Functions) resizeByteBuffer(n int) {
   306  	if n == 0 {
   307  		return
   308  	}
   309  	if f.byteBuf != (js.Value{}) && f.byteBuf.Length() >= n {
   310  		return
   311  	}
   312  	f.byteBuf = js.Global().Get("Uint8Array").New(n)
   313  }
   314  
   315  func paramVal(v js.Value) int {
   316  	switch v.Type() {
   317  	case js.TypeBoolean:
   318  		if b := v.Bool(); b {
   319  			return 1
   320  		} else {
   321  			return 0
   322  		}
   323  	case js.TypeNumber:
   324  		return v.Int()
   325  	default:
   326  		panic("unknown parameter type")
   327  	}
   328  }