Repository: goxjs/gl Branch: main Commit: 37525f4d9d35 Files: 16 Total size: 121.9 KB Directory structure: gitextract_ued_6ei5/ ├── LICENSE ├── README.md ├── consts.go ├── doc.go ├── gl_opengl.go ├── gl_opengles.go ├── gl_webgl.go ├── glutil/ │ └── glutil.go ├── go.mod ├── test/ │ ├── context_darwin.go │ ├── context_x11.go │ ├── doc.go │ └── glimage_test.go ├── types_opengl.go ├── types_opengles.go └── types_webgl.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE ================================================ Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ gl == [![Go Reference](https://pkg.go.dev/badge/github.com/goxjs/gl.svg)](https://pkg.go.dev/github.com/goxjs/gl) Package gl is a Go cross-platform binding for OpenGL, with an OpenGL ES 2-like API. It supports: - **macOS**, **Linux** and **Windows** via OpenGL 2.1 backend, - **iOS** and **Android** via OpenGL ES 2.0 backend, - **Modern Browsers** (desktop and mobile) via WebGL 1.0 backend. This is a fork of golang.org/x/mobile/gl package with [CL 8793](https://go-review.googlesource.com/8793) merged in and Windows support added. This package is fully functional, but may eventually become superceded by the new x/mobile/gl plan. It will exist and be fully supported until it can be safely replaced by a better package. Installation ------------ ```sh go get github.com/goxjs/gl ``` Usage ----- This OpenGL binding has a ContextWatcher, which implements [glfw.ContextWatcher](https://godoc.org/github.com/goxjs/glfw#ContextWatcher) interface. Recommended usage is with github.com/goxjs/glfw package, which accepts a ContextWatcher in its Init, and takes on the responsibility of notifying it when context is made current or detached. ```Go if err := glfw.Init(gl.ContextWatcher); err != nil { // Handle error. } defer glfw.Terminate() ``` If you're not using a ContextWatcher-aware glfw library, you must call methods of gl.ContextWatcher yourself whenever you make a context current or detached. ```Go window.MakeContextCurrent() gl.ContextWatcher.OnMakeCurrent(nil) glfw.DetachCurrentContext() gl.ContextWatcher.OnDetach() ``` Directories ----------- | Path | Synopsis | |---------------------------------------------------------|-----------------------------------------------------| | [glutil](https://pkg.go.dev/github.com/goxjs/gl/glutil) | Package glutil implements OpenGL utility functions. | | [test](https://pkg.go.dev/github.com/goxjs/gl/test) | Package test contains tests for goxjs/gl. | License ------- - [BSD-style License](LICENSE) ================================================ FILE: consts.go ================================================ // Copyright 2014 The Go 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 gl /* Partially generated from the Khronos OpenGL API specification in XML format, which is covered by the license: Copyright (c) 2013-2014 The Khronos Group Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and/or associated documentation files (the "Materials"), to deal in the Materials without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Materials, and to permit persons to whom the Materials are furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Materials. THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ const ( POINTS = 0x0000 LINES = 0x0001 LINE_LOOP = 0x0002 LINE_STRIP = 0x0003 TRIANGLES = 0x0004 TRIANGLE_STRIP = 0x0005 TRIANGLE_FAN = 0x0006 SRC_COLOR = 0x0300 ONE_MINUS_SRC_COLOR = 0x0301 SRC_ALPHA = 0x0302 ONE_MINUS_SRC_ALPHA = 0x0303 DST_ALPHA = 0x0304 ONE_MINUS_DST_ALPHA = 0x0305 DST_COLOR = 0x0306 ONE_MINUS_DST_COLOR = 0x0307 SRC_ALPHA_SATURATE = 0x0308 FUNC_ADD = 0x8006 BLEND_EQUATION = 0x8009 BLEND_EQUATION_RGB = 0x8009 BLEND_EQUATION_ALPHA = 0x883D FUNC_SUBTRACT = 0x800A FUNC_REVERSE_SUBTRACT = 0x800B BLEND_DST_RGB = 0x80C8 BLEND_SRC_RGB = 0x80C9 BLEND_DST_ALPHA = 0x80CA BLEND_SRC_ALPHA = 0x80CB CONSTANT_COLOR = 0x8001 ONE_MINUS_CONSTANT_COLOR = 0x8002 CONSTANT_ALPHA = 0x8003 ONE_MINUS_CONSTANT_ALPHA = 0x8004 BLEND_COLOR = 0x8005 ARRAY_BUFFER = 0x8892 ELEMENT_ARRAY_BUFFER = 0x8893 ARRAY_BUFFER_BINDING = 0x8894 ELEMENT_ARRAY_BUFFER_BINDING = 0x8895 STREAM_DRAW = 0x88E0 STATIC_DRAW = 0x88E4 DYNAMIC_DRAW = 0x88E8 BUFFER_SIZE = 0x8764 BUFFER_USAGE = 0x8765 CURRENT_VERTEX_ATTRIB = 0x8626 FRONT = 0x0404 BACK = 0x0405 FRONT_AND_BACK = 0x0408 TEXTURE_2D = 0x0DE1 CULL_FACE = 0x0B44 BLEND = 0x0BE2 DITHER = 0x0BD0 STENCIL_TEST = 0x0B90 DEPTH_TEST = 0x0B71 SCISSOR_TEST = 0x0C11 POLYGON_OFFSET_FILL = 0x8037 SAMPLE_ALPHA_TO_COVERAGE = 0x809E SAMPLE_COVERAGE = 0x80A0 INVALID_ENUM = 0x0500 INVALID_VALUE = 0x0501 INVALID_OPERATION = 0x0502 OUT_OF_MEMORY = 0x0505 CW = 0x0900 CCW = 0x0901 LINE_WIDTH = 0x0B21 ALIASED_POINT_SIZE_RANGE = 0x846D ALIASED_LINE_WIDTH_RANGE = 0x846E CULL_FACE_MODE = 0x0B45 FRONT_FACE = 0x0B46 DEPTH_RANGE = 0x0B70 DEPTH_WRITEMASK = 0x0B72 DEPTH_CLEAR_VALUE = 0x0B73 DEPTH_FUNC = 0x0B74 STENCIL_CLEAR_VALUE = 0x0B91 STENCIL_FUNC = 0x0B92 STENCIL_FAIL = 0x0B94 STENCIL_PASS_DEPTH_FAIL = 0x0B95 STENCIL_PASS_DEPTH_PASS = 0x0B96 STENCIL_REF = 0x0B97 STENCIL_VALUE_MASK = 0x0B93 STENCIL_WRITEMASK = 0x0B98 STENCIL_BACK_FUNC = 0x8800 STENCIL_BACK_FAIL = 0x8801 STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802 STENCIL_BACK_PASS_DEPTH_PASS = 0x8803 STENCIL_BACK_REF = 0x8CA3 STENCIL_BACK_VALUE_MASK = 0x8CA4 STENCIL_BACK_WRITEMASK = 0x8CA5 VIEWPORT = 0x0BA2 SCISSOR_BOX = 0x0C10 COLOR_CLEAR_VALUE = 0x0C22 COLOR_WRITEMASK = 0x0C23 UNPACK_ALIGNMENT = 0x0CF5 PACK_ALIGNMENT = 0x0D05 MAX_TEXTURE_SIZE = 0x0D33 MAX_VIEWPORT_DIMS = 0x0D3A SUBPIXEL_BITS = 0x0D50 RED_BITS = 0x0D52 GREEN_BITS = 0x0D53 BLUE_BITS = 0x0D54 ALPHA_BITS = 0x0D55 DEPTH_BITS = 0x0D56 STENCIL_BITS = 0x0D57 POLYGON_OFFSET_UNITS = 0x2A00 POLYGON_OFFSET_FACTOR = 0x8038 TEXTURE_BINDING_2D = 0x8069 SAMPLE_BUFFERS = 0x80A8 SAMPLES = 0x80A9 SAMPLE_COVERAGE_VALUE = 0x80AA SAMPLE_COVERAGE_INVERT = 0x80AB NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2 COMPRESSED_TEXTURE_FORMATS = 0x86A3 DONT_CARE = 0x1100 FASTEST = 0x1101 NICEST = 0x1102 GENERATE_MIPMAP_HINT = 0x8192 BYTE = 0x1400 UNSIGNED_BYTE = 0x1401 SHORT = 0x1402 UNSIGNED_SHORT = 0x1403 INT = 0x1404 UNSIGNED_INT = 0x1405 FLOAT = 0x1406 FIXED = 0x140C DEPTH_COMPONENT = 0x1902 ALPHA = 0x1906 RGB = 0x1907 RGBA = 0x1908 LUMINANCE = 0x1909 LUMINANCE_ALPHA = 0x190A UNSIGNED_SHORT_4_4_4_4 = 0x8033 UNSIGNED_SHORT_5_5_5_1 = 0x8034 UNSIGNED_SHORT_5_6_5 = 0x8363 MAX_VERTEX_ATTRIBS = 0x8869 MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB MAX_VARYING_VECTORS = 0x8DFC MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C MAX_TEXTURE_IMAGE_UNITS = 0x8872 MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD SHADER_TYPE = 0x8B4F DELETE_STATUS = 0x8B80 LINK_STATUS = 0x8B82 VALIDATE_STATUS = 0x8B83 ATTACHED_SHADERS = 0x8B85 ACTIVE_UNIFORMS = 0x8B86 ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87 ACTIVE_ATTRIBUTES = 0x8B89 ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A SHADING_LANGUAGE_VERSION = 0x8B8C CURRENT_PROGRAM = 0x8B8D NEVER = 0x0200 LESS = 0x0201 EQUAL = 0x0202 LEQUAL = 0x0203 GREATER = 0x0204 NOTEQUAL = 0x0205 GEQUAL = 0x0206 ALWAYS = 0x0207 KEEP = 0x1E00 REPLACE = 0x1E01 INCR = 0x1E02 DECR = 0x1E03 INVERT = 0x150A INCR_WRAP = 0x8507 DECR_WRAP = 0x8508 VENDOR = 0x1F00 RENDERER = 0x1F01 VERSION = 0x1F02 EXTENSIONS = 0x1F03 NEAREST = 0x2600 LINEAR = 0x2601 NEAREST_MIPMAP_NEAREST = 0x2700 LINEAR_MIPMAP_NEAREST = 0x2701 NEAREST_MIPMAP_LINEAR = 0x2702 LINEAR_MIPMAP_LINEAR = 0x2703 TEXTURE_MAG_FILTER = 0x2800 TEXTURE_MIN_FILTER = 0x2801 TEXTURE_WRAP_S = 0x2802 TEXTURE_WRAP_T = 0x2803 TEXTURE = 0x1702 TEXTURE_CUBE_MAP = 0x8513 TEXTURE_BINDING_CUBE_MAP = 0x8514 TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515 TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516 TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517 TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518 TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519 TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C TEXTURE0 = 0x84C0 TEXTURE1 = 0x84C1 TEXTURE2 = 0x84C2 TEXTURE3 = 0x84C3 TEXTURE4 = 0x84C4 TEXTURE5 = 0x84C5 TEXTURE6 = 0x84C6 TEXTURE7 = 0x84C7 TEXTURE8 = 0x84C8 TEXTURE9 = 0x84C9 TEXTURE10 = 0x84CA TEXTURE11 = 0x84CB TEXTURE12 = 0x84CC TEXTURE13 = 0x84CD TEXTURE14 = 0x84CE TEXTURE15 = 0x84CF TEXTURE16 = 0x84D0 TEXTURE17 = 0x84D1 TEXTURE18 = 0x84D2 TEXTURE19 = 0x84D3 TEXTURE20 = 0x84D4 TEXTURE21 = 0x84D5 TEXTURE22 = 0x84D6 TEXTURE23 = 0x84D7 TEXTURE24 = 0x84D8 TEXTURE25 = 0x84D9 TEXTURE26 = 0x84DA TEXTURE27 = 0x84DB TEXTURE28 = 0x84DC TEXTURE29 = 0x84DD TEXTURE30 = 0x84DE TEXTURE31 = 0x84DF ACTIVE_TEXTURE = 0x84E0 REPEAT = 0x2901 CLAMP_TO_EDGE = 0x812F MIRRORED_REPEAT = 0x8370 VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622 VERTEX_ATTRIB_ARRAY_SIZE = 0x8623 VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624 VERTEX_ATTRIB_ARRAY_TYPE = 0x8625 VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A VERTEX_ATTRIB_ARRAY_POINTER = 0x8645 VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B COMPILE_STATUS = 0x8B81 INFO_LOG_LENGTH = 0x8B84 SHADER_SOURCE_LENGTH = 0x8B88 SHADER_COMPILER = 0x8DFA SHADER_BINARY_FORMATS = 0x8DF8 NUM_SHADER_BINARY_FORMATS = 0x8DF9 LOW_FLOAT = 0x8DF0 MEDIUM_FLOAT = 0x8DF1 HIGH_FLOAT = 0x8DF2 LOW_INT = 0x8DF3 MEDIUM_INT = 0x8DF4 HIGH_INT = 0x8DF5 FRAMEBUFFER = 0x8D40 RENDERBUFFER = 0x8D41 RGBA4 = 0x8056 RGB5_A1 = 0x8057 RGB565 = 0x8D62 DEPTH_COMPONENT16 = 0x81A5 STENCIL_INDEX8 = 0x8D48 RENDERBUFFER_WIDTH = 0x8D42 RENDERBUFFER_HEIGHT = 0x8D43 RENDERBUFFER_INTERNAL_FORMAT = 0x8D44 RENDERBUFFER_RED_SIZE = 0x8D50 RENDERBUFFER_GREEN_SIZE = 0x8D51 RENDERBUFFER_BLUE_SIZE = 0x8D52 RENDERBUFFER_ALPHA_SIZE = 0x8D53 RENDERBUFFER_DEPTH_SIZE = 0x8D54 RENDERBUFFER_STENCIL_SIZE = 0x8D55 FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0 FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1 FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2 FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3 COLOR_ATTACHMENT0 = 0x8CE0 DEPTH_ATTACHMENT = 0x8D00 STENCIL_ATTACHMENT = 0x8D20 FRAMEBUFFER_COMPLETE = 0x8CD5 FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6 FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7 FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9 FRAMEBUFFER_UNSUPPORTED = 0x8CDD FRAMEBUFFER_BINDING = 0x8CA6 RENDERBUFFER_BINDING = 0x8CA7 MAX_RENDERBUFFER_SIZE = 0x84E8 INVALID_FRAMEBUFFER_OPERATION = 0x0506 ) const ( DEPTH_BUFFER_BIT = 0x00000100 STENCIL_BUFFER_BIT = 0x00000400 COLOR_BUFFER_BIT = 0x00004000 ) const ( FLOAT_VEC2 = 0x8B50 FLOAT_VEC3 = 0x8B51 FLOAT_VEC4 = 0x8B52 INT_VEC2 = 0x8B53 INT_VEC3 = 0x8B54 INT_VEC4 = 0x8B55 BOOL = 0x8B56 BOOL_VEC2 = 0x8B57 BOOL_VEC3 = 0x8B58 BOOL_VEC4 = 0x8B59 FLOAT_MAT2 = 0x8B5A FLOAT_MAT3 = 0x8B5B FLOAT_MAT4 = 0x8B5C SAMPLER_2D = 0x8B5E SAMPLER_CUBE = 0x8B60 ) const ( FRAGMENT_SHADER = 0x8B30 VERTEX_SHADER = 0x8B31 ) const ( FALSE = 0 TRUE = 1 ZERO = 0 ONE = 1 NO_ERROR = 0 NONE = 0 ) ================================================ FILE: doc.go ================================================ // Copyright 2014 The Go 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 gl is a Go cross-platform binding for OpenGL, with an OpenGL ES 2-like API. It supports: - macOS, Linux and Windows via OpenGL 2.1 backend, - iOS and Android via OpenGL ES 2.0 backend, - Modern Browsers (desktop and mobile) via WebGL 1.0 backend. This is a fork of golang.org/x/mobile/gl package with [CL 8793](https://go-review.googlesource.com/8793) merged in and Windows support added. This package is fully functional, but may eventually become superceded by the new x/mobile/gl plan. It will exist and be fully supported until it can be safely replaced by a better package. Usage This OpenGL binding has a ContextWatcher, which implements [glfw.ContextWatcher](https://godoc.org/github.com/goxjs/glfw#ContextWatcher) interface. Recommended usage is with github.com/goxjs/glfw package, which accepts a ContextWatcher in its Init, and takes on the responsibility of notifying it when context is made current or detached. if err := glfw.Init(gl.ContextWatcher); err != nil { // Handle error. } defer glfw.Terminate() If you're not using a ContextWatcher-aware glfw library, you must call methods of gl.ContextWatcher yourself whenever you make a context current or detached. window.MakeContextCurrent() gl.ContextWatcher.OnMakeCurrent(nil) glfw.DetachCurrentContext() gl.ContextWatcher.OnDetach() */ package gl ================================================ FILE: gl_opengl.go ================================================ // +build !js package gl import ( "log" "strings" "unsafe" "github.com/go-gl/gl/v2.1/gl" ) // ContextWatcher is this library's context watcher, satisfying glfw.ContextWatcher interface. // It must be notified when context is made current or detached. var ContextWatcher = new(contextWatcher) type contextWatcher struct { initGL bool } func (cw *contextWatcher) OnMakeCurrent(context interface{}) { if !cw.initGL { // Initialise gl bindings using the current context. err := gl.Init() if err != nil { log.Fatalln("gl.Init:", err) } cw.initGL = true } } func (contextWatcher) OnDetach() {} // ActiveTexture sets the active texture unit. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glActiveTexture.xhtml func ActiveTexture(texture Enum) { gl.ActiveTexture(uint32(texture)) } // AttachShader attaches a shader to a program. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glAttachShader.xhtml func AttachShader(p Program, s Shader) { gl.AttachShader(p.Value, s.Value) } // BindAttribLocation binds a vertex attribute index with a named // variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindAttribLocation.xhtml func BindAttribLocation(p Program, a Attrib, name string) { gl.BindAttribLocation(p.Value, uint32(a.Value), gl.Str(name+"\x00")) } // BindBuffer binds a buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindBuffer.xhtml func BindBuffer(target Enum, b Buffer) { gl.BindBuffer(uint32(target), b.Value) } // BindFramebuffer binds a framebuffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindFramebuffer.xhtml func BindFramebuffer(target Enum, fb Framebuffer) { gl.BindFramebuffer(uint32(target), fb.Value) } // BindRenderbuffer binds a render buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindRenderbuffer.xhtml func BindRenderbuffer(target Enum, rb Renderbuffer) { gl.BindRenderbuffer(uint32(target), rb.Value) } // BindTexture binds a texture. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindTexture.xhtml func BindTexture(target Enum, t Texture) { gl.BindTexture(uint32(target), t.Value) } // BlendColor sets the blend color. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendColor.xhtml func BlendColor(red, green, blue, alpha float32) { gl.BlendColor(red, green, blue, alpha) } // BlendEquation sets both RGB and alpha blend equations. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquation.xhtml func BlendEquation(mode Enum) { gl.BlendEquation(uint32(mode)) } // BlendEquationSeparate sets RGB and alpha blend equations separately. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquationSeparate.xhtml func BlendEquationSeparate(modeRGB, modeAlpha Enum) { gl.BlendEquationSeparate(uint32(modeRGB), uint32(modeAlpha)) } // BlendFunc sets the pixel blending factors. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFunc.xhtml func BlendFunc(sfactor, dfactor Enum) { gl.BlendFunc(uint32(sfactor), uint32(dfactor)) } // BlendFunc sets the pixel RGB and alpha blending factors separately. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFuncSeparate.xhtml func BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) { gl.BlendFuncSeparate(uint32(sfactorRGB), uint32(dfactorRGB), uint32(sfactorAlpha), uint32(dfactorAlpha)) } // BufferData creates a new data store for the bound buffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml func BufferData(target Enum, src []byte, usage Enum) { gl.BufferData(uint32(target), int(len(src)), gl.Ptr(&src[0]), uint32(usage)) } // BufferInit creates a new unitialized data store for the bound buffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml func BufferInit(target Enum, size int, usage Enum) { gl.BufferData(uint32(target), size, nil, uint32(usage)) } // BufferSubData sets some of data in the bound buffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferSubData.xhtml func BufferSubData(target Enum, offset int, data []byte) { gl.BufferSubData(uint32(target), offset, int(len(data)), gl.Ptr(&data[0])) } // CheckFramebufferStatus reports the completeness status of the // active framebuffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCheckFramebufferStatus.xhtml func CheckFramebufferStatus(target Enum) Enum { return Enum(gl.CheckFramebufferStatus(uint32(target))) } // Clear clears the window. // // The behavior of Clear is influenced by the pixel ownership test, // the scissor test, dithering, and the buffer writemasks. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glClear.xhtml func Clear(mask Enum) { gl.Clear(uint32(mask)) } // ClearColor specifies the RGBA values used to clear color buffers. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearColor.xhtml func ClearColor(red, green, blue, alpha float32) { gl.ClearColor(red, green, blue, alpha) } // ClearDepthf sets the depth value used to clear the depth buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearDepthf.xhtml func ClearDepthf(d float32) { gl.ClearDepthf(d) } // ClearStencil sets the index used to clear the stencil buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearStencil.xhtml func ClearStencil(s int) { gl.ClearStencil(int32(s)) } // ColorMask specifies whether color components in the framebuffer // can be written. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glColorMask.xhtml func ColorMask(red, green, blue, alpha bool) { gl.ColorMask(red, green, blue, alpha) } // CompileShader compiles the source code of s. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompileShader.xhtml func CompileShader(s Shader) { gl.CompileShader(s.Value) } // CompressedTexImage2D writes a compressed 2D texture. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexImage2D.xhtml func CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) { gl.CompressedTexImage2D(uint32(target), int32(level), uint32(internalformat), int32(width), int32(height), int32(border), int32(len(data)), gl.Ptr(data)) } // CompressedTexSubImage2D writes a subregion of a compressed 2D texture. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexSubImage2D.xhtml func CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) { gl.CompressedTexSubImage2D(uint32(target), int32(level), int32(xoffset), int32(yoffset), int32(width), int32(height), uint32(format), int32(len(data)), gl.Ptr(data)) } // CopyTexImage2D writes a 2D texture from the current framebuffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexImage2D.xhtml func CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) { gl.CopyTexImage2D(uint32(target), int32(level), uint32(internalformat), int32(x), int32(y), int32(width), int32(height), int32(border)) } // CopyTexSubImage2D writes a 2D texture subregion from the // current framebuffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexSubImage2D.xhtml func CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) { gl.CopyTexSubImage2D(uint32(target), int32(level), int32(xoffset), int32(yoffset), int32(x), int32(y), int32(width), int32(height)) } // CreateBuffer creates a buffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenBuffers.xhtml func CreateBuffer() Buffer { var b Buffer gl.GenBuffers(1, &b.Value) return b } // CreateFramebuffer creates a framebuffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenFramebuffers.xhtml func CreateFramebuffer() Framebuffer { var b Framebuffer gl.GenFramebuffers(1, &b.Value) return b } // CreateProgram creates a new empty program object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateProgram.xhtml func CreateProgram() Program { return Program{Value: uint32(gl.CreateProgram())} } // CreateRenderbuffer create a renderbuffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenRenderbuffers.xhtml func CreateRenderbuffer() Renderbuffer { var b Renderbuffer gl.GenRenderbuffers(1, &b.Value) return b } // CreateShader creates a new empty shader object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateShader.xhtml func CreateShader(ty Enum) Shader { return Shader{Value: uint32(gl.CreateShader(uint32(ty)))} } // CreateTexture creates a texture object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenTextures.xhtml func CreateTexture() Texture { var t Texture gl.GenTextures(1, &t.Value) return t } // CullFace specifies which polygons are candidates for culling. // // Valid modes: FRONT, BACK, FRONT_AND_BACK. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glCullFace.xhtml func CullFace(mode Enum) { gl.CullFace(uint32(mode)) } // DeleteBuffer deletes the given buffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteBuffers.xhtml func DeleteBuffer(v Buffer) { gl.DeleteBuffers(1, &v.Value) } // DeleteFramebuffer deletes the given framebuffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteFramebuffers.xhtml func DeleteFramebuffer(v Framebuffer) { gl.DeleteFramebuffers(1, &v.Value) } // DeleteProgram deletes the given program object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteProgram.xhtml func DeleteProgram(p Program) { gl.DeleteProgram(p.Value) } // DeleteRenderbuffer deletes the given render buffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteRenderbuffers.xhtml func DeleteRenderbuffer(v Renderbuffer) { gl.DeleteRenderbuffers(1, &v.Value) } // DeleteShader deletes shader s. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteShader.xhtml func DeleteShader(s Shader) { gl.DeleteShader(s.Value) } // DeleteTexture deletes the given texture object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteTextures.xhtml func DeleteTexture(v Texture) { gl.DeleteTextures(1, &v.Value) } // DepthFunc sets the function used for depth buffer comparisons. // // Valid fn values: // NEVER // LESS // EQUAL // LEQUAL // GREATER // NOTEQUAL // GEQUAL // ALWAYS // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthFunc.xhtml func DepthFunc(fn Enum) { gl.DepthFunc(uint32(fn)) } // DepthMask sets the depth buffer enabled for writing. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthMask.xhtml func DepthMask(flag bool) { gl.DepthMask(flag) } // DepthRangef sets the mapping from normalized device coordinates to // window coordinates. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthRangef.xhtml func DepthRangef(n, f float32) { gl.DepthRangef(n, f) } // DetachShader detaches the shader s from the program p. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDetachShader.xhtml func DetachShader(p Program, s Shader) { gl.DetachShader(p.Value, s.Value) } // Disable disables various GL capabilities. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDisable.xhtml func Disable(cap Enum) { gl.Disable(uint32(cap)) } // DisableVertexAttribArray disables a vertex attribute array. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDisableVertexAttribArray.xhtml func DisableVertexAttribArray(a Attrib) { gl.DisableVertexAttribArray(uint32(a.Value)) } // DrawArrays renders geometric primitives from the bound data. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawArrays.xhtml func DrawArrays(mode Enum, first, count int) { gl.DrawArrays(uint32(mode), int32(first), int32(count)) } // DrawElements renders primitives from a bound buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawElements.xhtml func DrawElements(mode Enum, count int, ty Enum, offset int) { gl.DrawElements(uint32(mode), int32(count), uint32(ty), gl.PtrOffset(offset)) } // Enable enables various GL capabilities. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glEnable.xhtml func Enable(cap Enum) { gl.Enable(uint32(cap)) } // EnableVertexAttribArray enables a vertex attribute array. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glEnableVertexAttribArray.xhtml func EnableVertexAttribArray(a Attrib) { gl.EnableVertexAttribArray(uint32(a.Value)) } // Finish blocks until the effects of all previously called GL // commands are complete. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glFinish.xhtml func Finish() { gl.Finish() } // Flush empties all buffers. It does not block. // // An OpenGL implementation may buffer network communication, // the command stream, or data inside the graphics accelerator. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glFlush.xhtml func Flush() { gl.Flush() } // FramebufferRenderbuffer attaches rb to the current frame buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferRenderbuffer.xhtml func FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) { gl.FramebufferRenderbuffer(uint32(target), uint32(attachment), uint32(rbTarget), rb.Value) } // FramebufferTexture2D attaches the t to the current frame buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferTexture2D.xhtml func FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) { gl.FramebufferTexture2D(uint32(target), uint32(attachment), uint32(texTarget), t.Value, int32(level)) } // FrontFace defines which polygons are front-facing. // // Valid modes: CW, CCW. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glFrontFace.xhtml func FrontFace(mode Enum) { gl.FrontFace(uint32(mode)) } // GenerateMipmap generates mipmaps for the current texture. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenerateMipmap.xhtml func GenerateMipmap(target Enum) { gl.GenerateMipmap(uint32(target)) } // GetActiveAttrib returns details about an active attribute variable. // A value of 0 for index selects the first active attribute variable. // Permissible values for index range from 0 to the number of active // attribute variables minus 1. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveAttrib.xhtml func GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) { var length, si int32 var typ uint32 name = strings.Repeat("\x00", 256) cname := gl.Str(name) gl.GetActiveAttrib(p.Value, uint32(index), int32(len(name)-1), &length, &si, &typ, cname) name = name[:strings.IndexRune(name, 0)] return name, int(si), Enum(typ) } // GetActiveUniform returns details about an active uniform variable. // A value of 0 for index selects the first active uniform variable. // Permissible values for index range from 0 to the number of active // uniform variables minus 1. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveUniform.xhtml func GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) { var length, si int32 var typ uint32 name = strings.Repeat("\x00", 256) cname := gl.Str(name) gl.GetActiveUniform(p.Value, uint32(index), int32(len(name)-1), &length, &si, &typ, cname) name = name[:strings.IndexRune(name, 0)] return name, int(si), Enum(typ) } // GetAttachedShaders returns the shader objects attached to program p. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttachedShaders.xhtml func GetAttachedShaders(p Program) []Shader { log.Println("GetAttachedShaders: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") shadersLen := GetProgrami(p, ATTACHED_SHADERS) var n int32 buf := make([]uint32, shadersLen) gl.GetAttachedShaders(uint32(p.Value), int32(shadersLen), &n, &buf[0]) buf = buf[:int(n)] shaders := make([]Shader, int(n)) for i, s := range buf { shaders[i] = Shader{Value: uint32(s)} } return shaders } // GetAttribLocation returns the location of an attribute variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttribLocation.xhtml func GetAttribLocation(p Program, name string) Attrib { return Attrib{Value: uint(gl.GetAttribLocation(p.Value, gl.Str(name+"\x00")))} } // GetBooleanv returns the boolean values of parameter pname. // // Many boolean parameters can be queried more easily using IsEnabled. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml func GetBooleanv(dst []bool, pname Enum) { gl.GetBooleanv(uint32(pname), &dst[0]) } // GetFloatv returns the float values of parameter pname. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml func GetFloatv(dst []float32, pname Enum) { gl.GetFloatv(uint32(pname), &dst[0]) } // GetIntegerv returns the int values of parameter pname. // // Single values may be queried more easily using GetInteger. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml func GetIntegerv(pname Enum, data []int32) { gl.GetIntegerv(uint32(pname), &data[0]) } // GetInteger returns the int value of parameter pname. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml func GetInteger(pname Enum) int { var data int32 gl.GetIntegerv(uint32(pname), &data) return int(data) } // GetBufferParameteri returns a parameter for the active buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetBufferParameteriv.xhtml func GetBufferParameteri(target, pname Enum) int { var params int32 gl.GetBufferParameteriv(uint32(target), uint32(pname), ¶ms) return int(params) } // GetError returns the next error. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetError.xhtml func GetError() Enum { return Enum(gl.GetError()) } // GetBoundFramebuffer returns the currently bound framebuffer. // Use this method instead of gl.GetInteger(gl.FRAMEBUFFER_BINDING) to // enable support on all platforms func GetBoundFramebuffer() Framebuffer { var b int32 gl.GetIntegerv(FRAMEBUFFER_BINDING, &b) return Framebuffer{Value: uint32(b)} } // GetFramebufferAttachmentParameteri returns attachment parameters // for the active framebuffer object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetFramebufferAttachmentParameteriv.xhtml func GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int { log.Println("GetFramebufferAttachmentParameteri: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") var param int32 gl.GetFramebufferAttachmentParameteriv(uint32(target), uint32(attachment), uint32(pname), ¶m) return int(param) } // GetProgrami returns a parameter value for a program. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramiv.xhtml func GetProgrami(p Program, pname Enum) int { var result int32 gl.GetProgramiv(p.Value, uint32(pname), &result) return int(result) } // GetProgramInfoLog returns the information log for a program. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramInfoLog.xhtml func GetProgramInfoLog(p Program) string { var logLength int32 gl.GetProgramiv(p.Value, gl.INFO_LOG_LENGTH, &logLength) if logLength == 0 { return "" } logBuffer := make([]uint8, logLength) gl.GetProgramInfoLog(p.Value, logLength, nil, &logBuffer[0]) return gl.GoStr(&logBuffer[0]) } // GetRenderbufferParameteri returns a parameter value for a render buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetRenderbufferParameteriv.xhtml func GetRenderbufferParameteri(target, pname Enum) int { log.Println("GetRenderbufferParameteri: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") var result int32 gl.GetRenderbufferParameteriv(uint32(target), uint32(pname), &result) return int(result) } // GetRenderbufferParameteri returns a parameter value for a shader. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderiv.xhtml func GetShaderi(s Shader, pname Enum) int { var result int32 gl.GetShaderiv(s.Value, uint32(pname), &result) return int(result) } // GetShaderInfoLog returns the information log for a shader. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderInfoLog.xhtml func GetShaderInfoLog(s Shader) string { var logLength int32 gl.GetShaderiv(s.Value, gl.INFO_LOG_LENGTH, &logLength) if logLength == 0 { return "" } logBuffer := make([]uint8, logLength) gl.GetShaderInfoLog(s.Value, logLength, nil, &logBuffer[0]) return gl.GoStr(&logBuffer[0]) } // GetShaderPrecisionFormat returns range and precision limits for // shader types. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderPrecisionFormat.xhtml func GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) { log.Println("GetShaderPrecisionFormat: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") var cRange [2]int32 var cPrecision int32 gl.GetShaderPrecisionFormat(uint32(shadertype), uint32(precisiontype), &cRange[0], &cPrecision) return int(cRange[0]), int(cRange[1]), int(cPrecision) } // GetShaderSource returns source code of shader s. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderSource.xhtml func GetShaderSource(s Shader) string { log.Println("GetShaderSource: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") sourceLen := GetShaderi(s, gl.SHADER_SOURCE_LENGTH) if sourceLen == 0 { return "" } buf := make([]byte, sourceLen) gl.GetShaderSource(s.Value, int32(sourceLen), nil, &buf[0]) return string(buf) } // GetString reports current GL state. // // Valid name values: // EXTENSIONS // RENDERER // SHADING_LANGUAGE_VERSION // VENDOR // VERSION // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetString.xhtml func GetString(pname Enum) string { return gl.GoStr(gl.GetString(uint32(pname))) } // GetTexParameterfv returns the float values of a texture parameter. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml func GetTexParameterfv(dst []float32, target, pname Enum) { gl.GetTexParameterfv(uint32(target), uint32(pname), &dst[0]) } // GetTexParameteriv returns the int values of a texture parameter. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml func GetTexParameteriv(dst []int32, target, pname Enum) { gl.GetTexParameteriv(uint32(target), uint32(pname), &dst[0]) } // GetUniformfv returns the float values of a uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml func GetUniformfv(dst []float32, src Uniform, p Program) { gl.GetUniformfv(p.Value, src.Value, &dst[0]) } // GetUniformiv returns the float values of a uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml func GetUniformiv(dst []int32, src Uniform, p Program) { gl.GetUniformiv(p.Value, src.Value, &dst[0]) } // GetUniformLocation returns the location of a uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniformLocation.xhtml func GetUniformLocation(p Program, name string) Uniform { return Uniform{Value: gl.GetUniformLocation(p.Value, gl.Str(name+"\x00"))} } // GetVertexAttribf reads the float value of a vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml func GetVertexAttribf(src Attrib, pname Enum) float32 { log.Println("GetVertexAttribf: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") var result float32 gl.GetVertexAttribfv(uint32(src.Value), uint32(pname), &result) return result } // GetVertexAttribfv reads float values of a vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml func GetVertexAttribfv(dst []float32, src Attrib, pname Enum) { gl.GetVertexAttribfv(uint32(src.Value), uint32(pname), &dst[0]) } // GetVertexAttribi reads the int value of a vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml func GetVertexAttribi(src Attrib, pname Enum) int32 { var result int32 gl.GetVertexAttribiv(uint32(src.Value), uint32(pname), &result) return result } // GetVertexAttribiv reads int values of a vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml func GetVertexAttribiv(dst []int32, src Attrib, pname Enum) { gl.GetVertexAttribiv(uint32(src.Value), uint32(pname), &dst[0]) } // Hint sets implementation-specific modes. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glHint.xhtml func Hint(target, mode Enum) { gl.Hint(uint32(target), uint32(mode)) } // IsBuffer reports if b is a valid buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsBuffer.xhtml func IsBuffer(b Buffer) bool { return gl.IsBuffer(b.Value) } // IsEnabled reports if cap is an enabled capability. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsEnabled.xhtml func IsEnabled(cap Enum) bool { return gl.IsEnabled(uint32(cap)) } // IsFramebuffer reports if fb is a valid frame buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsFramebuffer.xhtml func IsFramebuffer(fb Framebuffer) bool { return gl.IsFramebuffer(fb.Value) } // IsProgram reports if p is a valid program object. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsProgram.xhtml func IsProgram(p Program) bool { return gl.IsProgram(p.Value) } // IsRenderbuffer reports if rb is a valid render buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsRenderbuffer.xhtml func IsRenderbuffer(rb Renderbuffer) bool { return gl.IsRenderbuffer(rb.Value) } // IsShader reports if s is valid shader. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsShader.xhtml func IsShader(s Shader) bool { return gl.IsShader(s.Value) } // IsTexture reports if t is a valid texture. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsTexture.xhtml func IsTexture(t Texture) bool { return gl.IsTexture(t.Value) } // LineWidth specifies the width of lines. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glLineWidth.xhtml func LineWidth(width float32) { gl.LineWidth(width) } // LinkProgram links the specified program. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glLinkProgram.xhtml func LinkProgram(p Program) { gl.LinkProgram(p.Value) } // PixelStorei sets pixel storage parameters. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glPixelStorei.xhtml func PixelStorei(pname Enum, param int32) { gl.PixelStorei(uint32(pname), param) } // PolygonOffset sets the scaling factors for depth offsets. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glPolygonOffset.xhtml func PolygonOffset(factor, units float32) { gl.PolygonOffset(factor, units) } // ReadPixels returns pixel data from a buffer. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glReadPixels.xhtml func ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) { gl.ReadPixels(int32(x), int32(y), int32(width), int32(height), uint32(format), uint32(ty), gl.Ptr(&dst[0])) } // ReleaseShaderCompiler frees resources allocated by the shader compiler. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glReleaseShaderCompiler.xhtml func ReleaseShaderCompiler() { gl.ReleaseShaderCompiler() } // RenderbufferStorage establishes the data storage, format, and // dimensions of a renderbuffer object's image. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glRenderbufferStorage.xhtml func RenderbufferStorage(target, internalFormat Enum, width, height int) { gl.RenderbufferStorage(uint32(target), uint32(internalFormat), int32(width), int32(height)) } // SampleCoverage sets multisample coverage parameters. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glSampleCoverage.xhtml func SampleCoverage(value float32, invert bool) { gl.SampleCoverage(value, invert) } // Scissor defines the scissor box rectangle, in window coordinates. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glScissor.xhtml func Scissor(x, y, width, height int32) { gl.Scissor(x, y, width, height) } // ShaderSource sets the source code of s to the given source code. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glShaderSource.xhtml func ShaderSource(s Shader, src string) { glsource, free := gl.Strs(src + "\x00") gl.ShaderSource(s.Value, 1, glsource, nil) free() } // StencilFunc sets the front and back stencil test reference value. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFunc.xhtml func StencilFunc(fn Enum, ref int, mask uint32) { gl.StencilFunc(uint32(fn), int32(ref), mask) } // StencilFunc sets the front or back stencil test reference value. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFuncSeparate.xhtml func StencilFuncSeparate(face, fn Enum, ref int, mask uint32) { gl.StencilFuncSeparate(uint32(face), uint32(fn), int32(ref), mask) } // StencilMask controls the writing of bits in the stencil planes. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMask.xhtml func StencilMask(mask uint32) { gl.StencilMask(mask) } // StencilMaskSeparate controls the writing of bits in the stencil planes. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMaskSeparate.xhtml func StencilMaskSeparate(face Enum, mask uint32) { gl.StencilMaskSeparate(uint32(face), mask) } // StencilOp sets front and back stencil test actions. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOp.xhtml func StencilOp(fail, zfail, zpass Enum) { gl.StencilOp(uint32(fail), uint32(zfail), uint32(zpass)) } // StencilOpSeparate sets front or back stencil tests. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOpSeparate.xhtml func StencilOpSeparate(face, sfail, dpfail, dppass Enum) { gl.StencilOpSeparate(uint32(face), uint32(sfail), uint32(dpfail), uint32(dppass)) } // TexImage2D writes a 2D texture image. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexImage2D.xhtml func TexImage2D(target Enum, level int, width, height int, format Enum, ty Enum, data []byte) { p := unsafe.Pointer(nil) if len(data) > 0 { p = gl.Ptr(&data[0]) } gl.TexImage2D(uint32(target), int32(level), int32(format), int32(width), int32(height), 0, uint32(format), uint32(ty), p) } // TexSubImage2D writes a subregion of a 2D texture image. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexSubImage2D.xhtml func TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { gl.TexSubImage2D(uint32(target), int32(level), int32(x), int32(y), int32(width), int32(height), uint32(format), uint32(ty), gl.Ptr(&data[0])) } // TexParameterf sets a float texture parameter. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml func TexParameterf(target, pname Enum, param float32) { gl.TexParameterf(uint32(target), uint32(pname), param) } // TexParameterfv sets a float texture parameter array. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml func TexParameterfv(target, pname Enum, params []float32) { gl.TexParameterfv(uint32(target), uint32(pname), ¶ms[0]) } // TexParameteri sets an integer texture parameter. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml func TexParameteri(target, pname Enum, param int) { gl.TexParameteri(uint32(target), uint32(pname), int32(param)) } // TexParameteriv sets an integer texture parameter array. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml func TexParameteriv(target, pname Enum, params []int32) { gl.TexParameteriv(uint32(target), uint32(pname), ¶ms[0]) } // Uniform1f writes a float uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform1f(dst Uniform, v float32) { gl.Uniform1f(dst.Value, v) } // Uniform1fv writes a [len(src)]float uniform array. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform1fv(dst Uniform, src []float32) { gl.Uniform1fv(dst.Value, int32(len(src)), &src[0]) } // Uniform1i writes an int uniform variable. // // Uniform1i and Uniform1iv are the only two functions that may be used // to load uniform variables defined as sampler types. Loading samplers // with any other function will result in a INVALID_OPERATION error. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform1i(dst Uniform, v int) { gl.Uniform1i(dst.Value, int32(v)) } // Uniform1iv writes a int uniform array of len(src) elements. // // Uniform1i and Uniform1iv are the only two functions that may be used // to load uniform variables defined as sampler types. Loading samplers // with any other function will result in a INVALID_OPERATION error. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform1iv(dst Uniform, src []int32) { gl.Uniform1iv(dst.Value, int32(len(src)), &src[0]) } // Uniform2f writes a vec2 uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform2f(dst Uniform, v0, v1 float32) { gl.Uniform2f(dst.Value, v0, v1) } // Uniform2fv writes a vec2 uniform array of len(src)/2 elements. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform2fv(dst Uniform, src []float32) { gl.Uniform2fv(dst.Value, int32(len(src)/2), &src[0]) } // Uniform2i writes an ivec2 uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform2i(dst Uniform, v0, v1 int) { gl.Uniform2i(dst.Value, int32(v0), int32(v1)) } // Uniform2iv writes an ivec2 uniform array of len(src)/2 elements. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform2iv(dst Uniform, src []int32) { gl.Uniform2iv(dst.Value, int32(len(src)/2), &src[0]) } // Uniform3f writes a vec3 uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform3f(dst Uniform, v0, v1, v2 float32) { gl.Uniform3f(dst.Value, v0, v1, v2) } // Uniform3fv writes a vec3 uniform array of len(src)/3 elements. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform3fv(dst Uniform, src []float32) { gl.Uniform3fv(dst.Value, int32(len(src)/3), &src[0]) } // Uniform3i writes an ivec3 uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform3i(dst Uniform, v0, v1, v2 int32) { gl.Uniform3i(dst.Value, v0, v1, v2) } // Uniform3iv writes an ivec3 uniform array of len(src)/3 elements. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform3iv(dst Uniform, src []int32) { gl.Uniform3iv(dst.Value, int32(len(src)/3), &src[0]) } // Uniform4f writes a vec4 uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform4f(dst Uniform, v0, v1, v2, v3 float32) { gl.Uniform4f(dst.Value, v0, v1, v2, v3) } // Uniform4fv writes a vec4 uniform array of len(src)/4 elements. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform4fv(dst Uniform, src []float32) { gl.Uniform4fv(dst.Value, int32(len(src)/4), &src[0]) } // Uniform4i writes an ivec4 uniform variable. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform4i(dst Uniform, v0, v1, v2, v3 int32) { gl.Uniform4i(dst.Value, v0, v1, v2, v3) } // Uniform4i writes an ivec4 uniform array of len(src)/4 elements. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func Uniform4iv(dst Uniform, src []int32) { gl.Uniform4iv(dst.Value, int32(len(src)/4), &src[0]) } // UniformMatrix2fv writes 2x2 matrices. Each matrix uses four // float32 values, so the number of matrices written is len(src)/4. // // Each matrix must be supplied in column major order. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func UniformMatrix2fv(dst Uniform, src []float32) { gl.UniformMatrix2fv(dst.Value, int32(len(src)/(2*2)), false, &src[0]) } // UniformMatrix3fv writes 3x3 matrices. Each matrix uses nine // float32 values, so the number of matrices written is len(src)/9. // // Each matrix must be supplied in column major order. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func UniformMatrix3fv(dst Uniform, src []float32) { gl.UniformMatrix3fv(dst.Value, int32(len(src)/(3*3)), false, &src[0]) } // UniformMatrix4fv writes 4x4 matrices. Each matrix uses 16 // float32 values, so the number of matrices written is len(src)/16. // // Each matrix must be supplied in column major order. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml func UniformMatrix4fv(dst Uniform, src []float32) { gl.UniformMatrix4fv(dst.Value, int32(len(src)/(4*4)), false, &src[0]) } // UseProgram sets the active program. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glUseProgram.xhtml func UseProgram(p Program) { gl.UseProgram(p.Value) } // ValidateProgram checks to see whether the executables contained in // program can execute given the current OpenGL state. // // Typically only used for debugging. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glValidateProgram.xhtml func ValidateProgram(p Program) { gl.ValidateProgram(uint32(p.Value)) } // VertexAttrib1f writes a float vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib1f(dst Attrib, x float32) { gl.VertexAttrib1f(uint32(dst.Value), x) } // VertexAttrib1fv writes a float vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib1fv(dst Attrib, src []float32) { gl.VertexAttrib1fv(uint32(dst.Value), &src[0]) } // VertexAttrib2f writes a vec2 vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib2f(dst Attrib, x, y float32) { gl.VertexAttrib2f(uint32(dst.Value), x, y) } // VertexAttrib2fv writes a vec2 vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib2fv(dst Attrib, src []float32) { gl.VertexAttrib2fv(uint32(dst.Value), &src[0]) } // VertexAttrib3f writes a vec3 vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib3f(dst Attrib, x, y, z float32) { gl.VertexAttrib3f(uint32(dst.Value), x, y, z) } // VertexAttrib3fv writes a vec3 vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib3fv(dst Attrib, src []float32) { gl.VertexAttrib3fv(uint32(dst.Value), &src[0]) } // VertexAttrib4f writes a vec4 vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib4f(dst Attrib, x, y, z, w float32) { gl.VertexAttrib4f(uint32(dst.Value), x, y, z, w) } // VertexAttrib4fv writes a vec4 vertex attribute. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml func VertexAttrib4fv(dst Attrib, src []float32) { gl.VertexAttrib4fv(uint32(dst.Value), &src[0]) } // VertexAttribPointer uses a bound buffer to define vertex attribute data. // // Direct use of VertexAttribPointer to load data into OpenGL is not // supported via the Go bindings. Instead, use BindBuffer with an // ARRAY_BUFFER and then fill it using BufferData. // // The size argument specifies the number of components per attribute, // between 1-4. The stride argument specifies the byte offset between // consecutive vertex attributes. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttribPointer.xhtml func VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) { gl.VertexAttribPointer(uint32(dst.Value), int32(size), uint32(ty), normalized, int32(stride), gl.PtrOffset(offset)) } // Viewport sets the viewport, an affine transformation that // normalizes device coordinates to window coordinates. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glViewport.xhtml func Viewport(x, y, width, height int) { gl.Viewport(int32(x), int32(y), int32(width), int32(height)) } ================================================ FILE: gl_opengles.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ios android package gl /* #include #ifdef os_ios #include #endif #ifdef os_android #include #endif */ import "C" import "unsafe" var ContextWatcher contextWatcher type contextWatcher struct{} func (contextWatcher) OnMakeCurrent(context interface{}) {} func (contextWatcher) OnDetach() {} func ActiveTexture(texture Enum) { C.glActiveTexture(texture.c()) } func AttachShader(p Program, s Shader) { C.glAttachShader(p.c(), s.c()) } func BindAttribLocation(p Program, a Attrib, name string) { str := unsafe.Pointer(C.CString(name)) defer C.free(str) C.glBindAttribLocation(p.c(), a.c(), (*C.GLchar)(str)) } func BindBuffer(target Enum, b Buffer) { C.glBindBuffer(target.c(), b.c()) } func BindFramebuffer(target Enum, fb Framebuffer) { C.glBindFramebuffer(target.c(), fb.c()) } func BindRenderbuffer(target Enum, rb Renderbuffer) { C.glBindRenderbuffer(target.c(), rb.c()) } func BindTexture(target Enum, t Texture) { C.glBindTexture(target.c(), t.c()) } func BlendColor(red, green, blue, alpha float32) { blendColor(red, green, blue, alpha) } func BlendEquation(mode Enum) { C.glBlendEquation(mode.c()) } func BlendEquationSeparate(modeRGB, modeAlpha Enum) { C.glBlendEquationSeparate(modeRGB.c(), modeAlpha.c()) } func BlendFunc(sfactor, dfactor Enum) { C.glBlendFunc(sfactor.c(), dfactor.c()) } func BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) { C.glBlendFuncSeparate(sfactorRGB.c(), dfactorRGB.c(), sfactorAlpha.c(), dfactorAlpha.c()) } func BufferData(target Enum, src []byte, usage Enum) { C.glBufferData(target.c(), C.GLsizeiptr(len(src)), unsafe.Pointer(&src[0]), usage.c()) } func BufferInit(target Enum, size int, usage Enum) { C.glBufferData(target.c(), C.GLsizeiptr(size), nil, usage.c()) } func BufferSubData(target Enum, offset int, data []byte) { C.glBufferSubData(target.c(), C.GLintptr(offset), C.GLsizeiptr(len(data)), unsafe.Pointer(&data[0])) } func CheckFramebufferStatus(target Enum) Enum { return Enum(C.glCheckFramebufferStatus(target.c())) } func Clear(mask Enum) { C.glClear(C.GLbitfield(mask)) } func ClearColor(red, green, blue, alpha float32) { clearColor(red, green, blue, alpha) } func ClearDepthf(d float32) { clearDepthf(d) } func ClearStencil(s int) { C.glClearStencil(C.GLint(s)) } func ColorMask(red, green, blue, alpha bool) { C.glColorMask(glBoolean(red), glBoolean(green), glBoolean(blue), glBoolean(alpha)) } func CompileShader(s Shader) { C.glCompileShader(s.c()) } func CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) { C.glCompressedTexImage2D(target.c(), C.GLint(level), internalformat.c(), C.GLsizei(width), C.GLsizei(height), C.GLint(border), C.GLsizei(len(data)), unsafe.Pointer(&data[0])) } func CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) { C.glCompressedTexSubImage2D(target.c(), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLsizei(width), C.GLsizei(height), format.c(), C.GLsizei(len(data)), unsafe.Pointer(&data[0])) } func CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) { C.glCopyTexImage2D(target.c(), C.GLint(level), internalformat.c(), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLint(border)) } func CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) { C.glCopyTexSubImage2D(target.c(), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height)) } func CreateBuffer() Buffer { var b Buffer C.glGenBuffers(1, (*C.GLuint)(&b.Value)) return b } func CreateFramebuffer() Framebuffer { var b Framebuffer C.glGenFramebuffers(1, (*C.GLuint)(&b.Value)) return b } func CreateProgram() Program { return Program{Value: uint32(C.glCreateProgram())} } func CreateRenderbuffer() Renderbuffer { var b Renderbuffer C.glGenRenderbuffers(1, (*C.GLuint)(&b.Value)) return b } func CreateShader(ty Enum) Shader { return Shader{Value: uint32(C.glCreateShader(ty.c()))} } func CreateTexture() Texture { var t Texture C.glGenTextures(1, (*C.GLuint)(&t.Value)) return t } func CullFace(mode Enum) { C.glCullFace(mode.c()) } func DeleteBuffer(v Buffer) { C.glDeleteBuffers(1, (*C.GLuint)(&v.Value)) } func DeleteFramebuffer(v Framebuffer) { C.glDeleteFramebuffers(1, (*C.GLuint)(&v.Value)) } func DeleteProgram(p Program) { C.glDeleteProgram(p.c()) } func DeleteRenderbuffer(v Renderbuffer) { C.glDeleteRenderbuffers(1, (*C.GLuint)(&v.Value)) } func DeleteShader(s Shader) { C.glDeleteShader(s.c()) } func DeleteTexture(v Texture) { C.glDeleteTextures(1, (*C.GLuint)(&v.Value)) } func DepthFunc(fn Enum) { C.glDepthFunc(fn.c()) } func DepthMask(flag bool) { C.glDepthMask(glBoolean(flag)) } func DepthRangef(n, f float32) { depthRangef(n, f) } func DetachShader(p Program, s Shader) { C.glDetachShader(p.c(), s.c()) } func Disable(cap Enum) { C.glDisable(cap.c()) } func DisableVertexAttribArray(a Attrib) { C.glDisableVertexAttribArray(a.c()) } func DrawArrays(mode Enum, first, count int) { C.glDrawArrays(mode.c(), C.GLint(first), C.GLsizei(count)) } func DrawElements(mode Enum, count int, ty Enum, offset int) { C.glDrawElements(mode.c(), C.GLsizei(count), ty.c(), unsafe.Pointer(uintptr(offset))) } func Enable(cap Enum) { C.glEnable(cap.c()) } func EnableVertexAttribArray(a Attrib) { C.glEnableVertexAttribArray(a.c()) } func Finish() { C.glFinish() } func Flush() { C.glFlush() } func FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) { C.glFramebufferRenderbuffer(target.c(), attachment.c(), rbTarget.c(), rb.c()) } func FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) { C.glFramebufferTexture2D(target.c(), attachment.c(), texTarget.c(), t.c(), C.GLint(level)) } func FrontFace(mode Enum) { C.glFrontFace(mode.c()) } func GenerateMipmap(target Enum) { C.glGenerateMipmap(target.c()) } func GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) { bufSize := GetProgrami(p, ACTIVE_ATTRIBUTE_MAX_LENGTH) buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var cSize C.GLint var cType C.GLenum C.glGetActiveAttrib(p.c(), C.GLuint(index), C.GLsizei(bufSize), nil, &cSize, &cType, (*C.GLchar)(buf)) return C.GoString((*C.char)(buf)), int(cSize), Enum(cType) } func GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) { bufSize := GetProgrami(p, ACTIVE_UNIFORM_MAX_LENGTH) buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var cSize C.GLint var cType C.GLenum C.glGetActiveUniform(p.c(), C.GLuint(index), C.GLsizei(bufSize), nil, &cSize, &cType, (*C.GLchar)(buf)) return C.GoString((*C.char)(buf)), int(cSize), Enum(cType) } func GetAttachedShaders(p Program) []Shader { shadersLen := GetProgrami(p, ATTACHED_SHADERS) var n C.GLsizei buf := make([]C.GLuint, shadersLen) C.glGetAttachedShaders(p.c(), C.GLsizei(shadersLen), &n, &buf[0]) buf = buf[:int(n)] shaders := make([]Shader, len(buf)) for i, s := range buf { shaders[i] = Shader{Value: uint32(s)} } return shaders } func GetAttribLocation(p Program, name string) Attrib { str := unsafe.Pointer(C.CString(name)) defer C.free(str) return Attrib{Value: uint(C.glGetAttribLocation(p.c(), (*C.GLchar)(str)))} } func GetBooleanv(dst []bool, pname Enum) { buf := make([]C.GLboolean, len(dst)) C.glGetBooleanv(pname.c(), &buf[0]) for i, v := range buf { dst[i] = v != 0 } } func GetFloatv(dst []float32, pname Enum) { C.glGetFloatv(pname.c(), (*C.GLfloat)(&dst[0])) } func GetIntegerv(pname Enum, data []int32) { buf := make([]C.GLint, len(data)) C.glGetIntegerv(pname.c(), &buf[0]) for i, v := range buf { data[i] = int32(v) } } func GetInteger(pname Enum) int { var v C.GLint C.glGetIntegerv(pname.c(), &v) return int(v) } func GetBufferParameteri(target, pname Enum) int { var params C.GLint C.glGetBufferParameteriv(target.c(), pname.c(), ¶ms) return int(params) } func GetError() Enum { return Enum(C.glGetError()) } func GetBoundFramebuffer() Framebuffer { println("GetBoundFramebuffer: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") var b C.GLint C.glGetIntegerv(FRAMEBUFFER_BINDING, &b) return Framebuffer{Value: uint32(b)} } func GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int { var params C.GLint C.glGetFramebufferAttachmentParameteriv(target.c(), attachment.c(), pname.c(), ¶ms) return int(params) } func GetProgrami(p Program, pname Enum) int { var params C.GLint C.glGetProgramiv(p.c(), pname.c(), ¶ms) return int(params) } func GetProgramInfoLog(p Program) string { infoLen := GetProgrami(p, INFO_LOG_LENGTH) buf := C.malloc(C.size_t(infoLen)) C.free(buf) C.glGetProgramInfoLog(p.c(), C.GLsizei(infoLen), nil, (*C.GLchar)(buf)) return C.GoString((*C.char)(buf)) } func GetRenderbufferParameteri(target, pname Enum) int { var params C.GLint C.glGetRenderbufferParameteriv(target.c(), pname.c(), ¶ms) return int(params) } func GetShaderi(s Shader, pname Enum) int { var params C.GLint C.glGetShaderiv(s.c(), pname.c(), ¶ms) return int(params) } func GetShaderInfoLog(s Shader) string { infoLen := GetShaderi(s, INFO_LOG_LENGTH) buf := C.malloc(C.size_t(infoLen)) defer C.free(buf) C.glGetShaderInfoLog(s.c(), C.GLsizei(infoLen), nil, (*C.GLchar)(buf)) return C.GoString((*C.char)(buf)) } func GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) { const glintSize = 4 var cRange [2]C.GLint var cPrecision C.GLint C.glGetShaderPrecisionFormat(shadertype.c(), precisiontype.c(), &cRange[0], &cPrecision) return int(cRange[0]), int(cRange[1]), int(cPrecision) } func GetShaderSource(s Shader) string { sourceLen := GetShaderi(s, SHADER_SOURCE_LENGTH) if sourceLen == 0 { return "" } buf := C.malloc(C.size_t(sourceLen)) defer C.free(buf) C.glGetShaderSource(s.c(), C.GLsizei(sourceLen), nil, (*C.GLchar)(buf)) return C.GoString((*C.char)(buf)) } func GetString(pname Enum) string { // Bounce through unsafe.Pointer, because on some platforms // GetString returns an *unsigned char which doesn't convert. return C.GoString((*C.char)((unsafe.Pointer)(C.glGetString(pname.c())))) } func GetTexParameterfv(dst []float32, target, pname Enum) { C.glGetTexParameterfv(target.c(), pname.c(), (*C.GLfloat)(&dst[0])) } func GetTexParameteriv(dst []int32, target, pname Enum) { C.glGetTexParameteriv(target.c(), pname.c(), (*C.GLint)(&dst[0])) } func GetUniformfv(dst []float32, src Uniform, p Program) { C.glGetUniformfv(p.c(), src.c(), (*C.GLfloat)(&dst[0])) } func GetUniformiv(dst []int32, src Uniform, p Program) { C.glGetUniformiv(p.c(), src.c(), (*C.GLint)(&dst[0])) } func GetUniformLocation(p Program, name string) Uniform { str := unsafe.Pointer(C.CString(name)) defer C.free(str) return Uniform{Value: int32(C.glGetUniformLocation(p.c(), (*C.GLchar)(str)))} } func GetVertexAttribf(src Attrib, pname Enum) float32 { var params C.GLfloat C.glGetVertexAttribfv(src.c(), pname.c(), ¶ms) return float32(params) } func GetVertexAttribfv(dst []float32, src Attrib, pname Enum) { C.glGetVertexAttribfv(src.c(), pname.c(), (*C.GLfloat)(&dst[0])) } func GetVertexAttribi(src Attrib, pname Enum) int32 { var params C.GLint C.glGetVertexAttribiv(src.c(), pname.c(), ¶ms) return int32(params) } func GetVertexAttribiv(dst []int32, src Attrib, pname Enum) { C.glGetVertexAttribiv(src.c(), pname.c(), (*C.GLint)(&dst[0])) } func Hint(target, mode Enum) { C.glHint(target.c(), mode.c()) } func IsBuffer(b Buffer) bool { return C.glIsBuffer(b.c()) != 0 } func IsEnabled(cap Enum) bool { return C.glIsEnabled(cap.c()) != 0 } func IsFramebuffer(fb Framebuffer) bool { return C.glIsFramebuffer(fb.c()) != 0 } func IsProgram(p Program) bool { return C.glIsProgram(p.c()) != 0 } func IsRenderbuffer(rb Renderbuffer) bool { return C.glIsRenderbuffer(rb.c()) != 0 } func IsShader(s Shader) bool { return C.glIsShader(s.c()) != 0 } func IsTexture(t Texture) bool { return C.glIsTexture(t.c()) != 0 } func LineWidth(width float32) { C.glLineWidth(C.GLfloat(width)) } func LinkProgram(p Program) { C.glLinkProgram(p.c()) } func PixelStorei(pname Enum, param int32) { C.glPixelStorei(pname.c(), C.GLint(param)) } func PolygonOffset(factor, units float32) { C.glPolygonOffset(C.GLfloat(factor), C.GLfloat(units)) } func ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) { C.glReadPixels(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), format.c(), ty.c(), unsafe.Pointer(&dst[0])) } func ReleaseShaderCompiler() { C.glReleaseShaderCompiler() } func RenderbufferStorage(target, internalFormat Enum, width, height int) { C.glRenderbufferStorage(target.c(), internalFormat.c(), C.GLsizei(width), C.GLsizei(height)) } func SampleCoverage(value float32, invert bool) { sampleCoverage(value, invert) } func Scissor(x, y, width, height int32) { C.glScissor(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height)) } func ShaderSource(s Shader, src string) { str := (*C.GLchar)(C.CString(src)) defer C.free(unsafe.Pointer(str)) C.glShaderSource(s.c(), 1, &str, nil) } func StencilFunc(fn Enum, ref int, mask uint32) { C.glStencilFunc(fn.c(), C.GLint(ref), C.GLuint(mask)) } func StencilFuncSeparate(face, fn Enum, ref int, mask uint32) { C.glStencilFuncSeparate(face.c(), fn.c(), C.GLint(ref), C.GLuint(mask)) } func StencilMask(mask uint32) { C.glStencilMask(C.GLuint(mask)) } func StencilMaskSeparate(face Enum, mask uint32) { C.glStencilMaskSeparate(face.c(), C.GLuint(mask)) } func StencilOp(fail, zfail, zpass Enum) { C.glStencilOp(fail.c(), zfail.c(), zpass.c()) } func StencilOpSeparate(face, sfail, dpfail, dppass Enum) { C.glStencilOpSeparate(face.c(), sfail.c(), dpfail.c(), dppass.c()) } func TexImage2D(target Enum, level int, width, height int, format Enum, ty Enum, data []byte) { p := unsafe.Pointer(nil) if len(data) > 0 { p = unsafe.Pointer(&data[0]) } C.glTexImage2D(target.c(), C.GLint(level), C.GLint(format), C.GLsizei(width), C.GLsizei(height), 0, format.c(), ty.c(), p) } func TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { C.glTexSubImage2D(target.c(), C.GLint(level), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), format.c(), ty.c(), unsafe.Pointer(&data[0])) } func TexParameterf(target, pname Enum, param float32) { C.glTexParameterf(target.c(), pname.c(), C.GLfloat(param)) } func TexParameterfv(target, pname Enum, params []float32) { C.glTexParameterfv(target.c(), pname.c(), (*C.GLfloat)(¶ms[0])) } func TexParameteri(target, pname Enum, param int) { C.glTexParameteri(target.c(), pname.c(), C.GLint(param)) } func TexParameteriv(target, pname Enum, params []int32) { C.glTexParameteriv(target.c(), pname.c(), (*C.GLint)(¶ms[0])) } func Uniform1f(dst Uniform, v float32) { C.glUniform1f(dst.c(), C.GLfloat(v)) } func Uniform1fv(dst Uniform, src []float32) { C.glUniform1fv(dst.c(), C.GLsizei(len(src)), (*C.GLfloat)(&src[0])) } func Uniform1i(dst Uniform, v int) { C.glUniform1i(dst.c(), C.GLint(v)) } func Uniform1iv(dst Uniform, src []int32) { C.glUniform1iv(dst.c(), C.GLsizei(len(src)), (*C.GLint)(&src[0])) } func Uniform2f(dst Uniform, v0, v1 float32) { C.glUniform2f(dst.c(), C.GLfloat(v0), C.GLfloat(v1)) } func Uniform2fv(dst Uniform, src []float32) { C.glUniform2fv(dst.c(), C.GLsizei(len(src)/2), (*C.GLfloat)(&src[0])) } func Uniform2i(dst Uniform, v0, v1 int) { C.glUniform2i(dst.c(), C.GLint(v0), C.GLint(v1)) } func Uniform2iv(dst Uniform, src []int32) { C.glUniform2iv(dst.c(), C.GLsizei(len(src)/2), (*C.GLint)(&src[0])) } func Uniform3f(dst Uniform, v0, v1, v2 float32) { C.glUniform3f(dst.c(), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2)) } func Uniform3fv(dst Uniform, src []float32) { C.glUniform3fv(dst.c(), C.GLsizei(len(src)/3), (*C.GLfloat)(&src[0])) } func Uniform3i(dst Uniform, v0, v1, v2 int32) { C.glUniform3i(dst.c(), C.GLint(v0), C.GLint(v1), C.GLint(v2)) } func Uniform3iv(dst Uniform, src []int32) { C.glUniform3iv(dst.c(), C.GLsizei(len(src)/3), (*C.GLint)(&src[0])) } func Uniform4f(dst Uniform, v0, v1, v2, v3 float32) { C.glUniform4f(dst.c(), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2), C.GLfloat(v3)) } func Uniform4fv(dst Uniform, src []float32) { C.glUniform4fv(dst.c(), C.GLsizei(len(src)/4), (*C.GLfloat)(&src[0])) } func Uniform4i(dst Uniform, v0, v1, v2, v3 int32) { C.glUniform4i(dst.c(), C.GLint(v0), C.GLint(v1), C.GLint(v2), C.GLint(v3)) } func Uniform4iv(dst Uniform, src []int32) { C.glUniform4iv(dst.c(), C.GLsizei(len(src)/4), (*C.GLint)(&src[0])) } func UniformMatrix2fv(dst Uniform, src []float32) { // OpenGL ES 2 does not support transpose. C.glUniformMatrix2fv(dst.c(), C.GLsizei(len(src)/4), 0, (*C.GLfloat)(&src[0])) } func UniformMatrix3fv(dst Uniform, src []float32) { C.glUniformMatrix3fv(dst.c(), C.GLsizei(len(src)/9), 0, (*C.GLfloat)(&src[0])) } func UniformMatrix4fv(dst Uniform, src []float32) { C.glUniformMatrix4fv(dst.c(), C.GLsizei(len(src)/16), 0, (*C.GLfloat)(&src[0])) } func UseProgram(p Program) { C.glUseProgram(p.c()) } func ValidateProgram(p Program) { C.glValidateProgram(p.c()) } func VertexAttrib1f(dst Attrib, x float32) { C.glVertexAttrib1f(dst.c(), C.GLfloat(x)) } func VertexAttrib1fv(dst Attrib, src []float32) { C.glVertexAttrib1fv(dst.c(), (*C.GLfloat)(&src[0])) } func VertexAttrib2f(dst Attrib, x, y float32) { C.glVertexAttrib2f(dst.c(), C.GLfloat(x), C.GLfloat(y)) } func VertexAttrib2fv(dst Attrib, src []float32) { C.glVertexAttrib2fv(dst.c(), (*C.GLfloat)(&src[0])) } func VertexAttrib3f(dst Attrib, x, y, z float32) { C.glVertexAttrib3f(dst.c(), C.GLfloat(x), C.GLfloat(y), C.GLfloat(z)) } func VertexAttrib3fv(dst Attrib, src []float32) { C.glVertexAttrib3fv(dst.c(), (*C.GLfloat)(&src[0])) } func VertexAttrib4f(dst Attrib, x, y, z, w float32) { C.glVertexAttrib4f(dst.c(), C.GLfloat(x), C.GLfloat(y), C.GLfloat(z), C.GLfloat(w)) } func VertexAttrib4fv(dst Attrib, src []float32) { C.glVertexAttrib4fv(dst.c(), (*C.GLfloat)(&src[0])) } func VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) { n := glBoolean(normalized) s := C.GLsizei(stride) C.glVertexAttribPointer(dst.c(), C.GLint(size), ty.c(), n, s, unsafe.Pointer(uintptr(offset))) } func Viewport(x, y, width, height int) { C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height)) } ================================================ FILE: gl_webgl.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build js package gl import ( "encoding/binary" "math" "github.com/gopherjs/gopherjs/js" ) var ContextWatcher contextWatcher type contextWatcher struct{} func (contextWatcher) OnMakeCurrent(context interface{}) { // context must be a WebGLRenderingContext *js.Object. c = context.(*js.Object) } func (contextWatcher) OnDetach() { c = nil } // c is the current WebGL context, or nil if there is no current context. var c *js.Object func ActiveTexture(texture Enum) { c.Call("activeTexture", texture) } func AttachShader(p Program, s Shader) { c.Call("attachShader", p.Object, s.Object) } func BindAttribLocation(p Program, a Attrib, name string) { c.Call("bindAttribLocation", p.Object, a.Value, name) } func BindBuffer(target Enum, b Buffer) { c.Call("bindBuffer", target, b.Object) } func BindFramebuffer(target Enum, fb Framebuffer) { c.Call("bindFramebuffer", target, fb.Object) } func BindRenderbuffer(target Enum, rb Renderbuffer) { c.Call("bindRenderbuffer", target, rb.Object) } func BindTexture(target Enum, t Texture) { c.Call("bindTexture", target, t.Object) } func BlendColor(red, green, blue, alpha float32) { c.Call("blendColor", red, green, blue, alpha) } func BlendEquation(mode Enum) { c.Call("blendEquation", mode) } func BlendEquationSeparate(modeRGB, modeAlpha Enum) { c.Call("blendEquationSeparate", modeRGB, modeAlpha) } func BlendFunc(sfactor, dfactor Enum) { c.Call("blendFunc", sfactor, dfactor) } func BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) { c.Call("blendFuncSeparate", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha) } func BufferData(target Enum, src []byte, usage Enum) { c.Call("bufferData", target, src, usage) } func BufferInit(target Enum, size int, usage Enum) { c.Call("bufferData", target, size, usage) } func BufferSubData(target Enum, offset int, data []byte) { c.Call("bufferSubData", target, offset, data) } func CheckFramebufferStatus(target Enum) Enum { return Enum(c.Call("checkFramebufferStatus", target).Int()) } func Clear(mask Enum) { c.Call("clear", mask) } func ClearColor(red, green, blue, alpha float32) { c.Call("clearColor", red, green, blue, alpha) } func ClearDepthf(d float32) { c.Call("clearDepth", d) } func ClearStencil(s int) { c.Call("clearStencil", s) } func ColorMask(red, green, blue, alpha bool) { c.Call("colorMask", red, green, blue, alpha) } func CompileShader(s Shader) { c.Call("compileShader", s.Object) } func CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) { c.Call("compressedTexImage2D", target, level, internalformat, width, height, border, data) } func CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) { c.Call("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, data) } func CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) { c.Call("copyTexImage2D", target, level, internalformat, x, y, width, height, border) } func CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) { c.Call("copyTexSubImage2D", target, level, xoffset, yoffset, x, y, width, height) } func CreateBuffer() Buffer { return Buffer{Object: c.Call("createBuffer")} } func CreateFramebuffer() Framebuffer { return Framebuffer{Object: c.Call("createFramebuffer")} } func CreateProgram() Program { return Program{Object: c.Call("createProgram")} } func CreateRenderbuffer() Renderbuffer { return Renderbuffer{Object: c.Call("createRenderbuffer")} } func CreateShader(ty Enum) Shader { return Shader{Object: c.Call("createShader", ty)} } func CreateTexture() Texture { return Texture{Object: c.Call("createTexture")} } func CullFace(mode Enum) { c.Call("cullFace", mode) } func DeleteBuffer(v Buffer) { c.Call("deleteBuffer", v.Object) } func DeleteFramebuffer(v Framebuffer) { c.Call("deleteFramebuffer", v.Object) } func DeleteProgram(p Program) { c.Call("deleteProgram", p.Object) } func DeleteRenderbuffer(v Renderbuffer) { c.Call("deleteRenderbuffer", v.Object) } func DeleteShader(s Shader) { c.Call("deleteShader", s.Object) } func DeleteTexture(v Texture) { c.Call("deleteTexture", v.Object) } func DepthFunc(fn Enum) { c.Call("depthFunc", fn) } func DepthMask(flag bool) { c.Call("depthMask", flag) } func DepthRangef(n, f float32) { c.Call("depthRange", n, f) } func DetachShader(p Program, s Shader) { c.Call("detachShader", p.Object, s.Object) } func Disable(cap Enum) { c.Call("disable", cap) } func DisableVertexAttribArray(a Attrib) { c.Call("disableVertexAttribArray", a.Value) } func DrawArrays(mode Enum, first, count int) { c.Call("drawArrays", mode, first, count) } func DrawElements(mode Enum, count int, ty Enum, offset int) { c.Call("drawElements", mode, count, ty, offset) } func Enable(cap Enum) { c.Call("enable", cap) } func EnableVertexAttribArray(a Attrib) { c.Call("enableVertexAttribArray", a.Value) } func Finish() { c.Call("finish") } func Flush() { c.Call("flush") } func FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) { c.Call("framebufferRenderbuffer", target, attachment, rbTarget, rb.Object) } func FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) { c.Call("framebufferTexture2D", target, attachment, texTarget, t.Object, level) } func FrontFace(mode Enum) { c.Call("frontFace", mode) } func GenerateMipmap(target Enum) { c.Call("generateMipmap", target) } type activeInfo struct { *js.Object Size int `js:"size"` Type int `js:"type"` Name string `js:"name"` } func GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) { ai := activeInfo{Object: c.Call("getActiveAttrib", p.Object, index)} return ai.Name, ai.Size, Enum(ai.Type) } func GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) { ai := activeInfo{Object: c.Call("getActiveUniform", p.Object, index)} return ai.Name, ai.Size, Enum(ai.Type) } func GetAttachedShaders(p Program) []Shader { objs := c.Call("getAttachedShaders", p.Object) shaders := make([]Shader, objs.Length()) for i := 0; i < objs.Length(); i++ { shaders[i] = Shader{Object: objs.Index(i)} } return shaders } func GetAttribLocation(p Program, name string) Attrib { return Attrib{Value: c.Call("getAttribLocation", p.Object, name).Int()} } func GetBooleanv(dst []bool, pname Enum) { println("GetBooleanv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") result := c.Call("getParameter", pname) length := result.Length() for i := 0; i < length; i++ { dst[i] = result.Index(i).Bool() } } func GetFloatv(dst []float32, pname Enum) { println("GetFloatv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") result := c.Call("getParameter", pname) length := result.Length() for i := 0; i < length; i++ { dst[i] = float32(result.Index(i).Float()) } } func GetIntegerv(pname Enum, data []int32) { result := c.Call("getParameter", pname) length := result.Length() for i := 0; i < length; i++ { data[i] = int32(result.Index(i).Int()) } } func GetInteger(pname Enum) int { return c.Call("getParameter", pname).Int() } func GetBufferParameteri(target, pname Enum) int { return c.Call("getBufferParameter", target, pname).Int() } func GetError() Enum { return Enum(c.Call("getError").Int()) } func GetBoundFramebuffer() Framebuffer { return Framebuffer{Object: c.Call("getParameter", FRAMEBUFFER_BINDING)} } func GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int { return c.Call("getFramebufferAttachmentParameter", target, attachment, pname).Int() } func GetProgrami(p Program, pname Enum) int { switch pname { case DELETE_STATUS, LINK_STATUS, VALIDATE_STATUS: if c.Call("getProgramParameter", p.Object, pname).Bool() { return TRUE } return FALSE default: return c.Call("getProgramParameter", p.Object, pname).Int() } } func GetProgramInfoLog(p Program) string { return c.Call("getProgramInfoLog", p.Object).String() } func GetRenderbufferParameteri(target, pname Enum) int { return c.Call("getRenderbufferParameter", target, pname).Int() } func GetShaderi(s Shader, pname Enum) int { switch pname { case DELETE_STATUS, COMPILE_STATUS: if c.Call("getShaderParameter", s.Object, pname).Bool() { return TRUE } return FALSE default: return c.Call("getShaderParameter", s.Object, pname).Int() } } func GetShaderInfoLog(s Shader) string { return c.Call("getShaderInfoLog", s.Object).String() } func GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeMin, rangeMax, precision int) { println("GetShaderPrecisionFormat: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") format := c.Call("getShaderPrecisionFormat", shadertype, precisiontype) rangeMin = format.Get("rangeMin").Int() rangeMax = format.Get("rangeMax").Int() precision = format.Get("precision").Int() return } func GetShaderSource(s Shader) string { return c.Call("getShaderSource", s.Object).String() } func GetString(pname Enum) string { return c.Call("getParameter", pname).String() } func GetTexParameterfv(dst []float32, target, pname Enum) { dst[0] = float32(c.Call("getTexParameter", pname).Float()) } func GetTexParameteriv(dst []int32, target, pname Enum) { dst[0] = int32(c.Call("getTexParameter", pname).Int()) } func GetUniformfv(dst []float32, src Uniform, p Program) { println("GetUniformfv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") result := c.Call("getUniform") length := result.Length() for i := 0; i < length; i++ { dst[i] = float32(result.Index(i).Float()) } } func GetUniformiv(dst []int32, src Uniform, p Program) { println("GetUniformiv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") result := c.Call("getUniform") length := result.Length() for i := 0; i < length; i++ { dst[i] = int32(result.Index(i).Int()) } } func GetUniformLocation(p Program, name string) Uniform { return Uniform{Object: c.Call("getUniformLocation", p.Object, name)} } func GetVertexAttribf(src Attrib, pname Enum) float32 { return float32(c.Call("getVertexAttrib", src.Value, pname).Float()) } func GetVertexAttribfv(dst []float32, src Attrib, pname Enum) { println("GetVertexAttribfv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") result := c.Call("getVertexAttrib") length := result.Length() for i := 0; i < length; i++ { dst[i] = float32(result.Index(i).Float()) } } func GetVertexAttribi(src Attrib, pname Enum) int32 { return int32(c.Call("getVertexAttrib", src.Value, pname).Int()) } func GetVertexAttribiv(dst []int32, src Attrib, pname Enum) { println("GetVertexAttribiv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") result := c.Call("getVertexAttrib") length := result.Length() for i := 0; i < length; i++ { dst[i] = int32(result.Index(i).Int()) } } func Hint(target, mode Enum) { c.Call("hint", target, mode) } func IsBuffer(b Buffer) bool { return c.Call("isBuffer", b.Object).Bool() } func IsEnabled(cap Enum) bool { return c.Call("isEnabled", cap).Bool() } func IsFramebuffer(fb Framebuffer) bool { return c.Call("isFramebuffer", fb.Object).Bool() } func IsProgram(p Program) bool { return c.Call("isProgram", p.Object).Bool() } func IsRenderbuffer(rb Renderbuffer) bool { return c.Call("isRenderbuffer", rb.Object).Bool() } func IsShader(s Shader) bool { return c.Call("isShader", s.Object).Bool() } func IsTexture(t Texture) bool { return c.Call("isTexture", t.Object).Bool() } func LineWidth(width float32) { c.Call("lineWidth", width) } func LinkProgram(p Program) { c.Call("linkProgram", p.Object) } func PixelStorei(pname Enum, param int32) { c.Call("pixelStorei", pname, param) } func PolygonOffset(factor, units float32) { c.Call("polygonOffset", factor, units) } func ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) { println("ReadPixels: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") if ty == Enum(UNSIGNED_BYTE) { c.Call("readPixels", x, y, width, height, format, ty, dst) } else { tmpDst := make([]float32, len(dst)/4) c.Call("readPixels", x, y, width, height, format, ty, tmpDst) for i, f := range tmpDst { binary.LittleEndian.PutUint32(dst[i*4:], math.Float32bits(f)) } } } func ReleaseShaderCompiler() { // do nothing } func RenderbufferStorage(target, internalFormat Enum, width, height int) { c.Call("renderbufferStorage", target, internalFormat, width, height) } func SampleCoverage(value float32, invert bool) { c.Call("sampleCoverage", value, invert) } func Scissor(x, y, width, height int32) { c.Call("scissor", x, y, width, height) } func ShaderSource(s Shader, src string) { c.Call("shaderSource", s.Object, src) } func StencilFunc(fn Enum, ref int, mask uint32) { c.Call("stencilFunc", fn, ref, mask) } func StencilFuncSeparate(face, fn Enum, ref int, mask uint32) { c.Call("stencilFuncSeparate", face, fn, ref, mask) } func StencilMask(mask uint32) { c.Call("stencilMask", mask) } func StencilMaskSeparate(face Enum, mask uint32) { c.Call("stencilMaskSeparate", face, mask) } func StencilOp(fail, zfail, zpass Enum) { c.Call("stencilOp", fail, zfail, zpass) } func StencilOpSeparate(face, sfail, dpfail, dppass Enum) { c.Call("stencilOpSeparate", face, sfail, dpfail, dppass) } func TexImage2D(target Enum, level int, width, height int, format Enum, ty Enum, data []byte) { var p interface{} if data != nil { p = data } c.Call("texImage2D", target, level, format, width, height, 0, format, ty, p) } func TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { c.Call("texSubImage2D", target, level, x, y, width, height, format, ty, data) } func TexParameterf(target, pname Enum, param float32) { c.Call("texParameterf", target, pname, param) } func TexParameterfv(target, pname Enum, params []float32) { println("TexParameterfv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") for _, param := range params { c.Call("texParameterf", target, pname, param) } } func TexParameteri(target, pname Enum, param int) { c.Call("texParameteri", target, pname, param) } func TexParameteriv(target, pname Enum, params []int32) { println("TexParameteriv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)") for _, param := range params { c.Call("texParameteri", target, pname, param) } } func Uniform1f(dst Uniform, v float32) { c.Call("uniform1f", dst.Object, v) } func Uniform1fv(dst Uniform, src []float32) { c.Call("uniform1fv", dst.Object, src) } func Uniform1i(dst Uniform, v int) { c.Call("uniform1i", dst.Object, v) } func Uniform1iv(dst Uniform, src []int32) { c.Call("uniform1iv", dst.Object, src) } func Uniform2f(dst Uniform, v0, v1 float32) { c.Call("uniform2f", dst.Object, v0, v1) } func Uniform2fv(dst Uniform, src []float32) { c.Call("uniform2fv", dst.Object, src) } func Uniform2i(dst Uniform, v0, v1 int) { c.Call("uniform2i", dst.Object, v0, v1) } func Uniform2iv(dst Uniform, src []int32) { c.Call("uniform2iv", dst.Object, src) } func Uniform3f(dst Uniform, v0, v1, v2 float32) { c.Call("uniform3f", dst.Object, v0, v1, v2) } func Uniform3fv(dst Uniform, src []float32) { c.Call("uniform3fv", dst.Object, src) } func Uniform3i(dst Uniform, v0, v1, v2 int32) { c.Call("uniform3i", dst.Object, v0, v1, v2) } func Uniform3iv(dst Uniform, src []int32) { c.Call("uniform3iv", dst.Object, src) } func Uniform4f(dst Uniform, v0, v1, v2, v3 float32) { c.Call("uniform4f", dst.Object, v0, v1, v2, v3) } func Uniform4fv(dst Uniform, src []float32) { c.Call("uniform4fv", dst.Object, src) } func Uniform4i(dst Uniform, v0, v1, v2, v3 int32) { c.Call("uniform4i", dst.Object, v0, v1, v2, v3) } func Uniform4iv(dst Uniform, src []int32) { c.Call("uniform4iv", dst.Object, src) } func UniformMatrix2fv(dst Uniform, src []float32) { c.Call("uniformMatrix2fv", dst.Object, false, src) } func UniformMatrix3fv(dst Uniform, src []float32) { c.Call("uniformMatrix3fv", dst.Object, false, src) } func UniformMatrix4fv(dst Uniform, src []float32) { c.Call("uniformMatrix4fv", dst.Object, false, src) } func UseProgram(p Program) { c.Call("useProgram", p.Object) } func ValidateProgram(p Program) { c.Call("validateProgram", p.Object) } func VertexAttrib1f(dst Attrib, x float32) { c.Call("vertexAttrib1f", dst.Value, x) } func VertexAttrib1fv(dst Attrib, src []float32) { c.Call("vertexAttrib1fv", dst.Value, src) } func VertexAttrib2f(dst Attrib, x, y float32) { c.Call("vertexAttrib2f", dst.Value, x, y) } func VertexAttrib2fv(dst Attrib, src []float32) { c.Call("vertexAttrib2fv", dst.Value, src) } func VertexAttrib3f(dst Attrib, x, y, z float32) { c.Call("vertexAttrib3f", dst.Value, x, y, z) } func VertexAttrib3fv(dst Attrib, src []float32) { c.Call("vertexAttrib3fv", dst.Value, src) } func VertexAttrib4f(dst Attrib, x, y, z, w float32) { c.Call("vertexAttrib4f", dst.Value, x, y, z, w) } func VertexAttrib4fv(dst Attrib, src []float32) { c.Call("vertexAttrib4fv", dst.Value, src) } func VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) { c.Call("vertexAttribPointer", dst.Value, size, ty, normalized, stride, offset) } func Viewport(x, y, width, height int) { c.Call("viewport", x, y, width, height) } ================================================ FILE: glutil/glutil.go ================================================ // Copyright 2014 The Go 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 glutil implements OpenGL utility functions. package glutil import ( "fmt" "github.com/goxjs/gl" ) // CreateProgram creates, compiles, and links a gl.Program. func CreateProgram(vertexSrc, fragmentSrc string) (gl.Program, error) { program := gl.CreateProgram() if !program.Valid() { return gl.Program{}, fmt.Errorf("glutil: no programs available") } vertexShader, err := loadShader(gl.VERTEX_SHADER, vertexSrc) if err != nil { return gl.Program{}, err } fragmentShader, err := loadShader(gl.FRAGMENT_SHADER, fragmentSrc) if err != nil { gl.DeleteShader(vertexShader) return gl.Program{}, err } gl.AttachShader(program, vertexShader) gl.AttachShader(program, fragmentShader) gl.LinkProgram(program) // Flag shaders for deletion when program is unlinked. gl.DeleteShader(vertexShader) gl.DeleteShader(fragmentShader) if gl.GetProgrami(program, gl.LINK_STATUS) == 0 { defer gl.DeleteProgram(program) return gl.Program{}, fmt.Errorf("glutil: %s", gl.GetProgramInfoLog(program)) } return program, nil } func loadShader(shaderType gl.Enum, src string) (gl.Shader, error) { shader := gl.CreateShader(shaderType) if !shader.Valid() { return gl.Shader{}, fmt.Errorf("glutil: could not create shader (type %v)", shaderType) } gl.ShaderSource(shader, src) gl.CompileShader(shader) if gl.GetShaderi(shader, gl.COMPILE_STATUS) == 0 { defer gl.DeleteShader(shader) return gl.Shader{}, fmt.Errorf("shader compile: %s", gl.GetShaderInfoLog(shader)) } return shader, nil } ================================================ FILE: go.mod ================================================ module github.com/goxjs/gl go 1.19 ================================================ FILE: test/context_darwin.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build darwin package test // TODO(crawshaw): Only used in glutil tests for now (cgo is not support in _test.go files). // TODO(crawshaw): Export some kind of Context. Work out what we can offer, where. Maybe just for tests. // TODO(crawshaw): Support android and windows. /* #cgo CFLAGS: -DGL_SILENCE_DEPRECATION #cgo LDFLAGS: -framework OpenGL #import #import void CGCreate(CGLContextObj* ctx) { CGLPixelFormatAttribute attributes[] = { kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, kCGLPFAColorSize, (CGLPixelFormatAttribute)24, kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8, kCGLPFADepthSize, (CGLPixelFormatAttribute)16, kCGLPFAAccelerated, kCGLPFADoubleBuffer, (CGLPixelFormatAttribute) 0 }; CGLPixelFormatObj pix; GLint num; CGLChoosePixelFormat(attributes, &pix, &num); CGLCreateContext(pix, 0, ctx); CGLDestroyPixelFormat(pix); CGLSetCurrentContext(*ctx); CGLLockContext(*ctx); } */ import "C" import ( "runtime" "github.com/goxjs/gl" ) // contextGL holds a copy of the OpenGL Context from thread-local storage. // // Do not move a contextGL between goroutines or OS threads. type contextGL struct { ctx C.CGLContextObj } // createContext creates an OpenGL context, binds it as the current context // stored in thread-local storage, and locks the current goroutine to an os // thread. func createContext() *contextGL { // The OpenGL active context is stored in TLS. runtime.LockOSThread() c := new(contextGL) C.CGCreate(&c.ctx) gl.ContextWatcher.OnMakeCurrent(nil) // Using attribute arrays in OpenGL 3.3 requires the use of a VBA. // But VBAs don't exist in ES 2. So we bind a default one. var id C.GLuint C.glGenVertexArrays(1, &id) C.glBindVertexArray(id) return c } // destroy destroys an OpenGL context and unlocks the current goroutine from // its os thread. func (c *contextGL) destroy() { C.CGLUnlockContext(c.ctx) C.CGLSetCurrentContext(nil) gl.ContextWatcher.OnDetach() C.CGLDestroyContext(c.ctx) c.ctx = nil runtime.UnlockOSThread() } ================================================ FILE: test/context_x11.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build linux,!android package test /* #cgo LDFLAGS: -lEGL #include #include #include void createContext(EGLDisplay *out_dpy, EGLContext *out_ctx, EGLSurface *out_surf) { EGLDisplay e_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!e_dpy) { fprintf(stderr, "eglGetDisplay failed\n"); exit(1); } EGLint e_major, e_minor; if (!eglInitialize(e_dpy, &e_major, &e_minor)) { fprintf(stderr, "eglInitialize failed\n"); exit(1); } eglBindAPI(EGL_OPENGL_ES_API); static const EGLint config_attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_CONFIG_CAVEAT, EGL_NONE, EGL_NONE }; EGLConfig config; EGLint num_configs; if (!eglChooseConfig(e_dpy, config_attribs, &config, 1, &num_configs)) { fprintf(stderr, "eglChooseConfig failed\n"); exit(1); } static const EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLContext e_ctx = eglCreateContext(e_dpy, config, EGL_NO_CONTEXT, ctx_attribs); if (e_ctx == EGL_NO_CONTEXT) { fprintf(stderr, "eglCreateContext failed\n"); exit(1); } static const EGLint pbuf_attribs[] = { EGL_NONE }; EGLSurface e_surf = eglCreatePbufferSurface(e_dpy, config, pbuf_attribs); if (e_surf == EGL_NO_SURFACE) { fprintf(stderr, "eglCreatePbufferSurface failed\n"); exit(1); } if (!eglMakeCurrent(e_dpy, e_surf, e_surf, e_ctx)) { fprintf(stderr, "eglMakeCurrent failed\n"); exit(1); } *out_surf = e_surf; *out_ctx = e_ctx; *out_dpy = e_dpy; } void destroyContext(EGLDisplay e_dpy, EGLContext e_ctx, EGLSurface e_surf) { if (!eglMakeCurrent(e_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { fprintf(stderr, "eglMakeCurrent failed\n"); exit(1); } if (!eglDestroySurface(e_dpy, e_surf)) { fprintf(stderr, "eglDestroySurface failed\n"); exit(1); } if (!eglDestroyContext(e_dpy, e_ctx)) { fprintf(stderr, "eglDestroyContext failed\n"); exit(1); } } */ import "C" import ( "runtime" "github.com/goxjs/gl" ) type contextGL struct { dpy C.EGLDisplay ctx C.EGLContext surf C.EGLSurface } func createContext() *contextGL { runtime.LockOSThread() c := &contextGL{} C.createContext(&c.dpy, &c.ctx, &c.surf) gl.ContextWatcher.OnMakeCurrent(nil) return c } func (c *contextGL) destroy() { C.destroyContext(c.dpy, c.ctx, c.surf) gl.ContextWatcher.OnDetach() runtime.UnlockOSThread() } ================================================ FILE: test/doc.go ================================================ // Package test contains tests for goxjs/gl. package test ================================================ FILE: test/glimage_test.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build darwin linux,!android // TODO(crawshaw): Run tests on other OSs when more contexts are supported. package test import ( "encoding/binary" "image" "image/color" "image/draw" "image/png" "io/ioutil" "os" "path/filepath" "sync" "testing" "github.com/goxjs/gl" "github.com/goxjs/gl/glutil" "golang.org/x/mobile/event/size" "golang.org/x/mobile/exp/f32" "golang.org/x/mobile/geom" ) func TestImage(t *testing.T) { // GL testing strategy: // 1. Create an offscreen framebuffer object. // 2. Configure framebuffer to render to a GL texture. // 3. Run test code: use glimage to draw testdata. // 4. Copy GL texture back into system memory. // 5. Compare to a pre-computed image. f, err := os.Open(filepath.Join("testdata", "testpattern.png")) if err != nil { t.Fatal(err) } defer f.Close() src, _, err := image.Decode(f) if err != nil { t.Fatal(err) } ctxGL := createContext() defer ctxGL.destroy() const ( pixW = 100 pixH = 100 ptW = geom.Pt(50) ptH = geom.Pt(50) ) cfg := size.Event{ WidthPx: pixW, HeightPx: pixH, WidthPt: ptW, HeightPt: ptH, PixelsPerPt: float32(pixW) / float32(ptW), } fBuf := gl.CreateFramebuffer() gl.BindFramebuffer(gl.FRAMEBUFFER, fBuf) colorBuf := gl.CreateRenderbuffer() gl.BindRenderbuffer(gl.RENDERBUFFER, colorBuf) // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glRenderbufferStorage.xml // says that the internalFormat "must be one of the following symbolic constants: // GL_RGBA4, GL_RGB565, GL_RGB5_A1, GL_DEPTH_COMPONENT16, or GL_STENCIL_INDEX8". gl.RenderbufferStorage(gl.RENDERBUFFER, gl.RGB565, pixW, pixH) gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuf) if status := gl.CheckFramebufferStatus(gl.FRAMEBUFFER); status != gl.FRAMEBUFFER_COMPLETE { t.Fatalf("framebuffer create failed: %v", status) } gl.ClearColor(0, 0, 1, 1) // blue gl.Clear(gl.COLOR_BUFFER_BIT) gl.Viewport(0, 0, pixW, pixH) m := NewImage(src.Bounds().Dx(), src.Bounds().Dy()) b := m.RGBA.Bounds() draw.Draw(m.RGBA, b, src, src.Bounds().Min, draw.Src) m.Upload() b.Min.X += 10 b.Max.Y /= 2 // All-integer right-angled triangles offsetting the // box: 24-32-40, 12-16-20. ptTopLeft := geom.Point{0, 24} ptTopRight := geom.Point{32, 0} ptBottomLeft := geom.Point{12, 24 + 16} ptBottomRight := geom.Point{12 + 32, 16} m.Draw(cfg, ptTopLeft, ptTopRight, ptBottomLeft, b) // For unknown reasons, a windowless OpenGL context renders upside- // down. That is, a quad covering the initial viewport spans: // // (-1, -1) ( 1, -1) // (-1, 1) ( 1, 1) // // To avoid modifying live code for tests, we flip the rows // recovered from the renderbuffer. We are not the first: // // http://lists.apple.com/archives/mac-opengl/2010/Jun/msg00080.html got := image.NewRGBA(image.Rect(0, 0, pixW, pixH)) upsideDownPix := make([]byte, len(got.Pix)) gl.ReadPixels(upsideDownPix, 0, 0, pixW, pixH, gl.RGBA, gl.UNSIGNED_BYTE) for y := 0; y < pixH; y++ { i0 := (pixH - 1 - y) * got.Stride i1 := i0 + pixW*4 copy(got.Pix[y*got.Stride:], upsideDownPix[i0:i1]) } drawCross(got, 0, 0) drawCross(got, int(ptTopLeft.X.Px(cfg.PixelsPerPt)), int(ptTopLeft.Y.Px(cfg.PixelsPerPt))) drawCross(got, int(ptBottomRight.X.Px(cfg.PixelsPerPt)), int(ptBottomRight.Y.Px(cfg.PixelsPerPt))) drawCross(got, pixW-1, pixH-1) var wantPath = filepath.Join("testdata", "testpattern-window.png") f, err = os.Open(wantPath) if err != nil { t.Fatal(err) } defer f.Close() wantSrc, _, err := image.Decode(f) if err != nil { t.Fatal(err) } want, ok := wantSrc.(*image.RGBA) if !ok { b := wantSrc.Bounds() want = image.NewRGBA(b) draw.Draw(want, b, wantSrc, b.Min, draw.Src) } if !imageEq(got, want) { // Write out the image we got. f, err = ioutil.TempFile("", "testpattern-window-got") if err != nil { t.Fatal(err) } f.Close() gotPath := f.Name() + ".png" f, err = os.Create(gotPath) if err != nil { t.Fatal(err) } if err := png.Encode(f, got); err != nil { t.Fatal(err) } if err := f.Close(); err != nil { t.Fatal(err) } t.Errorf("got\n%s\nwant\n%s", gotPath, wantPath) } } func drawCross(m *image.RGBA, x, y int) { c := color.RGBA{0xff, 0, 0, 0xff} // red m.SetRGBA(x+0, y-2, c) m.SetRGBA(x+0, y-1, c) m.SetRGBA(x-2, y+0, c) m.SetRGBA(x-1, y+0, c) m.SetRGBA(x+0, y+0, c) m.SetRGBA(x+1, y+0, c) m.SetRGBA(x+2, y+0, c) m.SetRGBA(x+0, y+1, c) m.SetRGBA(x+0, y+2, c) } func eqEpsilon(x, y uint8) bool { const epsilon = 9 return x-y < epsilon || y-x < epsilon } func colorEq(c0, c1 color.RGBA) bool { return eqEpsilon(c0.R, c1.R) && eqEpsilon(c0.G, c1.G) && eqEpsilon(c0.B, c1.B) && eqEpsilon(c0.A, c1.A) } func imageEq(m0, m1 *image.RGBA) bool { b0 := m0.Bounds() b1 := m1.Bounds() if b0 != b1 { return false } badPx := 0 for y := b0.Min.Y; y < b0.Max.Y; y++ { for x := b0.Min.X; x < b0.Max.X; x++ { c0, c1 := m0.At(x, y).(color.RGBA), m1.At(x, y).(color.RGBA) if !colorEq(c0, c1) { badPx++ } } } badFrac := float64(badPx) / float64(b0.Dx()*b0.Dy()) return badFrac < 0.01 } var glimage struct { sync.Once quadXY gl.Buffer quadUV gl.Buffer program gl.Program pos gl.Attrib mvp gl.Uniform uvp gl.Uniform inUV gl.Attrib textureSample gl.Uniform } func glInit() { var err error glimage.program, err = glutil.CreateProgram(vertexShader, fragmentShader) if err != nil { panic(err) } glimage.quadXY = gl.CreateBuffer() glimage.quadUV = gl.CreateBuffer() gl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY) gl.BufferData(gl.ARRAY_BUFFER, quadXYCoords, gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadUV) gl.BufferData(gl.ARRAY_BUFFER, quadUVCoords, gl.STATIC_DRAW) glimage.pos = gl.GetAttribLocation(glimage.program, "pos") glimage.mvp = gl.GetUniformLocation(glimage.program, "mvp") glimage.uvp = gl.GetUniformLocation(glimage.program, "uvp") glimage.inUV = gl.GetAttribLocation(glimage.program, "inUV") glimage.textureSample = gl.GetUniformLocation(glimage.program, "textureSample") } // Image bridges between an *image.RGBA and an OpenGL texture. // // The contents of the embedded *image.RGBA can be uploaded as a // texture and drawn as a 2D quad. // // The number of active Images must fit in the system's OpenGL texture // limit. The typical use of an Image is as a texture atlas. type Image struct { *image.RGBA Texture gl.Texture texWidth int texHeight int } // NewImage creates an Image of the given size. // // Both a host-memory *image.RGBA and a GL texture are created. func NewImage(w, h int) *Image { dx := roundToPower2(w) dy := roundToPower2(h) // TODO(crawshaw): Using VertexAttribPointer we can pass texture // data with a stride, which would let us use the exact number of // pixels on the host instead of the rounded up power 2 size. m := image.NewRGBA(image.Rect(0, 0, dx, dy)) glimage.Do(glInit) img := &Image{ RGBA: m.SubImage(image.Rect(0, 0, w, h)).(*image.RGBA), Texture: gl.CreateTexture(), texWidth: dx, texHeight: dy, } // TODO(crawshaw): We don't have the context on a finalizer. Find a way. // runtime.SetFinalizer(img, func(img *Image) { gl.DeleteTexture(img.Texture) }) gl.BindTexture(gl.TEXTURE_2D, img.Texture) gl.TexImage2D(gl.TEXTURE_2D, 0, dx, dy, gl.RGBA, gl.UNSIGNED_BYTE, nil) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) return img } func roundToPower2(x int) int { x2 := 1 for x2 < x { x2 *= 2 } return x2 } // Upload copies the host image data to the GL device. func (img *Image) Upload() { gl.BindTexture(gl.TEXTURE_2D, img.Texture) gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, img.texWidth, img.texHeight, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix) } // Draw draws the srcBounds part of the image onto a parallelogram, defined by // three of its corners, in the current GL framebuffer. func (img *Image) Draw(c size.Event, topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle) { // TODO(crawshaw): Adjust viewport for the top bar on android? gl.UseProgram(glimage.program) { // We are drawing a parallelogram PQRS, defined by three of its // corners, onto the entire GL framebuffer ABCD. The two quads may // actually be equal, but in the general case, PQRS can be smaller, // and PQRS is not necessarily axis-aligned. // // A +---------------+ B // | P +-----+ Q | // | | | | // | S +-----+ R | // D +---------------+ C // // There are two co-ordinate spaces: geom space and framebuffer space. // In geom space, the ABCD rectangle is: // // (0, 0) (geom.Width, 0) // (0, geom.Height) (geom.Width, geom.Height) // // and the PQRS quad is: // // (topLeft.X, topLeft.Y) (topRight.X, topRight.Y) // (bottomLeft.X, bottomLeft.Y) (implicit, implicit) // // In framebuffer space, the ABCD rectangle is: // // (-1, +1) (+1, +1) // (-1, -1) (+1, -1) // // First of all, convert from geom space to framebuffer space. For // later convenience, we divide everything by 2 here: px2 is half of // the P.X co-ordinate (in framebuffer space). px2 := -0.5 + float32(topLeft.X/c.WidthPt) py2 := +0.5 - float32(topLeft.Y/c.HeightPt) qx2 := -0.5 + float32(topRight.X/c.WidthPt) qy2 := +0.5 - float32(topRight.Y/c.HeightPt) sx2 := -0.5 + float32(bottomLeft.X/c.WidthPt) sy2 := +0.5 - float32(bottomLeft.Y/c.HeightPt) // Next, solve for the affine transformation matrix // [ a00 a01 a02 ] // a = [ a10 a11 a12 ] // [ 0 0 1 ] // that maps A to P: // a × [ -1 +1 1 ]' = [ 2*px2 2*py2 1 ]' // and likewise maps B to Q and D to S. Solving those three constraints // implies that C maps to R, since affine transformations keep parallel // lines parallel. This gives 6 equations in 6 unknowns: // -a00 + a01 + a02 = 2*px2 // -a10 + a11 + a12 = 2*py2 // +a00 + a01 + a02 = 2*qx2 // +a10 + a11 + a12 = 2*qy2 // -a00 - a01 + a02 = 2*sx2 // -a10 - a11 + a12 = 2*sy2 // which gives: // a00 = (2*qx2 - 2*px2) / 2 = qx2 - px2 // and similarly for the other elements of a. writeAffine(glimage.mvp, &f32.Affine{{ qx2 - px2, px2 - sx2, qx2 + sx2, }, { qy2 - py2, py2 - sy2, qy2 + sy2, }}) } { // Mapping texture co-ordinates is similar, except that in texture // space, the ABCD rectangle is: // // (0,0) (1,0) // (0,1) (1,1) // // and the PQRS quad is always axis-aligned. First of all, convert // from pixel space to texture space. w := float32(img.texWidth) h := float32(img.texHeight) px := float32(srcBounds.Min.X-img.Rect.Min.X) / w py := float32(srcBounds.Min.Y-img.Rect.Min.Y) / h qx := float32(srcBounds.Max.X-img.Rect.Min.X) / w sy := float32(srcBounds.Max.Y-img.Rect.Min.Y) / h // Due to axis alignment, qy = py and sx = px. // // The simultaneous equations are: // 0 + 0 + a02 = px // 0 + 0 + a12 = py // a00 + 0 + a02 = qx // a10 + 0 + a12 = qy = py // 0 + a01 + a02 = sx = px // 0 + a11 + a12 = sy writeAffine(glimage.uvp, &f32.Affine{{ qx - px, 0, px, }, { 0, sy - py, py, }}) } gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, img.Texture) gl.Uniform1i(glimage.textureSample, 0) gl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY) gl.EnableVertexAttribArray(glimage.pos) gl.VertexAttribPointer(glimage.pos, 2, gl.FLOAT, false, 0, 0) gl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadUV) gl.EnableVertexAttribArray(glimage.inUV) gl.VertexAttribPointer(glimage.inUV, 2, gl.FLOAT, false, 0, 0) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.DisableVertexAttribArray(glimage.pos) gl.DisableVertexAttribArray(glimage.inUV) } // writeAffine writes the contents of an Affine to a 3x3 matrix GL uniform. func writeAffine(u gl.Uniform, a *f32.Affine) { var m [9]float32 m[0*3+0] = a[0][0] m[0*3+1] = a[1][0] m[0*3+2] = 0 m[1*3+0] = a[0][1] m[1*3+1] = a[1][1] m[1*3+2] = 0 m[2*3+0] = a[0][2] m[2*3+1] = a[1][2] m[2*3+2] = 1 gl.UniformMatrix3fv(u, m[:]) } var quadXYCoords = f32.Bytes(binary.LittleEndian, -1, +1, // top left +1, +1, // top right -1, -1, // bottom left +1, -1, // bottom right ) var quadUVCoords = f32.Bytes(binary.LittleEndian, 0, 0, // top left 1, 0, // top right 0, 1, // bottom left 1, 1, // bottom right ) const vertexShader = `#version 100 uniform mat3 mvp; uniform mat3 uvp; attribute vec3 pos; attribute vec2 inUV; varying vec2 UV; void main() { vec3 p = pos; p.z = 1.0; gl_Position = vec4(mvp * p, 1); UV = (uvp * vec3(inUV, 1)).xy; } ` const fragmentShader = `#version 100 precision mediump float; varying vec2 UV; uniform sampler2D textureSample; void main(){ gl_FragColor = texture2D(textureSample, UV); } ` ================================================ FILE: types_opengl.go ================================================ // +build !js package gl // Enum is equivalent to GLenum, and is normally used with one of the // constants defined in this package. type Enum uint32 // Attrib identifies the location of a specific attribute variable. type Attrib struct { Value uint } // Program identifies a compiled shader program. type Program struct { Value uint32 } // Shader identifies a GLSL shader. type Shader struct { Value uint32 } // Buffer identifies a GL buffer object. type Buffer struct { Value uint32 } // Framebuffer identifies a GL framebuffer. type Framebuffer struct { Value uint32 } // A Renderbuffer is a GL object that holds an image in an internal format. type Renderbuffer struct { Value uint32 } // A Texture identifies a GL texture unit. type Texture struct { Value uint32 } // Uniform identifies the location of a specific uniform variable. type Uniform struct { Value int32 } func (v Attrib) Valid() bool { return v.Value != 0 } func (v Program) Valid() bool { return v.Value != 0 } func (v Shader) Valid() bool { return v.Value != 0 } func (v Buffer) Valid() bool { return v.Value != 0 } func (v Framebuffer) Valid() bool { return v.Value != 0 } func (v Renderbuffer) Valid() bool { return v.Value != 0 } func (v Texture) Valid() bool { return v.Value != 0 } func (v Uniform) Valid() bool { return v.Value != 0 } ================================================ FILE: types_opengles.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ios android package gl /* #cgo ios LDFLAGS: -framework OpenGLES #cgo android LDFLAGS: -lGLESv2 #cgo ios CFLAGS: -Dos_ios #cgo android CFLAGS: -Dos_android #ifdef os_ios #include #endif #ifdef os_android #include #endif void blendColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { glBlendColor(r, g, b, a); } void clearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { glClearColor(r, g, b, a); } void clearDepthf(GLfloat d) { glClearDepthf(d); } void depthRangef(GLfloat n, GLfloat f) { glDepthRangef(n, f); } void sampleCoverage(GLfloat v, GLboolean invert) { glSampleCoverage(v, invert); } */ import "C" type Enum uint32 type Attrib struct { Value uint } type Program struct { Value uint32 } type Shader struct { Value uint32 } type Buffer struct { Value uint32 } type Framebuffer struct { Value uint32 } type Renderbuffer struct { Value uint32 } type Texture struct { Value uint32 } type Uniform struct { Value int32 } func (v Attrib) c() C.GLuint { return C.GLuint(v.Value) } func (v Enum) c() C.GLenum { return C.GLenum(v) } func (v Program) c() C.GLuint { return C.GLuint(v.Value) } func (v Shader) c() C.GLuint { return C.GLuint(v.Value) } func (v Buffer) c() C.GLuint { return C.GLuint(v.Value) } func (v Framebuffer) c() C.GLuint { return C.GLuint(v.Value) } func (v Renderbuffer) c() C.GLuint { return C.GLuint(v.Value) } func (v Texture) c() C.GLuint { return C.GLuint(v.Value) } func (v Uniform) c() C.GLint { return C.GLint(v.Value) } func (v Attrib) Valid() bool { return v.Value != 0 } func (v Program) Valid() bool { return v.Value != 0 } func (v Shader) Valid() bool { return v.Value != 0 } func (v Buffer) Valid() bool { return v.Value != 0 } func (v Framebuffer) Valid() bool { return v.Value != 0 } func (v Renderbuffer) Valid() bool { return v.Value != 0 } func (v Texture) Valid() bool { return v.Value != 0 } func (v Uniform) Valid() bool { return v.Value != 0 } func glBoolean(b bool) C.GLboolean { if b { return TRUE } return FALSE } // Desktop OpenGL and the ES 2/3 APIs have a very slight difference // that is imperceptible to C programmers: some function parameters // use the type Glclampf and some use GLfloat. These two types are // equivalent in size and bit layout (both are single-precision // floats), but it plays havoc with cgo. We adjust the types by using // C wrappers for the problematic functions. func blendColor(r, g, b, a float32) { C.blendColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a)) } func clearColor(r, g, b, a float32) { C.clearColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a)) } func clearDepthf(d float32) { C.clearDepthf(C.GLfloat(d)) } func depthRangef(n, f float32) { C.depthRangef(C.GLfloat(n), C.GLfloat(f)) } func sampleCoverage(v float32, i bool) { C.sampleCoverage(C.GLfloat(v), glBoolean(i)) } ================================================ FILE: types_webgl.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build js package gl import "github.com/gopherjs/gopherjs/js" type Enum int type Attrib struct { Value int } type Program struct { *js.Object } type Shader struct { *js.Object } type Buffer struct { *js.Object } type Framebuffer struct { *js.Object } type Renderbuffer struct { *js.Object } type Texture struct { *js.Object } type Uniform struct { *js.Object } func (v Attrib) Valid() bool { return v.Value != 0 } func (v Program) Valid() bool { return v.Object != nil } func (v Shader) Valid() bool { return v.Object != nil } func (v Buffer) Valid() bool { return v.Object != nil } func (v Framebuffer) Valid() bool { return v.Object != nil } func (v Renderbuffer) Valid() bool { return v.Object != nil } func (v Texture) Valid() bool { return v.Object != nil } func (v Uniform) Valid() bool { return v.Object != nil }