diff --git a/internal/opengl/context.go b/internal/opengl/context.go index 9e593d28f..bc5670557 100644 --- a/internal/opengl/context.go +++ b/internal/opengl/context.go @@ -26,8 +26,14 @@ type Texture int type Framebuffer int type Shader int type Program int -type UniformLocation int -type AttribLocation int +type UniformLocation gl.UniformLocation +type AttribLocation gl.AttribLocation + +type ProgramID int + +func GetProgramID(p Program) ProgramID { + return ProgramID(p) +} type context struct{} @@ -173,13 +179,17 @@ func (c *Context) UseProgram(p Program) { gl.Program(p).Use() } +func (c *Context) GetUniformLocation(p Program, location string) UniformLocation { + return UniformLocation(gl.Program(p).GetUniformLocation(location)) +} + func (c *Context) UniformInt(p Program, location string, v int) { - l := gl.Program(p).GetUniformLocation(location) + l := gl.UniformLocation(GetUniformLocation(c, p, location)) l.Uniform1i(v) } func (c *Context) UniformFloats(p Program, location string, v []float32) { - l := gl.Program(p).GetUniformLocation(location) + l := gl.UniformLocation(GetUniformLocation(c, p, location)) switch len(v) { case 4: l.Uniform4fv(1, v) @@ -192,16 +202,23 @@ func (c *Context) UniformFloats(p Program, location string, v []float32) { } } +func (c *Context) GetAttribLocation(p Program, location string) AttribLocation { + return AttribLocation(gl.Program(p).GetAttribLocation(location)) +} + func (c *Context) VertexAttribPointer(p Program, location string, stride int, v uintptr) { - gl.Program(p).GetAttribLocation(location).AttribPointer(2, gl.FLOAT, false, stride, v) + l := gl.AttribLocation(GetAttribLocation(c, p, location)) + l.AttribPointer(2, gl.FLOAT, false, stride, v) } func (c *Context) EnableVertexAttribArray(p Program, location string) { - gl.Program(p).GetAttribLocation(location).EnableArray() + l := gl.AttribLocation(GetAttribLocation(c, p, location)) + l.EnableArray() } func (c *Context) DisableVertexAttribArray(p Program, location string) { - gl.Program(p).GetAttribLocation(location).DisableArray() + l := gl.AttribLocation(GetAttribLocation(c, p, location)) + l.DisableArray() } func (c *Context) NewBuffer(bufferType BufferType, v interface{}, bufferUsageType BufferUsageType) { diff --git a/internal/opengl/context_js.go b/internal/opengl/context_js.go index 3c023e79a..45cbc161a 100644 --- a/internal/opengl/context_js.go +++ b/internal/opengl/context_js.go @@ -30,6 +30,12 @@ type Program js.Object type UniformLocation js.Object type AttribLocation int +type ProgramID int + +func GetProgramID(p Program) ProgramID { + return ProgramID(p.Get("__ebiten_programId").Int()) +} + type context struct { gl *webgl.Context } @@ -175,12 +181,16 @@ func (c *Context) DeleteShader(s Shader) { gl.DeleteShader(s) } +var lastProgramID ProgramID = 0 + func (c *Context) NewProgram(shaders []Shader) (Program, error) { gl := c.gl p := gl.CreateProgram() if p == nil { return nil, errors.New("glCreateProgram failed") } + p.Set("__ebiten_programId", lastProgramID) + lastProgramID++ for _, shader := range shaders { gl.AttachShader(p, shader) @@ -197,23 +207,20 @@ func (c *Context) UseProgram(p Program) { gl.UseProgram(p) } +func (c *Context) GetUniformLocation(p Program, location string) UniformLocation { + gl := c.gl + return gl.GetUniformLocation(p, location) +} + func (c *Context) UniformInt(p Program, location string, v int) { gl := c.gl - l, ok := uniformLocationCache[location] - if !ok { - l = gl.GetUniformLocation(p, location) - uniformLocationCache[location] = l - } + l := GetUniformLocation(c, p, location) gl.Uniform1i(l, v) } func (c *Context) UniformFloats(p Program, location string, v []float32) { gl := c.gl - l, ok := uniformLocationCache[location] - if !ok { - l = gl.GetUniformLocation(p, location) - uniformLocationCache[location] = l - } + l := GetUniformLocation(c, p, location) switch len(v) { case 4: gl.Call("uniform4fv", l, v) @@ -224,33 +231,26 @@ func (c *Context) UniformFloats(p Program, location string, v []float32) { } } +func (c *Context) GetAttribLocation(p Program, location string) AttribLocation { + gl := c.gl + return AttribLocation(gl.GetAttribLocation(p, location)) +} + func (c *Context) VertexAttribPointer(p Program, location string, stride int, v uintptr) { gl := c.gl - l, ok := attribLocationCache[location] - if !ok { - l = AttribLocation(gl.GetAttribLocation(p, location)) - attribLocationCache[location] = l - } + l := GetAttribLocation(c, p, location) gl.VertexAttribPointer(int(l), 2, gl.FLOAT, false, stride, int(v)) } func (c *Context) EnableVertexAttribArray(p Program, location string) { gl := c.gl - l, ok := attribLocationCache[location] - if !ok { - l = AttribLocation(gl.GetAttribLocation(p, location)) - attribLocationCache[location] = l - } + l := GetAttribLocation(c, p, location) gl.EnableVertexAttribArray(int(l)) } func (c *Context) DisableVertexAttribArray(p Program, location string) { gl := c.gl - l, ok := attribLocationCache[location] - if !ok { - l = AttribLocation(gl.GetAttribLocation(p, location)) - attribLocationCache[location] = l - } + l := GetAttribLocation(c, p, location) gl.DisableVertexAttribArray(int(l)) } diff --git a/internal/opengl/locationcache.go b/internal/opengl/locationcache.go index a01e7d9ca..f97605bc0 100644 --- a/internal/opengl/locationcache.go +++ b/internal/opengl/locationcache.go @@ -14,7 +14,41 @@ package opengl -// Note: This cache is created only for one program. -// If we use two or more programs, the key of the map should be changed. -var uniformLocationCache = map[string]UniformLocation{} -var attribLocationCache = map[string]AttribLocation{} +// Since js.Object (Program) can't be keys of a map, use integers (ProgramID) instead. + +var uniformLocationCache = map[ProgramID]map[string]UniformLocation{} +var attribLocationCache = map[ProgramID]map[string]AttribLocation{} + +type UniformLocationGetter interface { + GetUniformLocation(p Program, location string) UniformLocation +} + +func GetUniformLocation(g UniformLocationGetter, p Program, location string) UniformLocation { + id := GetProgramID(p) + if _, ok := uniformLocationCache[id]; !ok { + uniformLocationCache[id] = map[string]UniformLocation{} + } + l, ok := uniformLocationCache[id][location] + if !ok { + l = g.GetUniformLocation(p, location) + uniformLocationCache[id][location] = l + } + return l +} + +type AttribLocationGetter interface { + GetAttribLocation(p Program, location string) AttribLocation +} + +func GetAttribLocation(g AttribLocationGetter, p Program, location string) AttribLocation { + id := GetProgramID(p) + if _, ok := attribLocationCache[id]; !ok { + attribLocationCache[id] = map[string]AttribLocation{} + } + l, ok := attribLocationCache[id][location] + if !ok { + l = g.GetAttribLocation(p, location) + attribLocationCache[id][location] = l + } + return l +}