gls-desktop.go 29 KB

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