[
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "gl\n==\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/goxjs/gl.svg)](https://pkg.go.dev/github.com/goxjs/gl)\n\nPackage gl is a Go cross-platform binding for OpenGL, with an OpenGL ES 2-like API.\n\nIt supports:\n\n- **macOS**, **Linux** and **Windows** via OpenGL 2.1 backend,\n\n- **iOS** and **Android** via OpenGL ES 2.0 backend,\n\n- **Modern Browsers** (desktop and mobile) via WebGL 1.0 backend.\n\nThis is a fork of golang.org/x/mobile/gl package with [CL 8793](https://go-review.googlesource.com/8793)\nmerged in and Windows support added. This package is fully functional, but may eventually become superceded by\nthe new x/mobile/gl plan. It will exist and be fully supported until it can be safely replaced by a better package.\n\nInstallation\n------------\n\n```sh\ngo get github.com/goxjs/gl\n```\n\nUsage\n-----\n\nThis OpenGL binding has a ContextWatcher, which implements [glfw.ContextWatcher](https://godoc.org/github.com/goxjs/glfw#ContextWatcher)\ninterface. Recommended usage is with github.com/goxjs/glfw package, which accepts a ContextWatcher in its Init, and takes on the responsibility\nof notifying it when context is made current or detached.\n\n```Go\nif err := glfw.Init(gl.ContextWatcher); err != nil {\n\t// Handle error.\n}\ndefer glfw.Terminate()\n```\n\nIf you're not using a ContextWatcher-aware glfw library, you must call methods of gl.ContextWatcher yourself whenever\nyou make a context current or detached.\n\n```Go\nwindow.MakeContextCurrent()\ngl.ContextWatcher.OnMakeCurrent(nil)\n\nglfw.DetachCurrentContext()\ngl.ContextWatcher.OnDetach()\n```\n\nDirectories\n-----------\n\n| Path                                                    | Synopsis                                            |\n|---------------------------------------------------------|-----------------------------------------------------|\n| [glutil](https://pkg.go.dev/github.com/goxjs/gl/glutil) | Package glutil implements OpenGL utility functions. |\n| [test](https://pkg.go.dev/github.com/goxjs/gl/test)     | Package test contains tests for goxjs/gl.           |\n\nLicense\n-------\n\n-\t[BSD-style License](LICENSE)\n"
  },
  {
    "path": "consts.go",
    "content": "// Copyright 2014 The Go Authors.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage gl\n\n/*\nPartially generated from the Khronos OpenGL API specification in XML\nformat, which is covered by the license:\n\n\tCopyright (c) 2013-2014 The Khronos Group Inc.\n\n\tPermission is hereby granted, free of charge, to any person obtaining a\n\tcopy of this software and/or associated documentation files (the\n\t\"Materials\"), to deal in the Materials without restriction, including\n\twithout limitation the rights to use, copy, modify, merge, publish,\n\tdistribute, sublicense, and/or sell copies of the Materials, and to\n\tpermit persons to whom the Materials are furnished to do so, subject to\n\tthe following conditions:\n\n\tThe above copyright notice and this permission notice shall be included\n\tin all copies or substantial portions of the Materials.\n\n\tTHE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n\tMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n\tIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n\tCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n\tTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n\tMATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n\n*/\n\nconst (\n\tPOINTS                                       = 0x0000\n\tLINES                                        = 0x0001\n\tLINE_LOOP                                    = 0x0002\n\tLINE_STRIP                                   = 0x0003\n\tTRIANGLES                                    = 0x0004\n\tTRIANGLE_STRIP                               = 0x0005\n\tTRIANGLE_FAN                                 = 0x0006\n\tSRC_COLOR                                    = 0x0300\n\tONE_MINUS_SRC_COLOR                          = 0x0301\n\tSRC_ALPHA                                    = 0x0302\n\tONE_MINUS_SRC_ALPHA                          = 0x0303\n\tDST_ALPHA                                    = 0x0304\n\tONE_MINUS_DST_ALPHA                          = 0x0305\n\tDST_COLOR                                    = 0x0306\n\tONE_MINUS_DST_COLOR                          = 0x0307\n\tSRC_ALPHA_SATURATE                           = 0x0308\n\tFUNC_ADD                                     = 0x8006\n\tBLEND_EQUATION                               = 0x8009\n\tBLEND_EQUATION_RGB                           = 0x8009\n\tBLEND_EQUATION_ALPHA                         = 0x883D\n\tFUNC_SUBTRACT                                = 0x800A\n\tFUNC_REVERSE_SUBTRACT                        = 0x800B\n\tBLEND_DST_RGB                                = 0x80C8\n\tBLEND_SRC_RGB                                = 0x80C9\n\tBLEND_DST_ALPHA                              = 0x80CA\n\tBLEND_SRC_ALPHA                              = 0x80CB\n\tCONSTANT_COLOR                               = 0x8001\n\tONE_MINUS_CONSTANT_COLOR                     = 0x8002\n\tCONSTANT_ALPHA                               = 0x8003\n\tONE_MINUS_CONSTANT_ALPHA                     = 0x8004\n\tBLEND_COLOR                                  = 0x8005\n\tARRAY_BUFFER                                 = 0x8892\n\tELEMENT_ARRAY_BUFFER                         = 0x8893\n\tARRAY_BUFFER_BINDING                         = 0x8894\n\tELEMENT_ARRAY_BUFFER_BINDING                 = 0x8895\n\tSTREAM_DRAW                                  = 0x88E0\n\tSTATIC_DRAW                                  = 0x88E4\n\tDYNAMIC_DRAW                                 = 0x88E8\n\tBUFFER_SIZE                                  = 0x8764\n\tBUFFER_USAGE                                 = 0x8765\n\tCURRENT_VERTEX_ATTRIB                        = 0x8626\n\tFRONT                                        = 0x0404\n\tBACK                                         = 0x0405\n\tFRONT_AND_BACK                               = 0x0408\n\tTEXTURE_2D                                   = 0x0DE1\n\tCULL_FACE                                    = 0x0B44\n\tBLEND                                        = 0x0BE2\n\tDITHER                                       = 0x0BD0\n\tSTENCIL_TEST                                 = 0x0B90\n\tDEPTH_TEST                                   = 0x0B71\n\tSCISSOR_TEST                                 = 0x0C11\n\tPOLYGON_OFFSET_FILL                          = 0x8037\n\tSAMPLE_ALPHA_TO_COVERAGE                     = 0x809E\n\tSAMPLE_COVERAGE                              = 0x80A0\n\tINVALID_ENUM                                 = 0x0500\n\tINVALID_VALUE                                = 0x0501\n\tINVALID_OPERATION                            = 0x0502\n\tOUT_OF_MEMORY                                = 0x0505\n\tCW                                           = 0x0900\n\tCCW                                          = 0x0901\n\tLINE_WIDTH                                   = 0x0B21\n\tALIASED_POINT_SIZE_RANGE                     = 0x846D\n\tALIASED_LINE_WIDTH_RANGE                     = 0x846E\n\tCULL_FACE_MODE                               = 0x0B45\n\tFRONT_FACE                                   = 0x0B46\n\tDEPTH_RANGE                                  = 0x0B70\n\tDEPTH_WRITEMASK                              = 0x0B72\n\tDEPTH_CLEAR_VALUE                            = 0x0B73\n\tDEPTH_FUNC                                   = 0x0B74\n\tSTENCIL_CLEAR_VALUE                          = 0x0B91\n\tSTENCIL_FUNC                                 = 0x0B92\n\tSTENCIL_FAIL                                 = 0x0B94\n\tSTENCIL_PASS_DEPTH_FAIL                      = 0x0B95\n\tSTENCIL_PASS_DEPTH_PASS                      = 0x0B96\n\tSTENCIL_REF                                  = 0x0B97\n\tSTENCIL_VALUE_MASK                           = 0x0B93\n\tSTENCIL_WRITEMASK                            = 0x0B98\n\tSTENCIL_BACK_FUNC                            = 0x8800\n\tSTENCIL_BACK_FAIL                            = 0x8801\n\tSTENCIL_BACK_PASS_DEPTH_FAIL                 = 0x8802\n\tSTENCIL_BACK_PASS_DEPTH_PASS                 = 0x8803\n\tSTENCIL_BACK_REF                             = 0x8CA3\n\tSTENCIL_BACK_VALUE_MASK                      = 0x8CA4\n\tSTENCIL_BACK_WRITEMASK                       = 0x8CA5\n\tVIEWPORT                                     = 0x0BA2\n\tSCISSOR_BOX                                  = 0x0C10\n\tCOLOR_CLEAR_VALUE                            = 0x0C22\n\tCOLOR_WRITEMASK                              = 0x0C23\n\tUNPACK_ALIGNMENT                             = 0x0CF5\n\tPACK_ALIGNMENT                               = 0x0D05\n\tMAX_TEXTURE_SIZE                             = 0x0D33\n\tMAX_VIEWPORT_DIMS                            = 0x0D3A\n\tSUBPIXEL_BITS                                = 0x0D50\n\tRED_BITS                                     = 0x0D52\n\tGREEN_BITS                                   = 0x0D53\n\tBLUE_BITS                                    = 0x0D54\n\tALPHA_BITS                                   = 0x0D55\n\tDEPTH_BITS                                   = 0x0D56\n\tSTENCIL_BITS                                 = 0x0D57\n\tPOLYGON_OFFSET_UNITS                         = 0x2A00\n\tPOLYGON_OFFSET_FACTOR                        = 0x8038\n\tTEXTURE_BINDING_2D                           = 0x8069\n\tSAMPLE_BUFFERS                               = 0x80A8\n\tSAMPLES                                      = 0x80A9\n\tSAMPLE_COVERAGE_VALUE                        = 0x80AA\n\tSAMPLE_COVERAGE_INVERT                       = 0x80AB\n\tNUM_COMPRESSED_TEXTURE_FORMATS               = 0x86A2\n\tCOMPRESSED_TEXTURE_FORMATS                   = 0x86A3\n\tDONT_CARE                                    = 0x1100\n\tFASTEST                                      = 0x1101\n\tNICEST                                       = 0x1102\n\tGENERATE_MIPMAP_HINT                         = 0x8192\n\tBYTE                                         = 0x1400\n\tUNSIGNED_BYTE                                = 0x1401\n\tSHORT                                        = 0x1402\n\tUNSIGNED_SHORT                               = 0x1403\n\tINT                                          = 0x1404\n\tUNSIGNED_INT                                 = 0x1405\n\tFLOAT                                        = 0x1406\n\tFIXED                                        = 0x140C\n\tDEPTH_COMPONENT                              = 0x1902\n\tALPHA                                        = 0x1906\n\tRGB                                          = 0x1907\n\tRGBA                                         = 0x1908\n\tLUMINANCE                                    = 0x1909\n\tLUMINANCE_ALPHA                              = 0x190A\n\tUNSIGNED_SHORT_4_4_4_4                       = 0x8033\n\tUNSIGNED_SHORT_5_5_5_1                       = 0x8034\n\tUNSIGNED_SHORT_5_6_5                         = 0x8363\n\tMAX_VERTEX_ATTRIBS                           = 0x8869\n\tMAX_VERTEX_UNIFORM_VECTORS                   = 0x8DFB\n\tMAX_VARYING_VECTORS                          = 0x8DFC\n\tMAX_COMBINED_TEXTURE_IMAGE_UNITS             = 0x8B4D\n\tMAX_VERTEX_TEXTURE_IMAGE_UNITS               = 0x8B4C\n\tMAX_TEXTURE_IMAGE_UNITS                      = 0x8872\n\tMAX_FRAGMENT_UNIFORM_VECTORS                 = 0x8DFD\n\tSHADER_TYPE                                  = 0x8B4F\n\tDELETE_STATUS                                = 0x8B80\n\tLINK_STATUS                                  = 0x8B82\n\tVALIDATE_STATUS                              = 0x8B83\n\tATTACHED_SHADERS                             = 0x8B85\n\tACTIVE_UNIFORMS                              = 0x8B86\n\tACTIVE_UNIFORM_MAX_LENGTH                    = 0x8B87\n\tACTIVE_ATTRIBUTES                            = 0x8B89\n\tACTIVE_ATTRIBUTE_MAX_LENGTH                  = 0x8B8A\n\tSHADING_LANGUAGE_VERSION                     = 0x8B8C\n\tCURRENT_PROGRAM                              = 0x8B8D\n\tNEVER                                        = 0x0200\n\tLESS                                         = 0x0201\n\tEQUAL                                        = 0x0202\n\tLEQUAL                                       = 0x0203\n\tGREATER                                      = 0x0204\n\tNOTEQUAL                                     = 0x0205\n\tGEQUAL                                       = 0x0206\n\tALWAYS                                       = 0x0207\n\tKEEP                                         = 0x1E00\n\tREPLACE                                      = 0x1E01\n\tINCR                                         = 0x1E02\n\tDECR                                         = 0x1E03\n\tINVERT                                       = 0x150A\n\tINCR_WRAP                                    = 0x8507\n\tDECR_WRAP                                    = 0x8508\n\tVENDOR                                       = 0x1F00\n\tRENDERER                                     = 0x1F01\n\tVERSION                                      = 0x1F02\n\tEXTENSIONS                                   = 0x1F03\n\tNEAREST                                      = 0x2600\n\tLINEAR                                       = 0x2601\n\tNEAREST_MIPMAP_NEAREST                       = 0x2700\n\tLINEAR_MIPMAP_NEAREST                        = 0x2701\n\tNEAREST_MIPMAP_LINEAR                        = 0x2702\n\tLINEAR_MIPMAP_LINEAR                         = 0x2703\n\tTEXTURE_MAG_FILTER                           = 0x2800\n\tTEXTURE_MIN_FILTER                           = 0x2801\n\tTEXTURE_WRAP_S                               = 0x2802\n\tTEXTURE_WRAP_T                               = 0x2803\n\tTEXTURE                                      = 0x1702\n\tTEXTURE_CUBE_MAP                             = 0x8513\n\tTEXTURE_BINDING_CUBE_MAP                     = 0x8514\n\tTEXTURE_CUBE_MAP_POSITIVE_X                  = 0x8515\n\tTEXTURE_CUBE_MAP_NEGATIVE_X                  = 0x8516\n\tTEXTURE_CUBE_MAP_POSITIVE_Y                  = 0x8517\n\tTEXTURE_CUBE_MAP_NEGATIVE_Y                  = 0x8518\n\tTEXTURE_CUBE_MAP_POSITIVE_Z                  = 0x8519\n\tTEXTURE_CUBE_MAP_NEGATIVE_Z                  = 0x851A\n\tMAX_CUBE_MAP_TEXTURE_SIZE                    = 0x851C\n\tTEXTURE0                                     = 0x84C0\n\tTEXTURE1                                     = 0x84C1\n\tTEXTURE2                                     = 0x84C2\n\tTEXTURE3                                     = 0x84C3\n\tTEXTURE4                                     = 0x84C4\n\tTEXTURE5                                     = 0x84C5\n\tTEXTURE6                                     = 0x84C6\n\tTEXTURE7                                     = 0x84C7\n\tTEXTURE8                                     = 0x84C8\n\tTEXTURE9                                     = 0x84C9\n\tTEXTURE10                                    = 0x84CA\n\tTEXTURE11                                    = 0x84CB\n\tTEXTURE12                                    = 0x84CC\n\tTEXTURE13                                    = 0x84CD\n\tTEXTURE14                                    = 0x84CE\n\tTEXTURE15                                    = 0x84CF\n\tTEXTURE16                                    = 0x84D0\n\tTEXTURE17                                    = 0x84D1\n\tTEXTURE18                                    = 0x84D2\n\tTEXTURE19                                    = 0x84D3\n\tTEXTURE20                                    = 0x84D4\n\tTEXTURE21                                    = 0x84D5\n\tTEXTURE22                                    = 0x84D6\n\tTEXTURE23                                    = 0x84D7\n\tTEXTURE24                                    = 0x84D8\n\tTEXTURE25                                    = 0x84D9\n\tTEXTURE26                                    = 0x84DA\n\tTEXTURE27                                    = 0x84DB\n\tTEXTURE28                                    = 0x84DC\n\tTEXTURE29                                    = 0x84DD\n\tTEXTURE30                                    = 0x84DE\n\tTEXTURE31                                    = 0x84DF\n\tACTIVE_TEXTURE                               = 0x84E0\n\tREPEAT                                       = 0x2901\n\tCLAMP_TO_EDGE                                = 0x812F\n\tMIRRORED_REPEAT                              = 0x8370\n\tVERTEX_ATTRIB_ARRAY_ENABLED                  = 0x8622\n\tVERTEX_ATTRIB_ARRAY_SIZE                     = 0x8623\n\tVERTEX_ATTRIB_ARRAY_STRIDE                   = 0x8624\n\tVERTEX_ATTRIB_ARRAY_TYPE                     = 0x8625\n\tVERTEX_ATTRIB_ARRAY_NORMALIZED               = 0x886A\n\tVERTEX_ATTRIB_ARRAY_POINTER                  = 0x8645\n\tVERTEX_ATTRIB_ARRAY_BUFFER_BINDING           = 0x889F\n\tIMPLEMENTATION_COLOR_READ_TYPE               = 0x8B9A\n\tIMPLEMENTATION_COLOR_READ_FORMAT             = 0x8B9B\n\tCOMPILE_STATUS                               = 0x8B81\n\tINFO_LOG_LENGTH                              = 0x8B84\n\tSHADER_SOURCE_LENGTH                         = 0x8B88\n\tSHADER_COMPILER                              = 0x8DFA\n\tSHADER_BINARY_FORMATS                        = 0x8DF8\n\tNUM_SHADER_BINARY_FORMATS                    = 0x8DF9\n\tLOW_FLOAT                                    = 0x8DF0\n\tMEDIUM_FLOAT                                 = 0x8DF1\n\tHIGH_FLOAT                                   = 0x8DF2\n\tLOW_INT                                      = 0x8DF3\n\tMEDIUM_INT                                   = 0x8DF4\n\tHIGH_INT                                     = 0x8DF5\n\tFRAMEBUFFER                                  = 0x8D40\n\tRENDERBUFFER                                 = 0x8D41\n\tRGBA4                                        = 0x8056\n\tRGB5_A1                                      = 0x8057\n\tRGB565                                       = 0x8D62\n\tDEPTH_COMPONENT16                            = 0x81A5\n\tSTENCIL_INDEX8                               = 0x8D48\n\tRENDERBUFFER_WIDTH                           = 0x8D42\n\tRENDERBUFFER_HEIGHT                          = 0x8D43\n\tRENDERBUFFER_INTERNAL_FORMAT                 = 0x8D44\n\tRENDERBUFFER_RED_SIZE                        = 0x8D50\n\tRENDERBUFFER_GREEN_SIZE                      = 0x8D51\n\tRENDERBUFFER_BLUE_SIZE                       = 0x8D52\n\tRENDERBUFFER_ALPHA_SIZE                      = 0x8D53\n\tRENDERBUFFER_DEPTH_SIZE                      = 0x8D54\n\tRENDERBUFFER_STENCIL_SIZE                    = 0x8D55\n\tFRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           = 0x8CD0\n\tFRAMEBUFFER_ATTACHMENT_OBJECT_NAME           = 0x8CD1\n\tFRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         = 0x8CD2\n\tFRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3\n\tCOLOR_ATTACHMENT0                            = 0x8CE0\n\tDEPTH_ATTACHMENT                             = 0x8D00\n\tSTENCIL_ATTACHMENT                           = 0x8D20\n\tFRAMEBUFFER_COMPLETE                         = 0x8CD5\n\tFRAMEBUFFER_INCOMPLETE_ATTACHMENT            = 0x8CD6\n\tFRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT    = 0x8CD7\n\tFRAMEBUFFER_INCOMPLETE_DIMENSIONS            = 0x8CD9\n\tFRAMEBUFFER_UNSUPPORTED                      = 0x8CDD\n\tFRAMEBUFFER_BINDING                          = 0x8CA6\n\tRENDERBUFFER_BINDING                         = 0x8CA7\n\tMAX_RENDERBUFFER_SIZE                        = 0x84E8\n\tINVALID_FRAMEBUFFER_OPERATION                = 0x0506\n)\n\nconst (\n\tDEPTH_BUFFER_BIT   = 0x00000100\n\tSTENCIL_BUFFER_BIT = 0x00000400\n\tCOLOR_BUFFER_BIT   = 0x00004000\n)\n\nconst (\n\tFLOAT_VEC2   = 0x8B50\n\tFLOAT_VEC3   = 0x8B51\n\tFLOAT_VEC4   = 0x8B52\n\tINT_VEC2     = 0x8B53\n\tINT_VEC3     = 0x8B54\n\tINT_VEC4     = 0x8B55\n\tBOOL         = 0x8B56\n\tBOOL_VEC2    = 0x8B57\n\tBOOL_VEC3    = 0x8B58\n\tBOOL_VEC4    = 0x8B59\n\tFLOAT_MAT2   = 0x8B5A\n\tFLOAT_MAT3   = 0x8B5B\n\tFLOAT_MAT4   = 0x8B5C\n\tSAMPLER_2D   = 0x8B5E\n\tSAMPLER_CUBE = 0x8B60\n)\n\nconst (\n\tFRAGMENT_SHADER = 0x8B30\n\tVERTEX_SHADER   = 0x8B31\n)\n\nconst (\n\tFALSE    = 0\n\tTRUE     = 1\n\tZERO     = 0\n\tONE      = 1\n\tNO_ERROR = 0\n\tNONE     = 0\n)\n"
  },
  {
    "path": "doc.go",
    "content": "// Copyright 2014 The Go Authors.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n/*\nPackage gl is a Go cross-platform binding for OpenGL, with an OpenGL ES 2-like API.\n\nIt supports:\n\n- macOS, Linux and Windows via OpenGL 2.1 backend,\n\n- iOS and Android via OpenGL ES 2.0 backend,\n\n- Modern Browsers (desktop and mobile) via WebGL 1.0 backend.\n\nThis is a fork of golang.org/x/mobile/gl package with [CL 8793](https://go-review.googlesource.com/8793)\nmerged in and Windows support added. This package is fully functional, but may eventually become superceded by\nthe new x/mobile/gl plan. It will exist and be fully supported until it can be safely replaced by a better package.\n\nUsage\n\nThis OpenGL binding has a ContextWatcher, which implements [glfw.ContextWatcher](https://godoc.org/github.com/goxjs/glfw#ContextWatcher)\ninterface. Recommended usage is with github.com/goxjs/glfw package, which accepts a ContextWatcher in its Init, and takes on the responsibility\nof notifying it when context is made current or detached.\n\n\tif err := glfw.Init(gl.ContextWatcher); err != nil {\n\t\t// Handle error.\n\t}\n\tdefer glfw.Terminate()\n\nIf you're not using a ContextWatcher-aware glfw library, you must call methods of gl.ContextWatcher yourself whenever\nyou make a context current or detached.\n\n\twindow.MakeContextCurrent()\n\tgl.ContextWatcher.OnMakeCurrent(nil)\n\n\tglfw.DetachCurrentContext()\n\tgl.ContextWatcher.OnDetach()\n*/\npackage gl\n"
  },
  {
    "path": "gl_opengl.go",
    "content": "// +build !js\n\npackage gl\n\nimport (\n\t\"log\"\n\t\"strings\"\n\t\"unsafe\"\n\n\t\"github.com/go-gl/gl/v2.1/gl\"\n)\n\n// ContextWatcher is this library's context watcher, satisfying glfw.ContextWatcher interface.\n// It must be notified when context is made current or detached.\nvar ContextWatcher = new(contextWatcher)\n\ntype contextWatcher struct {\n\tinitGL bool\n}\n\nfunc (cw *contextWatcher) OnMakeCurrent(context interface{}) {\n\tif !cw.initGL {\n\t\t// Initialise gl bindings using the current context.\n\t\terr := gl.Init()\n\t\tif err != nil {\n\t\t\tlog.Fatalln(\"gl.Init:\", err)\n\t\t}\n\t\tcw.initGL = true\n\t}\n}\nfunc (contextWatcher) OnDetach() {}\n\n// ActiveTexture sets the active texture unit.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glActiveTexture.xhtml\nfunc ActiveTexture(texture Enum) {\n\tgl.ActiveTexture(uint32(texture))\n}\n\n// AttachShader attaches a shader to a program.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glAttachShader.xhtml\nfunc AttachShader(p Program, s Shader) {\n\tgl.AttachShader(p.Value, s.Value)\n}\n\n// BindAttribLocation binds a vertex attribute index with a named\n// variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBindAttribLocation.xhtml\nfunc BindAttribLocation(p Program, a Attrib, name string) {\n\tgl.BindAttribLocation(p.Value, uint32(a.Value), gl.Str(name+\"\\x00\"))\n}\n\n// BindBuffer binds a buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBindBuffer.xhtml\nfunc BindBuffer(target Enum, b Buffer) {\n\tgl.BindBuffer(uint32(target), b.Value)\n}\n\n// BindFramebuffer binds a framebuffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBindFramebuffer.xhtml\nfunc BindFramebuffer(target Enum, fb Framebuffer) {\n\tgl.BindFramebuffer(uint32(target), fb.Value)\n}\n\n// BindRenderbuffer binds a render buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBindRenderbuffer.xhtml\nfunc BindRenderbuffer(target Enum, rb Renderbuffer) {\n\tgl.BindRenderbuffer(uint32(target), rb.Value)\n}\n\n// BindTexture binds a texture.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBindTexture.xhtml\nfunc BindTexture(target Enum, t Texture) {\n\tgl.BindTexture(uint32(target), t.Value)\n}\n\n// BlendColor sets the blend color.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendColor.xhtml\nfunc BlendColor(red, green, blue, alpha float32) {\n\tgl.BlendColor(red, green, blue, alpha)\n}\n\n// BlendEquation sets both RGB and alpha blend equations.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquation.xhtml\nfunc BlendEquation(mode Enum) {\n\tgl.BlendEquation(uint32(mode))\n}\n\n// BlendEquationSeparate sets RGB and alpha blend equations separately.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquationSeparate.xhtml\nfunc BlendEquationSeparate(modeRGB, modeAlpha Enum) {\n\tgl.BlendEquationSeparate(uint32(modeRGB), uint32(modeAlpha))\n}\n\n// BlendFunc sets the pixel blending factors.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFunc.xhtml\nfunc BlendFunc(sfactor, dfactor Enum) {\n\tgl.BlendFunc(uint32(sfactor), uint32(dfactor))\n}\n\n// BlendFunc sets the pixel RGB and alpha blending factors separately.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFuncSeparate.xhtml\nfunc BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) {\n\tgl.BlendFuncSeparate(uint32(sfactorRGB), uint32(dfactorRGB), uint32(sfactorAlpha), uint32(dfactorAlpha))\n}\n\n// BufferData creates a new data store for the bound buffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml\nfunc BufferData(target Enum, src []byte, usage Enum) {\n\tgl.BufferData(uint32(target), int(len(src)), gl.Ptr(&src[0]), uint32(usage))\n}\n\n// BufferInit creates a new unitialized data store for the bound buffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml\nfunc BufferInit(target Enum, size int, usage Enum) {\n\tgl.BufferData(uint32(target), size, nil, uint32(usage))\n}\n\n// BufferSubData sets some of data in the bound buffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferSubData.xhtml\nfunc BufferSubData(target Enum, offset int, data []byte) {\n\tgl.BufferSubData(uint32(target), offset, int(len(data)), gl.Ptr(&data[0]))\n}\n\n// CheckFramebufferStatus reports the completeness status of the\n// active framebuffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCheckFramebufferStatus.xhtml\nfunc CheckFramebufferStatus(target Enum) Enum {\n\treturn Enum(gl.CheckFramebufferStatus(uint32(target)))\n}\n\n// Clear clears the window.\n//\n// The behavior of Clear is influenced by the pixel ownership test,\n// the scissor test, dithering, and the buffer writemasks.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glClear.xhtml\nfunc Clear(mask Enum) {\n\tgl.Clear(uint32(mask))\n}\n\n// ClearColor specifies the RGBA values used to clear color buffers.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glClearColor.xhtml\nfunc ClearColor(red, green, blue, alpha float32) {\n\tgl.ClearColor(red, green, blue, alpha)\n}\n\n// ClearDepthf sets the depth value used to clear the depth buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glClearDepthf.xhtml\nfunc ClearDepthf(d float32) {\n\tgl.ClearDepthf(d)\n}\n\n// ClearStencil sets the index used to clear the stencil buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glClearStencil.xhtml\nfunc ClearStencil(s int) {\n\tgl.ClearStencil(int32(s))\n}\n\n// ColorMask specifies whether color components in the framebuffer\n// can be written.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glColorMask.xhtml\nfunc ColorMask(red, green, blue, alpha bool) {\n\tgl.ColorMask(red, green, blue, alpha)\n}\n\n// CompileShader compiles the source code of s.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCompileShader.xhtml\nfunc CompileShader(s Shader) {\n\tgl.CompileShader(s.Value)\n}\n\n// CompressedTexImage2D writes a compressed 2D texture.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexImage2D.xhtml\nfunc CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) {\n\tgl.CompressedTexImage2D(uint32(target), int32(level), uint32(internalformat), int32(width), int32(height), int32(border), int32(len(data)), gl.Ptr(data))\n}\n\n// CompressedTexSubImage2D writes a subregion of a compressed 2D texture.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexSubImage2D.xhtml\nfunc CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) {\n\tgl.CompressedTexSubImage2D(uint32(target), int32(level), int32(xoffset), int32(yoffset), int32(width), int32(height), uint32(format), int32(len(data)), gl.Ptr(data))\n}\n\n// CopyTexImage2D writes a 2D texture from the current framebuffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexImage2D.xhtml\nfunc CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) {\n\tgl.CopyTexImage2D(uint32(target), int32(level), uint32(internalformat), int32(x), int32(y), int32(width), int32(height), int32(border))\n}\n\n// CopyTexSubImage2D writes a 2D texture subregion from the\n// current framebuffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexSubImage2D.xhtml\nfunc CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) {\n\tgl.CopyTexSubImage2D(uint32(target), int32(level), int32(xoffset), int32(yoffset), int32(x), int32(y), int32(width), int32(height))\n}\n\n// CreateBuffer creates a buffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGenBuffers.xhtml\nfunc CreateBuffer() Buffer {\n\tvar b Buffer\n\tgl.GenBuffers(1, &b.Value)\n\treturn b\n}\n\n// CreateFramebuffer creates a framebuffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGenFramebuffers.xhtml\nfunc CreateFramebuffer() Framebuffer {\n\tvar b Framebuffer\n\tgl.GenFramebuffers(1, &b.Value)\n\treturn b\n}\n\n// CreateProgram creates a new empty program object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateProgram.xhtml\nfunc CreateProgram() Program {\n\treturn Program{Value: uint32(gl.CreateProgram())}\n}\n\n// CreateRenderbuffer create a renderbuffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGenRenderbuffers.xhtml\nfunc CreateRenderbuffer() Renderbuffer {\n\tvar b Renderbuffer\n\tgl.GenRenderbuffers(1, &b.Value)\n\treturn b\n}\n\n// CreateShader creates a new empty shader object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateShader.xhtml\nfunc CreateShader(ty Enum) Shader {\n\treturn Shader{Value: uint32(gl.CreateShader(uint32(ty)))}\n}\n\n// CreateTexture creates a texture object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGenTextures.xhtml\nfunc CreateTexture() Texture {\n\tvar t Texture\n\tgl.GenTextures(1, &t.Value)\n\treturn t\n}\n\n// CullFace specifies which polygons are candidates for culling.\n//\n// Valid modes: FRONT, BACK, FRONT_AND_BACK.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glCullFace.xhtml\nfunc CullFace(mode Enum) {\n\tgl.CullFace(uint32(mode))\n}\n\n// DeleteBuffer deletes the given buffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteBuffers.xhtml\nfunc DeleteBuffer(v Buffer) {\n\tgl.DeleteBuffers(1, &v.Value)\n}\n\n// DeleteFramebuffer deletes the given framebuffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteFramebuffers.xhtml\nfunc DeleteFramebuffer(v Framebuffer) {\n\tgl.DeleteFramebuffers(1, &v.Value)\n}\n\n// DeleteProgram deletes the given program object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteProgram.xhtml\nfunc DeleteProgram(p Program) {\n\tgl.DeleteProgram(p.Value)\n}\n\n// DeleteRenderbuffer deletes the given render buffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteRenderbuffers.xhtml\nfunc DeleteRenderbuffer(v Renderbuffer) {\n\tgl.DeleteRenderbuffers(1, &v.Value)\n}\n\n// DeleteShader deletes shader s.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteShader.xhtml\nfunc DeleteShader(s Shader) {\n\tgl.DeleteShader(s.Value)\n}\n\n// DeleteTexture deletes the given texture object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteTextures.xhtml\nfunc DeleteTexture(v Texture) {\n\tgl.DeleteTextures(1, &v.Value)\n}\n\n// DepthFunc sets the function used for depth buffer comparisons.\n//\n// Valid fn values:\n//\tNEVER\n//\tLESS\n//\tEQUAL\n//\tLEQUAL\n//\tGREATER\n//\tNOTEQUAL\n//\tGEQUAL\n//\tALWAYS\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthFunc.xhtml\nfunc DepthFunc(fn Enum) {\n\tgl.DepthFunc(uint32(fn))\n}\n\n// DepthMask sets the depth buffer enabled for writing.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthMask.xhtml\nfunc DepthMask(flag bool) {\n\tgl.DepthMask(flag)\n}\n\n// DepthRangef sets the mapping from normalized device coordinates to\n// window coordinates.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthRangef.xhtml\nfunc DepthRangef(n, f float32) {\n\tgl.DepthRangef(n, f)\n}\n\n// DetachShader detaches the shader s from the program p.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDetachShader.xhtml\nfunc DetachShader(p Program, s Shader) {\n\tgl.DetachShader(p.Value, s.Value)\n}\n\n// Disable disables various GL capabilities.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDisable.xhtml\nfunc Disable(cap Enum) {\n\tgl.Disable(uint32(cap))\n}\n\n// DisableVertexAttribArray disables a vertex attribute array.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDisableVertexAttribArray.xhtml\nfunc DisableVertexAttribArray(a Attrib) {\n\tgl.DisableVertexAttribArray(uint32(a.Value))\n}\n\n// DrawArrays renders geometric primitives from the bound data.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawArrays.xhtml\nfunc DrawArrays(mode Enum, first, count int) {\n\tgl.DrawArrays(uint32(mode), int32(first), int32(count))\n}\n\n// DrawElements renders primitives from a bound buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawElements.xhtml\nfunc DrawElements(mode Enum, count int, ty Enum, offset int) {\n\tgl.DrawElements(uint32(mode), int32(count), uint32(ty), gl.PtrOffset(offset))\n}\n\n// Enable enables various GL capabilities.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glEnable.xhtml\nfunc Enable(cap Enum) {\n\tgl.Enable(uint32(cap))\n}\n\n// EnableVertexAttribArray enables a vertex attribute array.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glEnableVertexAttribArray.xhtml\nfunc EnableVertexAttribArray(a Attrib) {\n\tgl.EnableVertexAttribArray(uint32(a.Value))\n}\n\n// Finish blocks until the effects of all previously called GL\n// commands are complete.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glFinish.xhtml\nfunc Finish() {\n\tgl.Finish()\n}\n\n// Flush empties all buffers. It does not block.\n//\n// An OpenGL implementation may buffer network communication,\n// the command stream, or data inside the graphics accelerator.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glFlush.xhtml\nfunc Flush() {\n\tgl.Flush()\n}\n\n// FramebufferRenderbuffer attaches rb to the current frame buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferRenderbuffer.xhtml\nfunc FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) {\n\tgl.FramebufferRenderbuffer(uint32(target), uint32(attachment), uint32(rbTarget), rb.Value)\n}\n\n// FramebufferTexture2D attaches the t to the current frame buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferTexture2D.xhtml\nfunc FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) {\n\tgl.FramebufferTexture2D(uint32(target), uint32(attachment), uint32(texTarget), t.Value, int32(level))\n}\n\n// FrontFace defines which polygons are front-facing.\n//\n// Valid modes: CW, CCW.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glFrontFace.xhtml\nfunc FrontFace(mode Enum) {\n\tgl.FrontFace(uint32(mode))\n}\n\n// GenerateMipmap generates mipmaps for the current texture.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGenerateMipmap.xhtml\nfunc GenerateMipmap(target Enum) {\n\tgl.GenerateMipmap(uint32(target))\n}\n\n// GetActiveAttrib returns details about an active attribute variable.\n// A value of 0 for index selects the first active attribute variable.\n// Permissible values for index range from 0 to the number of active\n// attribute variables minus 1.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveAttrib.xhtml\nfunc GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) {\n\tvar length, si int32\n\tvar typ uint32\n\tname = strings.Repeat(\"\\x00\", 256)\n\tcname := gl.Str(name)\n\tgl.GetActiveAttrib(p.Value, uint32(index), int32(len(name)-1), &length, &si, &typ, cname)\n\tname = name[:strings.IndexRune(name, 0)]\n\treturn name, int(si), Enum(typ)\n}\n\n// GetActiveUniform returns details about an active uniform variable.\n// A value of 0 for index selects the first active uniform variable.\n// Permissible values for index range from 0 to the number of active\n// uniform variables minus 1.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveUniform.xhtml\nfunc GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) {\n\tvar length, si int32\n\tvar typ uint32\n\tname = strings.Repeat(\"\\x00\", 256)\n\tcname := gl.Str(name)\n\tgl.GetActiveUniform(p.Value, uint32(index), int32(len(name)-1), &length, &si, &typ, cname)\n\tname = name[:strings.IndexRune(name, 0)]\n\treturn name, int(si), Enum(typ)\n}\n\n// GetAttachedShaders returns the shader objects attached to program p.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttachedShaders.xhtml\nfunc GetAttachedShaders(p Program) []Shader {\n\tlog.Println(\"GetAttachedShaders: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tshadersLen := GetProgrami(p, ATTACHED_SHADERS)\n\tvar n int32\n\tbuf := make([]uint32, shadersLen)\n\tgl.GetAttachedShaders(uint32(p.Value), int32(shadersLen), &n, &buf[0])\n\tbuf = buf[:int(n)]\n\tshaders := make([]Shader, int(n))\n\tfor i, s := range buf {\n\t\tshaders[i] = Shader{Value: uint32(s)}\n\t}\n\treturn shaders\n}\n\n// GetAttribLocation returns the location of an attribute variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttribLocation.xhtml\nfunc GetAttribLocation(p Program, name string) Attrib {\n\treturn Attrib{Value: uint(gl.GetAttribLocation(p.Value, gl.Str(name+\"\\x00\")))}\n}\n\n// GetBooleanv returns the boolean values of parameter pname.\n//\n// Many boolean parameters can be queried more easily using IsEnabled.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml\nfunc GetBooleanv(dst []bool, pname Enum) {\n\tgl.GetBooleanv(uint32(pname), &dst[0])\n}\n\n// GetFloatv returns the float values of parameter pname.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml\nfunc GetFloatv(dst []float32, pname Enum) {\n\tgl.GetFloatv(uint32(pname), &dst[0])\n}\n\n// GetIntegerv returns the int values of parameter pname.\n//\n// Single values may be queried more easily using GetInteger.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml\nfunc GetIntegerv(pname Enum, data []int32) {\n\tgl.GetIntegerv(uint32(pname), &data[0])\n}\n\n// GetInteger returns the int value of parameter pname.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml\nfunc GetInteger(pname Enum) int {\n\tvar data int32\n\tgl.GetIntegerv(uint32(pname), &data)\n\treturn int(data)\n}\n\n// GetBufferParameteri returns a parameter for the active buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetBufferParameteriv.xhtml\nfunc GetBufferParameteri(target, pname Enum) int {\n\tvar params int32\n\tgl.GetBufferParameteriv(uint32(target), uint32(pname), &params)\n\treturn int(params)\n}\n\n// GetError returns the next error.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetError.xhtml\nfunc GetError() Enum {\n\treturn Enum(gl.GetError())\n}\n\n// GetBoundFramebuffer returns the currently bound framebuffer.\n// Use this method instead of gl.GetInteger(gl.FRAMEBUFFER_BINDING) to\n// enable support on all platforms\nfunc GetBoundFramebuffer() Framebuffer {\n\tvar b int32\n\tgl.GetIntegerv(FRAMEBUFFER_BINDING, &b)\n\treturn Framebuffer{Value: uint32(b)}\n}\n\n// GetFramebufferAttachmentParameteri returns attachment parameters\n// for the active framebuffer object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetFramebufferAttachmentParameteriv.xhtml\nfunc GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int {\n\tlog.Println(\"GetFramebufferAttachmentParameteri: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tvar param int32\n\tgl.GetFramebufferAttachmentParameteriv(uint32(target), uint32(attachment), uint32(pname), &param)\n\treturn int(param)\n}\n\n// GetProgrami returns a parameter value for a program.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramiv.xhtml\nfunc GetProgrami(p Program, pname Enum) int {\n\tvar result int32\n\tgl.GetProgramiv(p.Value, uint32(pname), &result)\n\treturn int(result)\n}\n\n// GetProgramInfoLog returns the information log for a program.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramInfoLog.xhtml\nfunc GetProgramInfoLog(p Program) string {\n\tvar logLength int32\n\tgl.GetProgramiv(p.Value, gl.INFO_LOG_LENGTH, &logLength)\n\tif logLength == 0 {\n\t\treturn \"\"\n\t}\n\n\tlogBuffer := make([]uint8, logLength)\n\tgl.GetProgramInfoLog(p.Value, logLength, nil, &logBuffer[0])\n\treturn gl.GoStr(&logBuffer[0])\n}\n\n// GetRenderbufferParameteri returns a parameter value for a render buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetRenderbufferParameteriv.xhtml\nfunc GetRenderbufferParameteri(target, pname Enum) int {\n\tlog.Println(\"GetRenderbufferParameteri: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tvar result int32\n\tgl.GetRenderbufferParameteriv(uint32(target), uint32(pname), &result)\n\treturn int(result)\n}\n\n// GetRenderbufferParameteri returns a parameter value for a shader.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderiv.xhtml\nfunc GetShaderi(s Shader, pname Enum) int {\n\tvar result int32\n\tgl.GetShaderiv(s.Value, uint32(pname), &result)\n\treturn int(result)\n}\n\n// GetShaderInfoLog returns the information log for a shader.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderInfoLog.xhtml\nfunc GetShaderInfoLog(s Shader) string {\n\tvar logLength int32\n\tgl.GetShaderiv(s.Value, gl.INFO_LOG_LENGTH, &logLength)\n\tif logLength == 0 {\n\t\treturn \"\"\n\t}\n\n\tlogBuffer := make([]uint8, logLength)\n\tgl.GetShaderInfoLog(s.Value, logLength, nil, &logBuffer[0])\n\treturn gl.GoStr(&logBuffer[0])\n}\n\n// GetShaderPrecisionFormat returns range and precision limits for\n// shader types.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderPrecisionFormat.xhtml\nfunc GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) {\n\tlog.Println(\"GetShaderPrecisionFormat: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tvar cRange [2]int32\n\tvar cPrecision int32\n\n\tgl.GetShaderPrecisionFormat(uint32(shadertype), uint32(precisiontype), &cRange[0], &cPrecision)\n\treturn int(cRange[0]), int(cRange[1]), int(cPrecision)\n}\n\n// GetShaderSource returns source code of shader s.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderSource.xhtml\nfunc GetShaderSource(s Shader) string {\n\tlog.Println(\"GetShaderSource: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tsourceLen := GetShaderi(s, gl.SHADER_SOURCE_LENGTH)\n\tif sourceLen == 0 {\n\t\treturn \"\"\n\t}\n\tbuf := make([]byte, sourceLen)\n\tgl.GetShaderSource(s.Value, int32(sourceLen), nil, &buf[0])\n\treturn string(buf)\n}\n\n// GetString reports current GL state.\n//\n// Valid name values:\n//\tEXTENSIONS\n//\tRENDERER\n//\tSHADING_LANGUAGE_VERSION\n//\tVENDOR\n//\tVERSION\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetString.xhtml\nfunc GetString(pname Enum) string {\n\treturn gl.GoStr(gl.GetString(uint32(pname)))\n}\n\n// GetTexParameterfv returns the float values of a texture parameter.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml\nfunc GetTexParameterfv(dst []float32, target, pname Enum) {\n\tgl.GetTexParameterfv(uint32(target), uint32(pname), &dst[0])\n}\n\n// GetTexParameteriv returns the int values of a texture parameter.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml\nfunc GetTexParameteriv(dst []int32, target, pname Enum) {\n\tgl.GetTexParameteriv(uint32(target), uint32(pname), &dst[0])\n}\n\n// GetUniformfv returns the float values of a uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml\nfunc GetUniformfv(dst []float32, src Uniform, p Program) {\n\tgl.GetUniformfv(p.Value, src.Value, &dst[0])\n}\n\n// GetUniformiv returns the float values of a uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml\nfunc GetUniformiv(dst []int32, src Uniform, p Program) {\n\tgl.GetUniformiv(p.Value, src.Value, &dst[0])\n}\n\n// GetUniformLocation returns the location of a uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniformLocation.xhtml\nfunc GetUniformLocation(p Program, name string) Uniform {\n\treturn Uniform{Value: gl.GetUniformLocation(p.Value, gl.Str(name+\"\\x00\"))}\n}\n\n// GetVertexAttribf reads the float value of a vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml\nfunc GetVertexAttribf(src Attrib, pname Enum) float32 {\n\tlog.Println(\"GetVertexAttribf: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tvar result float32\n\tgl.GetVertexAttribfv(uint32(src.Value), uint32(pname), &result)\n\treturn result\n}\n\n// GetVertexAttribfv reads float values of a vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml\nfunc GetVertexAttribfv(dst []float32, src Attrib, pname Enum) {\n\tgl.GetVertexAttribfv(uint32(src.Value), uint32(pname), &dst[0])\n}\n\n// GetVertexAttribi reads the int value of a vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml\nfunc GetVertexAttribi(src Attrib, pname Enum) int32 {\n\tvar result int32\n\tgl.GetVertexAttribiv(uint32(src.Value), uint32(pname), &result)\n\treturn result\n}\n\n// GetVertexAttribiv reads int values of a vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml\nfunc GetVertexAttribiv(dst []int32, src Attrib, pname Enum) {\n\tgl.GetVertexAttribiv(uint32(src.Value), uint32(pname), &dst[0])\n}\n\n// Hint sets implementation-specific modes.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glHint.xhtml\nfunc Hint(target, mode Enum) {\n\tgl.Hint(uint32(target), uint32(mode))\n}\n\n// IsBuffer reports if b is a valid buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glIsBuffer.xhtml\nfunc IsBuffer(b Buffer) bool {\n\treturn gl.IsBuffer(b.Value)\n}\n\n// IsEnabled reports if cap is an enabled capability.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glIsEnabled.xhtml\nfunc IsEnabled(cap Enum) bool {\n\treturn gl.IsEnabled(uint32(cap))\n}\n\n// IsFramebuffer reports if fb is a valid frame buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glIsFramebuffer.xhtml\nfunc IsFramebuffer(fb Framebuffer) bool {\n\treturn gl.IsFramebuffer(fb.Value)\n}\n\n// IsProgram reports if p is a valid program object.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glIsProgram.xhtml\nfunc IsProgram(p Program) bool {\n\treturn gl.IsProgram(p.Value)\n}\n\n// IsRenderbuffer reports if rb is a valid render buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glIsRenderbuffer.xhtml\nfunc IsRenderbuffer(rb Renderbuffer) bool {\n\treturn gl.IsRenderbuffer(rb.Value)\n}\n\n// IsShader reports if s is valid shader.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glIsShader.xhtml\nfunc IsShader(s Shader) bool {\n\treturn gl.IsShader(s.Value)\n}\n\n// IsTexture reports if t is a valid texture.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glIsTexture.xhtml\nfunc IsTexture(t Texture) bool {\n\treturn gl.IsTexture(t.Value)\n}\n\n// LineWidth specifies the width of lines.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glLineWidth.xhtml\nfunc LineWidth(width float32) {\n\tgl.LineWidth(width)\n}\n\n// LinkProgram links the specified program.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glLinkProgram.xhtml\nfunc LinkProgram(p Program) {\n\tgl.LinkProgram(p.Value)\n}\n\n// PixelStorei sets pixel storage parameters.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glPixelStorei.xhtml\nfunc PixelStorei(pname Enum, param int32) {\n\tgl.PixelStorei(uint32(pname), param)\n}\n\n// PolygonOffset sets the scaling factors for depth offsets.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glPolygonOffset.xhtml\nfunc PolygonOffset(factor, units float32) {\n\tgl.PolygonOffset(factor, units)\n}\n\n// ReadPixels returns pixel data from a buffer.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glReadPixels.xhtml\nfunc ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) {\n\tgl.ReadPixels(int32(x), int32(y), int32(width), int32(height), uint32(format), uint32(ty), gl.Ptr(&dst[0]))\n}\n\n// ReleaseShaderCompiler frees resources allocated by the shader compiler.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glReleaseShaderCompiler.xhtml\nfunc ReleaseShaderCompiler() {\n\tgl.ReleaseShaderCompiler()\n}\n\n// RenderbufferStorage establishes the data storage, format, and\n// dimensions of a renderbuffer object's image.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glRenderbufferStorage.xhtml\nfunc RenderbufferStorage(target, internalFormat Enum, width, height int) {\n\tgl.RenderbufferStorage(uint32(target), uint32(internalFormat), int32(width), int32(height))\n}\n\n// SampleCoverage sets multisample coverage parameters.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glSampleCoverage.xhtml\nfunc SampleCoverage(value float32, invert bool) {\n\tgl.SampleCoverage(value, invert)\n}\n\n// Scissor defines the scissor box rectangle, in window coordinates.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glScissor.xhtml\nfunc Scissor(x, y, width, height int32) {\n\tgl.Scissor(x, y, width, height)\n}\n\n// ShaderSource sets the source code of s to the given source code.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glShaderSource.xhtml\nfunc ShaderSource(s Shader, src string) {\n\tglsource, free := gl.Strs(src + \"\\x00\")\n\tgl.ShaderSource(s.Value, 1, glsource, nil)\n\tfree()\n}\n\n// StencilFunc sets the front and back stencil test reference value.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFunc.xhtml\nfunc StencilFunc(fn Enum, ref int, mask uint32) {\n\tgl.StencilFunc(uint32(fn), int32(ref), mask)\n}\n\n// StencilFunc sets the front or back stencil test reference value.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFuncSeparate.xhtml\nfunc StencilFuncSeparate(face, fn Enum, ref int, mask uint32) {\n\tgl.StencilFuncSeparate(uint32(face), uint32(fn), int32(ref), mask)\n}\n\n// StencilMask controls the writing of bits in the stencil planes.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMask.xhtml\nfunc StencilMask(mask uint32) {\n\tgl.StencilMask(mask)\n}\n\n// StencilMaskSeparate controls the writing of bits in the stencil planes.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMaskSeparate.xhtml\nfunc StencilMaskSeparate(face Enum, mask uint32) {\n\tgl.StencilMaskSeparate(uint32(face), mask)\n}\n\n// StencilOp sets front and back stencil test actions.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOp.xhtml\nfunc StencilOp(fail, zfail, zpass Enum) {\n\tgl.StencilOp(uint32(fail), uint32(zfail), uint32(zpass))\n}\n\n// StencilOpSeparate sets front or back stencil tests.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOpSeparate.xhtml\nfunc StencilOpSeparate(face, sfail, dpfail, dppass Enum) {\n\tgl.StencilOpSeparate(uint32(face), uint32(sfail), uint32(dpfail), uint32(dppass))\n}\n\n// TexImage2D writes a 2D texture image.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glTexImage2D.xhtml\nfunc TexImage2D(target Enum, level int, width, height int, format Enum, ty Enum, data []byte) {\n\tp := unsafe.Pointer(nil)\n\tif len(data) > 0 {\n\t\tp = gl.Ptr(&data[0])\n\t}\n\tgl.TexImage2D(uint32(target), int32(level), int32(format), int32(width), int32(height), 0, uint32(format), uint32(ty), p)\n}\n\n// TexSubImage2D writes a subregion of a 2D texture image.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glTexSubImage2D.xhtml\nfunc TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {\n\tgl.TexSubImage2D(uint32(target), int32(level), int32(x), int32(y), int32(width), int32(height), uint32(format), uint32(ty), gl.Ptr(&data[0]))\n}\n\n// TexParameterf sets a float texture parameter.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml\nfunc TexParameterf(target, pname Enum, param float32) {\n\tgl.TexParameterf(uint32(target), uint32(pname), param)\n}\n\n// TexParameterfv sets a float texture parameter array.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml\nfunc TexParameterfv(target, pname Enum, params []float32) {\n\tgl.TexParameterfv(uint32(target), uint32(pname), &params[0])\n}\n\n// TexParameteri sets an integer texture parameter.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml\nfunc TexParameteri(target, pname Enum, param int) {\n\tgl.TexParameteri(uint32(target), uint32(pname), int32(param))\n}\n\n// TexParameteriv sets an integer texture parameter array.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml\nfunc TexParameteriv(target, pname Enum, params []int32) {\n\tgl.TexParameteriv(uint32(target), uint32(pname), &params[0])\n}\n\n// Uniform1f writes a float uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform1f(dst Uniform, v float32) {\n\tgl.Uniform1f(dst.Value, v)\n}\n\n// Uniform1fv writes a [len(src)]float uniform array.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform1fv(dst Uniform, src []float32) {\n\tgl.Uniform1fv(dst.Value, int32(len(src)), &src[0])\n}\n\n// Uniform1i writes an int uniform variable.\n//\n// Uniform1i and Uniform1iv are the only two functions that may be used\n// to load uniform variables defined as sampler types. Loading samplers\n// with any other function will result in a INVALID_OPERATION error.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform1i(dst Uniform, v int) {\n\tgl.Uniform1i(dst.Value, int32(v))\n}\n\n// Uniform1iv writes a int uniform array of len(src) elements.\n//\n// Uniform1i and Uniform1iv are the only two functions that may be used\n// to load uniform variables defined as sampler types. Loading samplers\n// with any other function will result in a INVALID_OPERATION error.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform1iv(dst Uniform, src []int32) {\n\tgl.Uniform1iv(dst.Value, int32(len(src)), &src[0])\n}\n\n// Uniform2f writes a vec2 uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform2f(dst Uniform, v0, v1 float32) {\n\tgl.Uniform2f(dst.Value, v0, v1)\n}\n\n// Uniform2fv writes a vec2 uniform array of len(src)/2 elements.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform2fv(dst Uniform, src []float32) {\n\tgl.Uniform2fv(dst.Value, int32(len(src)/2), &src[0])\n}\n\n// Uniform2i writes an ivec2 uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform2i(dst Uniform, v0, v1 int) {\n\tgl.Uniform2i(dst.Value, int32(v0), int32(v1))\n}\n\n// Uniform2iv writes an ivec2 uniform array of len(src)/2 elements.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform2iv(dst Uniform, src []int32) {\n\tgl.Uniform2iv(dst.Value, int32(len(src)/2), &src[0])\n}\n\n// Uniform3f writes a vec3 uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform3f(dst Uniform, v0, v1, v2 float32) {\n\tgl.Uniform3f(dst.Value, v0, v1, v2)\n}\n\n// Uniform3fv writes a vec3 uniform array of len(src)/3 elements.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform3fv(dst Uniform, src []float32) {\n\tgl.Uniform3fv(dst.Value, int32(len(src)/3), &src[0])\n}\n\n// Uniform3i writes an ivec3 uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform3i(dst Uniform, v0, v1, v2 int32) {\n\tgl.Uniform3i(dst.Value, v0, v1, v2)\n}\n\n// Uniform3iv writes an ivec3 uniform array of len(src)/3 elements.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform3iv(dst Uniform, src []int32) {\n\tgl.Uniform3iv(dst.Value, int32(len(src)/3), &src[0])\n}\n\n// Uniform4f writes a vec4 uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {\n\tgl.Uniform4f(dst.Value, v0, v1, v2, v3)\n}\n\n// Uniform4fv writes a vec4 uniform array of len(src)/4 elements.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform4fv(dst Uniform, src []float32) {\n\tgl.Uniform4fv(dst.Value, int32(len(src)/4), &src[0])\n}\n\n// Uniform4i writes an ivec4 uniform variable.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform4i(dst Uniform, v0, v1, v2, v3 int32) {\n\tgl.Uniform4i(dst.Value, v0, v1, v2, v3)\n}\n\n// Uniform4i writes an ivec4 uniform array of len(src)/4 elements.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc Uniform4iv(dst Uniform, src []int32) {\n\tgl.Uniform4iv(dst.Value, int32(len(src)/4), &src[0])\n}\n\n// UniformMatrix2fv writes 2x2 matrices. Each matrix uses four\n// float32 values, so the number of matrices written is len(src)/4.\n//\n// Each matrix must be supplied in column major order.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc UniformMatrix2fv(dst Uniform, src []float32) {\n\tgl.UniformMatrix2fv(dst.Value, int32(len(src)/(2*2)), false, &src[0])\n}\n\n// UniformMatrix3fv writes 3x3 matrices. Each matrix uses nine\n// float32 values, so the number of matrices written is len(src)/9.\n//\n// Each matrix must be supplied in column major order.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc UniformMatrix3fv(dst Uniform, src []float32) {\n\tgl.UniformMatrix3fv(dst.Value, int32(len(src)/(3*3)), false, &src[0])\n}\n\n// UniformMatrix4fv writes 4x4 matrices. Each matrix uses 16\n// float32 values, so the number of matrices written is len(src)/16.\n//\n// Each matrix must be supplied in column major order.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml\nfunc UniformMatrix4fv(dst Uniform, src []float32) {\n\tgl.UniformMatrix4fv(dst.Value, int32(len(src)/(4*4)), false, &src[0])\n}\n\n// UseProgram sets the active program.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glUseProgram.xhtml\nfunc UseProgram(p Program) {\n\tgl.UseProgram(p.Value)\n}\n\n// ValidateProgram checks to see whether the executables contained in\n// program can execute given the current OpenGL state.\n//\n// Typically only used for debugging.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glValidateProgram.xhtml\nfunc ValidateProgram(p Program) {\n\tgl.ValidateProgram(uint32(p.Value))\n}\n\n// VertexAttrib1f writes a float vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib1f(dst Attrib, x float32) {\n\tgl.VertexAttrib1f(uint32(dst.Value), x)\n}\n\n// VertexAttrib1fv writes a float vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib1fv(dst Attrib, src []float32) {\n\tgl.VertexAttrib1fv(uint32(dst.Value), &src[0])\n}\n\n// VertexAttrib2f writes a vec2 vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib2f(dst Attrib, x, y float32) {\n\tgl.VertexAttrib2f(uint32(dst.Value), x, y)\n}\n\n// VertexAttrib2fv writes a vec2 vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib2fv(dst Attrib, src []float32) {\n\tgl.VertexAttrib2fv(uint32(dst.Value), &src[0])\n}\n\n// VertexAttrib3f writes a vec3 vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib3f(dst Attrib, x, y, z float32) {\n\tgl.VertexAttrib3f(uint32(dst.Value), x, y, z)\n}\n\n// VertexAttrib3fv writes a vec3 vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib3fv(dst Attrib, src []float32) {\n\tgl.VertexAttrib3fv(uint32(dst.Value), &src[0])\n}\n\n// VertexAttrib4f writes a vec4 vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib4f(dst Attrib, x, y, z, w float32) {\n\tgl.VertexAttrib4f(uint32(dst.Value), x, y, z, w)\n}\n\n// VertexAttrib4fv writes a vec4 vertex attribute.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml\nfunc VertexAttrib4fv(dst Attrib, src []float32) {\n\tgl.VertexAttrib4fv(uint32(dst.Value), &src[0])\n}\n\n// VertexAttribPointer uses a bound buffer to define vertex attribute data.\n//\n// Direct use of VertexAttribPointer to load data into OpenGL is not\n// supported via the Go bindings. Instead, use BindBuffer with an\n// ARRAY_BUFFER and then fill it using BufferData.\n//\n// The size argument specifies the number of components per attribute,\n// between 1-4. The stride argument specifies the byte offset between\n// consecutive vertex attributes.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttribPointer.xhtml\nfunc VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {\n\tgl.VertexAttribPointer(uint32(dst.Value), int32(size), uint32(ty), normalized, int32(stride), gl.PtrOffset(offset))\n}\n\n// Viewport sets the viewport, an affine transformation that\n// normalizes device coordinates to window coordinates.\n//\n// http://www.khronos.org/opengles/sdk/docs/man3/html/glViewport.xhtml\nfunc Viewport(x, y, width, height int) {\n\tgl.Viewport(int32(x), int32(y), int32(width), int32(height))\n}\n"
  },
  {
    "path": "gl_opengles.go",
    "content": "// Copyright 2014 The Go Authors.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build ios android\n\npackage gl\n\n/*\n#include <stdlib.h>\n\n#ifdef os_ios\n#include <OpenGLES/ES2/glext.h>\n#endif\n#ifdef os_android\n#include <GLES2/gl2.h>\n#endif\n*/\nimport \"C\"\n\nimport \"unsafe\"\n\nvar ContextWatcher contextWatcher\n\ntype contextWatcher struct{}\n\nfunc (contextWatcher) OnMakeCurrent(context interface{}) {}\nfunc (contextWatcher) OnDetach()                         {}\n\nfunc ActiveTexture(texture Enum) {\n\tC.glActiveTexture(texture.c())\n}\n\nfunc AttachShader(p Program, s Shader) {\n\tC.glAttachShader(p.c(), s.c())\n}\n\nfunc BindAttribLocation(p Program, a Attrib, name string) {\n\tstr := unsafe.Pointer(C.CString(name))\n\tdefer C.free(str)\n\tC.glBindAttribLocation(p.c(), a.c(), (*C.GLchar)(str))\n}\n\nfunc BindBuffer(target Enum, b Buffer) {\n\tC.glBindBuffer(target.c(), b.c())\n}\n\nfunc BindFramebuffer(target Enum, fb Framebuffer) {\n\tC.glBindFramebuffer(target.c(), fb.c())\n}\n\nfunc BindRenderbuffer(target Enum, rb Renderbuffer) {\n\tC.glBindRenderbuffer(target.c(), rb.c())\n}\n\nfunc BindTexture(target Enum, t Texture) {\n\tC.glBindTexture(target.c(), t.c())\n}\n\nfunc BlendColor(red, green, blue, alpha float32) {\n\tblendColor(red, green, blue, alpha)\n}\n\nfunc BlendEquation(mode Enum) {\n\tC.glBlendEquation(mode.c())\n}\n\nfunc BlendEquationSeparate(modeRGB, modeAlpha Enum) {\n\tC.glBlendEquationSeparate(modeRGB.c(), modeAlpha.c())\n}\n\nfunc BlendFunc(sfactor, dfactor Enum) {\n\tC.glBlendFunc(sfactor.c(), dfactor.c())\n}\n\nfunc BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) {\n\tC.glBlendFuncSeparate(sfactorRGB.c(), dfactorRGB.c(), sfactorAlpha.c(), dfactorAlpha.c())\n}\n\nfunc BufferData(target Enum, src []byte, usage Enum) {\n\tC.glBufferData(target.c(), C.GLsizeiptr(len(src)), unsafe.Pointer(&src[0]), usage.c())\n}\n\nfunc BufferInit(target Enum, size int, usage Enum) {\n\tC.glBufferData(target.c(), C.GLsizeiptr(size), nil, usage.c())\n}\n\nfunc BufferSubData(target Enum, offset int, data []byte) {\n\tC.glBufferSubData(target.c(), C.GLintptr(offset), C.GLsizeiptr(len(data)), unsafe.Pointer(&data[0]))\n}\n\nfunc CheckFramebufferStatus(target Enum) Enum {\n\treturn Enum(C.glCheckFramebufferStatus(target.c()))\n}\n\nfunc Clear(mask Enum) {\n\tC.glClear(C.GLbitfield(mask))\n}\n\nfunc ClearColor(red, green, blue, alpha float32) {\n\tclearColor(red, green, blue, alpha)\n}\n\nfunc ClearDepthf(d float32) {\n\tclearDepthf(d)\n}\n\nfunc ClearStencil(s int) {\n\tC.glClearStencil(C.GLint(s))\n}\n\nfunc ColorMask(red, green, blue, alpha bool) {\n\tC.glColorMask(glBoolean(red), glBoolean(green), glBoolean(blue), glBoolean(alpha))\n}\n\nfunc CompileShader(s Shader) {\n\tC.glCompileShader(s.c())\n}\n\nfunc CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) {\n\tC.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]))\n}\n\nfunc CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) {\n\tC.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]))\n}\n\nfunc CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) {\n\tC.glCopyTexImage2D(target.c(), C.GLint(level), internalformat.c(), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLint(border))\n}\n\nfunc CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) {\n\tC.glCopyTexSubImage2D(target.c(), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))\n}\n\nfunc CreateBuffer() Buffer {\n\tvar b Buffer\n\tC.glGenBuffers(1, (*C.GLuint)(&b.Value))\n\treturn b\n}\n\nfunc CreateFramebuffer() Framebuffer {\n\tvar b Framebuffer\n\tC.glGenFramebuffers(1, (*C.GLuint)(&b.Value))\n\treturn b\n}\n\nfunc CreateProgram() Program {\n\treturn Program{Value: uint32(C.glCreateProgram())}\n}\n\nfunc CreateRenderbuffer() Renderbuffer {\n\tvar b Renderbuffer\n\tC.glGenRenderbuffers(1, (*C.GLuint)(&b.Value))\n\treturn b\n}\n\nfunc CreateShader(ty Enum) Shader {\n\treturn Shader{Value: uint32(C.glCreateShader(ty.c()))}\n}\n\nfunc CreateTexture() Texture {\n\tvar t Texture\n\tC.glGenTextures(1, (*C.GLuint)(&t.Value))\n\treturn t\n}\n\nfunc CullFace(mode Enum) {\n\tC.glCullFace(mode.c())\n}\n\nfunc DeleteBuffer(v Buffer) {\n\tC.glDeleteBuffers(1, (*C.GLuint)(&v.Value))\n}\n\nfunc DeleteFramebuffer(v Framebuffer) {\n\tC.glDeleteFramebuffers(1, (*C.GLuint)(&v.Value))\n}\n\nfunc DeleteProgram(p Program) {\n\tC.glDeleteProgram(p.c())\n}\n\nfunc DeleteRenderbuffer(v Renderbuffer) {\n\tC.glDeleteRenderbuffers(1, (*C.GLuint)(&v.Value))\n}\n\nfunc DeleteShader(s Shader) {\n\tC.glDeleteShader(s.c())\n}\n\nfunc DeleteTexture(v Texture) {\n\tC.glDeleteTextures(1, (*C.GLuint)(&v.Value))\n}\n\nfunc DepthFunc(fn Enum) {\n\tC.glDepthFunc(fn.c())\n}\n\nfunc DepthMask(flag bool) {\n\tC.glDepthMask(glBoolean(flag))\n}\n\nfunc DepthRangef(n, f float32) {\n\tdepthRangef(n, f)\n}\n\nfunc DetachShader(p Program, s Shader) {\n\tC.glDetachShader(p.c(), s.c())\n}\n\nfunc Disable(cap Enum) {\n\tC.glDisable(cap.c())\n}\n\nfunc DisableVertexAttribArray(a Attrib) {\n\tC.glDisableVertexAttribArray(a.c())\n}\n\nfunc DrawArrays(mode Enum, first, count int) {\n\tC.glDrawArrays(mode.c(), C.GLint(first), C.GLsizei(count))\n}\n\nfunc DrawElements(mode Enum, count int, ty Enum, offset int) {\n\tC.glDrawElements(mode.c(), C.GLsizei(count), ty.c(), unsafe.Pointer(uintptr(offset)))\n}\n\nfunc Enable(cap Enum) {\n\tC.glEnable(cap.c())\n}\n\nfunc EnableVertexAttribArray(a Attrib) {\n\tC.glEnableVertexAttribArray(a.c())\n}\n\nfunc Finish() {\n\tC.glFinish()\n}\n\nfunc Flush() {\n\tC.glFlush()\n}\n\nfunc FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) {\n\tC.glFramebufferRenderbuffer(target.c(), attachment.c(), rbTarget.c(), rb.c())\n}\n\nfunc FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) {\n\tC.glFramebufferTexture2D(target.c(), attachment.c(), texTarget.c(), t.c(), C.GLint(level))\n}\n\nfunc FrontFace(mode Enum) {\n\tC.glFrontFace(mode.c())\n}\n\nfunc GenerateMipmap(target Enum) {\n\tC.glGenerateMipmap(target.c())\n}\n\nfunc GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) {\n\tbufSize := GetProgrami(p, ACTIVE_ATTRIBUTE_MAX_LENGTH)\n\tbuf := C.malloc(C.size_t(bufSize))\n\tdefer C.free(buf)\n\n\tvar cSize C.GLint\n\tvar cType C.GLenum\n\tC.glGetActiveAttrib(p.c(), C.GLuint(index), C.GLsizei(bufSize), nil, &cSize, &cType, (*C.GLchar)(buf))\n\treturn C.GoString((*C.char)(buf)), int(cSize), Enum(cType)\n}\n\nfunc GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) {\n\tbufSize := GetProgrami(p, ACTIVE_UNIFORM_MAX_LENGTH)\n\tbuf := C.malloc(C.size_t(bufSize))\n\tdefer C.free(buf)\n\n\tvar cSize C.GLint\n\tvar cType C.GLenum\n\n\tC.glGetActiveUniform(p.c(), C.GLuint(index), C.GLsizei(bufSize), nil, &cSize, &cType, (*C.GLchar)(buf))\n\treturn C.GoString((*C.char)(buf)), int(cSize), Enum(cType)\n}\n\nfunc GetAttachedShaders(p Program) []Shader {\n\tshadersLen := GetProgrami(p, ATTACHED_SHADERS)\n\tvar n C.GLsizei\n\tbuf := make([]C.GLuint, shadersLen)\n\tC.glGetAttachedShaders(p.c(), C.GLsizei(shadersLen), &n, &buf[0])\n\tbuf = buf[:int(n)]\n\tshaders := make([]Shader, len(buf))\n\tfor i, s := range buf {\n\t\tshaders[i] = Shader{Value: uint32(s)}\n\t}\n\treturn shaders\n}\n\nfunc GetAttribLocation(p Program, name string) Attrib {\n\tstr := unsafe.Pointer(C.CString(name))\n\tdefer C.free(str)\n\treturn Attrib{Value: uint(C.glGetAttribLocation(p.c(), (*C.GLchar)(str)))}\n}\n\nfunc GetBooleanv(dst []bool, pname Enum) {\n\tbuf := make([]C.GLboolean, len(dst))\n\tC.glGetBooleanv(pname.c(), &buf[0])\n\tfor i, v := range buf {\n\t\tdst[i] = v != 0\n\t}\n}\n\nfunc GetFloatv(dst []float32, pname Enum) {\n\tC.glGetFloatv(pname.c(), (*C.GLfloat)(&dst[0]))\n}\n\nfunc GetIntegerv(pname Enum, data []int32) {\n\tbuf := make([]C.GLint, len(data))\n\tC.glGetIntegerv(pname.c(), &buf[0])\n\tfor i, v := range buf {\n\t\tdata[i] = int32(v)\n\t}\n}\n\nfunc GetInteger(pname Enum) int {\n\tvar v C.GLint\n\tC.glGetIntegerv(pname.c(), &v)\n\treturn int(v)\n}\n\nfunc GetBufferParameteri(target, pname Enum) int {\n\tvar params C.GLint\n\tC.glGetBufferParameteriv(target.c(), pname.c(), &params)\n\treturn int(params)\n}\n\nfunc GetError() Enum {\n\treturn Enum(C.glGetError())\n}\n\nfunc GetBoundFramebuffer() Framebuffer {\n\tprintln(\"GetBoundFramebuffer: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tvar b C.GLint\n\tC.glGetIntegerv(FRAMEBUFFER_BINDING, &b)\n\treturn Framebuffer{Value: uint32(b)}\n}\n\nfunc GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int {\n\tvar params C.GLint\n\tC.glGetFramebufferAttachmentParameteriv(target.c(), attachment.c(), pname.c(), &params)\n\treturn int(params)\n}\n\nfunc GetProgrami(p Program, pname Enum) int {\n\tvar params C.GLint\n\tC.glGetProgramiv(p.c(), pname.c(), &params)\n\treturn int(params)\n}\n\nfunc GetProgramInfoLog(p Program) string {\n\tinfoLen := GetProgrami(p, INFO_LOG_LENGTH)\n\tbuf := C.malloc(C.size_t(infoLen))\n\tC.free(buf)\n\tC.glGetProgramInfoLog(p.c(), C.GLsizei(infoLen), nil, (*C.GLchar)(buf))\n\treturn C.GoString((*C.char)(buf))\n}\n\nfunc GetRenderbufferParameteri(target, pname Enum) int {\n\tvar params C.GLint\n\tC.glGetRenderbufferParameteriv(target.c(), pname.c(), &params)\n\treturn int(params)\n}\n\nfunc GetShaderi(s Shader, pname Enum) int {\n\tvar params C.GLint\n\tC.glGetShaderiv(s.c(), pname.c(), &params)\n\treturn int(params)\n}\n\nfunc GetShaderInfoLog(s Shader) string {\n\tinfoLen := GetShaderi(s, INFO_LOG_LENGTH)\n\tbuf := C.malloc(C.size_t(infoLen))\n\tdefer C.free(buf)\n\tC.glGetShaderInfoLog(s.c(), C.GLsizei(infoLen), nil, (*C.GLchar)(buf))\n\treturn C.GoString((*C.char)(buf))\n}\n\nfunc GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) {\n\tconst glintSize = 4\n\tvar cRange [2]C.GLint\n\tvar cPrecision C.GLint\n\n\tC.glGetShaderPrecisionFormat(shadertype.c(), precisiontype.c(), &cRange[0], &cPrecision)\n\treturn int(cRange[0]), int(cRange[1]), int(cPrecision)\n}\n\nfunc GetShaderSource(s Shader) string {\n\tsourceLen := GetShaderi(s, SHADER_SOURCE_LENGTH)\n\tif sourceLen == 0 {\n\t\treturn \"\"\n\t}\n\tbuf := C.malloc(C.size_t(sourceLen))\n\tdefer C.free(buf)\n\tC.glGetShaderSource(s.c(), C.GLsizei(sourceLen), nil, (*C.GLchar)(buf))\n\treturn C.GoString((*C.char)(buf))\n}\n\nfunc GetString(pname Enum) string {\n\t// Bounce through unsafe.Pointer, because on some platforms\n\t// GetString returns an *unsigned char which doesn't convert.\n\treturn C.GoString((*C.char)((unsafe.Pointer)(C.glGetString(pname.c()))))\n}\n\nfunc GetTexParameterfv(dst []float32, target, pname Enum) {\n\tC.glGetTexParameterfv(target.c(), pname.c(), (*C.GLfloat)(&dst[0]))\n}\n\nfunc GetTexParameteriv(dst []int32, target, pname Enum) {\n\tC.glGetTexParameteriv(target.c(), pname.c(), (*C.GLint)(&dst[0]))\n}\n\nfunc GetUniformfv(dst []float32, src Uniform, p Program) {\n\tC.glGetUniformfv(p.c(), src.c(), (*C.GLfloat)(&dst[0]))\n}\n\nfunc GetUniformiv(dst []int32, src Uniform, p Program) {\n\tC.glGetUniformiv(p.c(), src.c(), (*C.GLint)(&dst[0]))\n}\n\nfunc GetUniformLocation(p Program, name string) Uniform {\n\tstr := unsafe.Pointer(C.CString(name))\n\tdefer C.free(str)\n\treturn Uniform{Value: int32(C.glGetUniformLocation(p.c(), (*C.GLchar)(str)))}\n}\n\nfunc GetVertexAttribf(src Attrib, pname Enum) float32 {\n\tvar params C.GLfloat\n\tC.glGetVertexAttribfv(src.c(), pname.c(), &params)\n\treturn float32(params)\n}\n\nfunc GetVertexAttribfv(dst []float32, src Attrib, pname Enum) {\n\tC.glGetVertexAttribfv(src.c(), pname.c(), (*C.GLfloat)(&dst[0]))\n}\n\nfunc GetVertexAttribi(src Attrib, pname Enum) int32 {\n\tvar params C.GLint\n\tC.glGetVertexAttribiv(src.c(), pname.c(), &params)\n\treturn int32(params)\n}\n\nfunc GetVertexAttribiv(dst []int32, src Attrib, pname Enum) {\n\tC.glGetVertexAttribiv(src.c(), pname.c(), (*C.GLint)(&dst[0]))\n}\n\nfunc Hint(target, mode Enum) {\n\tC.glHint(target.c(), mode.c())\n}\n\nfunc IsBuffer(b Buffer) bool {\n\treturn C.glIsBuffer(b.c()) != 0\n}\n\nfunc IsEnabled(cap Enum) bool {\n\treturn C.glIsEnabled(cap.c()) != 0\n}\n\nfunc IsFramebuffer(fb Framebuffer) bool {\n\treturn C.glIsFramebuffer(fb.c()) != 0\n}\n\nfunc IsProgram(p Program) bool {\n\treturn C.glIsProgram(p.c()) != 0\n}\n\nfunc IsRenderbuffer(rb Renderbuffer) bool {\n\treturn C.glIsRenderbuffer(rb.c()) != 0\n}\n\nfunc IsShader(s Shader) bool {\n\treturn C.glIsShader(s.c()) != 0\n}\n\nfunc IsTexture(t Texture) bool {\n\treturn C.glIsTexture(t.c()) != 0\n}\n\nfunc LineWidth(width float32) {\n\tC.glLineWidth(C.GLfloat(width))\n}\n\nfunc LinkProgram(p Program) {\n\tC.glLinkProgram(p.c())\n}\n\nfunc PixelStorei(pname Enum, param int32) {\n\tC.glPixelStorei(pname.c(), C.GLint(param))\n}\n\nfunc PolygonOffset(factor, units float32) {\n\tC.glPolygonOffset(C.GLfloat(factor), C.GLfloat(units))\n}\n\nfunc ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) {\n\tC.glReadPixels(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), format.c(), ty.c(), unsafe.Pointer(&dst[0]))\n}\n\nfunc ReleaseShaderCompiler() {\n\tC.glReleaseShaderCompiler()\n}\n\nfunc RenderbufferStorage(target, internalFormat Enum, width, height int) {\n\tC.glRenderbufferStorage(target.c(), internalFormat.c(), C.GLsizei(width), C.GLsizei(height))\n}\n\nfunc SampleCoverage(value float32, invert bool) {\n\tsampleCoverage(value, invert)\n}\n\nfunc Scissor(x, y, width, height int32) {\n\tC.glScissor(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))\n}\n\nfunc ShaderSource(s Shader, src string) {\n\tstr := (*C.GLchar)(C.CString(src))\n\tdefer C.free(unsafe.Pointer(str))\n\tC.glShaderSource(s.c(), 1, &str, nil)\n}\n\nfunc StencilFunc(fn Enum, ref int, mask uint32) {\n\tC.glStencilFunc(fn.c(), C.GLint(ref), C.GLuint(mask))\n}\n\nfunc StencilFuncSeparate(face, fn Enum, ref int, mask uint32) {\n\tC.glStencilFuncSeparate(face.c(), fn.c(), C.GLint(ref), C.GLuint(mask))\n}\n\nfunc StencilMask(mask uint32) {\n\tC.glStencilMask(C.GLuint(mask))\n}\n\nfunc StencilMaskSeparate(face Enum, mask uint32) {\n\tC.glStencilMaskSeparate(face.c(), C.GLuint(mask))\n}\n\nfunc StencilOp(fail, zfail, zpass Enum) {\n\tC.glStencilOp(fail.c(), zfail.c(), zpass.c())\n}\n\nfunc StencilOpSeparate(face, sfail, dpfail, dppass Enum) {\n\tC.glStencilOpSeparate(face.c(), sfail.c(), dpfail.c(), dppass.c())\n}\n\nfunc TexImage2D(target Enum, level int, width, height int, format Enum, ty Enum, data []byte) {\n\tp := unsafe.Pointer(nil)\n\tif len(data) > 0 {\n\t\tp = unsafe.Pointer(&data[0])\n\t}\n\tC.glTexImage2D(target.c(), C.GLint(level), C.GLint(format), C.GLsizei(width), C.GLsizei(height), 0, format.c(), ty.c(), p)\n}\n\nfunc TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {\n\tC.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]))\n}\n\nfunc TexParameterf(target, pname Enum, param float32) {\n\tC.glTexParameterf(target.c(), pname.c(), C.GLfloat(param))\n}\n\nfunc TexParameterfv(target, pname Enum, params []float32) {\n\tC.glTexParameterfv(target.c(), pname.c(), (*C.GLfloat)(&params[0]))\n}\n\nfunc TexParameteri(target, pname Enum, param int) {\n\tC.glTexParameteri(target.c(), pname.c(), C.GLint(param))\n}\n\nfunc TexParameteriv(target, pname Enum, params []int32) {\n\tC.glTexParameteriv(target.c(), pname.c(), (*C.GLint)(&params[0]))\n}\n\nfunc Uniform1f(dst Uniform, v float32) {\n\tC.glUniform1f(dst.c(), C.GLfloat(v))\n}\n\nfunc Uniform1fv(dst Uniform, src []float32) {\n\tC.glUniform1fv(dst.c(), C.GLsizei(len(src)), (*C.GLfloat)(&src[0]))\n}\n\nfunc Uniform1i(dst Uniform, v int) {\n\tC.glUniform1i(dst.c(), C.GLint(v))\n}\n\nfunc Uniform1iv(dst Uniform, src []int32) {\n\tC.glUniform1iv(dst.c(), C.GLsizei(len(src)), (*C.GLint)(&src[0]))\n}\n\nfunc Uniform2f(dst Uniform, v0, v1 float32) {\n\tC.glUniform2f(dst.c(), C.GLfloat(v0), C.GLfloat(v1))\n}\n\nfunc Uniform2fv(dst Uniform, src []float32) {\n\tC.glUniform2fv(dst.c(), C.GLsizei(len(src)/2), (*C.GLfloat)(&src[0]))\n}\n\nfunc Uniform2i(dst Uniform, v0, v1 int) {\n\tC.glUniform2i(dst.c(), C.GLint(v0), C.GLint(v1))\n}\n\nfunc Uniform2iv(dst Uniform, src []int32) {\n\tC.glUniform2iv(dst.c(), C.GLsizei(len(src)/2), (*C.GLint)(&src[0]))\n}\n\nfunc Uniform3f(dst Uniform, v0, v1, v2 float32) {\n\tC.glUniform3f(dst.c(), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2))\n}\n\nfunc Uniform3fv(dst Uniform, src []float32) {\n\tC.glUniform3fv(dst.c(), C.GLsizei(len(src)/3), (*C.GLfloat)(&src[0]))\n}\n\nfunc Uniform3i(dst Uniform, v0, v1, v2 int32) {\n\tC.glUniform3i(dst.c(), C.GLint(v0), C.GLint(v1), C.GLint(v2))\n}\n\nfunc Uniform3iv(dst Uniform, src []int32) {\n\tC.glUniform3iv(dst.c(), C.GLsizei(len(src)/3), (*C.GLint)(&src[0]))\n}\n\nfunc Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {\n\tC.glUniform4f(dst.c(), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2), C.GLfloat(v3))\n}\n\nfunc Uniform4fv(dst Uniform, src []float32) {\n\tC.glUniform4fv(dst.c(), C.GLsizei(len(src)/4), (*C.GLfloat)(&src[0]))\n}\n\nfunc Uniform4i(dst Uniform, v0, v1, v2, v3 int32) {\n\tC.glUniform4i(dst.c(), C.GLint(v0), C.GLint(v1), C.GLint(v2), C.GLint(v3))\n}\n\nfunc Uniform4iv(dst Uniform, src []int32) {\n\tC.glUniform4iv(dst.c(), C.GLsizei(len(src)/4), (*C.GLint)(&src[0]))\n}\n\nfunc UniformMatrix2fv(dst Uniform, src []float32) {\n\t// OpenGL ES 2 does not support transpose.\n\tC.glUniformMatrix2fv(dst.c(), C.GLsizei(len(src)/4), 0, (*C.GLfloat)(&src[0]))\n}\n\nfunc UniformMatrix3fv(dst Uniform, src []float32) {\n\tC.glUniformMatrix3fv(dst.c(), C.GLsizei(len(src)/9), 0, (*C.GLfloat)(&src[0]))\n}\n\nfunc UniformMatrix4fv(dst Uniform, src []float32) {\n\tC.glUniformMatrix4fv(dst.c(), C.GLsizei(len(src)/16), 0, (*C.GLfloat)(&src[0]))\n}\n\nfunc UseProgram(p Program) {\n\tC.glUseProgram(p.c())\n}\n\nfunc ValidateProgram(p Program) {\n\tC.glValidateProgram(p.c())\n}\n\nfunc VertexAttrib1f(dst Attrib, x float32) {\n\tC.glVertexAttrib1f(dst.c(), C.GLfloat(x))\n}\n\nfunc VertexAttrib1fv(dst Attrib, src []float32) {\n\tC.glVertexAttrib1fv(dst.c(), (*C.GLfloat)(&src[0]))\n}\n\nfunc VertexAttrib2f(dst Attrib, x, y float32) {\n\tC.glVertexAttrib2f(dst.c(), C.GLfloat(x), C.GLfloat(y))\n}\n\nfunc VertexAttrib2fv(dst Attrib, src []float32) {\n\tC.glVertexAttrib2fv(dst.c(), (*C.GLfloat)(&src[0]))\n}\n\nfunc VertexAttrib3f(dst Attrib, x, y, z float32) {\n\tC.glVertexAttrib3f(dst.c(), C.GLfloat(x), C.GLfloat(y), C.GLfloat(z))\n}\n\nfunc VertexAttrib3fv(dst Attrib, src []float32) {\n\tC.glVertexAttrib3fv(dst.c(), (*C.GLfloat)(&src[0]))\n}\n\nfunc VertexAttrib4f(dst Attrib, x, y, z, w float32) {\n\tC.glVertexAttrib4f(dst.c(), C.GLfloat(x), C.GLfloat(y), C.GLfloat(z), C.GLfloat(w))\n}\n\nfunc VertexAttrib4fv(dst Attrib, src []float32) {\n\tC.glVertexAttrib4fv(dst.c(), (*C.GLfloat)(&src[0]))\n}\n\nfunc VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {\n\tn := glBoolean(normalized)\n\ts := C.GLsizei(stride)\n\tC.glVertexAttribPointer(dst.c(), C.GLint(size), ty.c(), n, s, unsafe.Pointer(uintptr(offset)))\n}\n\nfunc Viewport(x, y, width, height int) {\n\tC.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))\n}\n"
  },
  {
    "path": "gl_webgl.go",
    "content": "// Copyright 2014 The Go Authors.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build js\n\npackage gl\n\nimport (\n\t\"encoding/binary\"\n\t\"math\"\n\n\t\"github.com/gopherjs/gopherjs/js\"\n)\n\nvar ContextWatcher contextWatcher\n\ntype contextWatcher struct{}\n\nfunc (contextWatcher) OnMakeCurrent(context interface{}) {\n\t// context must be a WebGLRenderingContext *js.Object.\n\tc = context.(*js.Object)\n}\nfunc (contextWatcher) OnDetach() {\n\tc = nil\n}\n\n// c is the current WebGL context, or nil if there is no current context.\nvar c *js.Object\n\nfunc ActiveTexture(texture Enum) {\n\tc.Call(\"activeTexture\", texture)\n}\n\nfunc AttachShader(p Program, s Shader) {\n\tc.Call(\"attachShader\", p.Object, s.Object)\n}\n\nfunc BindAttribLocation(p Program, a Attrib, name string) {\n\tc.Call(\"bindAttribLocation\", p.Object, a.Value, name)\n}\n\nfunc BindBuffer(target Enum, b Buffer) {\n\tc.Call(\"bindBuffer\", target, b.Object)\n}\n\nfunc BindFramebuffer(target Enum, fb Framebuffer) {\n\tc.Call(\"bindFramebuffer\", target, fb.Object)\n}\n\nfunc BindRenderbuffer(target Enum, rb Renderbuffer) {\n\tc.Call(\"bindRenderbuffer\", target, rb.Object)\n}\n\nfunc BindTexture(target Enum, t Texture) {\n\tc.Call(\"bindTexture\", target, t.Object)\n}\n\nfunc BlendColor(red, green, blue, alpha float32) {\n\tc.Call(\"blendColor\", red, green, blue, alpha)\n}\n\nfunc BlendEquation(mode Enum) {\n\tc.Call(\"blendEquation\", mode)\n}\n\nfunc BlendEquationSeparate(modeRGB, modeAlpha Enum) {\n\tc.Call(\"blendEquationSeparate\", modeRGB, modeAlpha)\n}\n\nfunc BlendFunc(sfactor, dfactor Enum) {\n\tc.Call(\"blendFunc\", sfactor, dfactor)\n}\n\nfunc BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) {\n\tc.Call(\"blendFuncSeparate\", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha)\n}\n\nfunc BufferData(target Enum, src []byte, usage Enum) {\n\tc.Call(\"bufferData\", target, src, usage)\n}\n\nfunc BufferInit(target Enum, size int, usage Enum) {\n\tc.Call(\"bufferData\", target, size, usage)\n}\n\nfunc BufferSubData(target Enum, offset int, data []byte) {\n\tc.Call(\"bufferSubData\", target, offset, data)\n}\n\nfunc CheckFramebufferStatus(target Enum) Enum {\n\treturn Enum(c.Call(\"checkFramebufferStatus\", target).Int())\n}\n\nfunc Clear(mask Enum) {\n\tc.Call(\"clear\", mask)\n}\n\nfunc ClearColor(red, green, blue, alpha float32) {\n\tc.Call(\"clearColor\", red, green, blue, alpha)\n}\n\nfunc ClearDepthf(d float32) {\n\tc.Call(\"clearDepth\", d)\n}\n\nfunc ClearStencil(s int) {\n\tc.Call(\"clearStencil\", s)\n}\n\nfunc ColorMask(red, green, blue, alpha bool) {\n\tc.Call(\"colorMask\", red, green, blue, alpha)\n}\n\nfunc CompileShader(s Shader) {\n\tc.Call(\"compileShader\", s.Object)\n}\n\nfunc CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) {\n\tc.Call(\"compressedTexImage2D\", target, level, internalformat, width, height, border, data)\n}\n\nfunc CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) {\n\tc.Call(\"compressedTexSubImage2D\", target, level, xoffset, yoffset, width, height, format, data)\n}\n\nfunc CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) {\n\tc.Call(\"copyTexImage2D\", target, level, internalformat, x, y, width, height, border)\n}\n\nfunc CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) {\n\tc.Call(\"copyTexSubImage2D\", target, level, xoffset, yoffset, x, y, width, height)\n}\n\nfunc CreateBuffer() Buffer {\n\treturn Buffer{Object: c.Call(\"createBuffer\")}\n}\n\nfunc CreateFramebuffer() Framebuffer {\n\treturn Framebuffer{Object: c.Call(\"createFramebuffer\")}\n}\n\nfunc CreateProgram() Program {\n\treturn Program{Object: c.Call(\"createProgram\")}\n}\n\nfunc CreateRenderbuffer() Renderbuffer {\n\treturn Renderbuffer{Object: c.Call(\"createRenderbuffer\")}\n}\n\nfunc CreateShader(ty Enum) Shader {\n\treturn Shader{Object: c.Call(\"createShader\", ty)}\n}\n\nfunc CreateTexture() Texture {\n\treturn Texture{Object: c.Call(\"createTexture\")}\n}\n\nfunc CullFace(mode Enum) {\n\tc.Call(\"cullFace\", mode)\n}\n\nfunc DeleteBuffer(v Buffer) {\n\tc.Call(\"deleteBuffer\", v.Object)\n}\n\nfunc DeleteFramebuffer(v Framebuffer) {\n\tc.Call(\"deleteFramebuffer\", v.Object)\n}\n\nfunc DeleteProgram(p Program) {\n\tc.Call(\"deleteProgram\", p.Object)\n}\n\nfunc DeleteRenderbuffer(v Renderbuffer) {\n\tc.Call(\"deleteRenderbuffer\", v.Object)\n}\n\nfunc DeleteShader(s Shader) {\n\tc.Call(\"deleteShader\", s.Object)\n}\n\nfunc DeleteTexture(v Texture) {\n\tc.Call(\"deleteTexture\", v.Object)\n}\n\nfunc DepthFunc(fn Enum) {\n\tc.Call(\"depthFunc\", fn)\n}\n\nfunc DepthMask(flag bool) {\n\tc.Call(\"depthMask\", flag)\n}\n\nfunc DepthRangef(n, f float32) {\n\tc.Call(\"depthRange\", n, f)\n}\n\nfunc DetachShader(p Program, s Shader) {\n\tc.Call(\"detachShader\", p.Object, s.Object)\n}\n\nfunc Disable(cap Enum) {\n\tc.Call(\"disable\", cap)\n}\n\nfunc DisableVertexAttribArray(a Attrib) {\n\tc.Call(\"disableVertexAttribArray\", a.Value)\n}\n\nfunc DrawArrays(mode Enum, first, count int) {\n\tc.Call(\"drawArrays\", mode, first, count)\n}\n\nfunc DrawElements(mode Enum, count int, ty Enum, offset int) {\n\tc.Call(\"drawElements\", mode, count, ty, offset)\n}\n\nfunc Enable(cap Enum) {\n\tc.Call(\"enable\", cap)\n}\n\nfunc EnableVertexAttribArray(a Attrib) {\n\tc.Call(\"enableVertexAttribArray\", a.Value)\n}\n\nfunc Finish() {\n\tc.Call(\"finish\")\n}\n\nfunc Flush() {\n\tc.Call(\"flush\")\n}\n\nfunc FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) {\n\tc.Call(\"framebufferRenderbuffer\", target, attachment, rbTarget, rb.Object)\n}\n\nfunc FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) {\n\tc.Call(\"framebufferTexture2D\", target, attachment, texTarget, t.Object, level)\n}\n\nfunc FrontFace(mode Enum) {\n\tc.Call(\"frontFace\", mode)\n}\n\nfunc GenerateMipmap(target Enum) {\n\tc.Call(\"generateMipmap\", target)\n}\n\ntype activeInfo struct {\n\t*js.Object\n\tSize int    `js:\"size\"`\n\tType int    `js:\"type\"`\n\tName string `js:\"name\"`\n}\n\nfunc GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) {\n\tai := activeInfo{Object: c.Call(\"getActiveAttrib\", p.Object, index)}\n\treturn ai.Name, ai.Size, Enum(ai.Type)\n}\n\nfunc GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) {\n\tai := activeInfo{Object: c.Call(\"getActiveUniform\", p.Object, index)}\n\treturn ai.Name, ai.Size, Enum(ai.Type)\n}\n\nfunc GetAttachedShaders(p Program) []Shader {\n\tobjs := c.Call(\"getAttachedShaders\", p.Object)\n\tshaders := make([]Shader, objs.Length())\n\tfor i := 0; i < objs.Length(); i++ {\n\t\tshaders[i] = Shader{Object: objs.Index(i)}\n\t}\n\treturn shaders\n}\n\nfunc GetAttribLocation(p Program, name string) Attrib {\n\treturn Attrib{Value: c.Call(\"getAttribLocation\", p.Object, name).Int()}\n}\n\nfunc GetBooleanv(dst []bool, pname Enum) {\n\tprintln(\"GetBooleanv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tresult := c.Call(\"getParameter\", pname)\n\tlength := result.Length()\n\tfor i := 0; i < length; i++ {\n\t\tdst[i] = result.Index(i).Bool()\n\t}\n}\n\nfunc GetFloatv(dst []float32, pname Enum) {\n\tprintln(\"GetFloatv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tresult := c.Call(\"getParameter\", pname)\n\tlength := result.Length()\n\tfor i := 0; i < length; i++ {\n\t\tdst[i] = float32(result.Index(i).Float())\n\t}\n}\n\nfunc GetIntegerv(pname Enum, data []int32) {\n\tresult := c.Call(\"getParameter\", pname)\n\tlength := result.Length()\n\tfor i := 0; i < length; i++ {\n\t\tdata[i] = int32(result.Index(i).Int())\n\t}\n}\n\nfunc GetInteger(pname Enum) int {\n\treturn c.Call(\"getParameter\", pname).Int()\n}\n\nfunc GetBufferParameteri(target, pname Enum) int {\n\treturn c.Call(\"getBufferParameter\", target, pname).Int()\n}\n\nfunc GetError() Enum {\n\treturn Enum(c.Call(\"getError\").Int())\n}\n\nfunc GetBoundFramebuffer() Framebuffer {\n\treturn Framebuffer{Object: c.Call(\"getParameter\", FRAMEBUFFER_BINDING)}\n}\n\nfunc GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int {\n\treturn c.Call(\"getFramebufferAttachmentParameter\", target, attachment, pname).Int()\n}\n\nfunc GetProgrami(p Program, pname Enum) int {\n\tswitch pname {\n\tcase DELETE_STATUS, LINK_STATUS, VALIDATE_STATUS:\n\t\tif c.Call(\"getProgramParameter\", p.Object, pname).Bool() {\n\t\t\treturn TRUE\n\t\t}\n\t\treturn FALSE\n\tdefault:\n\t\treturn c.Call(\"getProgramParameter\", p.Object, pname).Int()\n\t}\n}\n\nfunc GetProgramInfoLog(p Program) string {\n\treturn c.Call(\"getProgramInfoLog\", p.Object).String()\n}\n\nfunc GetRenderbufferParameteri(target, pname Enum) int {\n\treturn c.Call(\"getRenderbufferParameter\", target, pname).Int()\n}\n\nfunc GetShaderi(s Shader, pname Enum) int {\n\tswitch pname {\n\tcase DELETE_STATUS, COMPILE_STATUS:\n\t\tif c.Call(\"getShaderParameter\", s.Object, pname).Bool() {\n\t\t\treturn TRUE\n\t\t}\n\t\treturn FALSE\n\tdefault:\n\t\treturn c.Call(\"getShaderParameter\", s.Object, pname).Int()\n\t}\n}\n\nfunc GetShaderInfoLog(s Shader) string {\n\treturn c.Call(\"getShaderInfoLog\", s.Object).String()\n}\n\nfunc GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeMin, rangeMax, precision int) {\n\tprintln(\"GetShaderPrecisionFormat: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tformat := c.Call(\"getShaderPrecisionFormat\", shadertype, precisiontype)\n\trangeMin = format.Get(\"rangeMin\").Int()\n\trangeMax = format.Get(\"rangeMax\").Int()\n\tprecision = format.Get(\"precision\").Int()\n\treturn\n}\n\nfunc GetShaderSource(s Shader) string {\n\treturn c.Call(\"getShaderSource\", s.Object).String()\n}\n\nfunc GetString(pname Enum) string {\n\treturn c.Call(\"getParameter\", pname).String()\n}\n\nfunc GetTexParameterfv(dst []float32, target, pname Enum) {\n\tdst[0] = float32(c.Call(\"getTexParameter\", pname).Float())\n}\n\nfunc GetTexParameteriv(dst []int32, target, pname Enum) {\n\tdst[0] = int32(c.Call(\"getTexParameter\", pname).Int())\n}\n\nfunc GetUniformfv(dst []float32, src Uniform, p Program) {\n\tprintln(\"GetUniformfv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tresult := c.Call(\"getUniform\")\n\tlength := result.Length()\n\tfor i := 0; i < length; i++ {\n\t\tdst[i] = float32(result.Index(i).Float())\n\t}\n}\n\nfunc GetUniformiv(dst []int32, src Uniform, p Program) {\n\tprintln(\"GetUniformiv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tresult := c.Call(\"getUniform\")\n\tlength := result.Length()\n\tfor i := 0; i < length; i++ {\n\t\tdst[i] = int32(result.Index(i).Int())\n\t}\n}\n\nfunc GetUniformLocation(p Program, name string) Uniform {\n\treturn Uniform{Object: c.Call(\"getUniformLocation\", p.Object, name)}\n}\n\nfunc GetVertexAttribf(src Attrib, pname Enum) float32 {\n\treturn float32(c.Call(\"getVertexAttrib\", src.Value, pname).Float())\n}\n\nfunc GetVertexAttribfv(dst []float32, src Attrib, pname Enum) {\n\tprintln(\"GetVertexAttribfv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tresult := c.Call(\"getVertexAttrib\")\n\tlength := result.Length()\n\tfor i := 0; i < length; i++ {\n\t\tdst[i] = float32(result.Index(i).Float())\n\t}\n}\n\nfunc GetVertexAttribi(src Attrib, pname Enum) int32 {\n\treturn int32(c.Call(\"getVertexAttrib\", src.Value, pname).Int())\n}\n\nfunc GetVertexAttribiv(dst []int32, src Attrib, pname Enum) {\n\tprintln(\"GetVertexAttribiv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tresult := c.Call(\"getVertexAttrib\")\n\tlength := result.Length()\n\tfor i := 0; i < length; i++ {\n\t\tdst[i] = int32(result.Index(i).Int())\n\t}\n}\n\nfunc Hint(target, mode Enum) {\n\tc.Call(\"hint\", target, mode)\n}\n\nfunc IsBuffer(b Buffer) bool {\n\treturn c.Call(\"isBuffer\", b.Object).Bool()\n}\n\nfunc IsEnabled(cap Enum) bool {\n\treturn c.Call(\"isEnabled\", cap).Bool()\n}\n\nfunc IsFramebuffer(fb Framebuffer) bool {\n\treturn c.Call(\"isFramebuffer\", fb.Object).Bool()\n}\n\nfunc IsProgram(p Program) bool {\n\treturn c.Call(\"isProgram\", p.Object).Bool()\n}\n\nfunc IsRenderbuffer(rb Renderbuffer) bool {\n\treturn c.Call(\"isRenderbuffer\", rb.Object).Bool()\n}\n\nfunc IsShader(s Shader) bool {\n\treturn c.Call(\"isShader\", s.Object).Bool()\n}\n\nfunc IsTexture(t Texture) bool {\n\treturn c.Call(\"isTexture\", t.Object).Bool()\n}\n\nfunc LineWidth(width float32) {\n\tc.Call(\"lineWidth\", width)\n}\n\nfunc LinkProgram(p Program) {\n\tc.Call(\"linkProgram\", p.Object)\n}\n\nfunc PixelStorei(pname Enum, param int32) {\n\tc.Call(\"pixelStorei\", pname, param)\n}\n\nfunc PolygonOffset(factor, units float32) {\n\tc.Call(\"polygonOffset\", factor, units)\n}\n\nfunc ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) {\n\tprintln(\"ReadPixels: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tif ty == Enum(UNSIGNED_BYTE) {\n\t\tc.Call(\"readPixels\", x, y, width, height, format, ty, dst)\n\t} else {\n\t\ttmpDst := make([]float32, len(dst)/4)\n\t\tc.Call(\"readPixels\", x, y, width, height, format, ty, tmpDst)\n\t\tfor i, f := range tmpDst {\n\t\t\tbinary.LittleEndian.PutUint32(dst[i*4:], math.Float32bits(f))\n\t\t}\n\t}\n}\n\nfunc ReleaseShaderCompiler() {\n\t// do nothing\n}\n\nfunc RenderbufferStorage(target, internalFormat Enum, width, height int) {\n\tc.Call(\"renderbufferStorage\", target, internalFormat, width, height)\n}\n\nfunc SampleCoverage(value float32, invert bool) {\n\tc.Call(\"sampleCoverage\", value, invert)\n}\n\nfunc Scissor(x, y, width, height int32) {\n\tc.Call(\"scissor\", x, y, width, height)\n}\n\nfunc ShaderSource(s Shader, src string) {\n\tc.Call(\"shaderSource\", s.Object, src)\n}\n\nfunc StencilFunc(fn Enum, ref int, mask uint32) {\n\tc.Call(\"stencilFunc\", fn, ref, mask)\n}\n\nfunc StencilFuncSeparate(face, fn Enum, ref int, mask uint32) {\n\tc.Call(\"stencilFuncSeparate\", face, fn, ref, mask)\n}\n\nfunc StencilMask(mask uint32) {\n\tc.Call(\"stencilMask\", mask)\n}\n\nfunc StencilMaskSeparate(face Enum, mask uint32) {\n\tc.Call(\"stencilMaskSeparate\", face, mask)\n}\n\nfunc StencilOp(fail, zfail, zpass Enum) {\n\tc.Call(\"stencilOp\", fail, zfail, zpass)\n}\n\nfunc StencilOpSeparate(face, sfail, dpfail, dppass Enum) {\n\tc.Call(\"stencilOpSeparate\", face, sfail, dpfail, dppass)\n}\n\nfunc TexImage2D(target Enum, level int, width, height int, format Enum, ty Enum, data []byte) {\n\tvar p interface{}\n\tif data != nil {\n\t\tp = data\n\t}\n\tc.Call(\"texImage2D\", target, level, format, width, height, 0, format, ty, p)\n}\n\nfunc TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {\n\tc.Call(\"texSubImage2D\", target, level, x, y, width, height, format, ty, data)\n}\n\nfunc TexParameterf(target, pname Enum, param float32) {\n\tc.Call(\"texParameterf\", target, pname, param)\n}\n\nfunc TexParameterfv(target, pname Enum, params []float32) {\n\tprintln(\"TexParameterfv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tfor _, param := range params {\n\t\tc.Call(\"texParameterf\", target, pname, param)\n\t}\n}\n\nfunc TexParameteri(target, pname Enum, param int) {\n\tc.Call(\"texParameteri\", target, pname, param)\n}\n\nfunc TexParameteriv(target, pname Enum, params []int32) {\n\tprintln(\"TexParameteriv: not yet tested (TODO: remove this after it's confirmed to work. Your feedback is welcome.)\")\n\tfor _, param := range params {\n\t\tc.Call(\"texParameteri\", target, pname, param)\n\t}\n}\n\nfunc Uniform1f(dst Uniform, v float32) {\n\tc.Call(\"uniform1f\", dst.Object, v)\n}\n\nfunc Uniform1fv(dst Uniform, src []float32) {\n\tc.Call(\"uniform1fv\", dst.Object, src)\n}\n\nfunc Uniform1i(dst Uniform, v int) {\n\tc.Call(\"uniform1i\", dst.Object, v)\n}\n\nfunc Uniform1iv(dst Uniform, src []int32) {\n\tc.Call(\"uniform1iv\", dst.Object, src)\n}\n\nfunc Uniform2f(dst Uniform, v0, v1 float32) {\n\tc.Call(\"uniform2f\", dst.Object, v0, v1)\n}\n\nfunc Uniform2fv(dst Uniform, src []float32) {\n\tc.Call(\"uniform2fv\", dst.Object, src)\n}\n\nfunc Uniform2i(dst Uniform, v0, v1 int) {\n\tc.Call(\"uniform2i\", dst.Object, v0, v1)\n}\n\nfunc Uniform2iv(dst Uniform, src []int32) {\n\tc.Call(\"uniform2iv\", dst.Object, src)\n}\n\nfunc Uniform3f(dst Uniform, v0, v1, v2 float32) {\n\tc.Call(\"uniform3f\", dst.Object, v0, v1, v2)\n}\n\nfunc Uniform3fv(dst Uniform, src []float32) {\n\tc.Call(\"uniform3fv\", dst.Object, src)\n}\n\nfunc Uniform3i(dst Uniform, v0, v1, v2 int32) {\n\tc.Call(\"uniform3i\", dst.Object, v0, v1, v2)\n}\n\nfunc Uniform3iv(dst Uniform, src []int32) {\n\tc.Call(\"uniform3iv\", dst.Object, src)\n}\n\nfunc Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {\n\tc.Call(\"uniform4f\", dst.Object, v0, v1, v2, v3)\n}\n\nfunc Uniform4fv(dst Uniform, src []float32) {\n\tc.Call(\"uniform4fv\", dst.Object, src)\n}\n\nfunc Uniform4i(dst Uniform, v0, v1, v2, v3 int32) {\n\tc.Call(\"uniform4i\", dst.Object, v0, v1, v2, v3)\n}\n\nfunc Uniform4iv(dst Uniform, src []int32) {\n\tc.Call(\"uniform4iv\", dst.Object, src)\n}\n\nfunc UniformMatrix2fv(dst Uniform, src []float32) {\n\tc.Call(\"uniformMatrix2fv\", dst.Object, false, src)\n}\n\nfunc UniformMatrix3fv(dst Uniform, src []float32) {\n\tc.Call(\"uniformMatrix3fv\", dst.Object, false, src)\n}\n\nfunc UniformMatrix4fv(dst Uniform, src []float32) {\n\tc.Call(\"uniformMatrix4fv\", dst.Object, false, src)\n}\n\nfunc UseProgram(p Program) {\n\tc.Call(\"useProgram\", p.Object)\n}\n\nfunc ValidateProgram(p Program) {\n\tc.Call(\"validateProgram\", p.Object)\n}\n\nfunc VertexAttrib1f(dst Attrib, x float32) {\n\tc.Call(\"vertexAttrib1f\", dst.Value, x)\n}\n\nfunc VertexAttrib1fv(dst Attrib, src []float32) {\n\tc.Call(\"vertexAttrib1fv\", dst.Value, src)\n}\n\nfunc VertexAttrib2f(dst Attrib, x, y float32) {\n\tc.Call(\"vertexAttrib2f\", dst.Value, x, y)\n}\n\nfunc VertexAttrib2fv(dst Attrib, src []float32) {\n\tc.Call(\"vertexAttrib2fv\", dst.Value, src)\n}\n\nfunc VertexAttrib3f(dst Attrib, x, y, z float32) {\n\tc.Call(\"vertexAttrib3f\", dst.Value, x, y, z)\n}\n\nfunc VertexAttrib3fv(dst Attrib, src []float32) {\n\tc.Call(\"vertexAttrib3fv\", dst.Value, src)\n}\n\nfunc VertexAttrib4f(dst Attrib, x, y, z, w float32) {\n\tc.Call(\"vertexAttrib4f\", dst.Value, x, y, z, w)\n}\n\nfunc VertexAttrib4fv(dst Attrib, src []float32) {\n\tc.Call(\"vertexAttrib4fv\", dst.Value, src)\n}\n\nfunc VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {\n\tc.Call(\"vertexAttribPointer\", dst.Value, size, ty, normalized, stride, offset)\n}\n\nfunc Viewport(x, y, width, height int) {\n\tc.Call(\"viewport\", x, y, width, height)\n}\n"
  },
  {
    "path": "glutil/glutil.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package glutil implements OpenGL utility functions.\npackage glutil\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/goxjs/gl\"\n)\n\n// CreateProgram creates, compiles, and links a gl.Program.\nfunc CreateProgram(vertexSrc, fragmentSrc string) (gl.Program, error) {\n\tprogram := gl.CreateProgram()\n\tif !program.Valid() {\n\t\treturn gl.Program{}, fmt.Errorf(\"glutil: no programs available\")\n\t}\n\n\tvertexShader, err := loadShader(gl.VERTEX_SHADER, vertexSrc)\n\tif err != nil {\n\t\treturn gl.Program{}, err\n\t}\n\tfragmentShader, err := loadShader(gl.FRAGMENT_SHADER, fragmentSrc)\n\tif err != nil {\n\t\tgl.DeleteShader(vertexShader)\n\t\treturn gl.Program{}, err\n\t}\n\n\tgl.AttachShader(program, vertexShader)\n\tgl.AttachShader(program, fragmentShader)\n\tgl.LinkProgram(program)\n\n\t// Flag shaders for deletion when program is unlinked.\n\tgl.DeleteShader(vertexShader)\n\tgl.DeleteShader(fragmentShader)\n\n\tif gl.GetProgrami(program, gl.LINK_STATUS) == 0 {\n\t\tdefer gl.DeleteProgram(program)\n\t\treturn gl.Program{}, fmt.Errorf(\"glutil: %s\", gl.GetProgramInfoLog(program))\n\t}\n\treturn program, nil\n}\n\nfunc loadShader(shaderType gl.Enum, src string) (gl.Shader, error) {\n\tshader := gl.CreateShader(shaderType)\n\tif !shader.Valid() {\n\t\treturn gl.Shader{}, fmt.Errorf(\"glutil: could not create shader (type %v)\", shaderType)\n\t}\n\tgl.ShaderSource(shader, src)\n\tgl.CompileShader(shader)\n\tif gl.GetShaderi(shader, gl.COMPILE_STATUS) == 0 {\n\t\tdefer gl.DeleteShader(shader)\n\t\treturn gl.Shader{}, fmt.Errorf(\"shader compile: %s\", gl.GetShaderInfoLog(shader))\n\t}\n\treturn shader, nil\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/goxjs/gl\n\ngo 1.19\n"
  },
  {
    "path": "test/context_darwin.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build darwin\n\npackage test\n\n// TODO(crawshaw): Only used in glutil tests for now (cgo is not support in _test.go files).\n// TODO(crawshaw): Export some kind of Context. Work out what we can offer, where. Maybe just for tests.\n// TODO(crawshaw): Support android and windows.\n\n/*\n#cgo CFLAGS: -DGL_SILENCE_DEPRECATION\n#cgo LDFLAGS: -framework OpenGL\n#import <OpenGL/OpenGL.h>\n#import <OpenGL/gl3.h>\n\nvoid CGCreate(CGLContextObj* ctx) {\n\tCGLPixelFormatAttribute attributes[] = {\n\t\tkCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,\n\t\tkCGLPFAColorSize, (CGLPixelFormatAttribute)24,\n\t\tkCGLPFAAlphaSize, (CGLPixelFormatAttribute)8,\n\t\tkCGLPFADepthSize, (CGLPixelFormatAttribute)16,\n\t\tkCGLPFAAccelerated,\n\t\tkCGLPFADoubleBuffer,\n\t\t(CGLPixelFormatAttribute) 0\n\t};\n\tCGLPixelFormatObj pix;\n\tGLint num;\n\tCGLChoosePixelFormat(attributes, &pix, &num);\n\tCGLCreateContext(pix, 0, ctx);\n\tCGLDestroyPixelFormat(pix);\n\tCGLSetCurrentContext(*ctx);\n\tCGLLockContext(*ctx);\n}\n*/\nimport \"C\"\n\nimport (\n\t\"runtime\"\n\n\t\"github.com/goxjs/gl\"\n)\n\n// contextGL holds a copy of the OpenGL Context from thread-local storage.\n//\n// Do not move a contextGL between goroutines or OS threads.\ntype contextGL struct {\n\tctx C.CGLContextObj\n}\n\n// createContext creates an OpenGL context, binds it as the current context\n// stored in thread-local storage, and locks the current goroutine to an os\n// thread.\nfunc createContext() *contextGL {\n\t// The OpenGL active context is stored in TLS.\n\truntime.LockOSThread()\n\n\tc := new(contextGL)\n\tC.CGCreate(&c.ctx)\n\tgl.ContextWatcher.OnMakeCurrent(nil)\n\n\t// Using attribute arrays in OpenGL 3.3 requires the use of a VBA.\n\t// But VBAs don't exist in ES 2. So we bind a default one.\n\tvar id C.GLuint\n\tC.glGenVertexArrays(1, &id)\n\tC.glBindVertexArray(id)\n\n\treturn c\n}\n\n// destroy destroys an OpenGL context and unlocks the current goroutine from\n// its os thread.\nfunc (c *contextGL) destroy() {\n\tC.CGLUnlockContext(c.ctx)\n\tC.CGLSetCurrentContext(nil)\n\tgl.ContextWatcher.OnDetach()\n\tC.CGLDestroyContext(c.ctx)\n\tc.ctx = nil\n\truntime.UnlockOSThread()\n}\n"
  },
  {
    "path": "test/context_x11.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build linux,!android\n\npackage test\n\n/*\n#cgo LDFLAGS: -lEGL\n#include <EGL/egl.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid createContext(EGLDisplay *out_dpy, EGLContext *out_ctx, EGLSurface *out_surf) {\n\tEGLDisplay e_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);\n\tif (!e_dpy) {\n\t\tfprintf(stderr, \"eglGetDisplay failed\\n\");\n\t\texit(1);\n\t}\n\tEGLint e_major, e_minor;\n\tif (!eglInitialize(e_dpy, &e_major, &e_minor)) {\n\t\tfprintf(stderr, \"eglInitialize failed\\n\");\n\t\texit(1);\n\t}\n\teglBindAPI(EGL_OPENGL_ES_API);\n\tstatic const EGLint config_attribs[] = {\n\t\tEGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,\n\t\tEGL_SURFACE_TYPE, EGL_PBUFFER_BIT,\n\t\tEGL_BLUE_SIZE, 8,\n\t\tEGL_GREEN_SIZE, 8,\n\t\tEGL_RED_SIZE, 8,\n\t\tEGL_CONFIG_CAVEAT, EGL_NONE,\n\t\tEGL_NONE\n\t};\n\tEGLConfig config;\n\tEGLint num_configs;\n\tif (!eglChooseConfig(e_dpy, config_attribs, &config, 1, &num_configs)) {\n\t\tfprintf(stderr, \"eglChooseConfig failed\\n\");\n\t\texit(1);\n\t}\n\tstatic const EGLint ctx_attribs[] = {\n\t\tEGL_CONTEXT_CLIENT_VERSION, 2,\n\t\tEGL_NONE\n\t};\n\tEGLContext e_ctx = eglCreateContext(e_dpy, config, EGL_NO_CONTEXT, ctx_attribs);\n\tif (e_ctx == EGL_NO_CONTEXT) {\n\t\tfprintf(stderr, \"eglCreateContext failed\\n\");\n\t\texit(1);\n\t}\n\tstatic const EGLint pbuf_attribs[] = {\n\t\tEGL_NONE\n\t};\n\tEGLSurface e_surf = eglCreatePbufferSurface(e_dpy, config, pbuf_attribs);\n\tif (e_surf == EGL_NO_SURFACE) {\n\t\tfprintf(stderr, \"eglCreatePbufferSurface failed\\n\");\n\t\texit(1);\n\t}\n\tif (!eglMakeCurrent(e_dpy, e_surf, e_surf, e_ctx)) {\n\t\tfprintf(stderr, \"eglMakeCurrent failed\\n\");\n\t\texit(1);\n\t}\n\t*out_surf = e_surf;\n\t*out_ctx = e_ctx;\n\t*out_dpy = e_dpy;\n}\n\nvoid destroyContext(EGLDisplay e_dpy, EGLContext e_ctx, EGLSurface e_surf) {\n\tif (!eglMakeCurrent(e_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {\n\t\tfprintf(stderr, \"eglMakeCurrent failed\\n\");\n\t\texit(1);\n\t}\n\tif (!eglDestroySurface(e_dpy, e_surf)) {\n\t\tfprintf(stderr, \"eglDestroySurface failed\\n\");\n\t\texit(1);\n\t}\n\tif (!eglDestroyContext(e_dpy, e_ctx)) {\n\t\tfprintf(stderr, \"eglDestroyContext failed\\n\");\n\t\texit(1);\n\t}\n}\n*/\nimport \"C\"\n\nimport (\n\t\"runtime\"\n\n\t\"github.com/goxjs/gl\"\n)\n\ntype contextGL struct {\n\tdpy  C.EGLDisplay\n\tctx  C.EGLContext\n\tsurf C.EGLSurface\n}\n\nfunc createContext() *contextGL {\n\truntime.LockOSThread()\n\tc := &contextGL{}\n\tC.createContext(&c.dpy, &c.ctx, &c.surf)\n\tgl.ContextWatcher.OnMakeCurrent(nil)\n\treturn c\n}\n\nfunc (c *contextGL) destroy() {\n\tC.destroyContext(c.dpy, c.ctx, c.surf)\n\tgl.ContextWatcher.OnDetach()\n\truntime.UnlockOSThread()\n}\n"
  },
  {
    "path": "test/doc.go",
    "content": "// Package test contains tests for goxjs/gl.\npackage test\n"
  },
  {
    "path": "test/glimage_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build darwin linux,!android\n\n// TODO(crawshaw): Run tests on other OSs when more contexts are supported.\n\npackage test\n\nimport (\n\t\"encoding/binary\"\n\t\"image\"\n\t\"image/color\"\n\t\"image/draw\"\n\t\"image/png\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/goxjs/gl\"\n\t\"github.com/goxjs/gl/glutil\"\n\t\"golang.org/x/mobile/event/size\"\n\t\"golang.org/x/mobile/exp/f32\"\n\t\"golang.org/x/mobile/geom\"\n)\n\nfunc TestImage(t *testing.T) {\n\t// GL testing strategy:\n\t// \t1. Create an offscreen framebuffer object.\n\t// \t2. Configure framebuffer to render to a GL texture.\n\t//\t3. Run test code: use glimage to draw testdata.\n\t//\t4. Copy GL texture back into system memory.\n\t//\t5. Compare to a pre-computed image.\n\n\tf, err := os.Open(filepath.Join(\"testdata\", \"testpattern.png\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer f.Close()\n\tsrc, _, err := image.Decode(f)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tctxGL := createContext()\n\tdefer ctxGL.destroy()\n\n\tconst (\n\t\tpixW = 100\n\t\tpixH = 100\n\t\tptW  = geom.Pt(50)\n\t\tptH  = geom.Pt(50)\n\t)\n\tcfg := size.Event{\n\t\tWidthPx:     pixW,\n\t\tHeightPx:    pixH,\n\t\tWidthPt:     ptW,\n\t\tHeightPt:    ptH,\n\t\tPixelsPerPt: float32(pixW) / float32(ptW),\n\t}\n\n\tfBuf := gl.CreateFramebuffer()\n\tgl.BindFramebuffer(gl.FRAMEBUFFER, fBuf)\n\tcolorBuf := gl.CreateRenderbuffer()\n\tgl.BindRenderbuffer(gl.RENDERBUFFER, colorBuf)\n\t// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glRenderbufferStorage.xml\n\t// says that the internalFormat \"must be one of the following symbolic constants:\n\t// GL_RGBA4, GL_RGB565, GL_RGB5_A1, GL_DEPTH_COMPONENT16, or GL_STENCIL_INDEX8\".\n\tgl.RenderbufferStorage(gl.RENDERBUFFER, gl.RGB565, pixW, pixH)\n\tgl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuf)\n\n\tif status := gl.CheckFramebufferStatus(gl.FRAMEBUFFER); status != gl.FRAMEBUFFER_COMPLETE {\n\t\tt.Fatalf(\"framebuffer create failed: %v\", status)\n\t}\n\n\tgl.ClearColor(0, 0, 1, 1) // blue\n\tgl.Clear(gl.COLOR_BUFFER_BIT)\n\tgl.Viewport(0, 0, pixW, pixH)\n\n\tm := NewImage(src.Bounds().Dx(), src.Bounds().Dy())\n\tb := m.RGBA.Bounds()\n\tdraw.Draw(m.RGBA, b, src, src.Bounds().Min, draw.Src)\n\tm.Upload()\n\tb.Min.X += 10\n\tb.Max.Y /= 2\n\n\t// All-integer right-angled triangles offsetting the\n\t// box: 24-32-40, 12-16-20.\n\tptTopLeft := geom.Point{0, 24}\n\tptTopRight := geom.Point{32, 0}\n\tptBottomLeft := geom.Point{12, 24 + 16}\n\tptBottomRight := geom.Point{12 + 32, 16}\n\tm.Draw(cfg, ptTopLeft, ptTopRight, ptBottomLeft, b)\n\n\t// For unknown reasons, a windowless OpenGL context renders upside-\n\t// down. That is, a quad covering the initial viewport spans:\n\t//\n\t//\t(-1, -1) ( 1, -1)\n\t//\t(-1,  1) ( 1,  1)\n\t//\n\t// To avoid modifying live code for tests, we flip the rows\n\t// recovered from the renderbuffer. We are not the first:\n\t//\n\t// http://lists.apple.com/archives/mac-opengl/2010/Jun/msg00080.html\n\tgot := image.NewRGBA(image.Rect(0, 0, pixW, pixH))\n\tupsideDownPix := make([]byte, len(got.Pix))\n\tgl.ReadPixels(upsideDownPix, 0, 0, pixW, pixH, gl.RGBA, gl.UNSIGNED_BYTE)\n\tfor y := 0; y < pixH; y++ {\n\t\ti0 := (pixH - 1 - y) * got.Stride\n\t\ti1 := i0 + pixW*4\n\t\tcopy(got.Pix[y*got.Stride:], upsideDownPix[i0:i1])\n\t}\n\n\tdrawCross(got, 0, 0)\n\tdrawCross(got, int(ptTopLeft.X.Px(cfg.PixelsPerPt)), int(ptTopLeft.Y.Px(cfg.PixelsPerPt)))\n\tdrawCross(got, int(ptBottomRight.X.Px(cfg.PixelsPerPt)), int(ptBottomRight.Y.Px(cfg.PixelsPerPt)))\n\tdrawCross(got, pixW-1, pixH-1)\n\n\tvar wantPath = filepath.Join(\"testdata\", \"testpattern-window.png\")\n\tf, err = os.Open(wantPath)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer f.Close()\n\twantSrc, _, err := image.Decode(f)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant, ok := wantSrc.(*image.RGBA)\n\tif !ok {\n\t\tb := wantSrc.Bounds()\n\t\twant = image.NewRGBA(b)\n\t\tdraw.Draw(want, b, wantSrc, b.Min, draw.Src)\n\t}\n\n\tif !imageEq(got, want) {\n\t\t// Write out the image we got.\n\t\tf, err = ioutil.TempFile(\"\", \"testpattern-window-got\")\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tf.Close()\n\t\tgotPath := f.Name() + \".png\"\n\t\tf, err = os.Create(gotPath)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := png.Encode(f, got); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := f.Close(); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tt.Errorf(\"got\\n%s\\nwant\\n%s\", gotPath, wantPath)\n\t}\n}\n\nfunc drawCross(m *image.RGBA, x, y int) {\n\tc := color.RGBA{0xff, 0, 0, 0xff} // red\n\tm.SetRGBA(x+0, y-2, c)\n\tm.SetRGBA(x+0, y-1, c)\n\tm.SetRGBA(x-2, y+0, c)\n\tm.SetRGBA(x-1, y+0, c)\n\tm.SetRGBA(x+0, y+0, c)\n\tm.SetRGBA(x+1, y+0, c)\n\tm.SetRGBA(x+2, y+0, c)\n\tm.SetRGBA(x+0, y+1, c)\n\tm.SetRGBA(x+0, y+2, c)\n}\n\nfunc eqEpsilon(x, y uint8) bool {\n\tconst epsilon = 9\n\treturn x-y < epsilon || y-x < epsilon\n}\n\nfunc colorEq(c0, c1 color.RGBA) bool {\n\treturn eqEpsilon(c0.R, c1.R) && eqEpsilon(c0.G, c1.G) && eqEpsilon(c0.B, c1.B) && eqEpsilon(c0.A, c1.A)\n}\n\nfunc imageEq(m0, m1 *image.RGBA) bool {\n\tb0 := m0.Bounds()\n\tb1 := m1.Bounds()\n\tif b0 != b1 {\n\t\treturn false\n\t}\n\tbadPx := 0\n\tfor y := b0.Min.Y; y < b0.Max.Y; y++ {\n\t\tfor x := b0.Min.X; x < b0.Max.X; x++ {\n\t\t\tc0, c1 := m0.At(x, y).(color.RGBA), m1.At(x, y).(color.RGBA)\n\t\t\tif !colorEq(c0, c1) {\n\t\t\t\tbadPx++\n\t\t\t}\n\t\t}\n\t}\n\tbadFrac := float64(badPx) / float64(b0.Dx()*b0.Dy())\n\treturn badFrac < 0.01\n}\n\nvar glimage struct {\n\tsync.Once\n\tquadXY        gl.Buffer\n\tquadUV        gl.Buffer\n\tprogram       gl.Program\n\tpos           gl.Attrib\n\tmvp           gl.Uniform\n\tuvp           gl.Uniform\n\tinUV          gl.Attrib\n\ttextureSample gl.Uniform\n}\n\nfunc glInit() {\n\tvar err error\n\tglimage.program, err = glutil.CreateProgram(vertexShader, fragmentShader)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tglimage.quadXY = gl.CreateBuffer()\n\tglimage.quadUV = gl.CreateBuffer()\n\n\tgl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY)\n\tgl.BufferData(gl.ARRAY_BUFFER, quadXYCoords, gl.STATIC_DRAW)\n\tgl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadUV)\n\tgl.BufferData(gl.ARRAY_BUFFER, quadUVCoords, gl.STATIC_DRAW)\n\n\tglimage.pos = gl.GetAttribLocation(glimage.program, \"pos\")\n\tglimage.mvp = gl.GetUniformLocation(glimage.program, \"mvp\")\n\tglimage.uvp = gl.GetUniformLocation(glimage.program, \"uvp\")\n\tglimage.inUV = gl.GetAttribLocation(glimage.program, \"inUV\")\n\tglimage.textureSample = gl.GetUniformLocation(glimage.program, \"textureSample\")\n}\n\n// Image bridges between an *image.RGBA and an OpenGL texture.\n//\n// The contents of the embedded *image.RGBA can be uploaded as a\n// texture and drawn as a 2D quad.\n//\n// The number of active Images must fit in the system's OpenGL texture\n// limit. The typical use of an Image is as a texture atlas.\ntype Image struct {\n\t*image.RGBA\n\n\tTexture   gl.Texture\n\ttexWidth  int\n\ttexHeight int\n}\n\n// NewImage creates an Image of the given size.\n//\n// Both a host-memory *image.RGBA and a GL texture are created.\nfunc NewImage(w, h int) *Image {\n\tdx := roundToPower2(w)\n\tdy := roundToPower2(h)\n\n\t// TODO(crawshaw): Using VertexAttribPointer we can pass texture\n\t// data with a stride, which would let us use the exact number of\n\t// pixels on the host instead of the rounded up power 2 size.\n\tm := image.NewRGBA(image.Rect(0, 0, dx, dy))\n\n\tglimage.Do(glInit)\n\n\timg := &Image{\n\t\tRGBA:      m.SubImage(image.Rect(0, 0, w, h)).(*image.RGBA),\n\t\tTexture:   gl.CreateTexture(),\n\t\ttexWidth:  dx,\n\t\ttexHeight: dy,\n\t}\n\t// TODO(crawshaw): We don't have the context on a finalizer. Find a way.\n\t// runtime.SetFinalizer(img, func(img *Image) { gl.DeleteTexture(img.Texture) })\n\tgl.BindTexture(gl.TEXTURE_2D, img.Texture)\n\tgl.TexImage2D(gl.TEXTURE_2D, 0, dx, dy, gl.RGBA, gl.UNSIGNED_BYTE, nil)\n\tgl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)\n\tgl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n\tgl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)\n\tgl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)\n\n\treturn img\n}\n\nfunc roundToPower2(x int) int {\n\tx2 := 1\n\tfor x2 < x {\n\t\tx2 *= 2\n\t}\n\treturn x2\n}\n\n// Upload copies the host image data to the GL device.\nfunc (img *Image) Upload() {\n\tgl.BindTexture(gl.TEXTURE_2D, img.Texture)\n\tgl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, img.texWidth, img.texHeight, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix)\n}\n\n// Draw draws the srcBounds part of the image onto a parallelogram, defined by\n// three of its corners, in the current GL framebuffer.\nfunc (img *Image) Draw(c size.Event, topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle) {\n\t// TODO(crawshaw): Adjust viewport for the top bar on android?\n\tgl.UseProgram(glimage.program)\n\n\t{\n\t\t// We are drawing a parallelogram PQRS, defined by three of its\n\t\t// corners, onto the entire GL framebuffer ABCD. The two quads may\n\t\t// actually be equal, but in the general case, PQRS can be smaller,\n\t\t// and PQRS is not necessarily axis-aligned.\n\t\t//\n\t\t//\tA +---------------+ B\n\t\t//\t  |  P +-----+ Q  |\n\t\t//\t  |    |     |    |\n\t\t//\t  |  S +-----+ R  |\n\t\t//\tD +---------------+ C\n\t\t//\n\t\t// There are two co-ordinate spaces: geom space and framebuffer space.\n\t\t// In geom space, the ABCD rectangle is:\n\t\t//\n\t\t//\t(0, 0)           (geom.Width, 0)\n\t\t//\t(0, geom.Height) (geom.Width, geom.Height)\n\t\t//\n\t\t// and the PQRS quad is:\n\t\t//\n\t\t//\t(topLeft.X,    topLeft.Y)    (topRight.X, topRight.Y)\n\t\t//\t(bottomLeft.X, bottomLeft.Y) (implicit,   implicit)\n\t\t//\n\t\t// In framebuffer space, the ABCD rectangle is:\n\t\t//\n\t\t//\t(-1, +1) (+1, +1)\n\t\t//\t(-1, -1) (+1, -1)\n\t\t//\n\t\t// First of all, convert from geom space to framebuffer space. For\n\t\t// later convenience, we divide everything by 2 here: px2 is half of\n\t\t// the P.X co-ordinate (in framebuffer space).\n\t\tpx2 := -0.5 + float32(topLeft.X/c.WidthPt)\n\t\tpy2 := +0.5 - float32(topLeft.Y/c.HeightPt)\n\t\tqx2 := -0.5 + float32(topRight.X/c.WidthPt)\n\t\tqy2 := +0.5 - float32(topRight.Y/c.HeightPt)\n\t\tsx2 := -0.5 + float32(bottomLeft.X/c.WidthPt)\n\t\tsy2 := +0.5 - float32(bottomLeft.Y/c.HeightPt)\n\t\t// Next, solve for the affine transformation matrix\n\t\t//\t    [ a00 a01 a02 ]\n\t\t//\ta = [ a10 a11 a12 ]\n\t\t//\t    [   0   0   1 ]\n\t\t// that maps A to P:\n\t\t//\ta × [ -1 +1 1 ]' = [ 2*px2 2*py2 1 ]'\n\t\t// and likewise maps B to Q and D to S. Solving those three constraints\n\t\t// implies that C maps to R, since affine transformations keep parallel\n\t\t// lines parallel. This gives 6 equations in 6 unknowns:\n\t\t//\t-a00 + a01 + a02 = 2*px2\n\t\t//\t-a10 + a11 + a12 = 2*py2\n\t\t//\t+a00 + a01 + a02 = 2*qx2\n\t\t//\t+a10 + a11 + a12 = 2*qy2\n\t\t//\t-a00 - a01 + a02 = 2*sx2\n\t\t//\t-a10 - a11 + a12 = 2*sy2\n\t\t// which gives:\n\t\t//\ta00 = (2*qx2 - 2*px2) / 2 = qx2 - px2\n\t\t// and similarly for the other elements of a.\n\t\twriteAffine(glimage.mvp, &f32.Affine{{\n\t\t\tqx2 - px2,\n\t\t\tpx2 - sx2,\n\t\t\tqx2 + sx2,\n\t\t}, {\n\t\t\tqy2 - py2,\n\t\t\tpy2 - sy2,\n\t\t\tqy2 + sy2,\n\t\t}})\n\t}\n\n\t{\n\t\t// Mapping texture co-ordinates is similar, except that in texture\n\t\t// space, the ABCD rectangle is:\n\t\t//\n\t\t//\t(0,0) (1,0)\n\t\t//\t(0,1) (1,1)\n\t\t//\n\t\t// and the PQRS quad is always axis-aligned. First of all, convert\n\t\t// from pixel space to texture space.\n\t\tw := float32(img.texWidth)\n\t\th := float32(img.texHeight)\n\t\tpx := float32(srcBounds.Min.X-img.Rect.Min.X) / w\n\t\tpy := float32(srcBounds.Min.Y-img.Rect.Min.Y) / h\n\t\tqx := float32(srcBounds.Max.X-img.Rect.Min.X) / w\n\t\tsy := float32(srcBounds.Max.Y-img.Rect.Min.Y) / h\n\t\t// Due to axis alignment, qy = py and sx = px.\n\t\t//\n\t\t// The simultaneous equations are:\n\t\t//\t  0 +   0 + a02 = px\n\t\t//\t  0 +   0 + a12 = py\n\t\t//\ta00 +   0 + a02 = qx\n\t\t//\ta10 +   0 + a12 = qy = py\n\t\t//\t  0 + a01 + a02 = sx = px\n\t\t//\t  0 + a11 + a12 = sy\n\t\twriteAffine(glimage.uvp, &f32.Affine{{\n\t\t\tqx - px,\n\t\t\t0,\n\t\t\tpx,\n\t\t}, {\n\t\t\t0,\n\t\t\tsy - py,\n\t\t\tpy,\n\t\t}})\n\t}\n\n\tgl.ActiveTexture(gl.TEXTURE0)\n\tgl.BindTexture(gl.TEXTURE_2D, img.Texture)\n\tgl.Uniform1i(glimage.textureSample, 0)\n\n\tgl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY)\n\tgl.EnableVertexAttribArray(glimage.pos)\n\tgl.VertexAttribPointer(glimage.pos, 2, gl.FLOAT, false, 0, 0)\n\n\tgl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadUV)\n\tgl.EnableVertexAttribArray(glimage.inUV)\n\tgl.VertexAttribPointer(glimage.inUV, 2, gl.FLOAT, false, 0, 0)\n\n\tgl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)\n\n\tgl.DisableVertexAttribArray(glimage.pos)\n\tgl.DisableVertexAttribArray(glimage.inUV)\n}\n\n// writeAffine writes the contents of an Affine to a 3x3 matrix GL uniform.\nfunc writeAffine(u gl.Uniform, a *f32.Affine) {\n\tvar m [9]float32\n\tm[0*3+0] = a[0][0]\n\tm[0*3+1] = a[1][0]\n\tm[0*3+2] = 0\n\tm[1*3+0] = a[0][1]\n\tm[1*3+1] = a[1][1]\n\tm[1*3+2] = 0\n\tm[2*3+0] = a[0][2]\n\tm[2*3+1] = a[1][2]\n\tm[2*3+2] = 1\n\tgl.UniformMatrix3fv(u, m[:])\n}\n\nvar quadXYCoords = f32.Bytes(binary.LittleEndian,\n\t-1, +1, // top left\n\t+1, +1, // top right\n\t-1, -1, // bottom left\n\t+1, -1, // bottom right\n)\n\nvar quadUVCoords = f32.Bytes(binary.LittleEndian,\n\t0, 0, // top left\n\t1, 0, // top right\n\t0, 1, // bottom left\n\t1, 1, // bottom right\n)\n\nconst vertexShader = `#version 100\nuniform mat3 mvp;\nuniform mat3 uvp;\nattribute vec3 pos;\nattribute vec2 inUV;\nvarying vec2 UV;\nvoid main() {\n\tvec3 p = pos;\n\tp.z = 1.0;\n\tgl_Position = vec4(mvp * p, 1);\n\tUV = (uvp * vec3(inUV, 1)).xy;\n}\n`\n\nconst fragmentShader = `#version 100\nprecision mediump float;\nvarying vec2 UV;\nuniform sampler2D textureSample;\nvoid main(){\n\tgl_FragColor = texture2D(textureSample, UV);\n}\n`\n"
  },
  {
    "path": "types_opengl.go",
    "content": "// +build !js\n\npackage gl\n\n// Enum is equivalent to GLenum, and is normally used with one of the\n// constants defined in this package.\ntype Enum uint32\n\n// Attrib identifies the location of a specific attribute variable.\ntype Attrib struct {\n\tValue uint\n}\n\n// Program identifies a compiled shader program.\ntype Program struct {\n\tValue uint32\n}\n\n// Shader identifies a GLSL shader.\ntype Shader struct {\n\tValue uint32\n}\n\n// Buffer identifies a GL buffer object.\ntype Buffer struct {\n\tValue uint32\n}\n\n// Framebuffer identifies a GL framebuffer.\ntype Framebuffer struct {\n\tValue uint32\n}\n\n// A Renderbuffer is a GL object that holds an image in an internal format.\ntype Renderbuffer struct {\n\tValue uint32\n}\n\n// A Texture identifies a GL texture unit.\ntype Texture struct {\n\tValue uint32\n}\n\n// Uniform identifies the location of a specific uniform variable.\ntype Uniform struct {\n\tValue int32\n}\n\nfunc (v Attrib) Valid() bool       { return v.Value != 0 }\nfunc (v Program) Valid() bool      { return v.Value != 0 }\nfunc (v Shader) Valid() bool       { return v.Value != 0 }\nfunc (v Buffer) Valid() bool       { return v.Value != 0 }\nfunc (v Framebuffer) Valid() bool  { return v.Value != 0 }\nfunc (v Renderbuffer) Valid() bool { return v.Value != 0 }\nfunc (v Texture) Valid() bool      { return v.Value != 0 }\nfunc (v Uniform) Valid() bool      { return v.Value != 0 }\n"
  },
  {
    "path": "types_opengles.go",
    "content": "// Copyright 2014 The Go Authors.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build ios android\n\npackage gl\n\n/*\n#cgo ios     LDFLAGS: -framework OpenGLES\n#cgo android LDFLAGS: -lGLESv2\n\n#cgo ios     CFLAGS: -Dos_ios\n#cgo android CFLAGS: -Dos_android\n\n#ifdef os_ios\n#include <OpenGLES/ES2/gl.h>\n#endif\n#ifdef os_android\n#include <GLES2/gl2.h>\n#endif\n\nvoid blendColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { glBlendColor(r, g, b, a); }\nvoid clearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { glClearColor(r, g, b, a); }\nvoid clearDepthf(GLfloat d)                                 { glClearDepthf(d); }\nvoid depthRangef(GLfloat n, GLfloat f)                      { glDepthRangef(n, f); }\nvoid sampleCoverage(GLfloat v, GLboolean invert)            { glSampleCoverage(v, invert); }\n*/\nimport \"C\"\n\ntype Enum uint32\n\ntype Attrib struct {\n\tValue uint\n}\n\ntype Program struct {\n\tValue uint32\n}\n\ntype Shader struct {\n\tValue uint32\n}\n\ntype Buffer struct {\n\tValue uint32\n}\n\ntype Framebuffer struct {\n\tValue uint32\n}\n\ntype Renderbuffer struct {\n\tValue uint32\n}\n\ntype Texture struct {\n\tValue uint32\n}\n\ntype Uniform struct {\n\tValue int32\n}\n\nfunc (v Attrib) c() C.GLuint       { return C.GLuint(v.Value) }\nfunc (v Enum) c() C.GLenum         { return C.GLenum(v) }\nfunc (v Program) c() C.GLuint      { return C.GLuint(v.Value) }\nfunc (v Shader) c() C.GLuint       { return C.GLuint(v.Value) }\nfunc (v Buffer) c() C.GLuint       { return C.GLuint(v.Value) }\nfunc (v Framebuffer) c() C.GLuint  { return C.GLuint(v.Value) }\nfunc (v Renderbuffer) c() C.GLuint { return C.GLuint(v.Value) }\nfunc (v Texture) c() C.GLuint      { return C.GLuint(v.Value) }\nfunc (v Uniform) c() C.GLint       { return C.GLint(v.Value) }\n\nfunc (v Attrib) Valid() bool       { return v.Value != 0 }\nfunc (v Program) Valid() bool      { return v.Value != 0 }\nfunc (v Shader) Valid() bool       { return v.Value != 0 }\nfunc (v Buffer) Valid() bool       { return v.Value != 0 }\nfunc (v Framebuffer) Valid() bool  { return v.Value != 0 }\nfunc (v Renderbuffer) Valid() bool { return v.Value != 0 }\nfunc (v Texture) Valid() bool      { return v.Value != 0 }\nfunc (v Uniform) Valid() bool      { return v.Value != 0 }\n\nfunc glBoolean(b bool) C.GLboolean {\n\tif b {\n\t\treturn TRUE\n\t}\n\treturn FALSE\n}\n\n// Desktop OpenGL and the ES 2/3 APIs have a very slight difference\n// that is imperceptible to C programmers: some function parameters\n// use the type Glclampf and some use GLfloat. These two types are\n// equivalent in size and bit layout (both are single-precision\n// floats), but it plays havoc with cgo. We adjust the types by using\n// C wrappers for the problematic functions.\n\nfunc blendColor(r, g, b, a float32) {\n\tC.blendColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a))\n}\nfunc clearColor(r, g, b, a float32) {\n\tC.clearColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a))\n}\nfunc clearDepthf(d float32)            { C.clearDepthf(C.GLfloat(d)) }\nfunc depthRangef(n, f float32)         { C.depthRangef(C.GLfloat(n), C.GLfloat(f)) }\nfunc sampleCoverage(v float32, i bool) { C.sampleCoverage(C.GLfloat(v), glBoolean(i)) }\n"
  },
  {
    "path": "types_webgl.go",
    "content": "// Copyright 2014 The Go Authors.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// +build js\n\npackage gl\n\nimport \"github.com/gopherjs/gopherjs/js\"\n\ntype Enum int\n\ntype Attrib struct {\n\tValue int\n}\n\ntype Program struct {\n\t*js.Object\n}\n\ntype Shader struct {\n\t*js.Object\n}\n\ntype Buffer struct {\n\t*js.Object\n}\n\ntype Framebuffer struct {\n\t*js.Object\n}\n\ntype Renderbuffer struct {\n\t*js.Object\n}\n\ntype Texture struct {\n\t*js.Object\n}\n\ntype Uniform struct {\n\t*js.Object\n}\n\nfunc (v Attrib) Valid() bool       { return v.Value != 0 }\nfunc (v Program) Valid() bool      { return v.Object != nil }\nfunc (v Shader) Valid() bool       { return v.Object != nil }\nfunc (v Buffer) Valid() bool       { return v.Object != nil }\nfunc (v Framebuffer) Valid() bool  { return v.Object != nil }\nfunc (v Renderbuffer) Valid() bool { return v.Object != nil }\nfunc (v Texture) Valid() bool      { return v.Object != nil }\nfunc (v Uniform) Valid() bool      { return v.Object != nil }\n"
  }
]