gls.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  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. // #include <stdlib.h>
  6. // #include "glcorearb.h"
  7. // #include "glapi.h"
  8. import "C"
  9. import (
  10. "fmt"
  11. "math"
  12. "reflect"
  13. "unsafe"
  14. )
  15. // GLS encapsulates the state of an OpenGL context and contains
  16. // methods to call OpenGL functions.
  17. type GLS struct {
  18. stats Stats // statistics
  19. prog *Program // current active shader program
  20. programs map[*Program]bool // shader programs cache
  21. checkErrors bool // check openGL API errors flag
  22. activeTexture uint32 // cached last set active texture unit
  23. viewportX int32 // cached last set viewport x
  24. viewportY int32 // cached last set viewport y
  25. viewportWidth int32 // cached last set viewport width
  26. viewportHeight int32 // cached last set viewport height
  27. lineWidth float32 // cached last set line width
  28. sideView int // cached last set triangle side view mode
  29. frontFace uint32 // cached last set glFrontFace value
  30. depthFunc uint32 // cached last set depth function
  31. depthMask int // cached last set depth mask
  32. capabilities map[int]int // cached capabilities (Enable/Disable)
  33. blendEquation uint32 // cached last set blend equation value
  34. blendSrc uint32 // cached last set blend src value
  35. blendDst uint32 // cached last set blend equation destination value
  36. blendEquationRGB uint32 // cached last set blend equation rgb value
  37. blendEquationAlpha uint32 // cached last set blend equation alpha value
  38. blendSrcRGB uint32 // cached last set blend src rgb
  39. blendSrcAlpha uint32 // cached last set blend src alpha value
  40. blendDstRGB uint32 // cached last set blend destination rgb value
  41. blendDstAlpha uint32 // cached last set blend destination alpha value
  42. polygonModeFace uint32 // cached last set polygon mode face
  43. polygonModeMode uint32 // cached last set polygon mode mode
  44. polygonOffsetFactor float32 // cached last set polygon offset factor
  45. polygonOffsetUnits float32 // cached last set polygon offset units
  46. gobuf []byte // conversion buffer with GO memory
  47. cbuf []byte // conversion buffer with C memory
  48. }
  49. // Stats contains counters of OpenGL resources being used as well
  50. // the cumulative numbers of some OpenGL calls for performance evaluation.
  51. type Stats struct {
  52. Shaders int // Current number of shader programs
  53. Vaos int // Number of Vertex Array Objects
  54. Buffers int // Number of Buffer Objects
  55. Textures int // Number of Textures
  56. Caphits uint64 // Cumulative number of hits for Enable/Disable
  57. UnilocHits uint64 // Cumulative number of uniform location cache hits
  58. UnilocMiss uint64 // Cumulative number of uniform location cache misses
  59. Unisets uint64 // Cumulative number of uniform sets
  60. Drawcalls uint64 // Cumulative number of draw calls
  61. }
  62. // Polygon side view.
  63. const (
  64. FrontSide = iota + 1
  65. BackSide
  66. DoubleSide
  67. )
  68. const (
  69. capUndef = 0
  70. capDisabled = 1
  71. capEnabled = 2
  72. uintUndef = math.MaxUint32
  73. intFalse = 0
  74. intTrue = 1
  75. )
  76. // New creates and returns a new instance of a GLS object,
  77. // which encapsulates the state of an OpenGL context.
  78. // This should be called only after an active OpenGL context
  79. // is established, such as by creating a new window.
  80. func New() (*GLS, error) {
  81. gs := new(GLS)
  82. gs.reset()
  83. // Load OpenGL functions
  84. err := C.glapiLoad()
  85. if err != 0 {
  86. return nil, fmt.Errorf("Error loading OpenGL")
  87. }
  88. gs.setDefaultState()
  89. gs.checkErrors = true
  90. // Preallocate conversion buffers
  91. size := 1 * 1024
  92. gs.gobuf = make([]byte, size)
  93. p := C.malloc(C.size_t(size))
  94. gs.cbuf = (*[1 << 30]byte)(unsafe.Pointer(p))[:size:size]
  95. return gs, nil
  96. }
  97. // SetCheckErrors enables/disables checking for errors after the
  98. // call of any OpenGL function. It is enabled by default but
  99. // could be disabled after an application is stable to improve the performance.
  100. func (gs *GLS) SetCheckErrors(enable bool) {
  101. if enable {
  102. C.glapiCheckError(1)
  103. } else {
  104. C.glapiCheckError(0)
  105. }
  106. gs.checkErrors = enable
  107. }
  108. // CheckErrors returns if error checking is enabled or not.
  109. func (gs *GLS) CheckErrors() bool {
  110. return gs.checkErrors
  111. }
  112. // reset resets the internal state kept of the OpenGL
  113. func (gs *GLS) reset() {
  114. gs.lineWidth = 0.0
  115. gs.sideView = uintUndef
  116. gs.frontFace = 0
  117. gs.depthFunc = 0
  118. gs.depthMask = uintUndef
  119. gs.capabilities = make(map[int]int)
  120. gs.programs = make(map[*Program]bool)
  121. gs.prog = nil
  122. gs.activeTexture = uintUndef
  123. gs.blendEquation = uintUndef
  124. gs.blendSrc = uintUndef
  125. gs.blendDst = uintUndef
  126. gs.blendEquationRGB = 0
  127. gs.blendEquationAlpha = 0
  128. gs.blendSrcRGB = uintUndef
  129. gs.blendSrcAlpha = uintUndef
  130. gs.blendDstRGB = uintUndef
  131. gs.blendDstAlpha = uintUndef
  132. gs.polygonModeFace = 0
  133. gs.polygonModeMode = 0
  134. gs.polygonOffsetFactor = -1
  135. gs.polygonOffsetUnits = -1
  136. }
  137. // setDefaultState is used internally to set the initial state of OpenGL
  138. // for this context.
  139. func (gs *GLS) setDefaultState() {
  140. C.glClearColor(0, 0, 0, 1)
  141. C.glClearDepth(1)
  142. C.glClearStencil(0)
  143. gs.Enable(DEPTH_TEST)
  144. gs.DepthFunc(LEQUAL)
  145. gs.FrontFace(CCW)
  146. gs.CullFace(BACK)
  147. gs.Enable(CULL_FACE)
  148. gs.Enable(BLEND)
  149. gs.BlendEquation(FUNC_ADD)
  150. gs.BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
  151. gs.Enable(VERTEX_PROGRAM_POINT_SIZE)
  152. gs.Enable(PROGRAM_POINT_SIZE)
  153. gs.Enable(MULTISAMPLE)
  154. gs.Enable(POLYGON_OFFSET_FILL)
  155. gs.Enable(POLYGON_OFFSET_LINE)
  156. gs.Enable(POLYGON_OFFSET_POINT)
  157. }
  158. // Stats copy the current values of the internal statistics structure
  159. // to the specified pointer.
  160. func (gs *GLS) Stats(s *Stats) {
  161. *s = gs.stats
  162. s.Shaders = len(gs.programs)
  163. }
  164. // ActiveTexture selects which texture unit subsequent texture state calls
  165. // will affect. The number of texture units an implementation supports is
  166. // implementation dependent, but must be at least 48 in GL 3.3.
  167. func (gs *GLS) ActiveTexture(texture uint32) {
  168. if gs.activeTexture == texture {
  169. return
  170. }
  171. C.glActiveTexture(C.GLenum(texture))
  172. gs.activeTexture = texture
  173. }
  174. // AttachShader attaches the specified shader object to the specified program object.
  175. func (gs *GLS) AttachShader(program, shader uint32) {
  176. C.glAttachShader(C.GLuint(program), C.GLuint(shader))
  177. }
  178. // BindBuffer binds a buffer object to the specified buffer binding point.
  179. func (gs *GLS) BindBuffer(target int, vbo uint32) {
  180. C.glBindBuffer(C.GLenum(target), C.GLuint(vbo))
  181. }
  182. // BindTexture lets you create or use a named texture.
  183. func (gs *GLS) BindTexture(target int, tex uint32) {
  184. C.glBindTexture(C.GLenum(target), C.GLuint(tex))
  185. }
  186. // BindVertexArray binds the vertex array object.
  187. func (gs *GLS) BindVertexArray(vao uint32) {
  188. C.glBindVertexArray(C.GLuint(vao))
  189. }
  190. // BlendEquation sets the blend equations for all draw buffers.
  191. func (gs *GLS) BlendEquation(mode uint32) {
  192. if gs.blendEquation == mode {
  193. return
  194. }
  195. C.glBlendEquation(C.GLenum(mode))
  196. gs.blendEquation = mode
  197. }
  198. // BlendEquationSeparate sets the blend equations for all draw buffers
  199. // allowing different equations for the RGB and alpha components.
  200. func (gs *GLS) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
  201. if gs.blendEquationRGB == modeRGB && gs.blendEquationAlpha == modeAlpha {
  202. return
  203. }
  204. C.glBlendEquationSeparate(C.GLenum(modeRGB), C.GLenum(modeAlpha))
  205. gs.blendEquationRGB = modeRGB
  206. gs.blendEquationAlpha = modeAlpha
  207. }
  208. // BlendFunc defines the operation of blending for
  209. // all draw buffers when blending is enabled.
  210. func (gs *GLS) BlendFunc(sfactor, dfactor uint32) {
  211. if gs.blendSrc == sfactor && gs.blendDst == dfactor {
  212. return
  213. }
  214. C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
  215. gs.blendSrc = sfactor
  216. gs.blendDst = dfactor
  217. }
  218. // BlendFuncSeparate defines the operation of blending for all draw buffers when blending
  219. // is enabled, allowing different operations for the RGB and alpha components.
  220. func (gs *GLS) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
  221. if gs.blendSrcRGB == srcRGB && gs.blendDstRGB == dstRGB &&
  222. gs.blendSrcAlpha == srcAlpha && gs.blendDstAlpha == dstAlpha {
  223. return
  224. }
  225. C.glBlendFuncSeparate(C.GLenum(srcRGB), C.GLenum(dstRGB), C.GLenum(srcAlpha), C.GLenum(dstAlpha))
  226. gs.blendSrcRGB = srcRGB
  227. gs.blendDstRGB = dstRGB
  228. gs.blendSrcAlpha = srcAlpha
  229. gs.blendDstAlpha = dstAlpha
  230. }
  231. // BufferData creates a new data store for the buffer object currently
  232. // bound to target, deleting any pre-existing data store.
  233. func (gs *GLS) BufferData(target uint32, size int, data interface{}, usage uint32) {
  234. C.glBufferData(C.GLenum(target), C.GLsizeiptr(size), ptr(data), C.GLenum(usage))
  235. }
  236. // ClearColor specifies the red, green, blue, and alpha values
  237. // used by glClear to clear the color buffers.
  238. func (gs *GLS) ClearColor(r, g, b, a float32) {
  239. C.glClearColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a))
  240. }
  241. // Clear sets the bitplane area of the window to values previously
  242. // selected by ClearColor, ClearDepth, and ClearStencil.
  243. func (gs *GLS) Clear(mask uint) {
  244. C.glClear(C.GLbitfield(mask))
  245. }
  246. // CompileShader compiles the source code strings that
  247. // have been stored in the specified shader object.
  248. func (gs *GLS) CompileShader(shader uint32) {
  249. C.glCompileShader(C.GLuint(shader))
  250. }
  251. // CreateProgram creates an empty program object and returns
  252. // a non-zero value by which it can be referenced.
  253. func (gs *GLS) CreateProgram() uint32 {
  254. p := C.glCreateProgram()
  255. return uint32(p)
  256. }
  257. // CreateShader creates an empty shader object and returns
  258. // a non-zero value by which it can be referenced.
  259. func (gs *GLS) CreateShader(stype uint32) uint32 {
  260. h := C.glCreateShader(C.GLenum(stype))
  261. return uint32(h)
  262. }
  263. // DeleteBuffers deletes n​buffer objects named
  264. // by the elements of the provided array.
  265. func (gs *GLS) DeleteBuffers(bufs ...uint32) {
  266. C.glDeleteBuffers(C.GLsizei(len(bufs)), (*C.GLuint)(&bufs[0]))
  267. gs.stats.Buffers -= len(bufs)
  268. }
  269. // DeleteShader frees the memory and invalidates the name
  270. // associated with the specified shader object.
  271. func (gs *GLS) DeleteShader(shader uint32) {
  272. C.glDeleteShader(C.GLuint(shader))
  273. }
  274. // DeleteProgram frees the memory and invalidates the name
  275. // associated with the specified program object.
  276. func (gs *GLS) DeleteProgram(program uint32) {
  277. C.glDeleteProgram(C.GLuint(program))
  278. }
  279. // DeleteTextures deletes n​textures named
  280. // by the elements of the provided array.
  281. func (gs *GLS) DeleteTextures(tex ...uint32) {
  282. C.glDeleteTextures(C.GLsizei(len(tex)), (*C.GLuint)(&tex[0]))
  283. gs.stats.Textures -= len(tex)
  284. }
  285. // DeleteVertexArrays deletes n​vertex array objects named
  286. // by the elements of the provided array.
  287. func (gs *GLS) DeleteVertexArrays(vaos ...uint32) {
  288. C.glDeleteVertexArrays(C.GLsizei(len(vaos)), (*C.GLuint)(&vaos[0]))
  289. gs.stats.Vaos -= len(vaos)
  290. }
  291. // DepthFunc specifies the function used to compare each incoming pixel
  292. // depth value with the depth value present in the depth buffer.
  293. func (gs *GLS) DepthFunc(mode uint32) {
  294. if gs.depthFunc == mode {
  295. return
  296. }
  297. C.glDepthFunc(C.GLenum(mode))
  298. gs.depthFunc = mode
  299. }
  300. // DepthMask enables or disables writing into the depth buffer.
  301. func (gs *GLS) DepthMask(flag bool) {
  302. if gs.depthMask == intTrue && flag {
  303. return
  304. }
  305. if gs.depthMask == intFalse && !flag {
  306. return
  307. }
  308. C.glDepthMask(bool2c(flag))
  309. if flag {
  310. gs.depthMask = intTrue
  311. } else {
  312. gs.depthMask = intFalse
  313. }
  314. }
  315. // DrawArrays renders primitives from array data.
  316. func (gs *GLS) DrawArrays(mode uint32, first int32, count int32) {
  317. C.glDrawArrays(C.GLenum(mode), C.GLint(first), C.GLsizei(count))
  318. gs.stats.Drawcalls++
  319. }
  320. // DrawBuffer specifies which color buffers are to be drawn into.
  321. func (gs *GLS) DrawBuffer(mode uint32) {
  322. C.glDrawBuffer(C.GLenum(mode))
  323. }
  324. // DrawElements renders primitives from array data.
  325. func (gs *GLS) DrawElements(mode uint32, count int32, itype uint32, start uint32) {
  326. C.glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(itype), unsafe.Pointer(uintptr(start)))
  327. gs.stats.Drawcalls++
  328. }
  329. // Enable enables the specified capability.
  330. func (gs *GLS) Enable(cap int) {
  331. if gs.capabilities[cap] == capEnabled {
  332. gs.stats.Caphits++
  333. return
  334. }
  335. C.glEnable(C.GLenum(cap))
  336. gs.capabilities[cap] = capEnabled
  337. }
  338. // Disable disables the specified capability.
  339. func (gs *GLS) Disable(cap int) {
  340. if gs.capabilities[cap] == capDisabled {
  341. gs.stats.Caphits++
  342. return
  343. }
  344. C.glDisable(C.GLenum(cap))
  345. gs.capabilities[cap] = capDisabled
  346. }
  347. // EnableVertexAttribArray enables a generic vertex attribute array.
  348. func (gs *GLS) EnableVertexAttribArray(index uint32) {
  349. C.glEnableVertexAttribArray(C.GLuint(index))
  350. }
  351. // CullFace specifies whether front- or back-facing facets can be culled.
  352. func (gs *GLS) CullFace(mode uint32) {
  353. C.glCullFace(C.GLenum(mode))
  354. }
  355. // FrontFace defines front- and back-facing polygons.
  356. func (gs *GLS) FrontFace(mode uint32) {
  357. if gs.frontFace == mode {
  358. return
  359. }
  360. C.glFrontFace(C.GLenum(mode))
  361. gs.frontFace = mode
  362. }
  363. // GenBuffer generates a​buffer object name.
  364. func (gs *GLS) GenBuffer() uint32 {
  365. var buf uint32
  366. C.glGenBuffers(1, (*C.GLuint)(&buf))
  367. gs.stats.Buffers++
  368. return buf
  369. }
  370. // GenerateMipmap generates mipmaps for the specified texture target.
  371. func (gs *GLS) GenerateMipmap(target uint32) {
  372. C.glGenerateMipmap(C.GLenum(target))
  373. }
  374. // GenTexture generates a texture object name.
  375. func (gs *GLS) GenTexture() uint32 {
  376. var tex uint32
  377. C.glGenTextures(1, (*C.GLuint)(&tex))
  378. gs.stats.Textures++
  379. return tex
  380. }
  381. // GenVertexArray generates a vertex array object name.
  382. func (gs *GLS) GenVertexArray() uint32 {
  383. var vao uint32
  384. C.glGenVertexArrays(1, (*C.GLuint)(&vao))
  385. gs.stats.Vaos++
  386. return vao
  387. }
  388. // GetAttribLocation returns the location of the specified attribute variable.
  389. func (gs *GLS) GetAttribLocation(program uint32, name string) int32 {
  390. loc := C.glGetAttribLocation(C.GLuint(program), gs.gobufStr(name))
  391. return int32(loc)
  392. }
  393. // GetProgramiv returns the specified parameter from the specified program object.
  394. func (gs *GLS) GetProgramiv(program, pname uint32, params *int32) {
  395. C.glGetProgramiv(C.GLuint(program), C.GLenum(pname), (*C.GLint)(params))
  396. }
  397. // GetProgramInfoLog returns the information log for the specified program object.
  398. func (gs *GLS) GetProgramInfoLog(program uint32) string {
  399. var length int32
  400. gs.GetProgramiv(program, INFO_LOG_LENGTH, &length)
  401. if length == 0 {
  402. return ""
  403. }
  404. C.glGetProgramInfoLog(C.GLuint(program), C.GLsizei(length), nil, gs.gobufSize(uint32(length)))
  405. return string(gs.gobuf[:length])
  406. }
  407. // GetShaderInfoLog returns the information log for the specified shader object.
  408. func (gs *GLS) GetShaderInfoLog(shader uint32) string {
  409. var length int32
  410. gs.GetShaderiv(shader, INFO_LOG_LENGTH, &length)
  411. if length == 0 {
  412. return ""
  413. }
  414. C.glGetShaderInfoLog(C.GLuint(shader), C.GLsizei(length), nil, gs.gobufSize(uint32(length)))
  415. return string(gs.gobuf[:length])
  416. }
  417. // GetString returns a string describing the specified aspect of the current GL connection.
  418. func (gs *GLS) GetString(name uint32) string {
  419. cs := C.glGetString(C.GLenum(name))
  420. return C.GoString((*C.char)(unsafe.Pointer(cs)))
  421. }
  422. // GetUniformLocation returns the location of a uniform variable for the specified program.
  423. func (gs *GLS) GetUniformLocation(program uint32, name string) int32 {
  424. loc := C.glGetUniformLocation(C.GLuint(program), gs.gobufStr(name))
  425. return int32(loc)
  426. }
  427. // GetViewport returns the current viewport information.
  428. func (gs *GLS) GetViewport() (x, y, width, height int32) {
  429. return gs.viewportX, gs.viewportY, gs.viewportWidth, gs.viewportHeight
  430. }
  431. // LineWidth specifies the rasterized width of both aliased and antialiased lines.
  432. func (gs *GLS) LineWidth(width float32) {
  433. if gs.lineWidth == width {
  434. return
  435. }
  436. C.glLineWidth(C.GLfloat(width))
  437. gs.lineWidth = width
  438. }
  439. // LinkProgram links the specified program object.
  440. func (gs *GLS) LinkProgram(program uint32) {
  441. C.glLinkProgram(C.GLuint(program))
  442. }
  443. // GetShaderiv returns the specified parameter from the specified shader object.
  444. func (gs *GLS) GetShaderiv(shader, pname uint32, params *int32) {
  445. C.glGetShaderiv(C.GLuint(shader), C.GLenum(pname), (*C.GLint)(params))
  446. }
  447. // Scissor defines the scissor box rectangle in window coordinates.
  448. func (gs *GLS) Scissor(x, y int32, width, height uint32) {
  449. C.glScissor(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
  450. }
  451. // ShaderSource sets the source code for the specified shader object.
  452. func (gs *GLS) ShaderSource(shader uint32, src string) {
  453. csource := gs.cbufStr(src)
  454. C.glShaderSource(C.GLuint(shader), 1, (**C.GLchar)(unsafe.Pointer(&csource)), nil)
  455. }
  456. // TexImage2D specifies a two-dimensional texture image.
  457. func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, border int32, format uint32, itype uint32, data interface{}) {
  458. C.glTexImage2D(C.GLenum(target),
  459. C.GLint(level),
  460. C.GLint(iformat),
  461. C.GLsizei(width),
  462. C.GLsizei(height),
  463. C.GLint(border),
  464. C.GLenum(format),
  465. C.GLenum(itype),
  466. ptr(data))
  467. }
  468. // TexParameteri sets the specified texture parameter on the specified texture.
  469. func (gs *GLS) TexParameteri(target uint32, pname uint32, param int32) {
  470. C.glTexParameteri(C.GLenum(target), C.GLenum(pname), C.GLint(param))
  471. }
  472. // PolygonMode controls the interpretation of polygons for rasterization.
  473. func (gs *GLS) PolygonMode(face, mode uint32) {
  474. if gs.polygonModeFace == face && gs.polygonModeMode == mode {
  475. return
  476. }
  477. C.glPolygonMode(C.GLenum(face), C.GLenum(mode))
  478. gs.polygonModeFace = face
  479. gs.polygonModeMode = mode
  480. }
  481. // PolygonOffset sets the scale and units used to calculate depth values.
  482. func (gs *GLS) PolygonOffset(factor float32, units float32) {
  483. if gs.polygonOffsetFactor == factor && gs.polygonOffsetUnits == units {
  484. return
  485. }
  486. C.glPolygonOffset(C.GLfloat(factor), C.GLfloat(units))
  487. gs.polygonOffsetFactor = factor
  488. gs.polygonOffsetUnits = units
  489. }
  490. // Uniform1i sets the value of an int uniform variable for the current program object.
  491. func (gs *GLS) Uniform1i(location int32, v0 int32) {
  492. C.glUniform1i(C.GLint(location), C.GLint(v0))
  493. gs.stats.Unisets++
  494. }
  495. // Uniform1f sets the value of a float uniform variable for the current program object.
  496. func (gs *GLS) Uniform1f(location int32, v0 float32) {
  497. C.glUniform1f(C.GLint(location), C.GLfloat(v0))
  498. gs.stats.Unisets++
  499. }
  500. // Uniform2f sets the value of a vec2 uniform variable for the current program object.
  501. func (gs *GLS) Uniform2f(location int32, v0, v1 float32) {
  502. C.glUniform2f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1))
  503. gs.stats.Unisets++
  504. }
  505. // Uniform3f sets the value of a vec3 uniform variable for the current program object.
  506. func (gs *GLS) Uniform3f(location int32, v0, v1, v2 float32) {
  507. C.glUniform3f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2))
  508. gs.stats.Unisets++
  509. }
  510. // Uniform4f sets the value of a vec4 uniform variable for the current program object.
  511. func (gs *GLS) Uniform4f(location int32, v0, v1, v2, v3 float32) {
  512. C.glUniform4f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2), C.GLfloat(v3))
  513. gs.stats.Unisets++
  514. }
  515. // UniformMatrix3fv sets the value of one or many 3x3 float matrices for the current program object.
  516. func (gs *GLS) UniformMatrix3fv(location int32, count int32, transpose bool, pm *float32) {
  517. C.glUniformMatrix3fv(C.GLint(location), C.GLsizei(count), bool2c(transpose), (*C.GLfloat)(pm))
  518. gs.stats.Unisets++
  519. }
  520. // UniformMatrix4fv sets the value of one or many 4x4 float matrices for the current program object.
  521. func (gs *GLS) UniformMatrix4fv(location int32, count int32, transpose bool, pm *float32) {
  522. C.glUniformMatrix4fv(C.GLint(location), C.GLsizei(count), bool2c(transpose), (*C.GLfloat)(pm))
  523. gs.stats.Unisets++
  524. }
  525. // Uniform1fv sets the value of one or many float uniform variables for the current program object.
  526. func (gs *GLS) Uniform1fv(location int32, count int32, v []float32) {
  527. C.glUniform1fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  528. gs.stats.Unisets++
  529. }
  530. // Uniform2fv sets the value of one or many vec2 uniform variables for the current program object.
  531. func (gs *GLS) Uniform2fv(location int32, count int32, v *float32) {
  532. C.glUniform2fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(v))
  533. gs.stats.Unisets++
  534. }
  535. func (gs *GLS) Uniform2fvUP(location int32, count int32, v unsafe.Pointer) {
  536. C.glUniform2fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(v))
  537. gs.stats.Unisets++
  538. }
  539. // Uniform3fv sets the value of one or many vec3 uniform variables for the current program object.
  540. func (gs *GLS) Uniform3fv(location int32, count int32, v *float32) {
  541. C.glUniform3fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(v))
  542. gs.stats.Unisets++
  543. }
  544. func (gs *GLS) Uniform3fvUP(location int32, count int32, v unsafe.Pointer) {
  545. C.glUniform3fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(v))
  546. gs.stats.Unisets++
  547. }
  548. // Uniform4fv sets the value of one or many vec4 uniform variables for the current program object.
  549. func (gs *GLS) Uniform4fv(location int32, count int32, v []float32) {
  550. C.glUniform4fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  551. gs.stats.Unisets++
  552. }
  553. func (gs *GLS) Uniform4fvUP(location int32, count int32, v unsafe.Pointer) {
  554. C.glUniform4fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(v))
  555. gs.stats.Unisets++
  556. }
  557. // VertexAttribPointer defines an array of generic vertex attribute data.
  558. func (gs *GLS) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset uint32) {
  559. C.glVertexAttribPointer(C.GLuint(index), C.GLint(size), C.GLenum(xtype), bool2c(normalized), C.GLsizei(stride), unsafe.Pointer(uintptr(offset)))
  560. }
  561. // Viewport sets the viewport.
  562. func (gs *GLS) Viewport(x, y, width, height int32) {
  563. C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
  564. gs.viewportX = x
  565. gs.viewportY = y
  566. gs.viewportWidth = width
  567. gs.viewportHeight = height
  568. }
  569. // UseProgram sets the specified program as the current program.
  570. func (gs *GLS) UseProgram(prog *Program) {
  571. if prog.handle == 0 {
  572. panic("Invalid program")
  573. }
  574. C.glUseProgram(C.GLuint(prog.handle))
  575. gs.prog = prog
  576. // Inserts program in cache if not already there.
  577. if !gs.programs[prog] {
  578. gs.programs[prog] = true
  579. log.Debug("New Program activated. Total: %d", len(gs.programs))
  580. }
  581. }
  582. // Ptr takes a slice or pointer (to a singular scalar value or the first
  583. // element of an array or slice) and returns its GL-compatible address.
  584. //
  585. // For example:
  586. //
  587. // var data []uint8
  588. // ...
  589. // gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
  590. func ptr(data interface{}) unsafe.Pointer {
  591. if data == nil {
  592. return unsafe.Pointer(nil)
  593. }
  594. var addr unsafe.Pointer
  595. v := reflect.ValueOf(data)
  596. switch v.Type().Kind() {
  597. case reflect.Ptr:
  598. e := v.Elem()
  599. switch e.Kind() {
  600. case
  601. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  602. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  603. reflect.Float32, reflect.Float64:
  604. addr = unsafe.Pointer(e.UnsafeAddr())
  605. default:
  606. 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()))
  607. }
  608. case reflect.Uintptr:
  609. addr = unsafe.Pointer(v.Pointer())
  610. case reflect.Slice:
  611. addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
  612. default:
  613. 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()))
  614. }
  615. return addr
  616. }
  617. // bool2c convert a Go bool to C.GLboolean
  618. func bool2c(b bool) C.GLboolean {
  619. if b {
  620. return C.GLboolean(1)
  621. }
  622. return C.GLboolean(0)
  623. }
  624. // gobufSize returns a pointer to static buffer with the specified size not including the terminator.
  625. // If there is available space, there is no memory allocation.
  626. func (gs *GLS) gobufSize(size uint32) *C.GLchar {
  627. if size+1 > uint32(len(gs.gobuf)) {
  628. gs.gobuf = make([]byte, size+1)
  629. }
  630. return (*C.GLchar)(unsafe.Pointer(&gs.gobuf[0]))
  631. }
  632. // gobufStr converts a Go String to a C string by copying it to a static buffer
  633. // and returning a pointer to the start of the buffer.
  634. // If there is available space, there is no memory allocation.
  635. func (gs *GLS) gobufStr(s string) *C.GLchar {
  636. p := gs.gobufSize(uint32(len(s) + 1))
  637. copy(gs.gobuf, s)
  638. gs.gobuf[len(s)] = 0
  639. return p
  640. }
  641. // cbufSize returns a pointer to static buffer with C memory
  642. // If there is available space, there is no memory allocation.
  643. func (gs *GLS) cbufSize(size uint32) *C.GLchar {
  644. if size > uint32(len(gs.cbuf)) {
  645. if len(gs.cbuf) > 0 {
  646. C.free(unsafe.Pointer(&gs.cbuf[0]))
  647. }
  648. p := C.malloc(C.size_t(size))
  649. gs.cbuf = (*[1 << 30]byte)(unsafe.Pointer(p))[:size:size]
  650. }
  651. return (*C.GLchar)(unsafe.Pointer(&gs.cbuf[0]))
  652. }
  653. // cbufStr converts a Go String to a C string by copying it to a single pre-allocated buffer
  654. // using C memory and returning a pointer to the start of the buffer.
  655. // If there is available space, there is no memory allocation.
  656. func (gs *GLS) cbufStr(s string) *C.GLchar {
  657. p := gs.cbufSize(uint32(len(s) + 1))
  658. copy(gs.cbuf, s)
  659. gs.cbuf[len(s)] = 0
  660. return p
  661. }