gls.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gls
  5. // // Platform build flags
  6. // #cgo freebsd CFLAGS: -DGL_GLEXT_PROTOTYPES
  7. // #cgo freebsd LDFLAGS: -ldl -lGL
  8. //
  9. // #cgo linux CFLAGS: -DGL_GLEXT_PROTOTYPES
  10. // #cgo linux LDFLAGS: -ldl -lGL
  11. //
  12. // #cgo windows CFLAGS: -DGL_GEXT_PROTOTYPES
  13. // #cgo windows LDFLAGS: -lopengl32
  14. //
  15. // #include <stdlib.h>
  16. // #include "glcorearb.h"
  17. // #include "glapi.h"
  18. import "C"
  19. import (
  20. "fmt"
  21. "math"
  22. "reflect"
  23. "unsafe"
  24. )
  25. // GLS encapsulates the state of an OpenGL context which should be
  26. // associated with a single Window.
  27. type GLS struct {
  28. stats Stats // statistics
  29. Prog *Program // current active program
  30. programs map[*Program]bool // programs cache
  31. checkErrors bool // check openGL API errors flag
  32. viewportX int32 // cached last set viewport x
  33. viewportY int32 // cached last set viewport y
  34. viewportWidth int32 // cached last set viewport width
  35. viewportHeight int32 // cached last set viewport height
  36. lineWidth float32 // cached last set line width
  37. sideView int // cached last set triangle side view mode
  38. depthFunc uint32 // cached last set depth function
  39. depthMask int // cached last set depth mask
  40. capabilities map[int]int // cached capabilities (Enable/Disable)
  41. blendEquation uint32 // cached last set blend equation value
  42. blendSrc uint32 // cached last set blend src value
  43. blendDst uint32 // cached last set blend equation destination value
  44. blendEquationRGB uint32 // cached last set blend equation rgb value
  45. blendEquationAlpha uint32 // cached last set blend equation alpha value
  46. blendSrcRGB uint32 // cached last set blend src rgb
  47. blendSrcAlpha uint32 // cached last set blend src alpha value
  48. blendDstRGB uint32 // cached last set blend destination rgb value
  49. blendDstAlpha uint32 // cached last set blend destination alpha value
  50. polygonOffsetFactor float32 // cached last set polygon offset factor
  51. polygonOffsetUnits float32 // cached last set polygon offset units
  52. gobuf []byte // pre allocated buffer to convert Go strings to C strings
  53. }
  54. // Stats contains several counter
  55. type Stats struct {
  56. Vaos int // Number of Vertex Array Objects
  57. Vbos int // Number of Vertex Buffer Objects
  58. Textures int // Number of Textures
  59. Caphits uint64 // Cummulative number of hits for Enable/Disable
  60. Unisets uint64 // Cummulative number of uniform sets
  61. Drawcalls uint64 // Cummulative number of draw calls
  62. }
  63. // Polygon side view.
  64. const (
  65. FrontSide = iota + 1
  66. BackSide
  67. DoubleSide
  68. )
  69. const (
  70. capUndef = 0
  71. capDisabled = 1
  72. capEnabled = 2
  73. uintUndef = math.MaxUint32
  74. intFalse = 0
  75. intTrue = 1
  76. )
  77. // New creates and returns a new instance of an GLS object
  78. // which encapsulates the state of an OpenGL context
  79. // This should be called only after an active OpenGL context
  80. // was established, such as by creating a new window.
  81. func New() (*GLS, error) {
  82. gs := new(GLS)
  83. gs.reset()
  84. // Load OpenGL functions
  85. err := C.glapiLoad()
  86. if err != 0 {
  87. return nil, fmt.Errorf("Error loading OpenGL")
  88. }
  89. gs.SetDefaultState()
  90. gs.checkErrors = true
  91. // Preallocates buffer for C string with initial size
  92. gs.gobuf = make([]byte, 1*1024)
  93. return gs, nil
  94. }
  95. // SetCheckErrors enables/disables checking for errors after the
  96. // call of any OpenGL function. It is enabled by default but
  97. // could be disabled after an application is stable to improve the performance.
  98. func (gs *GLS) SetCheckErrors(enable bool) {
  99. if enable {
  100. C.glapiCheckError(1)
  101. } else {
  102. C.glapiCheckError(1)
  103. }
  104. gs.checkErrors = enable
  105. }
  106. // ChecksErrors returns if error checking is enabled or not.
  107. func (gs *GLS) CheckErrors() bool {
  108. return gs.checkErrors
  109. }
  110. // reset resets the internal state kept of the OpenGL
  111. func (gs *GLS) reset() {
  112. gs.lineWidth = 0.0
  113. gs.sideView = uintUndef
  114. gs.depthFunc = 0
  115. gs.depthMask = uintUndef
  116. gs.capabilities = make(map[int]int)
  117. gs.programs = make(map[*Program]bool)
  118. gs.Prog = nil
  119. gs.blendEquation = uintUndef
  120. gs.blendSrc = uintUndef
  121. gs.blendDst = uintUndef
  122. gs.blendEquationRGB = 0
  123. gs.blendEquationAlpha = 0
  124. gs.blendSrcRGB = uintUndef
  125. gs.blendSrcAlpha = uintUndef
  126. gs.blendDstRGB = uintUndef
  127. gs.blendDstAlpha = uintUndef
  128. gs.polygonOffsetFactor = -1
  129. gs.polygonOffsetUnits = -1
  130. }
  131. func (gs *GLS) SetDefaultState() {
  132. C.glClearColor(0, 0, 0, 1)
  133. C.glClearDepth(1)
  134. C.glClearStencil(0)
  135. gs.Enable(DEPTH_TEST)
  136. gs.DepthFunc(LEQUAL)
  137. gs.FrontFace(CCW)
  138. gs.CullFace(BACK)
  139. gs.Enable(CULL_FACE)
  140. gs.Enable(BLEND)
  141. gs.BlendEquation(FUNC_ADD)
  142. gs.BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
  143. gs.Enable(VERTEX_PROGRAM_POINT_SIZE)
  144. gs.Enable(PROGRAM_POINT_SIZE)
  145. gs.Enable(MULTISAMPLE)
  146. gs.Enable(POLYGON_OFFSET_FILL)
  147. gs.Enable(POLYGON_OFFSET_LINE)
  148. gs.Enable(POLYGON_OFFSET_POINT)
  149. }
  150. // Stats copy the current values of the internal statistics structure
  151. // to the specified pointer.
  152. func (gs *GLS) Stats(s *Stats) {
  153. *s = gs.stats
  154. }
  155. func (gs *GLS) ActiveTexture(texture uint32) {
  156. C.glActiveTexture(C.GLenum(texture))
  157. }
  158. func (gs *GLS) AttachShader(program, shader uint32) {
  159. C.glAttachShader(C.GLuint(program), C.GLuint(shader))
  160. }
  161. func (gs *GLS) BindBuffer(target int, vbo uint32) {
  162. C.glBindBuffer(C.GLenum(target), C.GLuint(vbo))
  163. }
  164. func (gs *GLS) BindTexture(target int, tex uint32) {
  165. C.glBindTexture(C.GLenum(target), C.GLuint(tex))
  166. }
  167. func (gs *GLS) BindVertexArray(vao uint32) {
  168. C.glBindVertexArray(C.GLuint(vao))
  169. }
  170. func (gs *GLS) BlendEquation(mode uint32) {
  171. if gs.blendEquation == mode {
  172. return
  173. }
  174. C.glBlendEquation(C.GLenum(mode))
  175. gs.blendEquation = mode
  176. }
  177. func (gs *GLS) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
  178. if gs.blendEquationRGB == modeRGB && gs.blendEquationAlpha == modeAlpha {
  179. return
  180. }
  181. C.glBlendEquationSeparate(C.GLenum(modeRGB), C.GLenum(modeAlpha))
  182. gs.blendEquationRGB = modeRGB
  183. gs.blendEquationAlpha = modeAlpha
  184. }
  185. func (gs *GLS) BlendFunc(sfactor, dfactor uint32) {
  186. if gs.blendSrc == sfactor && gs.blendDst == dfactor {
  187. return
  188. }
  189. C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
  190. gs.blendSrc = sfactor
  191. gs.blendDst = dfactor
  192. }
  193. func (gs *GLS) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
  194. if gs.blendSrcRGB == srcRGB && gs.blendDstRGB == dstRGB &&
  195. gs.blendSrcAlpha == srcAlpha && gs.blendDstAlpha == dstAlpha {
  196. return
  197. }
  198. C.glBlendFuncSeparate(C.GLenum(srcRGB), C.GLenum(dstRGB), C.GLenum(srcAlpha), C.GLenum(dstAlpha))
  199. gs.blendSrcRGB = srcRGB
  200. gs.blendDstRGB = dstRGB
  201. gs.blendSrcAlpha = srcAlpha
  202. gs.blendDstAlpha = dstAlpha
  203. }
  204. func (gs *GLS) BufferData(target uint32, size int, data interface{}, usage uint32) {
  205. C.glBufferData(C.GLenum(target), C.GLsizeiptr(size), ptr(data), C.GLenum(usage))
  206. }
  207. func (gs *GLS) ClearColor(r, g, b, a float32) {
  208. C.glClearColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a))
  209. }
  210. func (gs *GLS) Clear(mask uint) {
  211. C.glClear(C.GLbitfield(mask))
  212. }
  213. func (gs *GLS) CompileShader(shader uint32) {
  214. C.glCompileShader(C.GLuint(shader))
  215. }
  216. func (gs *GLS) CreateProgram() uint32 {
  217. p := C.glCreateProgram()
  218. return uint32(p)
  219. }
  220. func (gs *GLS) CreateShader(stype uint32) uint32 {
  221. h := C.glCreateShader(C.GLenum(stype))
  222. return uint32(h)
  223. }
  224. func (gs *GLS) DeleteBuffers(vbos ...uint32) {
  225. C.glDeleteBuffers(C.GLsizei(len(vbos)), (*C.GLuint)(&vbos[0]))
  226. }
  227. func (gs *GLS) DeleteShader(shader uint32) {
  228. C.glDeleteShader(C.GLuint(shader))
  229. }
  230. func (gs *GLS) DeleteProgram(program uint32) {
  231. C.glDeleteProgram(C.GLuint(program))
  232. }
  233. func (gs *GLS) DeleteTextures(tex ...uint32) {
  234. C.glDeleteTextures(C.GLsizei(len(tex)), (*C.GLuint)(&tex[0]))
  235. gs.stats.Textures -= len(tex)
  236. }
  237. func (gs *GLS) DeleteVertexArrays(vaos ...uint32) {
  238. C.glDeleteVertexArrays(C.GLsizei(len(vaos)), (*C.GLuint)(&vaos[0]))
  239. }
  240. func (gs *GLS) DepthFunc(mode uint32) {
  241. if gs.depthFunc == mode {
  242. return
  243. }
  244. C.glDepthFunc(C.GLenum(mode))
  245. gs.depthFunc = mode
  246. }
  247. func (gs *GLS) DepthMask(flag bool) {
  248. if gs.depthMask == intTrue && flag {
  249. return
  250. }
  251. if gs.depthMask == intFalse && !flag {
  252. return
  253. }
  254. C.glDepthMask(bool2c(flag))
  255. if flag {
  256. gs.depthMask = intTrue
  257. } else {
  258. gs.depthMask = intFalse
  259. }
  260. }
  261. func (gs *GLS) DrawArrays(mode uint32, first int32, count int32) {
  262. C.glDrawArrays(C.GLenum(mode), C.GLint(first), C.GLsizei(count))
  263. gs.stats.Drawcalls++
  264. }
  265. func (gs *GLS) DrawElements(mode uint32, count int32, itype uint32, start uint32) {
  266. C.glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(itype), unsafe.Pointer(uintptr(start)))
  267. gs.stats.Drawcalls++
  268. }
  269. func (gs *GLS) Enable(cap int) {
  270. if gs.capabilities[cap] == capEnabled {
  271. gs.stats.Caphits++
  272. return
  273. }
  274. C.glEnable(C.GLenum(cap))
  275. gs.capabilities[cap] = capEnabled
  276. }
  277. func (gs *GLS) EnableVertexAttribArray(index uint32) {
  278. C.glEnableVertexAttribArray(C.GLuint(index))
  279. }
  280. func (gs *GLS) Disable(cap int) {
  281. if gs.capabilities[cap] == capDisabled {
  282. gs.stats.Caphits++
  283. return
  284. }
  285. C.glDisable(C.GLenum(cap))
  286. gs.capabilities[cap] = capDisabled
  287. }
  288. func (gs *GLS) CullFace(mode uint32) {
  289. C.glCullFace(C.GLenum(mode))
  290. }
  291. func (gs *GLS) FrontFace(mode uint32) {
  292. C.glFrontFace(C.GLenum(mode))
  293. }
  294. func (gs *GLS) GenBuffer() uint32 {
  295. var buf uint32
  296. C.glGenBuffers(1, (*C.GLuint)(&buf))
  297. gs.stats.Vbos++
  298. return buf
  299. }
  300. func (gs *GLS) GenerateMipmap(target uint32) {
  301. C.glGenerateMipmap(C.GLenum(target))
  302. }
  303. func (gs *GLS) GenTexture() uint32 {
  304. var tex uint32
  305. C.glGenTextures(1, (*C.GLuint)(&tex))
  306. gs.stats.Textures++
  307. return tex
  308. }
  309. func (gs *GLS) GenVertexArray() uint32 {
  310. var vao uint32
  311. C.glGenVertexArrays(1, (*C.GLuint)(&vao))
  312. gs.stats.Vaos++
  313. return vao
  314. }
  315. func (gs *GLS) GetAttribLocation(program uint32, name string) int32 {
  316. loc := C.glGetAttribLocation(C.GLuint(program), gs.gobufStr(name))
  317. return int32(loc)
  318. }
  319. func (gs *GLS) GetProgramiv(program, pname uint32, params *int32) {
  320. C.glGetProgramiv(C.GLuint(program), C.GLenum(pname), (*C.GLint)(params))
  321. }
  322. // GetProgramInfoLog returns the information log for the specified program object.
  323. func (gs *GLS) GetProgramInfoLog(program uint32) string {
  324. var length int32
  325. gs.GetProgramiv(program, INFO_LOG_LENGTH, &length)
  326. if length == 0 {
  327. return ""
  328. }
  329. C.glGetProgramInfoLog(C.GLuint(program), C.GLsizei(length), nil, gs.gobufSize(uint32(length)))
  330. return string(gs.gobuf[:length])
  331. }
  332. // GetShaderInfoLog returns the information log for the specified shader object.
  333. func (gs *GLS) GetShaderInfoLog(shader uint32) string {
  334. var length int32
  335. gs.GetShaderiv(shader, INFO_LOG_LENGTH, &length)
  336. if length == 0 {
  337. return ""
  338. }
  339. C.glGetShaderInfoLog(C.GLuint(shader), C.GLsizei(length), nil, gs.gobufSize(uint32(length)))
  340. return string(gs.gobuf[:length])
  341. }
  342. func (gs *GLS) GetString(name uint32) string {
  343. cs := C.glGetString(C.GLenum(name))
  344. return C.GoString((*C.char)(unsafe.Pointer(cs)))
  345. }
  346. // GetUniformLocation returns the location of a uniform variable for the specified program.
  347. func (gs *GLS) GetUniformLocation(program uint32, name string) int32 {
  348. loc := C.glGetUniformLocation(C.GLuint(program), gs.gobufStr(name))
  349. return int32(loc)
  350. }
  351. func (gs *GLS) GetViewport() (x, y, width, height int32) {
  352. return gs.viewportX, gs.viewportY, gs.viewportWidth, gs.viewportHeight
  353. }
  354. func (gs *GLS) LineWidth(width float32) {
  355. if gs.lineWidth == width {
  356. return
  357. }
  358. C.glLineWidth(C.GLfloat(width))
  359. gs.lineWidth = width
  360. }
  361. func (gs *GLS) LinkProgram(program uint32) {
  362. C.glLinkProgram(C.GLuint(program))
  363. }
  364. func (gs *GLS) SetDepthTest(enable bool) {
  365. if enable {
  366. gs.Enable(DEPTH_TEST)
  367. } else {
  368. gs.Disable(DEPTH_TEST)
  369. }
  370. }
  371. func (gs *GLS) SetSideView(mode int) {
  372. if gs.sideView == mode {
  373. return
  374. }
  375. switch mode {
  376. // Default: show only the front size
  377. case FrontSide:
  378. gs.Enable(CULL_FACE)
  379. C.glFrontFace(CCW)
  380. // Show only the back side
  381. case BackSide:
  382. gs.Enable(CULL_FACE)
  383. C.glFrontFace(CW)
  384. // Show both sides
  385. case DoubleSide:
  386. gs.Disable(CULL_FACE)
  387. default:
  388. panic("SetSideView() invalid mode")
  389. }
  390. gs.sideView = mode
  391. }
  392. func (gs *GLS) GetShaderiv(shader, pname uint32, params *int32) {
  393. C.glGetShaderiv(C.GLuint(shader), C.GLenum(pname), (*C.GLint)(params))
  394. }
  395. func (gs *GLS) ShaderSource(shader uint32, src string) {
  396. csource := C.CString(src)
  397. defer C.free(unsafe.Pointer(csource))
  398. C.glShaderSource(C.GLuint(shader), 1, (**C.GLchar)(unsafe.Pointer(&csource)), nil)
  399. }
  400. func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, border int32, format uint32, itype uint32, data interface{}) {
  401. C.glTexImage2D(C.GLenum(target),
  402. C.GLint(level),
  403. C.GLint(iformat),
  404. C.GLsizei(width),
  405. C.GLsizei(height),
  406. C.GLint(border),
  407. C.GLenum(format),
  408. C.GLenum(itype),
  409. ptr(data))
  410. }
  411. func (gs *GLS) TexStorage2D(target int, levels int, iformat int, width, height int) {
  412. C.glTexStorage2D(C.GLenum(target), C.GLsizei(levels), C.GLenum(iformat), C.GLsizei(width), C.GLsizei(height))
  413. }
  414. func (gs *GLS) TexParameteri(target uint32, pname uint32, param int32) {
  415. C.glTexParameteri(C.GLenum(target), C.GLenum(pname), C.GLint(param))
  416. }
  417. func (gs *GLS) PolygonMode(face, mode int) {
  418. C.glPolygonMode(C.GLenum(face), C.GLenum(mode))
  419. }
  420. func (gs *GLS) PolygonOffset(factor float32, units float32) {
  421. if gs.polygonOffsetFactor == factor && gs.polygonOffsetUnits == units {
  422. return
  423. }
  424. C.glPolygonOffset(C.GLfloat(factor), C.GLfloat(units))
  425. gs.polygonOffsetFactor = factor
  426. gs.polygonOffsetUnits = units
  427. }
  428. func (gs *GLS) Uniform1i(location int32, v0 int32) {
  429. C.glUniform1i(C.GLint(location), C.GLint(v0))
  430. gs.stats.Unisets++
  431. }
  432. func (gs *GLS) Uniform1f(location int32, v0 float32) {
  433. C.glUniform1f(C.GLint(location), C.GLfloat(v0))
  434. gs.stats.Unisets++
  435. }
  436. func (gs *GLS) Uniform2f(location int32, v0, v1 float32) {
  437. C.glUniform2f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1))
  438. gs.stats.Unisets++
  439. }
  440. func (gs *GLS) Uniform3f(location int32, v0, v1, v2 float32) {
  441. C.glUniform3f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2))
  442. gs.stats.Unisets++
  443. }
  444. func (gs *GLS) Uniform4f(location int32, v0, v1, v2, v3 float32) {
  445. C.glUniform4f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2), C.GLfloat(v3))
  446. gs.stats.Unisets++
  447. }
  448. func (gs *GLS) UniformMatrix3fv(location int32, count int32, transpose bool, pm *float32) {
  449. C.glUniformMatrix3fv(C.GLint(location), C.GLsizei(count), bool2c(transpose), (*C.GLfloat)(pm))
  450. gs.stats.Unisets++
  451. }
  452. func (gs *GLS) UniformMatrix4fv(location int32, count int32, transpose bool, pm *float32) {
  453. C.glUniformMatrix4fv(C.GLint(location), C.GLsizei(count), bool2c(transpose), (*C.GLfloat)(pm))
  454. gs.stats.Unisets++
  455. }
  456. func (gs *GLS) Uniform1fv(location int32, count int32, v []float32) {
  457. C.glUniform1fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  458. gs.stats.Unisets++
  459. }
  460. func (gs *GLS) Uniform2fv(location int32, count int32, v []float32) {
  461. C.glUniform2fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  462. gs.stats.Unisets++
  463. }
  464. func (gs *GLS) Uniform3fv(location int32, count int32, v []float32) {
  465. C.glUniform3fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  466. gs.stats.Unisets++
  467. }
  468. func (gs *GLS) Uniform4fv(location int32, count int32, v []float32) {
  469. C.glUniform4fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  470. gs.stats.Unisets++
  471. }
  472. func (gs *GLS) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset uint32) {
  473. C.glVertexAttribPointer(C.GLuint(index), C.GLint(size), C.GLenum(xtype), bool2c(normalized), C.GLsizei(stride), unsafe.Pointer(uintptr(offset)))
  474. }
  475. func (gs *GLS) Viewport(x, y, width, height int32) {
  476. C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
  477. gs.viewportX = x
  478. gs.viewportY = y
  479. gs.viewportWidth = width
  480. gs.viewportHeight = height
  481. }
  482. // Use set this program as the current program.
  483. func (gs *GLS) UseProgram(prog *Program) {
  484. if prog.handle == 0 {
  485. panic("Invalid program")
  486. }
  487. C.glUseProgram(C.GLuint(prog.handle))
  488. gs.Prog = prog
  489. // Inserts program in cache if not already there.
  490. if !gs.programs[prog] {
  491. gs.programs[prog] = true
  492. log.Debug("New Program activated. Total: %d", len(gs.programs))
  493. }
  494. }
  495. // Ptr takes a slice or pointer (to a singular scalar value or the first
  496. // element of an array or slice) and returns its GL-compatible address.
  497. //
  498. // For example:
  499. //
  500. // var data []uint8
  501. // ...
  502. // gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
  503. func ptr(data interface{}) unsafe.Pointer {
  504. if data == nil {
  505. return unsafe.Pointer(nil)
  506. }
  507. var addr unsafe.Pointer
  508. v := reflect.ValueOf(data)
  509. switch v.Type().Kind() {
  510. case reflect.Ptr:
  511. e := v.Elem()
  512. switch e.Kind() {
  513. case
  514. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  515. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  516. reflect.Float32, reflect.Float64:
  517. addr = unsafe.Pointer(e.UnsafeAddr())
  518. default:
  519. panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
  520. }
  521. case reflect.Uintptr:
  522. addr = unsafe.Pointer(v.Pointer())
  523. case reflect.Slice:
  524. addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
  525. default:
  526. panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
  527. }
  528. return addr
  529. }
  530. // bool2c convert a Go bool to C.GLboolean
  531. func bool2c(b bool) C.GLboolean {
  532. if b {
  533. return C.GLboolean(1)
  534. }
  535. return C.GLboolean(0)
  536. }
  537. // gobufStr converts a Go String to a C string copying it to a single pre-allocated buffer
  538. // and returning a pointer to the start of the buffer
  539. func (gs *GLS) gobufStr(s string) *C.GLchar {
  540. if len(s)+1 > len(gs.gobuf) {
  541. gs.gobuf = make([]byte, len(s)+1)
  542. }
  543. copy(gs.gobuf, s)
  544. gs.gobuf[len(s)] = 0
  545. return (*C.GLchar)(unsafe.Pointer(&gs.gobuf[0]))
  546. }
  547. // gobufSize returns a pointer to C buffer with the specified size not including the terminator.
  548. // Currently the function uses a single pre-allocated area to avoid Go allocations
  549. func (gs *GLS) gobufSize(size uint32) *C.GLchar {
  550. if size+1 > uint32(len(gs.gobuf)) {
  551. gs.gobuf = make([]byte, size+1)
  552. }
  553. return (*C.GLchar)(unsafe.Pointer(&gs.gobuf[0]))
  554. }