Procházet zdrojové kódy

new opengl binding dev

leonsal před 8 roky
rodič
revize
330d390ec3
2 změnil soubory, kde provedl 92 přidání a 156 odebrání
  1. 90 87
      gls/gls.go
  2. 2 69
      gls/program.go

+ 90 - 87
gls/gls.go

@@ -1,3 +1,6 @@
+// Copyright 2016 The G3N Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
 package gls
 
 // // Platform build flags
@@ -22,10 +25,12 @@ import (
 	"unsafe"
 )
 
+// GLS encapsulates the state of an OpenGL context which should be
+// associated with a single Window.
 type GLS struct {
 	stats               Stats             // statistics
-	Prog                *Program          // Current active program
-	programs            map[*Program]bool // Programs cache
+	Prog                *Program          // current active program
+	programs            map[*Program]bool // programs cache
 	checkErrors         bool              // check openGL API errors flag
 	viewportX           int32             // cached last set viewport x
 	viewportY           int32             // cached last set viewport y
@@ -36,28 +41,29 @@ type GLS struct {
 	depthFunc           uint32            // cached last set depth function
 	depthMask           int               // cached last set depth mask
 	capabilities        map[int]int       // cached capabilities (Enable/Disable)
-	blendEquation       uint32
-	blendSrc            uint32
-	blendDst            uint32
-	blendEquationRGB    uint32
-	blendEquationAlpha  uint32
-	blendSrcRGB         uint32
-	blendSrcAlpha       uint32
-	blendDstRGB         uint32
-	blendDstAlpha       uint32
-	polygonOffsetFactor float32
-	polygonOffsetUnits  float32
-	logBuf              []byte // pre allocated buffer for program/shader logs
-}
-
+	blendEquation       uint32            // cached last set blend equation value
+	blendSrc            uint32            // cached last set blend src value
+	blendDst            uint32            // cached last set blend equation destination value
+	blendEquationRGB    uint32            // cached last set blend equation rgb value
+	blendEquationAlpha  uint32            // cached last set blend equation alpha value
+	blendSrcRGB         uint32            // cached last set blend src rgb
+	blendSrcAlpha       uint32            // cached last set blend src alpha value
+	blendDstRGB         uint32            // cached last set blend destination rgb value
+	blendDstAlpha       uint32            // cached last set blend destination alpha value
+	polygonOffsetFactor float32           // cached last set polygon offset factor
+	polygonOffsetUnits  float32           // cached last set polygon offset units
+	cbuf                []byte            // pre allocated buffer to convert Go strings to C strings
+}
+
+// Stats contains several counter
 type Stats struct {
 	Vaos     int // Number of Vertex Array Objects
 	Vbos     int // Number of Vertex Buffer Objects
 	Textures int // Number of Textures
 	// Cummulative fields
-	Caphits   int // Number of hits for Enable/Disable
-	Unisets   int // Number of uniform sets
-	Drawcalls int // Number of draw calls
+	Caphits   uint64 // Number of hits for Enable/Disable
+	Unisets   uint64 // Number of uniform sets
+	Drawcalls uint64 // Number of draw calls
 }
 
 const (
@@ -67,7 +73,6 @@ const (
 	uintUndef   = math.MaxUint32
 	intFalse    = 0
 	intTrue     = 1
-	maxLogBuf   = 32 * 1024
 )
 
 // Polygon side view.
@@ -84,16 +89,16 @@ const (
 func New() (*GLS, error) {
 
 	gs := new(GLS)
-	gs.Reset()
-
-	// Initialize GL
+	gs.reset()
+	// Load OpenGL functions
 	err := C.glapiLoad()
 	if err != 0 {
 		return nil, fmt.Errorf("Error loading OpenGL")
 	}
 	gs.SetDefaultState()
 	gs.checkErrors = true
-	gs.logBuf = make([]byte, maxLogBuf)
+	// Preallocates buffer for C string with initial size
+	gs.cbuf = make([]byte, 1*1024)
 	return gs, nil
 }
 
@@ -116,8 +121,8 @@ func (gs *GLS) CheckErrors() bool {
 	return gs.checkErrors
 }
 
-// Reset resets the internal state kept of the OpenGL
-func (gs *GLS) Reset() {
+// reset resets the internal state kept of the OpenGL
+func (gs *GLS) reset() {
 
 	gs.lineWidth = 0.0
 	gs.sideView = uintUndef
@@ -161,6 +166,13 @@ func (gs *GLS) SetDefaultState() {
 	gs.Enable(POLYGON_OFFSET_POINT)
 }
 
+// Stats copy the current values of the internal statistics structure
+// to the specified pointer.
+func (gs *GLS) Stats(s *Stats) {
+
+	*s = gs.stats
+}
+
 func (gs *GLS) ActiveTexture(texture uint32) {
 
 	C.glActiveTexture(C.GLenum(texture))
@@ -319,7 +331,7 @@ func (gs *GLS) DrawArrays(mode uint32, first int32, count int32) {
 
 func (gs *GLS) DrawElements(mode uint32, count int32, itype uint32, start uint32) {
 
-	C.glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(itype), ptrOffset(int(start)))
+	C.glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(itype), unsafe.Pointer(uintptr(start)))
 	gs.stats.Drawcalls++
 }
 
@@ -389,10 +401,8 @@ func (gs *GLS) GenVertexArray() uint32 {
 
 func (gs *GLS) GetAttribLocation(program uint32, name string) int32 {
 
-	cname := C.CString(name)
-	defer C.free(unsafe.Pointer(cname))
-	res := C.glGetAttribLocation(C.GLuint(program), (*C.GLchar)(cname))
-	return int32(res)
+	loc := C.glGetAttribLocation(C.GLuint(program), gs.cbufStr(name))
+	return int32(loc)
 }
 
 func (gs *GLS) GetProgramiv(program, pname uint32, params *int32) {
@@ -400,42 +410,40 @@ func (gs *GLS) GetProgramiv(program, pname uint32, params *int32) {
 	C.glGetProgramiv(C.GLuint(program), C.GLenum(pname), (*C.GLint)(params))
 }
 
+// GetProgramInfoLog returns the information log for the specified program object.
 func (gs *GLS) GetProgramInfoLog(program uint32) string {
 
-	// Get length of program info log buffer
-	var logLength int32
-	gs.GetProgramiv(program, INFO_LOG_LENGTH, &logLength)
-	if logLength == 0 {
+	var length int32
+	gs.GetProgramiv(program, INFO_LOG_LENGTH, &length)
+	if length == 0 {
 		return ""
 	}
-	C.glGetProgramInfoLog(C.GLuint(program), maxLogBuf, nil, (*C.GLchar)(unsafe.Pointer(&gs.logBuf[0])))
-	return string(gs.logBuf)
+	C.glGetProgramInfoLog(C.GLuint(program), C.GLsizei(length), nil, gs.cbufSize(uint32(length)))
+	return string(gs.cbuf[:length])
 }
 
+// GetShaderInfoLog returns the information log for the specified shader object.
 func (gs *GLS) GetShaderInfoLog(shader uint32) string {
 
-	// Get length of shaderinfo log buffer
-	var logLength int32
-	gs.GetShaderiv(shader, INFO_LOG_LENGTH, &logLength)
-	if logLength == 0 {
+	var length int32
+	gs.GetShaderiv(shader, INFO_LOG_LENGTH, &length)
+	if length == 0 {
 		return ""
 	}
-	buf := make([]byte, logLength)
-	C.glGetShaderInfoLog(C.GLuint(shader), C.GLsizei(logLength), nil, (*C.GLchar)(unsafe.Pointer(&gs.logBuf[0])))
-	return string(buf)
+	C.glGetShaderInfoLog(C.GLuint(shader), C.GLsizei(length), nil, gs.cbufSize(uint32(length)))
+	return string(gs.cbuf[:length])
 }
 
 func (gs *GLS) GetString(name uint32) string {
 
-	cstr := C.glGetString(C.GLenum(name))
-	return goStr((*uint8)(cstr))
+	cbufStr := C.glGetString(C.GLenum(name))
+	return C.GoString((*C.char)(unsafe.Pointer(cbufStr)))
 }
 
+// GetUniformLocation returns the location of a uniform variable for the specified program.
 func (gs *GLS) GetUniformLocation(program uint32, name string) int32 {
 
-	cname := C.CString(name)
-	defer C.free(unsafe.Pointer(cname))
-	loc := C.glGetUniformLocation(C.GLuint(program), (*C.GLchar)(cname))
+	loc := C.glGetUniformLocation(C.GLuint(program), gs.cbufStr(name))
 	return int32(loc)
 }
 
@@ -497,9 +505,8 @@ func (gs *GLS) GetShaderiv(shader, pname uint32, params *int32) {
 
 func (gs *GLS) ShaderSource(shader uint32, src string) {
 
-	csource := C.CString(src)
-	defer C.free(unsafe.Pointer(csource))
-	C.glShaderSource(C.GLuint(shader), 1, (**C.GLchar)(unsafe.Pointer(csource)), nil)
+	csource := gs.cbufStr(src)
+	C.glShaderSource(C.GLuint(shader), 1, (**C.GLchar)(unsafe.Pointer(&csource)), nil)
 }
 
 func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, border int32, format uint32, itype uint32, data interface{}) {
@@ -608,7 +615,7 @@ func (gs *GLS) Uniform4fv(location int32, count int32, v []float32) {
 
 func (gs *GLS) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset uint32) {
 
-	C.glVertexAttribPointer(C.GLuint(index), C.GLint(size), C.GLenum(xtype), bool2c(normalized), C.GLsizei(stride), ptrOffset(int(offset)))
+	C.glVertexAttribPointer(C.GLuint(index), C.GLint(size), C.GLenum(xtype), bool2c(normalized), C.GLsizei(stride), unsafe.Pointer(uintptr(offset)))
 }
 
 func (gs *GLS) Viewport(x, y, width, height int32) {
@@ -621,20 +628,20 @@ func (gs *GLS) Viewport(x, y, width, height int32) {
 }
 
 // Use set this program as the current program.
-//func (gs *GLS) UseProgram(prog *Program) {
-//
-//	if prog.handle == 0 {
-//		panic("Invalid program")
-//	}
-//	C.glUseProgram(prog.handle)
-//	gs.Prog = prog
-//
-//	// Inserts program in cache if not already there.
-//	if !gs.programs[prog] {
-//		gs.programs[prog] = true
-//		log.Debug("New Program activated. Total: %d", len(gs.programs))
-//	}
-//}
+func (gs *GLS) UseProgram(prog *Program) {
+
+	if prog.handle == 0 {
+		panic("Invalid program")
+	}
+	C.glUseProgram(C.GLuint(prog.handle))
+	gs.Prog = prog
+
+	// Inserts program in cache if not already there.
+	if !gs.programs[prog] {
+		gs.programs[prog] = true
+		log.Debug("New Program activated. Total: %d", len(gs.programs))
+	}
+}
 
 // Ptr takes a slice or pointer (to a singular scalar value or the first
 // element of an array or slice) and returns its GL-compatible address.
@@ -681,28 +688,24 @@ func bool2c(b bool) C.GLboolean {
 	return C.GLboolean(0)
 }
 
-// ptrOffset takes a pointer offset and returns a GL-compatible pointer.
-// Useful for functions such as glVertexAttribPointer that take pointer
-// parameters indicating an offset rather than an absolute memory address.
-func ptrOffset(offset int) unsafe.Pointer {
+// cbufStr converts a Go String to a C string copying it to a single pre-allocated buffer
+// and returning a pointer to the start of the buffer
+func (gs *GLS) cbufStr(s string) *C.GLchar {
 
-	return unsafe.Pointer(uintptr(offset))
+	if len(s)+1 > len(gs.cbuf) {
+		gs.cbuf = make([]byte, len(s)+1)
+	}
+	copy(gs.cbuf, s)
+	gs.cbuf[len(s)] = 0
+	return (*C.GLchar)(unsafe.Pointer(&gs.cbuf[0]))
 }
 
-//// Str takes a null-terminated Go string and returns its GL-compatible address.
-//// This function reaches into Go string storage in an unsafe way so the caller
-//// must ensure the string is not garbage collected.
-//func Str(str string) *uint8 {
-//	if !strings.HasSuffix(str, "\x00") {
-//		panic("str argument missing null terminator: " + str)
-//	}
-//	header := (*reflect.StringHeader)(unsafe.Pointer(&str))
-//	return (*uint8)(unsafe.Pointer(header.Data))
-//}
+// cbufSize returns a pointer to C buffer with the specified size not including the terminator.
+// Currently the function uses a single pre-allocated area to avoid Go allocations
+func (gs *GLS) cbufSize(size uint32) *C.GLchar {
 
-// goStr takes a null-terminated string returned by OpenGL and constructs a
-// corresponding Go string.
-func goStr(cstr *uint8) string {
-
-	return C.GoString((*C.char)(unsafe.Pointer(cstr)))
+	if size+1 > uint32(len(gs.cbuf)) {
+		gs.cbuf = make([]byte, size+1)
+	}
+	return (*C.GLchar)(unsafe.Pointer(&gs.cbuf[0]))
 }

+ 2 - 69
gls/program.go

@@ -34,8 +34,8 @@ type shaderInfo struct {
 
 // Map shader types to names
 var shaderNames = map[uint32]string{
-//gl.VERTEX_SHADER:   "Vertex Shader",
-//gl.FRAGMENT_SHADER: "Fragment Shader",
+	VERTEX_SHADER:   "Vertex Shader",
+	FRAGMENT_SHADER: "Fragment Shader",
 }
 
 // NewProgram creates a new empty shader program object.
@@ -145,36 +145,6 @@ func (prog *Program) Handle() uint32 {
 	return prog.handle
 }
 
-//// GetActiveUniformBlockSize returns the minimum number of bytes
-//// to contain the data for the uniform block specified by its index.
-//func (prog *Program) GetActiveUniformBlockSize(ubindex uint32) int32 {
-//
-//	var uboSize int32
-//	gl.GetActiveUniformBlockiv(prog.handle, ubindex, gl.UNIFORM_BLOCK_DATA_SIZE, &uboSize)
-//	if prog.gs.CheckErrors() {
-//		ecode := gl.GetError()
-//		if ecode != 0 {
-//			log.Fatal("GetUniformBlockSize(%v) error: %d", ubindex, ecode)
-//		}
-//	}
-//	return uboSize
-//}
-
-//// GetActiveUniformsiv returns information about the specified uniforms
-//// specified by its indices
-//func (prog *Program) GetActiveUniformsiv(indices []uint32, pname uint32) []int32 {
-//
-//	data := make([]int32, len(indices))
-//	gl.GetActiveUniformsiv(prog.handle, int32(len(indices)), &indices[0], pname, &data[0])
-//	if prog.gs.CheckErrors() {
-//		ecode := gl.GetError()
-//		if ecode != 0 {
-//			log.Fatal("GetActiveUniformsiv() error: %d", ecode)
-//		}
-//	}
-//	return data
-//}
-
 // GetAttributeLocation returns the location of the specified attribute
 // in this program. This location is internally cached.
 func (prog *Program) GetAttribLocation(name string) int32 {
@@ -182,43 +152,6 @@ func (prog *Program) GetAttribLocation(name string) int32 {
 	return prog.gs.GetAttribLocation(prog.handle, name)
 }
 
-//// GetUniformBlockIndex returns the index of the named uniform block.
-//// If the supplied name is not valid, the function returns gl.INVALID_INDEX
-//func (prog *Program) GetUniformBlockIndex(name string) uint32 {
-//
-//	index := gl.GetUniformBlockIndex(prog.handle, gl.Str(name+"\x00"))
-//	if prog.gs.CheckErrors() {
-//		ecode := gl.GetError()
-//		if ecode != 0 {
-//			log.Fatal("GetUniformBlockIndex(%s) error", name)
-//		}
-//	}
-//	return index
-//}
-
-//// GetUniformIndices returns the indices for each specified named
-//// uniform. If an specified name is not valid the corresponding
-//// index value will be gl.INVALID_INDEX
-//func (prog *Program) GetUniformIndices(names []string) []uint32 {
-//
-//	// Add C terminators to uniform names
-//	for _, s := range names {
-//		s += "\x00"
-//	}
-//	unames, freefunc := gl.Strs(names...)
-//
-//	indices := make([]uint32, len(names))
-//	gl.GetUniformIndices(prog.handle, int32(len(names)), unames, &indices[0])
-//	if prog.gs.CheckErrors() {
-//		ecode := gl.GetError()
-//		if ecode != 0 {
-//			log.Fatal("GetUniformIndices() error: %d", ecode)
-//		}
-//	}
-//	freefunc()
-//	return indices
-//}
-
 // GetUniformLocation returns the location of the specified uniform in this program.
 // This location is internally cached.
 func (prog *Program) GetUniformLocation(name string) int32 {