Move some methods to opengl.Context

This commit is contained in:
Hajime Hoshi 2014-12-31 18:23:18 +09:00
parent 4e3beb65f0
commit e10bcb3dd8
9 changed files with 146 additions and 147 deletions

View File

@ -55,16 +55,16 @@ func (c *graphicsContext) dispose() {
framebuffer := c.screen.framebuffer
texture := c.screen.texture
framebuffer.Dispose()
texture.Dispose()
framebuffer.Dispose(c.glContext)
texture.Dispose(c.glContext)
}
func (c *graphicsContext) preUpdate() error {
return c.screen.Clear()
return c.screen.Clear(c.glContext)
}
func (c *graphicsContext) postUpdate() error {
if err := c.defaultR.Clear(); err != nil {
if err := c.defaultR.Clear(c.glContext); err != nil {
return err
}

View File

@ -39,13 +39,13 @@ func (i *innerImage) size() (width, height int) {
return i.framebuffer.Size()
}
func (i *innerImage) Clear() error {
return i.Fill(color.Transparent)
func (i *innerImage) Clear(c *opengl.Context) error {
return i.Fill(c, color.Transparent)
}
func (i *innerImage) Fill(clr color.Color) error {
func (i *innerImage) Fill(c *opengl.Context, clr color.Color) error {
r, g, b, a := internal.RGBA(clr)
return i.framebuffer.Fill(r, g, b, a)
return i.framebuffer.Fill(c, r, g, b, a)
}
func (i *innerImage) drawImage(c *opengl.Context, img *innerImage, options *DrawImageOptions) error {
@ -120,7 +120,7 @@ func (i *Image) Size() (width, height int) {
func (i *Image) Clear() (err error) {
i.pixels = nil
i.syncer.Sync(func() {
err = i.inner.Clear()
err = i.inner.Clear(currentUI.glContext)
})
return
}
@ -129,7 +129,7 @@ func (i *Image) Clear() (err error) {
func (i *Image) Fill(clr color.Color) (err error) {
i.pixels = nil
i.syncer.Sync(func() {
err = i.inner.Fill(clr)
err = i.inner.Fill(currentUI.glContext, clr)
})
return
}
@ -175,7 +175,7 @@ func (i *Image) At(x, y int) color.Color {
if i.pixels == nil {
i.syncer.Sync(func() {
var err error
i.pixels, err = i.inner.texture.Pixels()
i.pixels, err = i.inner.texture.Pixels(currentUI.glContext)
if err != nil {
panic(err)
}

View File

@ -67,14 +67,14 @@ func (f *Framebuffer) Size() (width, height int) {
return f.width, f.height
}
func (f *Framebuffer) Dispose() {
f.native.Delete()
func (f *Framebuffer) Dispose(c *opengl.Context) {
c.DeleteFramebuffer(f.native)
}
func (f *Framebuffer) setAsViewport() error {
func (f *Framebuffer) setAsViewport(c *opengl.Context) error {
width := internal.NextPowerOf2Int(f.width)
height := internal.NextPowerOf2Int(f.height)
return f.native.SetAsViewport(width, height)
return c.SetViewport(f.native, width, height)
}
func (f *Framebuffer) projectionMatrix() [4][4]float64 {
@ -98,15 +98,15 @@ type TextureQuads interface {
Texture(i int) (u0, v0, u1, v1 float32)
}
func (f *Framebuffer) Fill(r, g, b, a float64) error {
if err := f.setAsViewport(); err != nil {
func (f *Framebuffer) Fill(c *opengl.Context, r, g, b, a float64) error {
if err := f.setAsViewport(c); err != nil {
return err
}
return f.native.Fill(r, g, b, a)
return c.FillFramebuffer(f.native, r, g, b, a)
}
func (f *Framebuffer) DrawTexture(c *opengl.Context, t *Texture, quads TextureQuads, geo, clr Matrix) error {
if err := f.setAsViewport(); err != nil {
if err := f.setAsViewport(c); err != nil {
return err
}
projectionMatrix := f.projectionMatrix()

View File

@ -58,23 +58,20 @@ func DrawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix [4]
}
// TODO: Check performance
program := useProgramColorMatrix(glMatrix(projectionMatrix), geo, color)
program := useProgramColorMatrix(c, glMatrix(projectionMatrix), geo, color)
// TODO: Do we have to call gl.ActiveTexture(gl.TEXTURE0)?
texture.Bind()
c.BindTexture(texture)
vertexAttrLocation := program.GetAttributeLocation("vertex")
texCoordAttrLocation := program.GetAttributeLocation("tex_coord")
vertexAttrLocation.EnableArray()
texCoordAttrLocation.EnableArray()
c.EnableVertexAttribArray(program, "vertex")
c.EnableVertexAttribArray(program, "tex_coord")
defer func() {
texCoordAttrLocation.DisableArray()
vertexAttrLocation.DisableArray()
c.DisableVertexAttribArray(program, "tex_coord")
c.DisableVertexAttribArray(program, "vertex")
}()
vertexAttrLocation.AttribPointer(stride, uintptr(float32Size*0))
texCoordAttrLocation.AttribPointer(stride, uintptr(float32Size*2))
c.VertexAttribPointer(program, "vertex", stride, uintptr(float32Size*0))
c.VertexAttribPointer(program, "tex_coord", stride, uintptr(float32Size*2))
vertices := []float32{}
for i := 0; i < quads.Len(); i++ {

View File

@ -29,13 +29,13 @@ func initialize(c *opengl.Context) error {
if err != nil {
return err
}
defer shaders[shaderVertex].native.Delete()
defer c.DeleteShader(shaders[shaderVertex].native)
shaders[shaderColorMatrix].native, err = c.NewShader(c.FragmentShader, shaders[shaderColorMatrix].source)
if err != nil {
return err
}
defer shaders[shaderColorMatrix].native.Delete()
defer c.DeleteShader(shaders[shaderColorMatrix].native)
shaders := []opengl.Shader{
shaders[shaderVertex].native,
@ -66,31 +66,30 @@ func initialize(c *opengl.Context) error {
var lastProgram opengl.Program = 0
func useProgramColorMatrix(projectionMatrix [16]float32, geo Matrix, color Matrix) opengl.Program {
func useProgramColorMatrix(c *opengl.Context, projectionMatrix [16]float32, geo Matrix, color Matrix) opengl.Program {
if lastProgram != programColorMatrix {
programColorMatrix.Use()
c.UseProgram(programColorMatrix)
lastProgram = programColorMatrix
}
// TODO: Check the performance.
program := programColorMatrix
program.GetUniformLocation("projection_matrix").UniformMatrix4fv(projectionMatrix)
c.UniformMatrix4fv(program, "projection_matrix", projectionMatrix)
a := float32(geo.Element(0, 0))
b := float32(geo.Element(0, 1))
c := float32(geo.Element(1, 0))
d := float32(geo.Element(1, 1))
ma := float32(geo.Element(0, 0))
mb := float32(geo.Element(0, 1))
mc := float32(geo.Element(1, 0))
md := float32(geo.Element(1, 1))
tx := float32(geo.Element(0, 2))
ty := float32(geo.Element(1, 2))
glModelviewMatrix := [...]float32{
a, c, 0, 0,
b, d, 0, 0,
ma, mc, 0, 0,
mb, md, 0, 0,
0, 0, 1, 0,
tx, ty, 0, 1,
}
program.GetUniformLocation("modelview_matrix").UniformMatrix4fv(glModelviewMatrix)
program.GetUniformLocation("texture").Uniform1i(0)
c.UniformMatrix4fv(program, "modelview_matrix", glModelviewMatrix)
c.Uniform1i(program, "texture", 0)
e := [4][5]float32{}
for i := 0; i < 4; i++ {
@ -105,11 +104,11 @@ func useProgramColorMatrix(projectionMatrix [16]float32, geo Matrix, color Matri
e[0][2], e[1][2], e[2][2], e[3][2],
e[0][3], e[1][3], e[2][3], e[3][3],
}
program.GetUniformLocation("color_matrix").UniformMatrix4fv(glColorMatrix)
c.UniformMatrix4fv(program, "color_matrix", glColorMatrix)
glColorMatrixTranslation := [...]float32{
e[0][4], e[1][4], e[2][4], e[3][4],
}
program.GetUniformLocation("color_matrix_translation").Uniform4fv(1, glColorMatrixTranslation[:])
c.Uniform4fv(program, "color_matrix_translation", glColorMatrixTranslation)
return program
}

View File

@ -87,11 +87,11 @@ func NewTextureFromImage(c *opengl.Context, img image.Image, filter opengl.Filte
return &Texture{native, origSize.X, origSize.Y}, nil
}
func (t *Texture) Dispose() {
t.native.Delete()
func (t *Texture) Dispose(c *opengl.Context) {
c.DeleteTexture(t.native)
}
func (t *Texture) Pixels() ([]uint8, error) {
func (t *Texture) Pixels(c *opengl.Context) ([]uint8, error) {
w, h := internal.NextPowerOf2Int(t.width), internal.NextPowerOf2Int(t.height)
return t.native.Pixels(w, h)
return c.TexturePixels(t.native, w, h)
}

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !js
package opengl
import (
@ -20,107 +22,11 @@ import (
"github.com/go-gl/gl"
)
type FilterType int
type ShaderType int
type BufferType int
type BufferUsageType int
type Texture gl.Texture
func (t Texture) Pixels(width, height int) ([]uint8, error) {
// TODO: Use glGetTexLevelParameteri and GL_TEXTURE_WIDTH?
pixels := make([]uint8, 4*width*height)
gl.Texture(t).Bind(gl.TEXTURE_2D)
gl.GetTexImage(gl.TEXTURE_2D, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels)
if e := gl.GetError(); e != gl.NO_ERROR {
// TODO: Use glu.ErrorString
return nil, errors.New(fmt.Sprintf("gl error: %d", e))
}
return pixels, nil
}
func (t Texture) Bind() {
gl.Texture(t).Bind(gl.TEXTURE_2D)
}
func (t Texture) Delete() {
gl.Texture(t).Delete()
}
type Framebuffer gl.Framebuffer
func (f Framebuffer) SetAsViewport(width, height int) error {
gl.Flush()
gl.Framebuffer(f).Bind()
err := gl.CheckFramebufferStatus(gl.FRAMEBUFFER)
if err != gl.FRAMEBUFFER_COMPLETE {
if gl.GetError() != 0 {
return errors.New(fmt.Sprintf("glBindFramebuffer failed: %d", gl.GetError()))
}
return errors.New("glBindFramebuffer failed: the context is different?")
}
gl.Viewport(0, 0, width, height)
return nil
}
func (f Framebuffer) Fill(r, g, b, a float64) error {
gl.ClearColor(gl.GLclampf(r), gl.GLclampf(g), gl.GLclampf(b), gl.GLclampf(a))
gl.Clear(gl.COLOR_BUFFER_BIT)
return nil
}
func (f Framebuffer) Delete() {
gl.Framebuffer(f).Delete()
}
type Shader gl.Shader
func (s Shader) Delete() {
gl.Shader(s).Delete()
}
type Program gl.Program
func (p Program) Use() {
gl.Program(p).Use()
}
func (p Program) GetAttributeLocation(name string) AttribLocation {
return AttribLocation(gl.Program(p).GetAttribLocation(name))
}
func (p Program) GetUniformLocation(name string) UniformLocation {
return UniformLocation(gl.Program(p).GetUniformLocation(name))
}
type AttribLocation int
func (a AttribLocation) EnableArray() {
gl.AttribLocation(a).EnableArray()
}
func (a AttribLocation) DisableArray() {
gl.AttribLocation(a).DisableArray()
}
func (a AttribLocation) AttribPointer(stride int, x uintptr) {
gl.AttribLocation(a).AttribPointer(2, gl.FLOAT, false, stride, x)
}
type UniformLocation int
func (u UniformLocation) UniformMatrix4fv(matrix [16]float32) {
gl.UniformLocation(u).UniformMatrix4fv(false, matrix)
}
func (u UniformLocation) Uniform4fv(count int, v []float32) {
gl.UniformLocation(u).Uniform4fv(count, v)
}
func (u UniformLocation) Uniform1i(v int) {
gl.UniformLocation(u).Uniform1i(v)
}
type Context struct {
Nearest FilterType
Linear FilterType
@ -172,6 +78,26 @@ func (c *Context) NewTexture(width, height int, pixels []uint8, filter FilterTyp
return Texture(t), nil
}
func (c *Context) TexturePixels(t Texture, width, height int) ([]uint8, error) {
// TODO: Use glGetTexLevelParameteri and GL_TEXTURE_WIDTH?
pixels := make([]uint8, 4*width*height)
gl.Texture(t).Bind(gl.TEXTURE_2D)
gl.GetTexImage(gl.TEXTURE_2D, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels)
if e := gl.GetError(); e != gl.NO_ERROR {
// TODO: Use glu.ErrorString
return nil, errors.New(fmt.Sprintf("gl error: %d", e))
}
return pixels, nil
}
func (c *Context) BindTexture(t Texture) {
gl.Texture(t).Bind(gl.TEXTURE_2D)
}
func (c *Context) DeleteTexture(t Texture) {
gl.Texture(t).Delete()
}
func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) {
f := gl.GenFramebuffer()
f.Bind()
@ -184,6 +110,30 @@ func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) {
return Framebuffer(f), nil
}
func (c *Context) SetViewport(f Framebuffer, width, height int) error {
gl.Flush()
gl.Framebuffer(f).Bind()
err := gl.CheckFramebufferStatus(gl.FRAMEBUFFER)
if err != gl.FRAMEBUFFER_COMPLETE {
if gl.GetError() != 0 {
return errors.New(fmt.Sprintf("glBindFramebuffer failed: %d", gl.GetError()))
}
return errors.New("glBindFramebuffer failed: the context is different?")
}
gl.Viewport(0, 0, width, height)
return nil
}
func (c *Context) FillFramebuffer(f Framebuffer, r, g, b, a float64) error {
gl.ClearColor(gl.GLclampf(r), gl.GLclampf(g), gl.GLclampf(b), gl.GLclampf(a))
gl.Clear(gl.COLOR_BUFFER_BIT)
return nil
}
func (c *Context) DeleteFramebuffer(f Framebuffer) {
gl.Framebuffer(f).Delete()
}
func (c *Context) NewShader(shaderType ShaderType, source string) (Shader, error) {
s := gl.CreateShader(gl.GLenum(shaderType))
if s == 0 {
@ -204,6 +154,10 @@ func (c *Context) NewShader(shaderType ShaderType, source string) (Shader, error
return Shader(s), nil
}
func (c *Context) DeleteShader(s Shader) {
gl.Shader(s).Delete()
}
func (c *Context) NewProgram(shaders []Shader) (Program, error) {
p := gl.CreateProgram()
if p == 0 {
@ -220,6 +174,35 @@ func (c *Context) NewProgram(shaders []Shader) (Program, error) {
return Program(p), nil
}
func (c *Context) UseProgram(p Program) {
gl.Program(p).Use()
}
func (c *Context) Uniform1i(p Program, location string, v int) {
// TODO: Cache the location names.
gl.Program(p).GetUniformLocation(location).Uniform1i(v)
}
func (c *Context) Uniform4fv(p Program, location string, v [4]float32) {
gl.Program(p).GetUniformLocation(location).Uniform4fv(1, v[:])
}
func (c *Context) UniformMatrix4fv(p Program, location string, v [16]float32) {
gl.Program(p).GetUniformLocation(location).UniformMatrix4fv(false, v)
}
func (c *Context) VertexAttribPointer(p Program, location string, stride int, v uintptr) {
gl.Program(p).GetAttribLocation(location).AttribPointer(2, gl.FLOAT, false, stride, v)
}
func (c *Context) EnableVertexAttribArray(p Program, location string) {
gl.Program(p).GetAttribLocation(location).EnableArray()
}
func (c *Context) DisableVertexAttribArray(p Program, location string) {
gl.Program(p).GetAttribLocation(location).DisableArray()
}
func (c *Context) NewBuffer(bufferType BufferType, size int, ptr interface{}, bufferUsageType BufferUsageType) {
gl.GenBuffer().Bind(gl.GLenum(bufferType))
gl.BufferData(gl.GLenum(bufferType), size, ptr, gl.GLenum(bufferUsageType))

20
internal/opengl/types.go Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package opengl
type FilterType int
type ShaderType int
type BufferType int
type BufferUsageType int

2
ui.go
View File

@ -174,7 +174,7 @@ func (u *ui) newImage(width, height int, filter Filter) (*Image, error) {
return
}
innerImage, err = newInnerImage(u.glContext, texture)
innerImage.Clear()
innerImage.Clear(u.glContext)
})
if err != nil {
return nil, err