From 560fc9e11fc6f66419b59ce5a63450ddf9f90fac Mon Sep 17 00:00:00 2001 From: mstar Date: Thu, 10 Apr 2025 14:05:55 +0200 Subject: [PATCH] Remove everything that might depend on cgo --- backend/goglbackend/clip.go | 77 - backend/goglbackend/fill.go | 339 --- backend/goglbackend/gl/conversions.go | 109 - backend/goglbackend/gl/khrplatform.h | 282 --- backend/goglbackend/gl/package.go | 2053 ----------------- backend/goglbackend/gl/procaddr.go | 72 - backend/goglbackend/gl/procaddr_mobile.go | 312 --- backend/goglbackend/gogl.go | 400 ---- backend/goglbackend/gradients.go | 90 - backend/goglbackend/imagedata.go | 102 - backend/goglbackend/images.go | 221 -- backend/goglbackend/shader.go | 202 -- backend/goglbackend/shaders.go | 158 -- canvas_test.go | 657 ------ .../android/CanvasAndroidExample/.gitignore | 10 - .../.idea/caches/build_file_checksums.ser | Bin 534 -> 0 bytes .../.idea/codeStyles/Project.xml | 29 - .../CanvasAndroidExample/.idea/encodings.xml | 6 - .../CanvasAndroidExample/.idea/gradle.xml | 18 - .../CanvasAndroidExample/.idea/misc.xml | 34 - .../.idea/runConfigurations.xml | 12 - .../CanvasAndroidExample/.idea/vcs.xml | 6 - .../CanvasAndroidExample/app/.gitignore | 1 - .../CanvasAndroidExample/app/build.gradle | 27 - .../app/proguard-rules.pro | 21 - .../ExampleInstrumentedTest.java | 26 - .../app/src/main/AndroidManifest.xml | 21 - .../canvasandroidexample/MainActivity.java | 61 - .../drawable-v24/ic_launcher_foreground.xml | 34 - .../res/drawable/ic_launcher_background.xml | 171 -- .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3056 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 5024 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2096 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2858 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4569 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 7098 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 6464 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 10676 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9250 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 15523 -> 0 bytes .../app/src/main/res/values/colors.xml | 6 - .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/styles.xml | 8 - .../canvasandroidexample/ExampleUnitTest.java | 17 - .../android/CanvasAndroidExample/build.gradle | 27 - .../CanvasAndroidExample/gradle.properties | 13 - .../gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - examples/android/CanvasAndroidExample/gradlew | 172 -- .../android/CanvasAndroidExample/gradlew.bat | 84 - .../CanvasAndroidExample/settings.gradle | 1 - examples/android/README.md | 3 - examples/android/android.go | 42 - examples/drawing/Righteous-Regular.ttf | Bin 43104 -> 0 bytes examples/drawing/cat.jpg | Bin 135161 -> 0 bytes examples/drawing/drawing.go | 134 -- examples/events/events.go | 77 - examples/glfw/glfw.go | 89 - examples/gomobile/gomobile.go | 71 - examples/ios/CanvasIOSExample/.gitignore | 4 - .../project.pbxproj | 325 --- .../CanvasIOSExample/AppDelegate.swift | 38 - .../AppIcon.appiconset/Contents.json | 93 - .../Base.lproj/LaunchScreen.storyboard | 25 - .../CanvasIOSExample/Info.plist | 43 - .../CanvasIOSExample/MainViewController.swift | 54 - examples/ios/README.md | 7 - examples/ios/ios.go | 39 - examples/sdl/sdl.go | 130 -- examples/shiny/shiny.go | 58 - glfwcanvas/glfwcanvas.go | 184 -- glfwcanvas/keynames.go | 216 -- sdlcanvas/keynames.go | 216 -- sdlcanvas/sdlcanvas.go | 275 --- 76 files changed, 8021 deletions(-) delete mode 100644 backend/goglbackend/clip.go delete mode 100644 backend/goglbackend/fill.go delete mode 100644 backend/goglbackend/gl/conversions.go delete mode 100644 backend/goglbackend/gl/khrplatform.h delete mode 100644 backend/goglbackend/gl/package.go delete mode 100644 backend/goglbackend/gl/procaddr.go delete mode 100644 backend/goglbackend/gl/procaddr_mobile.go delete mode 100644 backend/goglbackend/gogl.go delete mode 100644 backend/goglbackend/gradients.go delete mode 100644 backend/goglbackend/imagedata.go delete mode 100644 backend/goglbackend/images.go delete mode 100644 backend/goglbackend/shader.go delete mode 100755 backend/goglbackend/shaders.go delete mode 100644 canvas_test.go delete mode 100644 examples/android/CanvasAndroidExample/.gitignore delete mode 100644 examples/android/CanvasAndroidExample/.idea/caches/build_file_checksums.ser delete mode 100644 examples/android/CanvasAndroidExample/.idea/codeStyles/Project.xml delete mode 100644 examples/android/CanvasAndroidExample/.idea/encodings.xml delete mode 100644 examples/android/CanvasAndroidExample/.idea/gradle.xml delete mode 100644 examples/android/CanvasAndroidExample/.idea/misc.xml delete mode 100644 examples/android/CanvasAndroidExample/.idea/runConfigurations.xml delete mode 100644 examples/android/CanvasAndroidExample/.idea/vcs.xml delete mode 100644 examples/android/CanvasAndroidExample/app/.gitignore delete mode 100644 examples/android/CanvasAndroidExample/app/build.gradle delete mode 100644 examples/android/CanvasAndroidExample/app/proguard-rules.pro delete mode 100644 examples/android/CanvasAndroidExample/app/src/androidTest/java/com/example/canvasandroidexample/ExampleInstrumentedTest.java delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/AndroidManifest.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/java/com/example/canvasandroidexample/MainActivity.java delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/values/colors.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/values/strings.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/main/res/values/styles.xml delete mode 100644 examples/android/CanvasAndroidExample/app/src/test/java/com/example/canvasandroidexample/ExampleUnitTest.java delete mode 100644 examples/android/CanvasAndroidExample/build.gradle delete mode 100644 examples/android/CanvasAndroidExample/gradle.properties delete mode 100644 examples/android/CanvasAndroidExample/gradle/wrapper/gradle-wrapper.jar delete mode 100644 examples/android/CanvasAndroidExample/gradle/wrapper/gradle-wrapper.properties delete mode 100755 examples/android/CanvasAndroidExample/gradlew delete mode 100644 examples/android/CanvasAndroidExample/gradlew.bat delete mode 100644 examples/android/CanvasAndroidExample/settings.gradle delete mode 100644 examples/android/README.md delete mode 100644 examples/android/android.go delete mode 100644 examples/drawing/Righteous-Regular.ttf delete mode 100755 examples/drawing/cat.jpg delete mode 100644 examples/drawing/drawing.go delete mode 100644 examples/events/events.go delete mode 100644 examples/glfw/glfw.go delete mode 100644 examples/gomobile/gomobile.go delete mode 100644 examples/ios/CanvasIOSExample/.gitignore delete mode 100644 examples/ios/CanvasIOSExample/CanvasIOSExample.xcodeproj/project.pbxproj delete mode 100644 examples/ios/CanvasIOSExample/CanvasIOSExample/AppDelegate.swift delete mode 100644 examples/ios/CanvasIOSExample/CanvasIOSExample/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 examples/ios/CanvasIOSExample/CanvasIOSExample/Base.lproj/LaunchScreen.storyboard delete mode 100644 examples/ios/CanvasIOSExample/CanvasIOSExample/Info.plist delete mode 100644 examples/ios/CanvasIOSExample/CanvasIOSExample/MainViewController.swift delete mode 100644 examples/ios/README.md delete mode 100644 examples/ios/ios.go delete mode 100644 examples/sdl/sdl.go delete mode 100644 examples/shiny/shiny.go delete mode 100644 glfwcanvas/glfwcanvas.go delete mode 100644 glfwcanvas/keynames.go delete mode 100644 sdlcanvas/keynames.go delete mode 100644 sdlcanvas/sdlcanvas.go diff --git a/backend/goglbackend/clip.go b/backend/goglbackend/clip.go deleted file mode 100644 index 194d105..0000000 --- a/backend/goglbackend/clip.go +++ /dev/null @@ -1,77 +0,0 @@ -package goglbackend - -import ( - "unsafe" - - "github.com/tfriedel6/canvas/backend/backendbase" - "github.com/tfriedel6/canvas/backend/goglbackend/gl" -) - -func (b *GoGLBackend) ClearClip() { - b.activate() - - gl.StencilMask(0xFF) - gl.Clear(gl.STENCIL_BUFFER_BIT) -} - -func (b *GoGLBackend) Clip(pts []backendbase.Vec) { - b.activate() - - b.ptsBuf = b.ptsBuf[:0] - b.ptsBuf = append(b.ptsBuf, - 0, 0, - 0, float32(b.fh), - float32(b.fw), float32(b.fh), - float32(b.fw), 0) - for _, pt := range pts { - b.ptsBuf = append(b.ptsBuf, float32(pt[0]), float32(pt[1])) - } - - mode := uint32(gl.TRIANGLES) - if len(pts) == 4 { - mode = gl.TRIANGLE_FAN - } - - gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) - gl.BufferData(gl.ARRAY_BUFFER, len(b.ptsBuf)*4, unsafe.Pointer(&b.ptsBuf[0]), gl.STREAM_DRAW) - gl.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, nil) - - gl.UseProgram(b.shd.ID) - gl.Uniform4f(b.shd.Color, 1, 1, 1, 1) - gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) - gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) - gl.Uniform1f(b.shd.GlobalAlpha, 1) - gl.Uniform1i(b.shd.UseAlphaTex, 0) - gl.Uniform1i(b.shd.Func, shdFuncSolid) - gl.EnableVertexAttribArray(b.shd.Vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - - gl.ColorMask(false, false, false, false) - - // set bit 2 in the stencil buffer in the given shape - gl.StencilMask(0x04) - gl.StencilFunc(gl.ALWAYS, 4, 0) - gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) - gl.DrawArrays(mode, 4, int32(len(pts))) - - // on entire screen, where neither bit 1 or 2 are set, invert bit 1 - gl.StencilMask(0x02) - gl.StencilFunc(gl.EQUAL, 0, 0x06) - gl.StencilOp(gl.KEEP, gl.INVERT, gl.INVERT) - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) - - // on entire screen, clear bit 2 - gl.StencilMask(0x04) - gl.StencilFunc(gl.ALWAYS, 0, 0) - gl.StencilOp(gl.ZERO, gl.ZERO, gl.ZERO) - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) - - gl.DisableVertexAttribArray(b.shd.Vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) - - gl.ColorMask(true, true, true, true) - gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) - gl.StencilMask(0xFF) - gl.StencilFunc(gl.EQUAL, 0, 0xFF) -} diff --git a/backend/goglbackend/fill.go b/backend/goglbackend/fill.go deleted file mode 100644 index 4d614fd..0000000 --- a/backend/goglbackend/fill.go +++ /dev/null @@ -1,339 +0,0 @@ -package goglbackend - -import ( - "image" - "math" - "unsafe" - - "github.com/tfriedel6/canvas/backend/backendbase" - "github.com/tfriedel6/canvas/backend/goglbackend/gl" -) - -func (b *GoGLBackend) Clear(pts [4]backendbase.Vec) { - b.activate() - - // first check if the four points are aligned to form a nice rectangle, which can be more easily - // cleared using glScissor and glClear - aligned := pts[0][0] == pts[1][0] && pts[2][0] == pts[3][0] && pts[0][1] == pts[3][1] && pts[1][1] == pts[2][1] - if !aligned { - aligned = pts[0][0] == pts[3][0] && pts[1][0] == pts[2][0] && pts[0][1] == pts[1][1] && pts[2][1] == pts[3][1] - } - if aligned { - minX := math.Floor(math.Min(pts[0][0], pts[2][0])) - maxX := math.Ceil(math.Max(pts[0][0], pts[2][0])) - minY := math.Floor(math.Min(pts[0][1], pts[2][1])) - maxY := math.Ceil(math.Max(pts[0][1], pts[2][1])) - b.clearRect(int(minX), int(minY), int(maxX)-int(minX), int(maxY)-int(minY)) - return - } - - data := [8]float32{ - float32(pts[0][0]), float32(pts[0][1]), - float32(pts[1][0]), float32(pts[1][1]), - float32(pts[2][0]), float32(pts[2][1]), - float32(pts[3][0]), float32(pts[3][1])} - - gl.UseProgram(b.shd.ID) - gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) - gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) - gl.Uniform4f(b.shd.Color, 0, 0, 0, 0) - gl.Uniform1f(b.shd.GlobalAlpha, 1) - gl.Uniform1i(b.shd.UseAlphaTex, 0) - gl.Uniform1i(b.shd.Func, shdFuncSolid) - - gl.Disable(gl.BLEND) - - gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) - gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) - - gl.StencilFunc(gl.EQUAL, 0, 0xFF) - - gl.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, nil) - gl.EnableVertexAttribArray(b.shd.Vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) - gl.DisableVertexAttribArray(b.shd.Vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) - - gl.StencilFunc(gl.ALWAYS, 0, 0xFF) - - gl.Enable(gl.BLEND) -} - -func (b *GoGLBackend) clearRect(x, y, w, h int) { - gl.Enable(gl.SCISSOR_TEST) - - var box [4]int32 - gl.GetIntegerv(gl.SCISSOR_BOX, &box[0]) - - gl.Scissor(int32(x), int32(b.h-y-h), int32(w), int32(h)) - gl.ClearColor(0, 0, 0, 0) - gl.Clear(gl.COLOR_BUFFER_BIT) - gl.Scissor(box[0], box[1], box[2], box[3]) - - gl.Disable(gl.SCISSOR_TEST) -} - -func extent(pts []backendbase.Vec) (min, max backendbase.Vec) { - max[0] = -math.MaxFloat64 - max[1] = -math.MaxFloat64 - min[0] = math.MaxFloat64 - min[1] = math.MaxFloat64 - for _, v := range pts { - min[0] = math.Min(min[0], v[0]) - min[1] = math.Min(min[1], v[1]) - max[0] = math.Max(max[0], v[0]) - max[1] = math.Max(max[1], v[1]) - } - return -} - -func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, tf backendbase.Mat, canOverlap bool) { - b.activate() - - if style.Blur > 0 { - b.offscr1.alpha = true - b.enableTextureRenderTarget(&b.offscr1) - gl.ClearColor(0, 0, 0, 0) - gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) - } - - b.ptsBuf = b.ptsBuf[:0] - min, max := extent(pts) - b.ptsBuf = append(b.ptsBuf, - float32(min[0]), float32(min[1]), - float32(min[0]), float32(max[1]), - float32(max[0]), float32(max[1]), - float32(max[0]), float32(min[1])) - for _, pt := range pts { - b.ptsBuf = append(b.ptsBuf, float32(pt[0]), float32(pt[1])) - } - - mode := uint32(gl.TRIANGLES) - if len(pts) == 4 { - mode = gl.TRIANGLE_FAN - } - - gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) - gl.BufferData(gl.ARRAY_BUFFER, len(b.ptsBuf)*4, unsafe.Pointer(&b.ptsBuf[0]), gl.STREAM_DRAW) - - if !canOverlap || style.Color.A >= 255 { - vertex, _ := b.useShader(style, mat3(tf), false, 0) - - gl.StencilFunc(gl.EQUAL, 0, 0xFF) - gl.EnableVertexAttribArray(vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, nil) - gl.DrawArrays(mode, 4, int32(len(pts))) - gl.DisableVertexAttribArray(vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) - gl.StencilFunc(gl.ALWAYS, 0, 0xFF) - } else { - gl.ColorMask(false, false, false, false) - gl.StencilFunc(gl.ALWAYS, 1, 0xFF) - gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) - gl.StencilMask(0x01) - - gl.UseProgram(b.shd.ID) - gl.Uniform4f(b.shd.Color, 0, 0, 0, 0) - gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) - m3 := mat3(tf) - gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &m3[0]) - gl.Uniform1f(b.shd.GlobalAlpha, 1) - gl.Uniform1i(b.shd.UseAlphaTex, 0) - gl.Uniform1i(b.shd.Func, shdFuncSolid) - - gl.EnableVertexAttribArray(b.shd.Vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - gl.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, nil) - gl.DrawArrays(mode, 4, int32(len(pts))) - gl.DisableVertexAttribArray(b.shd.Vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) - - gl.ColorMask(true, true, true, true) - - gl.StencilFunc(gl.EQUAL, 1, 0xFF) - - vertex, _ := b.useShader(style, mat3identity, false, 0) - gl.EnableVertexAttribArray(vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, nil) - - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) - gl.DisableVertexAttribArray(vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) - - gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) - gl.StencilFunc(gl.ALWAYS, 0, 0xFF) - - gl.Clear(gl.STENCIL_BUFFER_BIT) - gl.StencilMask(0xFF) - } - - if style.Blur > 0 { - b.drawBlurred(style.Blur, min, max) - } -} - -func (b *GoGLBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [4]backendbase.Vec) { - b.activate() - - w, h := mask.Rect.Dx(), mask.Rect.Dy() - - gl.ActiveTexture(gl.TEXTURE1) - gl.BindTexture(gl.TEXTURE_2D, b.alphaTex) - gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, int32(mask.Stride), int32(h), gl.ALPHA, gl.UNSIGNED_BYTE, gl.Ptr(&mask.Pix[0])) - if w < alphaTexSize { - gl.TexSubImage2D(gl.TEXTURE_2D, 0, int32(w), 0, 1, int32(h), gl.ALPHA, gl.UNSIGNED_BYTE, gl.Ptr(&zeroes[0])) - } - if h < alphaTexSize { - gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, int32(h), int32(w), 1, gl.ALPHA, gl.UNSIGNED_BYTE, gl.Ptr(&zeroes[0])) - } - - if style.Blur > 0 { - b.offscr1.alpha = true - b.enableTextureRenderTarget(&b.offscr1) - gl.ClearColor(0, 0, 0, 0) - gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) - } - - gl.StencilFunc(gl.EQUAL, 0, 0xFF) - - gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) - - vertex, alphaTexCoord := b.useShader(style, mat3identity, true, 1) - - gl.EnableVertexAttribArray(vertex) - gl.EnableVertexAttribArray(alphaTexCoord) - - tw := float64(w) / alphaTexSize - th := float64(h) / alphaTexSize - var buf [16]float32 - data := buf[:0] - for _, pt := range pts { - data = append(data, float32(math.Round(pt[0])), float32(math.Round(pt[1]))) - } - data = append(data, 0, 0, 0, float32(th), float32(tw), float32(th), float32(tw), 0) - - gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) - - gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(alphaTexCoord, 2, gl.FLOAT, false, 0, gl.PtrOffset(8*4)) - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) - - gl.DisableVertexAttribArray(vertex) - gl.DisableVertexAttribArray(alphaTexCoord) - - gl.ActiveTexture(gl.TEXTURE1) - gl.BindTexture(gl.TEXTURE_2D, b.alphaTex) - - gl.StencilFunc(gl.ALWAYS, 0, 0xFF) - - gl.ActiveTexture(gl.TEXTURE0) - - if style.Blur > 0 { - min, max := extent(pts[:]) - b.drawBlurred(style.Blur, min, max) - } -} - -func (b *GoGLBackend) drawBlurred(size float64, min, max backendbase.Vec) { - b.offscr1.alpha = true - b.offscr2.alpha = true - - // calculate box blur size - fsize := math.Max(1, math.Floor(size)) - sizea := int(fsize) - sizeb := sizea - sizec := sizea - if size-fsize > 0.333333333 { - sizeb++ - } - if size-fsize > 0.666666666 { - sizec++ - } - - min[0] -= fsize * 3 - min[1] -= fsize * 3 - max[0] += fsize * 3 - max[1] += fsize * 3 - min[0] = math.Max(0.0, math.Min(b.fw, min[0])) - min[1] = math.Max(0.0, math.Min(b.fh, min[1])) - max[0] = math.Max(0.0, math.Min(b.fw, max[0])) - max[1] = math.Max(0.0, math.Min(b.fh, max[1])) - - gl.BindBuffer(gl.ARRAY_BUFFER, b.shadowBuf) - data := [16]float32{ - float32(min[0]), float32(min[1]), - float32(min[0]), float32(max[1]), - float32(max[0]), float32(max[1]), - float32(max[0]), float32(min[1]), - float32(min[0] / b.fw), 1 - float32(min[1]/b.fh), - float32(min[0] / b.fw), 1 - float32(max[1]/b.fh), - float32(max[0] / b.fw), 1 - float32(max[1]/b.fh), - float32(max[0] / b.fw), 1 - float32(min[1]/b.fh), - } - gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) - - gl.UseProgram(b.shd.ID) - gl.Uniform1i(b.shd.Image, 0) - gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) - gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) - gl.Uniform1i(b.shd.UseAlphaTex, 0) - gl.Uniform1i(b.shd.Func, shdFuncBoxBlur) - - gl.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, gl.PtrOffset(8*4)) - gl.EnableVertexAttribArray(b.shd.Vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - - gl.Disable(gl.BLEND) - - gl.ActiveTexture(gl.TEXTURE0) - - gl.ClearColor(0, 0, 0, 0) - - b.enableTextureRenderTarget(&b.offscr2) - gl.BindTexture(gl.TEXTURE_2D, b.offscr1.tex) - gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) - b.box3(sizea, 0, false) - b.enableTextureRenderTarget(&b.offscr1) - gl.BindTexture(gl.TEXTURE_2D, b.offscr2.tex) - b.box3(sizeb, -0.5, false) - b.enableTextureRenderTarget(&b.offscr2) - gl.BindTexture(gl.TEXTURE_2D, b.offscr1.tex) - b.box3(sizec, 0, false) - b.enableTextureRenderTarget(&b.offscr1) - gl.BindTexture(gl.TEXTURE_2D, b.offscr2.tex) - b.box3(sizea, 0, true) - b.enableTextureRenderTarget(&b.offscr2) - gl.BindTexture(gl.TEXTURE_2D, b.offscr1.tex) - b.box3(sizeb, -0.5, true) - gl.Enable(gl.BLEND) - gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) - b.disableTextureRenderTarget() - gl.BindTexture(gl.TEXTURE_2D, b.offscr2.tex) - b.box3(sizec, 0, true) - - gl.DisableVertexAttribArray(b.shd.Vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) - - gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) -} - -func (b *GoGLBackend) box3(size int, offset float32, vertical bool) { - gl.Uniform1i(b.shd.BoxSize, int32(size)) - if vertical { - gl.Uniform1i(b.shd.BoxVertical, 1) - gl.Uniform1f(b.shd.BoxScale, 1/float32(b.fh)) - } else { - gl.Uniform1i(b.shd.BoxVertical, 0) - gl.Uniform1f(b.shd.BoxScale, 1/float32(b.fw)) - } - gl.Uniform1f(b.shd.BoxOffset, offset) - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) -} diff --git a/backend/goglbackend/gl/conversions.go b/backend/goglbackend/gl/conversions.go deleted file mode 100644 index 0bad423..0000000 --- a/backend/goglbackend/gl/conversions.go +++ /dev/null @@ -1,109 +0,0 @@ -// Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. - -package gl - -import ( - "fmt" - "reflect" - "strings" - "unsafe" -) - -// #include -import "C" - -// Ptr takes a slice or pointer (to a singular scalar value or the first -// element of an array or slice) and returns its GL-compatible address. -// -// For example: -// -// var data []uint8 -// ... -// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0])) -func Ptr(data interface{}) unsafe.Pointer { - if data == nil { - return unsafe.Pointer(nil) - } - var addr unsafe.Pointer - v := reflect.ValueOf(data) - switch v.Type().Kind() { - case reflect.Ptr: - e := v.Elem() - switch e.Kind() { - case - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, - reflect.Float32, reflect.Float64: - addr = unsafe.Pointer(e.UnsafeAddr()) - default: - panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind())) - } - case reflect.Uintptr: - addr = unsafe.Pointer(v.Pointer()) - case reflect.Slice: - addr = unsafe.Pointer(v.Index(0).UnsafeAddr()) - default: - panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type())) - } - return addr -} - -// PtrOffset takes a pointer offset and returns a GL-compatible pointer. -// Useful for functions such as glVertexAttribPointer that take pointer -// parameters indicating an offset rather than an absolute memory address. -func PtrOffset(offset int) unsafe.Pointer { - return unsafe.Pointer(uintptr(offset)) -} - -// Str takes a null-terminated Go string and returns its GL-compatible address. -// This function reaches into Go string storage in an unsafe way so the caller -// must ensure the string is not garbage collected. -func Str(str string) *uint8 { - if !strings.HasSuffix(str, "\x00") { - panic("str argument missing null terminator: " + str) - } - header := (*reflect.StringHeader)(unsafe.Pointer(&str)) - return (*uint8)(unsafe.Pointer(header.Data)) -} - -// GoStr takes a null-terminated string returned by OpenGL and constructs a -// corresponding Go string. -func GoStr(cstr *uint8) string { - return C.GoString((*C.char)(unsafe.Pointer(cstr))) -} - -// Strs takes a list of Go strings (with or without null-termination) and -// returns their C counterpart. -// -// The returned free function must be called once you are done using the strings -// in order to free the memory. -// -// If no strings are provided as a parameter this function will panic. -func Strs(strs ...string) (cstrs **uint8, free func()) { - if len(strs) == 0 { - panic("Strs: expected at least 1 string") - } - - // Allocate a contiguous array large enough to hold all the strings' contents. - n := 0 - for i := range strs { - n += len(strs[i]) - } - data := C.malloc(C.size_t(n)) - - // Copy all the strings into data. - dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(data), - Len: n, - Cap: n, - })) - css := make([]*uint8, len(strs)) // Populated with pointers to each string. - offset := 0 - for i := range strs { - copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location. - css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it. - offset += len(strs[i]) - } - - return (**uint8)(&css[0]), func() { C.free(data) } -} diff --git a/backend/goglbackend/gl/khrplatform.h b/backend/goglbackend/gl/khrplatform.h deleted file mode 100644 index db80a18..0000000 --- a/backend/goglbackend/gl/khrplatform.h +++ /dev/null @@ -1,282 +0,0 @@ -#ifndef __khrplatform_h_ -#define __khrplatform_h_ - -/* -** Copyright (c) 2008-2009 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -/* Khronos platform-specific types and definitions. - * - * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $ - * - * Adopters may modify this file to suit their platform. Adopters are - * encouraged to submit platform specific modifications to the Khronos - * group so that they can be included in future versions of this file. - * Please submit changes by sending them to the public Khronos Bugzilla - * (http://khronos.org/bugzilla) by filing a bug against product - * "Khronos (general)" component "Registry". - * - * A predefined template which fills in some of the bug fields can be - * reached using http://tinyurl.com/khrplatform-h-bugreport, but you - * must create a Bugzilla login first. - * - * - * See the Implementer's Guidelines for information about where this file - * should be located on your system and for more details of its use: - * http://www.khronos.org/registry/implementers_guide.pdf - * - * This file should be included as - * #include - * by Khronos client API header files that use its types and defines. - * - * The types in khrplatform.h should only be used to define API-specific types. - * - * Types defined in khrplatform.h: - * khronos_int8_t signed 8 bit - * khronos_uint8_t unsigned 8 bit - * khronos_int16_t signed 16 bit - * khronos_uint16_t unsigned 16 bit - * khronos_int32_t signed 32 bit - * khronos_uint32_t unsigned 32 bit - * khronos_int64_t signed 64 bit - * khronos_uint64_t unsigned 64 bit - * khronos_intptr_t signed same number of bits as a pointer - * khronos_uintptr_t unsigned same number of bits as a pointer - * khronos_ssize_t signed size - * khronos_usize_t unsigned size - * khronos_float_t signed 32 bit floating point - * khronos_time_ns_t unsigned 64 bit time in nanoseconds - * khronos_utime_nanoseconds_t unsigned time interval or absolute time in - * nanoseconds - * khronos_stime_nanoseconds_t signed time interval in nanoseconds - * khronos_boolean_enum_t enumerated boolean type. This should - * only be used as a base type when a client API's boolean type is - * an enum. Client APIs which use an integer or other type for - * booleans cannot use this as the base type for their boolean. - * - * Tokens defined in khrplatform.h: - * - * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. - * - * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. - * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. - * - * Calling convention macros defined in this file: - * KHRONOS_APICALL - * KHRONOS_APIENTRY - * KHRONOS_APIATTRIBUTES - * - * These may be used in function prototypes as: - * - * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( - * int arg1, - * int arg2) KHRONOS_APIATTRIBUTES; - */ - -/*------------------------------------------------------------------------- - * Definition of KHRONOS_APICALL - *------------------------------------------------------------------------- - * This precedes the return type of the function in the function prototype. - */ -#if defined(_WIN32) && !defined(__SCITECH_SNAP__) -# define KHRONOS_APICALL __declspec(dllimport) -#elif defined (__SYMBIAN32__) -# define KHRONOS_APICALL IMPORT_C -#else -# define KHRONOS_APICALL -#endif - -/*------------------------------------------------------------------------- - * Definition of KHRONOS_APIENTRY - *------------------------------------------------------------------------- - * This follows the return type of the function and precedes the function - * name in the function prototype. - */ -#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) - /* Win32 but not WinCE */ -# define KHRONOS_APIENTRY __stdcall -#else -# define KHRONOS_APIENTRY -#endif - -/*------------------------------------------------------------------------- - * Definition of KHRONOS_APIATTRIBUTES - *------------------------------------------------------------------------- - * This follows the closing parenthesis of the function prototype arguments. - */ -#if defined (__ARMCC_2__) -#define KHRONOS_APIATTRIBUTES __softfp -#else -#define KHRONOS_APIATTRIBUTES -#endif - -/*------------------------------------------------------------------------- - * basic type definitions - *-----------------------------------------------------------------------*/ -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) - - -/* - * Using - */ -#include -typedef int32_t khronos_int32_t; -typedef uint32_t khronos_uint32_t; -typedef int64_t khronos_int64_t; -typedef uint64_t khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif defined(__VMS ) || defined(__sgi) - -/* - * Using - */ -#include -typedef int32_t khronos_int32_t; -typedef uint32_t khronos_uint32_t; -typedef int64_t khronos_int64_t; -typedef uint64_t khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) - -/* - * Win32 - */ -typedef __int32 khronos_int32_t; -typedef unsigned __int32 khronos_uint32_t; -typedef __int64 khronos_int64_t; -typedef unsigned __int64 khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif defined(__sun__) || defined(__digital__) - -/* - * Sun or Digital - */ -typedef int khronos_int32_t; -typedef unsigned int khronos_uint32_t; -#if defined(__arch64__) || defined(_LP64) -typedef long int khronos_int64_t; -typedef unsigned long int khronos_uint64_t; -#else -typedef long long int khronos_int64_t; -typedef unsigned long long int khronos_uint64_t; -#endif /* __arch64__ */ -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#elif 0 - -/* - * Hypothetical platform with no float or int64 support - */ -typedef int khronos_int32_t; -typedef unsigned int khronos_uint32_t; -#define KHRONOS_SUPPORT_INT64 0 -#define KHRONOS_SUPPORT_FLOAT 0 - -#else - -/* - * Generic fallback - */ -#include -typedef int32_t khronos_int32_t; -typedef uint32_t khronos_uint32_t; -typedef int64_t khronos_int64_t; -typedef uint64_t khronos_uint64_t; -#define KHRONOS_SUPPORT_INT64 1 -#define KHRONOS_SUPPORT_FLOAT 1 - -#endif - - -/* - * Types that are (so far) the same on all platforms - */ -typedef signed char khronos_int8_t; -typedef unsigned char khronos_uint8_t; -typedef signed short int khronos_int16_t; -typedef unsigned short int khronos_uint16_t; - -/* - * Types that differ between LLP64 and LP64 architectures - in LLP64, - * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears - * to be the only LLP64 architecture in current use. - */ -#ifdef _WIN64 -typedef signed long long int khronos_intptr_t; -typedef unsigned long long int khronos_uintptr_t; -typedef signed long long int khronos_ssize_t; -typedef unsigned long long int khronos_usize_t; -#else -typedef signed long int khronos_intptr_t; -typedef unsigned long int khronos_uintptr_t; -typedef signed long int khronos_ssize_t; -typedef unsigned long int khronos_usize_t; -#endif - -#if KHRONOS_SUPPORT_FLOAT -/* - * Float type - */ -typedef float khronos_float_t; -#endif - -#if KHRONOS_SUPPORT_INT64 -/* Time types - * - * These types can be used to represent a time interval in nanoseconds or - * an absolute Unadjusted System Time. Unadjusted System Time is the number - * of nanoseconds since some arbitrary system event (e.g. since the last - * time the system booted). The Unadjusted System Time is an unsigned - * 64 bit value that wraps back to 0 every 584 years. Time intervals - * may be either signed or unsigned. - */ -typedef khronos_uint64_t khronos_utime_nanoseconds_t; -typedef khronos_int64_t khronos_stime_nanoseconds_t; -#endif - -/* - * Dummy value used to pad enum types to 32 bits. - */ -#ifndef KHRONOS_MAX_ENUM -#define KHRONOS_MAX_ENUM 0x7FFFFFFF -#endif - -/* - * Enumerated boolean type - * - * Values other than zero should be considered to be true. Therefore - * comparisons should not be made against KHRONOS_TRUE. - */ -typedef enum { - KHRONOS_FALSE = 0, - KHRONOS_TRUE = 1, - KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM -} khronos_boolean_enum_t; - -#endif /* __khrplatform_h_ */ \ No newline at end of file diff --git a/backend/goglbackend/gl/package.go b/backend/goglbackend/gl/package.go deleted file mode 100644 index 46e3c13..0000000 --- a/backend/goglbackend/gl/package.go +++ /dev/null @@ -1,2053 +0,0 @@ -// Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. - -// Copyright (c) 2010 Khronos Group. -// This material may be distributed subject to the terms and conditions -// set forth in the Open Publication License, v 1.0, 8 June 1999. -// http://opencontent.org/openpub/. -// -// Copyright (c) 1991-2006 Silicon Graphics, Inc. -// This document is licensed under the SGI Free Software B License. -// For details, see http://oss.sgi.com/projects/FreeB. - -// Package gl implements Go bindings to OpenGL. -// -// This package was automatically generated using Glow: -// https://github.com/go-gl/glow -// -package gl - -// #cgo darwin,!ios LDFLAGS: -framework OpenGL -// #cgo darwin,ios LDFLAGS: -framework OpenGLES -// #cgo linux,!android LDFLAGS: -lGL -// #cgo freebsd,!android LDFLAGS: -lGL -// #cgo windows LDFLAGS: -lopengl32 -// #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -// #ifndef WIN32_LEAN_AND_MEAN -// #define WIN32_LEAN_AND_MEAN 1 -// #endif -// #include -// #endif -// #ifndef APIENTRY -// #define APIENTRY -// #endif -// #ifndef APIENTRYP -// #define APIENTRYP APIENTRY * -// #endif -// #ifndef GLAPI -// #define GLAPI extern -// #endif -// #include -// typedef unsigned int GLenum; -// typedef unsigned char GLboolean; -// typedef unsigned int GLbitfield; -// typedef signed char GLbyte; -// typedef short GLshort; -// typedef int GLint; -// typedef unsigned char GLubyte; -// typedef unsigned short GLushort; -// typedef unsigned int GLuint; -// typedef int GLsizei; -// typedef float GLfloat; -// typedef double GLdouble; -// typedef char GLchar; -// #include "khrplatform.h" -// typedef unsigned int GLenum; -// typedef unsigned char GLboolean; -// typedef unsigned int GLbitfield; -// typedef int GLint; -// typedef unsigned int GLuint; -// typedef int GLsizei; -// typedef char GLchar; -// typedef khronos_uint8_t GLubyte; -// typedef khronos_float_t GLfloat; -// typedef khronos_intptr_t GLintptr; -// typedef khronos_ssize_t GLsizeiptr; -// typedef void (APIENTRYP GPACTIVETEXTURE)(GLenum texture); -// typedef void (APIENTRYP GPATTACHSHADER)(GLuint program, GLuint shader); -// typedef void (APIENTRYP GPBINDATTRIBLOCATION)(GLuint program, GLuint index, const GLchar * name); -// typedef void (APIENTRYP GPBINDBUFFER)(GLenum target, GLuint buffer); -// typedef void (APIENTRYP GPBINDFRAMEBUFFER)(GLenum target, GLuint framebuffer); -// typedef void (APIENTRYP GPBINDRENDERBUFFER)(GLenum target, GLuint renderbuffer); -// typedef void (APIENTRYP GPBINDTEXTURE)(GLenum target, GLuint texture); -// typedef void (APIENTRYP GPBLENDCOLOR)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -// typedef void (APIENTRYP GPBLENDEQUATION)(GLenum mode); -// typedef void (APIENTRYP GPBLENDEQUATIONSEPARATE)(GLenum modeRGB, GLenum modeAlpha); -// typedef void (APIENTRYP GPBLENDFUNC)(GLenum sfactor, GLenum dfactor); -// typedef void (APIENTRYP GPBLENDFUNCSEPARATE)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -// typedef void (APIENTRYP GPBUFFERDATA)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); -// typedef void (APIENTRYP GPBUFFERSUBDATA)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); -// typedef GLenum (APIENTRYP GPCHECKFRAMEBUFFERSTATUS)(GLenum target); -// typedef void (APIENTRYP GPCLEAR)(GLbitfield mask); -// typedef void (APIENTRYP GPCLEARCOLOR)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -// typedef void (APIENTRYP GPCLEARSTENCIL)(GLint s); -// typedef void (APIENTRYP GPCOLORMASK)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -// typedef void (APIENTRYP GPCOMPILESHADER)(GLuint shader); -// typedef void (APIENTRYP GPCOMPRESSEDTEXIMAGE2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); -// typedef void (APIENTRYP GPCOMPRESSEDTEXSUBIMAGE2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); -// typedef void (APIENTRYP GPCOPYTEXIMAGE2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -// typedef void (APIENTRYP GPCOPYTEXSUBIMAGE2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -// typedef GLuint (APIENTRYP GPCREATEPROGRAM)(); -// typedef GLuint (APIENTRYP GPCREATESHADER)(GLenum type); -// typedef void (APIENTRYP GPCULLFACE)(GLenum mode); -// typedef void (APIENTRYP GPDELETEBUFFERS)(GLsizei n, const GLuint * buffers); -// typedef void (APIENTRYP GPDELETEFRAMEBUFFERS)(GLsizei n, const GLuint * framebuffers); -// typedef void (APIENTRYP GPDELETEPROGRAM)(GLuint program); -// typedef void (APIENTRYP GPDELETERENDERBUFFERS)(GLsizei n, const GLuint * renderbuffers); -// typedef void (APIENTRYP GPDELETESHADER)(GLuint shader); -// typedef void (APIENTRYP GPDELETETEXTURES)(GLsizei n, const GLuint * textures); -// typedef void (APIENTRYP GPDEPTHFUNC)(GLenum func); -// typedef void (APIENTRYP GPDEPTHMASK)(GLboolean flag); -// typedef void (APIENTRYP GPDETACHSHADER)(GLuint program, GLuint shader); -// typedef void (APIENTRYP GPDISABLE)(GLenum cap); -// typedef void (APIENTRYP GPDISABLEVERTEXATTRIBARRAY)(GLuint index); -// typedef void (APIENTRYP GPDRAWARRAYS)(GLenum mode, GLint first, GLsizei count); -// typedef void (APIENTRYP GPDRAWELEMENTS)(GLenum mode, GLsizei count, GLenum type, const void * indices); -// typedef void (APIENTRYP GPENABLE)(GLenum cap); -// typedef void (APIENTRYP GPENABLEVERTEXATTRIBARRAY)(GLuint index); -// typedef void (APIENTRYP GPFINISH)(); -// typedef void (APIENTRYP GPFLUSH)(); -// typedef void (APIENTRYP GPFRAMEBUFFERRENDERBUFFER)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -// typedef void (APIENTRYP GPFRAMEBUFFERTEXTURE2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -// typedef void (APIENTRYP GPFRONTFACE)(GLenum mode); -// typedef void (APIENTRYP GPGENBUFFERS)(GLsizei n, GLuint * buffers); -// typedef void (APIENTRYP GPGENFRAMEBUFFERS)(GLsizei n, GLuint * framebuffers); -// typedef void (APIENTRYP GPGENRENDERBUFFERS)(GLsizei n, GLuint * renderbuffers); -// typedef void (APIENTRYP GPGENTEXTURES)(GLsizei n, GLuint * textures); -// typedef void (APIENTRYP GPGENERATEMIPMAP)(GLenum target); -// typedef void (APIENTRYP GPGETACTIVEATTRIB)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); -// typedef void (APIENTRYP GPGETACTIVEUNIFORM)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); -// typedef void (APIENTRYP GPGETATTACHEDSHADERS)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); -// typedef GLint (APIENTRYP GPGETATTRIBLOCATION)(GLuint program, const GLchar * name); -// typedef void (APIENTRYP GPGETBOOLEANV)(GLenum pname, GLboolean * data); -// typedef void (APIENTRYP GPGETBUFFERPARAMETERIV)(GLenum target, GLenum pname, GLint * params); -// typedef GLenum (APIENTRYP GPGETERROR)(); -// typedef void (APIENTRYP GPGETFLOATV)(GLenum pname, GLfloat * data); -// typedef void (APIENTRYP GPGETFRAMEBUFFERATTACHMENTPARAMETERIV)(GLenum target, GLenum attachment, GLenum pname, GLint * params); -// typedef void (APIENTRYP GPGETINTEGERV)(GLenum pname, GLint * data); -// typedef void (APIENTRYP GPGETPROGRAMINFOLOG)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); -// typedef void (APIENTRYP GPGETPROGRAMIV)(GLuint program, GLenum pname, GLint * params); -// typedef void (APIENTRYP GPGETRENDERBUFFERPARAMETERIV)(GLenum target, GLenum pname, GLint * params); -// typedef void (APIENTRYP GPGETSHADERINFOLOG)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); -// typedef void (APIENTRYP GPGETSHADERSOURCE)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); -// typedef void (APIENTRYP GPGETSHADERIV)(GLuint shader, GLenum pname, GLint * params); -// typedef const GLubyte * (APIENTRYP GPGETSTRING)(GLenum name); -// typedef void (APIENTRYP GPGETTEXPARAMETERFV)(GLenum target, GLenum pname, GLfloat * params); -// typedef void (APIENTRYP GPGETTEXPARAMETERIV)(GLenum target, GLenum pname, GLint * params); -// typedef GLint (APIENTRYP GPGETUNIFORMLOCATION)(GLuint program, const GLchar * name); -// typedef void (APIENTRYP GPGETUNIFORMFV)(GLuint program, GLint location, GLfloat * params); -// typedef void (APIENTRYP GPGETUNIFORMIV)(GLuint program, GLint location, GLint * params); -// typedef void (APIENTRYP GPGETVERTEXATTRIBPOINTERV)(GLuint index, GLenum pname, void ** pointer); -// typedef void (APIENTRYP GPGETVERTEXATTRIBFV)(GLuint index, GLenum pname, GLfloat * params); -// typedef void (APIENTRYP GPGETVERTEXATTRIBIV)(GLuint index, GLenum pname, GLint * params); -// typedef void (APIENTRYP GPHINT)(GLenum target, GLenum mode); -// typedef GLboolean (APIENTRYP GPISBUFFER)(GLuint buffer); -// typedef GLboolean (APIENTRYP GPISENABLED)(GLenum cap); -// typedef GLboolean (APIENTRYP GPISFRAMEBUFFER)(GLuint framebuffer); -// typedef GLboolean (APIENTRYP GPISPROGRAM)(GLuint program); -// typedef GLboolean (APIENTRYP GPISRENDERBUFFER)(GLuint renderbuffer); -// typedef GLboolean (APIENTRYP GPISSHADER)(GLuint shader); -// typedef GLboolean (APIENTRYP GPISTEXTURE)(GLuint texture); -// typedef void (APIENTRYP GPLINEWIDTH)(GLfloat width); -// typedef void (APIENTRYP GPLINKPROGRAM)(GLuint program); -// typedef void (APIENTRYP GPPIXELSTOREI)(GLenum pname, GLint param); -// typedef void (APIENTRYP GPPOLYGONOFFSET)(GLfloat factor, GLfloat units); -// typedef void (APIENTRYP GPREADPIXELS)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); -// typedef void (APIENTRYP GPRENDERBUFFERSTORAGE)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -// typedef void (APIENTRYP GPSAMPLECOVERAGE)(GLfloat value, GLboolean invert); -// typedef void (APIENTRYP GPSCISSOR)(GLint x, GLint y, GLsizei width, GLsizei height); -// typedef void (APIENTRYP GPSHADERSOURCE)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); -// typedef void (APIENTRYP GPSTENCILFUNC)(GLenum func, GLint ref, GLuint mask); -// typedef void (APIENTRYP GPSTENCILFUNCSEPARATE)(GLenum face, GLenum func, GLint ref, GLuint mask); -// typedef void (APIENTRYP GPSTENCILMASK)(GLuint mask); -// typedef void (APIENTRYP GPSTENCILMASKSEPARATE)(GLenum face, GLuint mask); -// typedef void (APIENTRYP GPSTENCILOP)(GLenum fail, GLenum zfail, GLenum zpass); -// typedef void (APIENTRYP GPSTENCILOPSEPARATE)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -// typedef void (APIENTRYP GPTEXIMAGE2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); -// typedef void (APIENTRYP GPTEXPARAMETERF)(GLenum target, GLenum pname, GLfloat param); -// typedef void (APIENTRYP GPTEXPARAMETERFV)(GLenum target, GLenum pname, const GLfloat * params); -// typedef void (APIENTRYP GPTEXPARAMETERI)(GLenum target, GLenum pname, GLint param); -// typedef void (APIENTRYP GPTEXPARAMETERIV)(GLenum target, GLenum pname, const GLint * params); -// typedef void (APIENTRYP GPTEXSUBIMAGE2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); -// typedef void (APIENTRYP GPUNIFORM1F)(GLint location, GLfloat v0); -// typedef void (APIENTRYP GPUNIFORM1FV)(GLint location, GLsizei count, const GLfloat * value); -// typedef void (APIENTRYP GPUNIFORM1I)(GLint location, GLint v0); -// typedef void (APIENTRYP GPUNIFORM1IV)(GLint location, GLsizei count, const GLint * value); -// typedef void (APIENTRYP GPUNIFORM2F)(GLint location, GLfloat v0, GLfloat v1); -// typedef void (APIENTRYP GPUNIFORM2FV)(GLint location, GLsizei count, const GLfloat * value); -// typedef void (APIENTRYP GPUNIFORM2I)(GLint location, GLint v0, GLint v1); -// typedef void (APIENTRYP GPUNIFORM2IV)(GLint location, GLsizei count, const GLint * value); -// typedef void (APIENTRYP GPUNIFORM3F)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -// typedef void (APIENTRYP GPUNIFORM3FV)(GLint location, GLsizei count, const GLfloat * value); -// typedef void (APIENTRYP GPUNIFORM3I)(GLint location, GLint v0, GLint v1, GLint v2); -// typedef void (APIENTRYP GPUNIFORM3IV)(GLint location, GLsizei count, const GLint * value); -// typedef void (APIENTRYP GPUNIFORM4F)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -// typedef void (APIENTRYP GPUNIFORM4FV)(GLint location, GLsizei count, const GLfloat * value); -// typedef void (APIENTRYP GPUNIFORM4I)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -// typedef void (APIENTRYP GPUNIFORM4IV)(GLint location, GLsizei count, const GLint * value); -// typedef void (APIENTRYP GPUNIFORMMATRIX2FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -// typedef void (APIENTRYP GPUNIFORMMATRIX3FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -// typedef void (APIENTRYP GPUNIFORMMATRIX4FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -// typedef void (APIENTRYP GPUSEPROGRAM)(GLuint program); -// typedef void (APIENTRYP GPVALIDATEPROGRAM)(GLuint program); -// typedef void (APIENTRYP GPVERTEXATTRIB1F)(GLuint index, GLfloat x); -// typedef void (APIENTRYP GPVERTEXATTRIB1FV)(GLuint index, const GLfloat * v); -// typedef void (APIENTRYP GPVERTEXATTRIB2F)(GLuint index, GLfloat x, GLfloat y); -// typedef void (APIENTRYP GPVERTEXATTRIB2FV)(GLuint index, const GLfloat * v); -// typedef void (APIENTRYP GPVERTEXATTRIB3F)(GLuint index, GLfloat x, GLfloat y, GLfloat z); -// typedef void (APIENTRYP GPVERTEXATTRIB3FV)(GLuint index, const GLfloat * v); -// typedef void (APIENTRYP GPVERTEXATTRIB4F)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -// typedef void (APIENTRYP GPVERTEXATTRIB4FV)(GLuint index, const GLfloat * v); -// typedef void (APIENTRYP GPVERTEXATTRIBPOINTER)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); -// typedef void (APIENTRYP GPVIEWPORT)(GLint x, GLint y, GLsizei width, GLsizei height); -// static void glowActiveTexture(GPACTIVETEXTURE fnptr, GLenum texture) { -// (*fnptr)(texture); -// } -// static void glowAttachShader(GPATTACHSHADER fnptr, GLuint program, GLuint shader) { -// (*fnptr)(program, shader); -// } -// static void glowBindAttribLocation(GPBINDATTRIBLOCATION fnptr, GLuint program, GLuint index, const GLchar * name) { -// (*fnptr)(program, index, name); -// } -// static void glowBindBuffer(GPBINDBUFFER fnptr, GLenum target, GLuint buffer) { -// (*fnptr)(target, buffer); -// } -// static void glowBindFramebuffer(GPBINDFRAMEBUFFER fnptr, GLenum target, GLuint framebuffer) { -// (*fnptr)(target, framebuffer); -// } -// static void glowBindRenderbuffer(GPBINDRENDERBUFFER fnptr, GLenum target, GLuint renderbuffer) { -// (*fnptr)(target, renderbuffer); -// } -// static void glowBindTexture(GPBINDTEXTURE fnptr, GLenum target, GLuint texture) { -// (*fnptr)(target, texture); -// } -// static void glowBlendColor(GPBLENDCOLOR fnptr, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { -// (*fnptr)(red, green, blue, alpha); -// } -// static void glowBlendEquation(GPBLENDEQUATION fnptr, GLenum mode) { -// (*fnptr)(mode); -// } -// static void glowBlendEquationSeparate(GPBLENDEQUATIONSEPARATE fnptr, GLenum modeRGB, GLenum modeAlpha) { -// (*fnptr)(modeRGB, modeAlpha); -// } -// static void glowBlendFunc(GPBLENDFUNC fnptr, GLenum sfactor, GLenum dfactor) { -// (*fnptr)(sfactor, dfactor); -// } -// static void glowBlendFuncSeparate(GPBLENDFUNCSEPARATE fnptr, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) { -// (*fnptr)(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); -// } -// static void glowBufferData(GPBUFFERDATA fnptr, GLenum target, GLsizeiptr size, const void * data, GLenum usage) { -// (*fnptr)(target, size, data, usage); -// } -// static void glowBufferSubData(GPBUFFERSUBDATA fnptr, GLenum target, GLintptr offset, GLsizeiptr size, const void * data) { -// (*fnptr)(target, offset, size, data); -// } -// static GLenum glowCheckFramebufferStatus(GPCHECKFRAMEBUFFERSTATUS fnptr, GLenum target) { -// return (*fnptr)(target); -// } -// static void glowClear(GPCLEAR fnptr, GLbitfield mask) { -// (*fnptr)(mask); -// } -// static void glowClearColor(GPCLEARCOLOR fnptr, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { -// (*fnptr)(red, green, blue, alpha); -// } -// static void glowClearStencil(GPCLEARSTENCIL fnptr, GLint s) { -// (*fnptr)(s); -// } -// static void glowColorMask(GPCOLORMASK fnptr, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { -// (*fnptr)(red, green, blue, alpha); -// } -// static void glowCompileShader(GPCOMPILESHADER fnptr, GLuint shader) { -// (*fnptr)(shader); -// } -// static void glowCompressedTexImage2D(GPCOMPRESSEDTEXIMAGE2D fnptr, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data) { -// (*fnptr)(target, level, internalformat, width, height, border, imageSize, data); -// } -// static void glowCompressedTexSubImage2D(GPCOMPRESSEDTEXSUBIMAGE2D fnptr, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data) { -// (*fnptr)(target, level, xoffset, yoffset, width, height, format, imageSize, data); -// } -// static void glowCopyTexImage2D(GPCOPYTEXIMAGE2D fnptr, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { -// (*fnptr)(target, level, internalformat, x, y, width, height, border); -// } -// static void glowCopyTexSubImage2D(GPCOPYTEXSUBIMAGE2D fnptr, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { -// (*fnptr)(target, level, xoffset, yoffset, x, y, width, height); -// } -// static GLuint glowCreateProgram(GPCREATEPROGRAM fnptr) { -// return (*fnptr)(); -// } -// static GLuint glowCreateShader(GPCREATESHADER fnptr, GLenum type) { -// return (*fnptr)(type); -// } -// static void glowCullFace(GPCULLFACE fnptr, GLenum mode) { -// (*fnptr)(mode); -// } -// static void glowDeleteBuffers(GPDELETEBUFFERS fnptr, GLsizei n, const GLuint * buffers) { -// (*fnptr)(n, buffers); -// } -// static void glowDeleteFramebuffers(GPDELETEFRAMEBUFFERS fnptr, GLsizei n, const GLuint * framebuffers) { -// (*fnptr)(n, framebuffers); -// } -// static void glowDeleteProgram(GPDELETEPROGRAM fnptr, GLuint program) { -// (*fnptr)(program); -// } -// static void glowDeleteRenderbuffers(GPDELETERENDERBUFFERS fnptr, GLsizei n, const GLuint * renderbuffers) { -// (*fnptr)(n, renderbuffers); -// } -// static void glowDeleteShader(GPDELETESHADER fnptr, GLuint shader) { -// (*fnptr)(shader); -// } -// static void glowDeleteTextures(GPDELETETEXTURES fnptr, GLsizei n, const GLuint * textures) { -// (*fnptr)(n, textures); -// } -// static void glowDepthFunc(GPDEPTHFUNC fnptr, GLenum func) { -// (*fnptr)(func); -// } -// static void glowDepthMask(GPDEPTHMASK fnptr, GLboolean flag) { -// (*fnptr)(flag); -// } -// static void glowDetachShader(GPDETACHSHADER fnptr, GLuint program, GLuint shader) { -// (*fnptr)(program, shader); -// } -// static void glowDisable(GPDISABLE fnptr, GLenum cap) { -// (*fnptr)(cap); -// } -// static void glowDisableVertexAttribArray(GPDISABLEVERTEXATTRIBARRAY fnptr, GLuint index) { -// (*fnptr)(index); -// } -// static void glowDrawArrays(GPDRAWARRAYS fnptr, GLenum mode, GLint first, GLsizei count) { -// (*fnptr)(mode, first, count); -// } -// static void glowDrawElements(GPDRAWELEMENTS fnptr, GLenum mode, GLsizei count, GLenum type, const void * indices) { -// (*fnptr)(mode, count, type, indices); -// } -// static void glowEnable(GPENABLE fnptr, GLenum cap) { -// (*fnptr)(cap); -// } -// static void glowEnableVertexAttribArray(GPENABLEVERTEXATTRIBARRAY fnptr, GLuint index) { -// (*fnptr)(index); -// } -// static void glowFinish(GPFINISH fnptr) { -// (*fnptr)(); -// } -// static void glowFlush(GPFLUSH fnptr) { -// (*fnptr)(); -// } -// static void glowFramebufferRenderbuffer(GPFRAMEBUFFERRENDERBUFFER fnptr, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { -// (*fnptr)(target, attachment, renderbuffertarget, renderbuffer); -// } -// static void glowFramebufferTexture2D(GPFRAMEBUFFERTEXTURE2D fnptr, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { -// (*fnptr)(target, attachment, textarget, texture, level); -// } -// static void glowFrontFace(GPFRONTFACE fnptr, GLenum mode) { -// (*fnptr)(mode); -// } -// static void glowGenBuffers(GPGENBUFFERS fnptr, GLsizei n, GLuint * buffers) { -// (*fnptr)(n, buffers); -// } -// static void glowGenFramebuffers(GPGENFRAMEBUFFERS fnptr, GLsizei n, GLuint * framebuffers) { -// (*fnptr)(n, framebuffers); -// } -// static void glowGenRenderbuffers(GPGENRENDERBUFFERS fnptr, GLsizei n, GLuint * renderbuffers) { -// (*fnptr)(n, renderbuffers); -// } -// static void glowGenTextures(GPGENTEXTURES fnptr, GLsizei n, GLuint * textures) { -// (*fnptr)(n, textures); -// } -// static void glowGenerateMipmap(GPGENERATEMIPMAP fnptr, GLenum target) { -// (*fnptr)(target); -// } -// static void glowGetActiveAttrib(GPGETACTIVEATTRIB fnptr, GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) { -// (*fnptr)(program, index, bufSize, length, size, type, name); -// } -// static void glowGetActiveUniform(GPGETACTIVEUNIFORM fnptr, GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) { -// (*fnptr)(program, index, bufSize, length, size, type, name); -// } -// static void glowGetAttachedShaders(GPGETATTACHEDSHADERS fnptr, GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders) { -// (*fnptr)(program, maxCount, count, shaders); -// } -// static GLint glowGetAttribLocation(GPGETATTRIBLOCATION fnptr, GLuint program, const GLchar * name) { -// return (*fnptr)(program, name); -// } -// static void glowGetBooleanv(GPGETBOOLEANV fnptr, GLenum pname, GLboolean * data) { -// (*fnptr)(pname, data); -// } -// static void glowGetBufferParameteriv(GPGETBUFFERPARAMETERIV fnptr, GLenum target, GLenum pname, GLint * params) { -// (*fnptr)(target, pname, params); -// } -// static GLenum glowGetError(GPGETERROR fnptr) { -// return (*fnptr)(); -// } -// static void glowGetFloatv(GPGETFLOATV fnptr, GLenum pname, GLfloat * data) { -// (*fnptr)(pname, data); -// } -// static void glowGetFramebufferAttachmentParameteriv(GPGETFRAMEBUFFERATTACHMENTPARAMETERIV fnptr, GLenum target, GLenum attachment, GLenum pname, GLint * params) { -// (*fnptr)(target, attachment, pname, params); -// } -// static void glowGetIntegerv(GPGETINTEGERV fnptr, GLenum pname, GLint * data) { -// (*fnptr)(pname, data); -// } -// static void glowGetProgramInfoLog(GPGETPROGRAMINFOLOG fnptr, GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog) { -// (*fnptr)(program, bufSize, length, infoLog); -// } -// static void glowGetProgramiv(GPGETPROGRAMIV fnptr, GLuint program, GLenum pname, GLint * params) { -// (*fnptr)(program, pname, params); -// } -// static void glowGetRenderbufferParameteriv(GPGETRENDERBUFFERPARAMETERIV fnptr, GLenum target, GLenum pname, GLint * params) { -// (*fnptr)(target, pname, params); -// } -// static void glowGetShaderInfoLog(GPGETSHADERINFOLOG fnptr, GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog) { -// (*fnptr)(shader, bufSize, length, infoLog); -// } -// static void glowGetShaderSource(GPGETSHADERSOURCE fnptr, GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source) { -// (*fnptr)(shader, bufSize, length, source); -// } -// static void glowGetShaderiv(GPGETSHADERIV fnptr, GLuint shader, GLenum pname, GLint * params) { -// (*fnptr)(shader, pname, params); -// } -// static const GLubyte * glowGetString(GPGETSTRING fnptr, GLenum name) { -// return (*fnptr)(name); -// } -// static void glowGetTexParameterfv(GPGETTEXPARAMETERFV fnptr, GLenum target, GLenum pname, GLfloat * params) { -// (*fnptr)(target, pname, params); -// } -// static void glowGetTexParameteriv(GPGETTEXPARAMETERIV fnptr, GLenum target, GLenum pname, GLint * params) { -// (*fnptr)(target, pname, params); -// } -// static GLint glowGetUniformLocation(GPGETUNIFORMLOCATION fnptr, GLuint program, const GLchar * name) { -// return (*fnptr)(program, name); -// } -// static void glowGetUniformfv(GPGETUNIFORMFV fnptr, GLuint program, GLint location, GLfloat * params) { -// (*fnptr)(program, location, params); -// } -// static void glowGetUniformiv(GPGETUNIFORMIV fnptr, GLuint program, GLint location, GLint * params) { -// (*fnptr)(program, location, params); -// } -// static void glowGetVertexAttribPointerv(GPGETVERTEXATTRIBPOINTERV fnptr, GLuint index, GLenum pname, void ** pointer) { -// (*fnptr)(index, pname, pointer); -// } -// static void glowGetVertexAttribfv(GPGETVERTEXATTRIBFV fnptr, GLuint index, GLenum pname, GLfloat * params) { -// (*fnptr)(index, pname, params); -// } -// static void glowGetVertexAttribiv(GPGETVERTEXATTRIBIV fnptr, GLuint index, GLenum pname, GLint * params) { -// (*fnptr)(index, pname, params); -// } -// static void glowHint(GPHINT fnptr, GLenum target, GLenum mode) { -// (*fnptr)(target, mode); -// } -// static GLboolean glowIsBuffer(GPISBUFFER fnptr, GLuint buffer) { -// return (*fnptr)(buffer); -// } -// static GLboolean glowIsEnabled(GPISENABLED fnptr, GLenum cap) { -// return (*fnptr)(cap); -// } -// static GLboolean glowIsFramebuffer(GPISFRAMEBUFFER fnptr, GLuint framebuffer) { -// return (*fnptr)(framebuffer); -// } -// static GLboolean glowIsProgram(GPISPROGRAM fnptr, GLuint program) { -// return (*fnptr)(program); -// } -// static GLboolean glowIsRenderbuffer(GPISRENDERBUFFER fnptr, GLuint renderbuffer) { -// return (*fnptr)(renderbuffer); -// } -// static GLboolean glowIsShader(GPISSHADER fnptr, GLuint shader) { -// return (*fnptr)(shader); -// } -// static GLboolean glowIsTexture(GPISTEXTURE fnptr, GLuint texture) { -// return (*fnptr)(texture); -// } -// static void glowLineWidth(GPLINEWIDTH fnptr, GLfloat width) { -// (*fnptr)(width); -// } -// static void glowLinkProgram(GPLINKPROGRAM fnptr, GLuint program) { -// (*fnptr)(program); -// } -// static void glowPixelStorei(GPPIXELSTOREI fnptr, GLenum pname, GLint param) { -// (*fnptr)(pname, param); -// } -// static void glowPolygonOffset(GPPOLYGONOFFSET fnptr, GLfloat factor, GLfloat units) { -// (*fnptr)(factor, units); -// } -// static void glowReadPixels(GPREADPIXELS fnptr, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels) { -// (*fnptr)(x, y, width, height, format, type, pixels); -// } -// static void glowRenderbufferStorage(GPRENDERBUFFERSTORAGE fnptr, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { -// (*fnptr)(target, internalformat, width, height); -// } -// static void glowSampleCoverage(GPSAMPLECOVERAGE fnptr, GLfloat value, GLboolean invert) { -// (*fnptr)(value, invert); -// } -// static void glowScissor(GPSCISSOR fnptr, GLint x, GLint y, GLsizei width, GLsizei height) { -// (*fnptr)(x, y, width, height); -// } -// static void glowShaderSource(GPSHADERSOURCE fnptr, GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length) { -// (*fnptr)(shader, count, string, length); -// } -// static void glowStencilFunc(GPSTENCILFUNC fnptr, GLenum func, GLint ref, GLuint mask) { -// (*fnptr)(func, ref, mask); -// } -// static void glowStencilFuncSeparate(GPSTENCILFUNCSEPARATE fnptr, GLenum face, GLenum func, GLint ref, GLuint mask) { -// (*fnptr)(face, func, ref, mask); -// } -// static void glowStencilMask(GPSTENCILMASK fnptr, GLuint mask) { -// (*fnptr)(mask); -// } -// static void glowStencilMaskSeparate(GPSTENCILMASKSEPARATE fnptr, GLenum face, GLuint mask) { -// (*fnptr)(face, mask); -// } -// static void glowStencilOp(GPSTENCILOP fnptr, GLenum fail, GLenum zfail, GLenum zpass) { -// (*fnptr)(fail, zfail, zpass); -// } -// static void glowStencilOpSeparate(GPSTENCILOPSEPARATE fnptr, GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) { -// (*fnptr)(face, sfail, dpfail, dppass); -// } -// static void glowTexImage2D(GPTEXIMAGE2D fnptr, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels) { -// (*fnptr)(target, level, internalformat, width, height, border, format, type, pixels); -// } -// static void glowTexParameterf(GPTEXPARAMETERF fnptr, GLenum target, GLenum pname, GLfloat param) { -// (*fnptr)(target, pname, param); -// } -// static void glowTexParameterfv(GPTEXPARAMETERFV fnptr, GLenum target, GLenum pname, const GLfloat * params) { -// (*fnptr)(target, pname, params); -// } -// static void glowTexParameteri(GPTEXPARAMETERI fnptr, GLenum target, GLenum pname, GLint param) { -// (*fnptr)(target, pname, param); -// } -// static void glowTexParameteriv(GPTEXPARAMETERIV fnptr, GLenum target, GLenum pname, const GLint * params) { -// (*fnptr)(target, pname, params); -// } -// static void glowTexSubImage2D(GPTEXSUBIMAGE2D fnptr, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) { -// (*fnptr)(target, level, xoffset, yoffset, width, height, format, type, pixels); -// } -// static void glowUniform1f(GPUNIFORM1F fnptr, GLint location, GLfloat v0) { -// (*fnptr)(location, v0); -// } -// static void glowUniform1fv(GPUNIFORM1FV fnptr, GLint location, GLsizei count, const GLfloat * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniform1i(GPUNIFORM1I fnptr, GLint location, GLint v0) { -// (*fnptr)(location, v0); -// } -// static void glowUniform1iv(GPUNIFORM1IV fnptr, GLint location, GLsizei count, const GLint * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniform2f(GPUNIFORM2F fnptr, GLint location, GLfloat v0, GLfloat v1) { -// (*fnptr)(location, v0, v1); -// } -// static void glowUniform2fv(GPUNIFORM2FV fnptr, GLint location, GLsizei count, const GLfloat * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniform2i(GPUNIFORM2I fnptr, GLint location, GLint v0, GLint v1) { -// (*fnptr)(location, v0, v1); -// } -// static void glowUniform2iv(GPUNIFORM2IV fnptr, GLint location, GLsizei count, const GLint * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniform3f(GPUNIFORM3F fnptr, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { -// (*fnptr)(location, v0, v1, v2); -// } -// static void glowUniform3fv(GPUNIFORM3FV fnptr, GLint location, GLsizei count, const GLfloat * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniform3i(GPUNIFORM3I fnptr, GLint location, GLint v0, GLint v1, GLint v2) { -// (*fnptr)(location, v0, v1, v2); -// } -// static void glowUniform3iv(GPUNIFORM3IV fnptr, GLint location, GLsizei count, const GLint * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniform4f(GPUNIFORM4F fnptr, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { -// (*fnptr)(location, v0, v1, v2, v3); -// } -// static void glowUniform4fv(GPUNIFORM4FV fnptr, GLint location, GLsizei count, const GLfloat * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniform4i(GPUNIFORM4I fnptr, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) { -// (*fnptr)(location, v0, v1, v2, v3); -// } -// static void glowUniform4iv(GPUNIFORM4IV fnptr, GLint location, GLsizei count, const GLint * value) { -// (*fnptr)(location, count, value); -// } -// static void glowUniformMatrix2fv(GPUNIFORMMATRIX2FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { -// (*fnptr)(location, count, transpose, value); -// } -// static void glowUniformMatrix3fv(GPUNIFORMMATRIX3FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { -// (*fnptr)(location, count, transpose, value); -// } -// static void glowUniformMatrix4fv(GPUNIFORMMATRIX4FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { -// (*fnptr)(location, count, transpose, value); -// } -// static void glowUseProgram(GPUSEPROGRAM fnptr, GLuint program) { -// (*fnptr)(program); -// } -// static void glowValidateProgram(GPVALIDATEPROGRAM fnptr, GLuint program) { -// (*fnptr)(program); -// } -// static void glowVertexAttrib1f(GPVERTEXATTRIB1F fnptr, GLuint index, GLfloat x) { -// (*fnptr)(index, x); -// } -// static void glowVertexAttrib1fv(GPVERTEXATTRIB1FV fnptr, GLuint index, const GLfloat * v) { -// (*fnptr)(index, v); -// } -// static void glowVertexAttrib2f(GPVERTEXATTRIB2F fnptr, GLuint index, GLfloat x, GLfloat y) { -// (*fnptr)(index, x, y); -// } -// static void glowVertexAttrib2fv(GPVERTEXATTRIB2FV fnptr, GLuint index, const GLfloat * v) { -// (*fnptr)(index, v); -// } -// static void glowVertexAttrib3f(GPVERTEXATTRIB3F fnptr, GLuint index, GLfloat x, GLfloat y, GLfloat z) { -// (*fnptr)(index, x, y, z); -// } -// static void glowVertexAttrib3fv(GPVERTEXATTRIB3FV fnptr, GLuint index, const GLfloat * v) { -// (*fnptr)(index, v); -// } -// static void glowVertexAttrib4f(GPVERTEXATTRIB4F fnptr, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { -// (*fnptr)(index, x, y, z, w); -// } -// static void glowVertexAttrib4fv(GPVERTEXATTRIB4FV fnptr, GLuint index, const GLfloat * v) { -// (*fnptr)(index, v); -// } -// static void glowVertexAttribPointer(GPVERTEXATTRIBPOINTER fnptr, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer) { -// (*fnptr)(index, size, type, normalized, stride, pointer); -// } -// static void glowViewport(GPVIEWPORT fnptr, GLint x, GLint y, GLsizei width, GLsizei height) { -// (*fnptr)(x, y, width, height); -// } -import "C" -import ( - "errors" - "unsafe" -) - -const ( - ACTIVE_ATTRIBUTES = 0x8B89 - ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A - ACTIVE_TEXTURE = 0x84E0 - ACTIVE_UNIFORMS = 0x8B86 - ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87 - ALIASED_LINE_WIDTH_RANGE = 0x846E - ALIASED_POINT_SIZE_RANGE = 0x846D - ALPHA = 0x1906 - ALPHA_BITS = 0x0D55 - ALWAYS = 0x0207 - ARRAY_BUFFER = 0x8892 - ARRAY_BUFFER_BINDING = 0x8894 - ATTACHED_SHADERS = 0x8B85 - BACK = 0x0405 - BLEND = 0x0BE2 - BLEND_DST_ALPHA = 0x80CA - BLEND_DST_RGB = 0x80C8 - BLEND_EQUATION_ALPHA = 0x883D - BLEND_EQUATION_RGB = 0x8009 - BLEND_SRC_ALPHA = 0x80CB - BLEND_SRC_RGB = 0x80C9 - BLUE_BITS = 0x0D54 - BOOL = 0x8B56 - BOOL_VEC2 = 0x8B57 - BOOL_VEC3 = 0x8B58 - BOOL_VEC4 = 0x8B59 - BUFFER_SIZE = 0x8764 - BUFFER_USAGE = 0x8765 - BYTE = 0x1400 - CCW = 0x0901 - CLAMP_TO_EDGE = 0x812F - COLOR_ATTACHMENT0 = 0x8CE0 - COLOR_BUFFER_BIT = 0x00004000 - COLOR_CLEAR_VALUE = 0x0C22 - COLOR_WRITEMASK = 0x0C23 - COMPILE_STATUS = 0x8B81 - COMPRESSED_TEXTURE_FORMATS = 0x86A3 - CONSTANT_ALPHA = 0x8003 - CONSTANT_COLOR = 0x8001 - CULL_FACE = 0x0B44 - CULL_FACE_MODE = 0x0B45 - CURRENT_PROGRAM = 0x8B8D - CURRENT_VERTEX_ATTRIB = 0x8626 - CW = 0x0900 - DECR = 0x1E03 - DECR_WRAP = 0x8508 - DELETE_STATUS = 0x8B80 - DEPTH_ATTACHMENT = 0x8D00 - DEPTH_BITS = 0x0D56 - DEPTH_BUFFER_BIT = 0x00000100 - DEPTH_CLEAR_VALUE = 0x0B73 - DEPTH_COMPONENT = 0x1902 - DEPTH_COMPONENT16 = 0x81A5 - DEPTH_FUNC = 0x0B74 - DEPTH_RANGE = 0x0B70 - DEPTH_TEST = 0x0B71 - DEPTH_WRITEMASK = 0x0B72 - DITHER = 0x0BD0 - DONT_CARE = 0x1100 - DST_ALPHA = 0x0304 - DST_COLOR = 0x0306 - DYNAMIC_DRAW = 0x88E8 - ELEMENT_ARRAY_BUFFER = 0x8893 - ELEMENT_ARRAY_BUFFER_BINDING = 0x8895 - EQUAL = 0x0202 - EXTENSIONS = 0x1F03 - FALSE = 0 - FASTEST = 0x1101 - FLOAT = 0x1406 - FLOAT_MAT2 = 0x8B5A - FLOAT_MAT3 = 0x8B5B - FLOAT_MAT4 = 0x8B5C - FLOAT_VEC2 = 0x8B50 - FLOAT_VEC3 = 0x8B51 - FLOAT_VEC4 = 0x8B52 - FRAGMENT_SHADER = 0x8B30 - FRAMEBUFFER = 0x8D40 - FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1 - FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0 - FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3 - FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2 - FRAMEBUFFER_BINDING = 0x8CA6 - FRAMEBUFFER_COMPLETE = 0x8CD5 - FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6 - FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7 - FRAMEBUFFER_UNSUPPORTED = 0x8CDD - FRONT = 0x0404 - FRONT_AND_BACK = 0x0408 - FRONT_FACE = 0x0B46 - FUNC_ADD = 0x8006 - FUNC_REVERSE_SUBTRACT = 0x800B - FUNC_SUBTRACT = 0x800A - GENERATE_MIPMAP_HINT = 0x8192 - GEQUAL = 0x0206 - GREATER = 0x0204 - GREEN_BITS = 0x0D53 - INCR = 0x1E02 - INCR_WRAP = 0x8507 - INFO_LOG_LENGTH = 0x8B84 - INT = 0x1404 - INT_VEC2 = 0x8B53 - INT_VEC3 = 0x8B54 - INT_VEC4 = 0x8B55 - INVALID_ENUM = 0x0500 - INVALID_FRAMEBUFFER_OPERATION = 0x0506 - INVALID_OPERATION = 0x0502 - INVALID_VALUE = 0x0501 - INVERT = 0x150A - KEEP = 0x1E00 - LEQUAL = 0x0203 - LESS = 0x0201 - LINEAR = 0x2601 - LINEAR_MIPMAP_LINEAR = 0x2703 - LINEAR_MIPMAP_NEAREST = 0x2701 - LINES = 0x0001 - LINE_LOOP = 0x0002 - LINE_STRIP = 0x0003 - LINE_WIDTH = 0x0B21 - LINK_STATUS = 0x8B82 - LUMINANCE = 0x1909 - LUMINANCE_ALPHA = 0x190A - MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D - MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C - MAX_RENDERBUFFER_SIZE = 0x84E8 - MAX_TEXTURE_IMAGE_UNITS = 0x8872 - MAX_TEXTURE_SIZE = 0x0D33 - MAX_VERTEX_ATTRIBS = 0x8869 - MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C - MAX_VIEWPORT_DIMS = 0x0D3A - MIRRORED_REPEAT = 0x8370 - NEAREST = 0x2600 - NEAREST_MIPMAP_LINEAR = 0x2702 - NEAREST_MIPMAP_NEAREST = 0x2700 - NEVER = 0x0200 - NICEST = 0x1102 - NONE = 0 - NOTEQUAL = 0x0205 - NO_ERROR = 0 - NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2 - ONE = 1 - ONE_MINUS_CONSTANT_ALPHA = 0x8004 - ONE_MINUS_CONSTANT_COLOR = 0x8002 - ONE_MINUS_DST_ALPHA = 0x0305 - ONE_MINUS_DST_COLOR = 0x0307 - ONE_MINUS_SRC_ALPHA = 0x0303 - ONE_MINUS_SRC_COLOR = 0x0301 - OUT_OF_MEMORY = 0x0505 - PACK_ALIGNMENT = 0x0D05 - POINTS = 0x0000 - POLYGON_OFFSET_FACTOR = 0x8038 - POLYGON_OFFSET_FILL = 0x8037 - POLYGON_OFFSET_UNITS = 0x2A00 - RED_BITS = 0x0D52 - RENDERBUFFER = 0x8D41 - RENDERBUFFER_ALPHA_SIZE = 0x8D53 - RENDERBUFFER_BINDING = 0x8CA7 - RENDERBUFFER_BLUE_SIZE = 0x8D52 - RENDERBUFFER_DEPTH_SIZE = 0x8D54 - RENDERBUFFER_GREEN_SIZE = 0x8D51 - RENDERBUFFER_HEIGHT = 0x8D43 - RENDERBUFFER_INTERNAL_FORMAT = 0x8D44 - RENDERBUFFER_RED_SIZE = 0x8D50 - RENDERBUFFER_STENCIL_SIZE = 0x8D55 - RENDERBUFFER_WIDTH = 0x8D42 - RENDERER = 0x1F01 - REPEAT = 0x2901 - REPLACE = 0x1E01 - RGB = 0x1907 - RGB5_A1 = 0x8057 - RGBA = 0x1908 - RGBA4 = 0x8056 - SAMPLER_2D = 0x8B5E - SAMPLER_CUBE = 0x8B60 - SAMPLES = 0x80A9 - SAMPLE_ALPHA_TO_COVERAGE = 0x809E - SAMPLE_BUFFERS = 0x80A8 - SAMPLE_COVERAGE = 0x80A0 - SAMPLE_COVERAGE_INVERT = 0x80AB - SAMPLE_COVERAGE_VALUE = 0x80AA - SCISSOR_BOX = 0x0C10 - SCISSOR_TEST = 0x0C11 - SHADER_SOURCE_LENGTH = 0x8B88 - SHADER_TYPE = 0x8B4F - SHADING_LANGUAGE_VERSION = 0x8B8C - SHORT = 0x1402 - SRC_ALPHA = 0x0302 - SRC_ALPHA_SATURATE = 0x0308 - SRC_COLOR = 0x0300 - STATIC_DRAW = 0x88E4 - STENCIL_ATTACHMENT = 0x8D20 - STENCIL_BACK_FAIL = 0x8801 - STENCIL_BACK_FUNC = 0x8800 - STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802 - STENCIL_BACK_PASS_DEPTH_PASS = 0x8803 - STENCIL_BACK_REF = 0x8CA3 - STENCIL_BACK_VALUE_MASK = 0x8CA4 - STENCIL_BACK_WRITEMASK = 0x8CA5 - STENCIL_BITS = 0x0D57 - STENCIL_BUFFER_BIT = 0x00000400 - STENCIL_CLEAR_VALUE = 0x0B91 - STENCIL_FAIL = 0x0B94 - STENCIL_FUNC = 0x0B92 - STENCIL_INDEX8 = 0x8D48 - STENCIL_PASS_DEPTH_FAIL = 0x0B95 - STENCIL_PASS_DEPTH_PASS = 0x0B96 - STENCIL_REF = 0x0B97 - STENCIL_TEST = 0x0B90 - STENCIL_VALUE_MASK = 0x0B93 - STENCIL_WRITEMASK = 0x0B98 - STREAM_DRAW = 0x88E0 - SUBPIXEL_BITS = 0x0D50 - TEXTURE = 0x1702 - TEXTURE0 = 0x84C0 - TEXTURE1 = 0x84C1 - TEXTURE10 = 0x84CA - TEXTURE11 = 0x84CB - TEXTURE12 = 0x84CC - TEXTURE13 = 0x84CD - TEXTURE14 = 0x84CE - TEXTURE15 = 0x84CF - TEXTURE16 = 0x84D0 - TEXTURE17 = 0x84D1 - TEXTURE18 = 0x84D2 - TEXTURE19 = 0x84D3 - TEXTURE2 = 0x84C2 - TEXTURE20 = 0x84D4 - TEXTURE21 = 0x84D5 - TEXTURE22 = 0x84D6 - TEXTURE23 = 0x84D7 - TEXTURE24 = 0x84D8 - TEXTURE25 = 0x84D9 - TEXTURE26 = 0x84DA - TEXTURE27 = 0x84DB - TEXTURE28 = 0x84DC - TEXTURE29 = 0x84DD - TEXTURE3 = 0x84C3 - TEXTURE30 = 0x84DE - TEXTURE31 = 0x84DF - TEXTURE4 = 0x84C4 - TEXTURE5 = 0x84C5 - TEXTURE6 = 0x84C6 - TEXTURE7 = 0x84C7 - TEXTURE8 = 0x84C8 - TEXTURE9 = 0x84C9 - TEXTURE_2D = 0x0DE1 - TEXTURE_BINDING_2D = 0x8069 - TEXTURE_BINDING_CUBE_MAP = 0x8514 - TEXTURE_CUBE_MAP = 0x8513 - TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516 - TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518 - TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A - TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515 - TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517 - TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519 - TEXTURE_MAG_FILTER = 0x2800 - TEXTURE_MIN_FILTER = 0x2801 - TEXTURE_WRAP_S = 0x2802 - TEXTURE_WRAP_T = 0x2803 - TRIANGLES = 0x0004 - TRIANGLE_FAN = 0x0006 - TRIANGLE_STRIP = 0x0005 - TRUE = 1 - UNPACK_ALIGNMENT = 0x0CF5 - UNSIGNED_BYTE = 0x1401 - UNSIGNED_INT = 0x1405 - UNSIGNED_SHORT = 0x1403 - UNSIGNED_SHORT_4_4_4_4 = 0x8033 - UNSIGNED_SHORT_5_5_5_1 = 0x8034 - UNSIGNED_SHORT_5_6_5 = 0x8363 - VALIDATE_STATUS = 0x8B83 - VENDOR = 0x1F00 - VERSION = 0x1F02 - VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F - VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622 - VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A - VERTEX_ATTRIB_ARRAY_POINTER = 0x8645 - VERTEX_ATTRIB_ARRAY_SIZE = 0x8623 - VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624 - VERTEX_ATTRIB_ARRAY_TYPE = 0x8625 - VERTEX_SHADER = 0x8B31 - VIEWPORT = 0x0BA2 - ZERO = 0 -) - -var ( - gpActiveTexture C.GPACTIVETEXTURE - gpAttachShader C.GPATTACHSHADER - gpBindAttribLocation C.GPBINDATTRIBLOCATION - gpBindBuffer C.GPBINDBUFFER - gpBindFramebuffer C.GPBINDFRAMEBUFFER - gpBindRenderbuffer C.GPBINDRENDERBUFFER - gpBindTexture C.GPBINDTEXTURE - gpBlendColor C.GPBLENDCOLOR - gpBlendEquation C.GPBLENDEQUATION - gpBlendEquationSeparate C.GPBLENDEQUATIONSEPARATE - gpBlendFunc C.GPBLENDFUNC - gpBlendFuncSeparate C.GPBLENDFUNCSEPARATE - gpBufferData C.GPBUFFERDATA - gpBufferSubData C.GPBUFFERSUBDATA - gpCheckFramebufferStatus C.GPCHECKFRAMEBUFFERSTATUS - gpClear C.GPCLEAR - gpClearColor C.GPCLEARCOLOR - gpClearStencil C.GPCLEARSTENCIL - gpColorMask C.GPCOLORMASK - gpCompileShader C.GPCOMPILESHADER - gpCompressedTexImage2D C.GPCOMPRESSEDTEXIMAGE2D - gpCompressedTexSubImage2D C.GPCOMPRESSEDTEXSUBIMAGE2D - gpCopyTexImage2D C.GPCOPYTEXIMAGE2D - gpCopyTexSubImage2D C.GPCOPYTEXSUBIMAGE2D - gpCreateProgram C.GPCREATEPROGRAM - gpCreateShader C.GPCREATESHADER - gpCullFace C.GPCULLFACE - gpDeleteBuffers C.GPDELETEBUFFERS - gpDeleteFramebuffers C.GPDELETEFRAMEBUFFERS - gpDeleteProgram C.GPDELETEPROGRAM - gpDeleteRenderbuffers C.GPDELETERENDERBUFFERS - gpDeleteShader C.GPDELETESHADER - gpDeleteTextures C.GPDELETETEXTURES - gpDepthFunc C.GPDEPTHFUNC - gpDepthMask C.GPDEPTHMASK - gpDetachShader C.GPDETACHSHADER - gpDisable C.GPDISABLE - gpDisableVertexAttribArray C.GPDISABLEVERTEXATTRIBARRAY - gpDrawArrays C.GPDRAWARRAYS - gpDrawElements C.GPDRAWELEMENTS - gpEnable C.GPENABLE - gpEnableVertexAttribArray C.GPENABLEVERTEXATTRIBARRAY - gpFinish C.GPFINISH - gpFlush C.GPFLUSH - gpFramebufferRenderbuffer C.GPFRAMEBUFFERRENDERBUFFER - gpFramebufferTexture2D C.GPFRAMEBUFFERTEXTURE2D - gpFrontFace C.GPFRONTFACE - gpGenBuffers C.GPGENBUFFERS - gpGenFramebuffers C.GPGENFRAMEBUFFERS - gpGenRenderbuffers C.GPGENRENDERBUFFERS - gpGenTextures C.GPGENTEXTURES - gpGenerateMipmap C.GPGENERATEMIPMAP - gpGetActiveAttrib C.GPGETACTIVEATTRIB - gpGetActiveUniform C.GPGETACTIVEUNIFORM - gpGetAttachedShaders C.GPGETATTACHEDSHADERS - gpGetAttribLocation C.GPGETATTRIBLOCATION - gpGetBooleanv C.GPGETBOOLEANV - gpGetBufferParameteriv C.GPGETBUFFERPARAMETERIV - gpGetError C.GPGETERROR - gpGetFloatv C.GPGETFLOATV - gpGetFramebufferAttachmentParameteriv C.GPGETFRAMEBUFFERATTACHMENTPARAMETERIV - gpGetIntegerv C.GPGETINTEGERV - gpGetProgramInfoLog C.GPGETPROGRAMINFOLOG - gpGetProgramiv C.GPGETPROGRAMIV - gpGetRenderbufferParameteriv C.GPGETRENDERBUFFERPARAMETERIV - gpGetShaderInfoLog C.GPGETSHADERINFOLOG - gpGetShaderSource C.GPGETSHADERSOURCE - gpGetShaderiv C.GPGETSHADERIV - gpGetString C.GPGETSTRING - gpGetTexParameterfv C.GPGETTEXPARAMETERFV - gpGetTexParameteriv C.GPGETTEXPARAMETERIV - gpGetUniformLocation C.GPGETUNIFORMLOCATION - gpGetUniformfv C.GPGETUNIFORMFV - gpGetUniformiv C.GPGETUNIFORMIV - gpGetVertexAttribPointerv C.GPGETVERTEXATTRIBPOINTERV - gpGetVertexAttribfv C.GPGETVERTEXATTRIBFV - gpGetVertexAttribiv C.GPGETVERTEXATTRIBIV - gpHint C.GPHINT - gpIsBuffer C.GPISBUFFER - gpIsEnabled C.GPISENABLED - gpIsFramebuffer C.GPISFRAMEBUFFER - gpIsProgram C.GPISPROGRAM - gpIsRenderbuffer C.GPISRENDERBUFFER - gpIsShader C.GPISSHADER - gpIsTexture C.GPISTEXTURE - gpLineWidth C.GPLINEWIDTH - gpLinkProgram C.GPLINKPROGRAM - gpPixelStorei C.GPPIXELSTOREI - gpPolygonOffset C.GPPOLYGONOFFSET - gpReadPixels C.GPREADPIXELS - gpRenderbufferStorage C.GPRENDERBUFFERSTORAGE - gpSampleCoverage C.GPSAMPLECOVERAGE - gpScissor C.GPSCISSOR - gpShaderSource C.GPSHADERSOURCE - gpStencilFunc C.GPSTENCILFUNC - gpStencilFuncSeparate C.GPSTENCILFUNCSEPARATE - gpStencilMask C.GPSTENCILMASK - gpStencilMaskSeparate C.GPSTENCILMASKSEPARATE - gpStencilOp C.GPSTENCILOP - gpStencilOpSeparate C.GPSTENCILOPSEPARATE - gpTexImage2D C.GPTEXIMAGE2D - gpTexParameterf C.GPTEXPARAMETERF - gpTexParameterfv C.GPTEXPARAMETERFV - gpTexParameteri C.GPTEXPARAMETERI - gpTexParameteriv C.GPTEXPARAMETERIV - gpTexSubImage2D C.GPTEXSUBIMAGE2D - gpUniform1f C.GPUNIFORM1F - gpUniform1fv C.GPUNIFORM1FV - gpUniform1i C.GPUNIFORM1I - gpUniform1iv C.GPUNIFORM1IV - gpUniform2f C.GPUNIFORM2F - gpUniform2fv C.GPUNIFORM2FV - gpUniform2i C.GPUNIFORM2I - gpUniform2iv C.GPUNIFORM2IV - gpUniform3f C.GPUNIFORM3F - gpUniform3fv C.GPUNIFORM3FV - gpUniform3i C.GPUNIFORM3I - gpUniform3iv C.GPUNIFORM3IV - gpUniform4f C.GPUNIFORM4F - gpUniform4fv C.GPUNIFORM4FV - gpUniform4i C.GPUNIFORM4I - gpUniform4iv C.GPUNIFORM4IV - gpUniformMatrix2fv C.GPUNIFORMMATRIX2FV - gpUniformMatrix3fv C.GPUNIFORMMATRIX3FV - gpUniformMatrix4fv C.GPUNIFORMMATRIX4FV - gpUseProgram C.GPUSEPROGRAM - gpValidateProgram C.GPVALIDATEPROGRAM - gpVertexAttrib1f C.GPVERTEXATTRIB1F - gpVertexAttrib1fv C.GPVERTEXATTRIB1FV - gpVertexAttrib2f C.GPVERTEXATTRIB2F - gpVertexAttrib2fv C.GPVERTEXATTRIB2FV - gpVertexAttrib3f C.GPVERTEXATTRIB3F - gpVertexAttrib3fv C.GPVERTEXATTRIB3FV - gpVertexAttrib4f C.GPVERTEXATTRIB4F - gpVertexAttrib4fv C.GPVERTEXATTRIB4FV - gpVertexAttribPointer C.GPVERTEXATTRIBPOINTER - gpViewport C.GPVIEWPORT -) - -// Helper functions -func boolToInt(b bool) int { - if b { - return 1 - } - return 0 -} -func ActiveTexture(texture uint32) { - C.glowActiveTexture(gpActiveTexture, (C.GLenum)(texture)) -} -func AttachShader(program uint32, shader uint32) { - C.glowAttachShader(gpAttachShader, (C.GLuint)(program), (C.GLuint)(shader)) -} -func BindAttribLocation(program uint32, index uint32, name *uint8) { - C.glowBindAttribLocation(gpBindAttribLocation, (C.GLuint)(program), (C.GLuint)(index), (*C.GLchar)(unsafe.Pointer(name))) -} -func BindBuffer(target uint32, buffer uint32) { - C.glowBindBuffer(gpBindBuffer, (C.GLenum)(target), (C.GLuint)(buffer)) -} -func BindFramebuffer(target uint32, framebuffer uint32) { - C.glowBindFramebuffer(gpBindFramebuffer, (C.GLenum)(target), (C.GLuint)(framebuffer)) -} -func BindRenderbuffer(target uint32, renderbuffer uint32) { - C.glowBindRenderbuffer(gpBindRenderbuffer, (C.GLenum)(target), (C.GLuint)(renderbuffer)) -} -func BindTexture(target uint32, texture uint32) { - C.glowBindTexture(gpBindTexture, (C.GLenum)(target), (C.GLuint)(texture)) -} -func BlendColor(red float32, green float32, blue float32, alpha float32) { - C.glowBlendColor(gpBlendColor, (C.GLfloat)(red), (C.GLfloat)(green), (C.GLfloat)(blue), (C.GLfloat)(alpha)) -} -func BlendEquation(mode uint32) { - C.glowBlendEquation(gpBlendEquation, (C.GLenum)(mode)) -} -func BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) { - C.glowBlendEquationSeparate(gpBlendEquationSeparate, (C.GLenum)(modeRGB), (C.GLenum)(modeAlpha)) -} -func BlendFunc(sfactor uint32, dfactor uint32) { - C.glowBlendFunc(gpBlendFunc, (C.GLenum)(sfactor), (C.GLenum)(dfactor)) -} -func BlendFuncSeparate(sfactorRGB uint32, dfactorRGB uint32, sfactorAlpha uint32, dfactorAlpha uint32) { - C.glowBlendFuncSeparate(gpBlendFuncSeparate, (C.GLenum)(sfactorRGB), (C.GLenum)(dfactorRGB), (C.GLenum)(sfactorAlpha), (C.GLenum)(dfactorAlpha)) -} -func BufferData(target uint32, size int, data unsafe.Pointer, usage uint32) { - C.glowBufferData(gpBufferData, (C.GLenum)(target), (C.GLsizeiptr)(size), data, (C.GLenum)(usage)) -} -func BufferSubData(target uint32, offset int, size int, data unsafe.Pointer) { - C.glowBufferSubData(gpBufferSubData, (C.GLenum)(target), (C.GLintptr)(offset), (C.GLsizeiptr)(size), data) -} -func CheckFramebufferStatus(target uint32) uint32 { - ret := C.glowCheckFramebufferStatus(gpCheckFramebufferStatus, (C.GLenum)(target)) - return (uint32)(ret) -} -func Clear(mask uint32) { - C.glowClear(gpClear, (C.GLbitfield)(mask)) -} -func ClearColor(red float32, green float32, blue float32, alpha float32) { - C.glowClearColor(gpClearColor, (C.GLfloat)(red), (C.GLfloat)(green), (C.GLfloat)(blue), (C.GLfloat)(alpha)) -} -func ClearStencil(s int32) { - C.glowClearStencil(gpClearStencil, (C.GLint)(s)) -} -func ColorMask(red bool, green bool, blue bool, alpha bool) { - C.glowColorMask(gpColorMask, (C.GLboolean)(boolToInt(red)), (C.GLboolean)(boolToInt(green)), (C.GLboolean)(boolToInt(blue)), (C.GLboolean)(boolToInt(alpha))) -} -func CompileShader(shader uint32) { - C.glowCompileShader(gpCompileShader, (C.GLuint)(shader)) -} -func CompressedTexImage2D(target uint32, level int32, internalformat uint32, width int32, height int32, border int32, imageSize int32, data unsafe.Pointer) { - C.glowCompressedTexImage2D(gpCompressedTexImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLenum)(internalformat), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLint)(border), (C.GLsizei)(imageSize), data) -} -func CompressedTexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, imageSize int32, data unsafe.Pointer) { - C.glowCompressedTexSubImage2D(gpCompressedTexSubImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLint)(xoffset), (C.GLint)(yoffset), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLenum)(format), (C.GLsizei)(imageSize), data) -} -func CopyTexImage2D(target uint32, level int32, internalformat uint32, x int32, y int32, width int32, height int32, border int32) { - C.glowCopyTexImage2D(gpCopyTexImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLenum)(internalformat), (C.GLint)(x), (C.GLint)(y), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLint)(border)) -} -func CopyTexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, x int32, y int32, width int32, height int32) { - C.glowCopyTexSubImage2D(gpCopyTexSubImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLint)(xoffset), (C.GLint)(yoffset), (C.GLint)(x), (C.GLint)(y), (C.GLsizei)(width), (C.GLsizei)(height)) -} -func CreateProgram() uint32 { - ret := C.glowCreateProgram(gpCreateProgram) - return (uint32)(ret) -} -func CreateShader(xtype uint32) uint32 { - ret := C.glowCreateShader(gpCreateShader, (C.GLenum)(xtype)) - return (uint32)(ret) -} -func CullFace(mode uint32) { - C.glowCullFace(gpCullFace, (C.GLenum)(mode)) -} -func DeleteBuffers(n int32, buffers *uint32) { - C.glowDeleteBuffers(gpDeleteBuffers, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(buffers))) -} -func DeleteFramebuffers(n int32, framebuffers *uint32) { - C.glowDeleteFramebuffers(gpDeleteFramebuffers, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(framebuffers))) -} -func DeleteProgram(program uint32) { - C.glowDeleteProgram(gpDeleteProgram, (C.GLuint)(program)) -} -func DeleteRenderbuffers(n int32, renderbuffers *uint32) { - C.glowDeleteRenderbuffers(gpDeleteRenderbuffers, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(renderbuffers))) -} -func DeleteShader(shader uint32) { - C.glowDeleteShader(gpDeleteShader, (C.GLuint)(shader)) -} -func DeleteTextures(n int32, textures *uint32) { - C.glowDeleteTextures(gpDeleteTextures, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(textures))) -} -func DepthFunc(xfunc uint32) { - C.glowDepthFunc(gpDepthFunc, (C.GLenum)(xfunc)) -} -func DepthMask(flag bool) { - C.glowDepthMask(gpDepthMask, (C.GLboolean)(boolToInt(flag))) -} -func DetachShader(program uint32, shader uint32) { - C.glowDetachShader(gpDetachShader, (C.GLuint)(program), (C.GLuint)(shader)) -} -func Disable(cap uint32) { - C.glowDisable(gpDisable, (C.GLenum)(cap)) -} -func DisableVertexAttribArray(index uint32) { - C.glowDisableVertexAttribArray(gpDisableVertexAttribArray, (C.GLuint)(index)) -} -func DrawArrays(mode uint32, first int32, count int32) { - C.glowDrawArrays(gpDrawArrays, (C.GLenum)(mode), (C.GLint)(first), (C.GLsizei)(count)) -} -func DrawElements(mode uint32, count int32, xtype uint32, indices unsafe.Pointer) { - C.glowDrawElements(gpDrawElements, (C.GLenum)(mode), (C.GLsizei)(count), (C.GLenum)(xtype), indices) -} -func Enable(cap uint32) { - C.glowEnable(gpEnable, (C.GLenum)(cap)) -} -func EnableVertexAttribArray(index uint32) { - C.glowEnableVertexAttribArray(gpEnableVertexAttribArray, (C.GLuint)(index)) -} -func Finish() { - C.glowFinish(gpFinish) -} -func Flush() { - C.glowFlush(gpFlush) -} -func FramebufferRenderbuffer(target uint32, attachment uint32, renderbuffertarget uint32, renderbuffer uint32) { - C.glowFramebufferRenderbuffer(gpFramebufferRenderbuffer, (C.GLenum)(target), (C.GLenum)(attachment), (C.GLenum)(renderbuffertarget), (C.GLuint)(renderbuffer)) -} -func FramebufferTexture2D(target uint32, attachment uint32, textarget uint32, texture uint32, level int32) { - C.glowFramebufferTexture2D(gpFramebufferTexture2D, (C.GLenum)(target), (C.GLenum)(attachment), (C.GLenum)(textarget), (C.GLuint)(texture), (C.GLint)(level)) -} -func FrontFace(mode uint32) { - C.glowFrontFace(gpFrontFace, (C.GLenum)(mode)) -} -func GenBuffers(n int32, buffers *uint32) { - C.glowGenBuffers(gpGenBuffers, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(buffers))) -} -func GenFramebuffers(n int32, framebuffers *uint32) { - C.glowGenFramebuffers(gpGenFramebuffers, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(framebuffers))) -} -func GenRenderbuffers(n int32, renderbuffers *uint32) { - C.glowGenRenderbuffers(gpGenRenderbuffers, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(renderbuffers))) -} -func GenTextures(n int32, textures *uint32) { - C.glowGenTextures(gpGenTextures, (C.GLsizei)(n), (*C.GLuint)(unsafe.Pointer(textures))) -} -func GenerateMipmap(target uint32) { - C.glowGenerateMipmap(gpGenerateMipmap, (C.GLenum)(target)) -} -func GetActiveAttrib(program uint32, index uint32, bufSize int32, length *int32, size *int32, xtype *uint32, name *uint8) { - C.glowGetActiveAttrib(gpGetActiveAttrib, (C.GLuint)(program), (C.GLuint)(index), (C.GLsizei)(bufSize), (*C.GLsizei)(unsafe.Pointer(length)), (*C.GLint)(unsafe.Pointer(size)), (*C.GLenum)(unsafe.Pointer(xtype)), (*C.GLchar)(unsafe.Pointer(name))) -} -func GetActiveUniform(program uint32, index uint32, bufSize int32, length *int32, size *int32, xtype *uint32, name *uint8) { - C.glowGetActiveUniform(gpGetActiveUniform, (C.GLuint)(program), (C.GLuint)(index), (C.GLsizei)(bufSize), (*C.GLsizei)(unsafe.Pointer(length)), (*C.GLint)(unsafe.Pointer(size)), (*C.GLenum)(unsafe.Pointer(xtype)), (*C.GLchar)(unsafe.Pointer(name))) -} -func GetAttachedShaders(program uint32, maxCount int32, count *int32, shaders *uint32) { - C.glowGetAttachedShaders(gpGetAttachedShaders, (C.GLuint)(program), (C.GLsizei)(maxCount), (*C.GLsizei)(unsafe.Pointer(count)), (*C.GLuint)(unsafe.Pointer(shaders))) -} -func GetAttribLocation(program uint32, name *uint8) int32 { - ret := C.glowGetAttribLocation(gpGetAttribLocation, (C.GLuint)(program), (*C.GLchar)(unsafe.Pointer(name))) - return (int32)(ret) -} -func GetBooleanv(pname uint32, data *bool) { - C.glowGetBooleanv(gpGetBooleanv, (C.GLenum)(pname), (*C.GLboolean)(unsafe.Pointer(data))) -} -func GetBufferParameteriv(target uint32, pname uint32, params *int32) { - C.glowGetBufferParameteriv(gpGetBufferParameteriv, (C.GLenum)(target), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func GetError() uint32 { - ret := C.glowGetError(gpGetError) - return (uint32)(ret) -} -func GetFloatv(pname uint32, data *float32) { - C.glowGetFloatv(gpGetFloatv, (C.GLenum)(pname), (*C.GLfloat)(unsafe.Pointer(data))) -} -func GetFramebufferAttachmentParameteriv(target uint32, attachment uint32, pname uint32, params *int32) { - C.glowGetFramebufferAttachmentParameteriv(gpGetFramebufferAttachmentParameteriv, (C.GLenum)(target), (C.GLenum)(attachment), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func GetIntegerv(pname uint32, data *int32) { - C.glowGetIntegerv(gpGetIntegerv, (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(data))) -} -func GetProgramInfoLog(program uint32, bufSize int32, length *int32, infoLog *uint8) { - C.glowGetProgramInfoLog(gpGetProgramInfoLog, (C.GLuint)(program), (C.GLsizei)(bufSize), (*C.GLsizei)(unsafe.Pointer(length)), (*C.GLchar)(unsafe.Pointer(infoLog))) -} -func GetProgramiv(program uint32, pname uint32, params *int32) { - C.glowGetProgramiv(gpGetProgramiv, (C.GLuint)(program), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func GetRenderbufferParameteriv(target uint32, pname uint32, params *int32) { - C.glowGetRenderbufferParameteriv(gpGetRenderbufferParameteriv, (C.GLenum)(target), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func GetShaderInfoLog(shader uint32, bufSize int32, length *int32, infoLog *uint8) { - C.glowGetShaderInfoLog(gpGetShaderInfoLog, (C.GLuint)(shader), (C.GLsizei)(bufSize), (*C.GLsizei)(unsafe.Pointer(length)), (*C.GLchar)(unsafe.Pointer(infoLog))) -} -func GetShaderSource(shader uint32, bufSize int32, length *int32, source *uint8) { - C.glowGetShaderSource(gpGetShaderSource, (C.GLuint)(shader), (C.GLsizei)(bufSize), (*C.GLsizei)(unsafe.Pointer(length)), (*C.GLchar)(unsafe.Pointer(source))) -} -func GetShaderiv(shader uint32, pname uint32, params *int32) { - C.glowGetShaderiv(gpGetShaderiv, (C.GLuint)(shader), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func GetString(name uint32) *uint8 { - ret := C.glowGetString(gpGetString, (C.GLenum)(name)) - return (*uint8)(ret) -} -func GetTexParameterfv(target uint32, pname uint32, params *float32) { - C.glowGetTexParameterfv(gpGetTexParameterfv, (C.GLenum)(target), (C.GLenum)(pname), (*C.GLfloat)(unsafe.Pointer(params))) -} -func GetTexParameteriv(target uint32, pname uint32, params *int32) { - C.glowGetTexParameteriv(gpGetTexParameteriv, (C.GLenum)(target), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func GetUniformLocation(program uint32, name *uint8) int32 { - ret := C.glowGetUniformLocation(gpGetUniformLocation, (C.GLuint)(program), (*C.GLchar)(unsafe.Pointer(name))) - return (int32)(ret) -} -func GetUniformfv(program uint32, location int32, params *float32) { - C.glowGetUniformfv(gpGetUniformfv, (C.GLuint)(program), (C.GLint)(location), (*C.GLfloat)(unsafe.Pointer(params))) -} -func GetUniformiv(program uint32, location int32, params *int32) { - C.glowGetUniformiv(gpGetUniformiv, (C.GLuint)(program), (C.GLint)(location), (*C.GLint)(unsafe.Pointer(params))) -} -func GetVertexAttribPointerv(index uint32, pname uint32, pointer *unsafe.Pointer) { - C.glowGetVertexAttribPointerv(gpGetVertexAttribPointerv, (C.GLuint)(index), (C.GLenum)(pname), pointer) -} -func GetVertexAttribfv(index uint32, pname uint32, params *float32) { - C.glowGetVertexAttribfv(gpGetVertexAttribfv, (C.GLuint)(index), (C.GLenum)(pname), (*C.GLfloat)(unsafe.Pointer(params))) -} -func GetVertexAttribiv(index uint32, pname uint32, params *int32) { - C.glowGetVertexAttribiv(gpGetVertexAttribiv, (C.GLuint)(index), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func Hint(target uint32, mode uint32) { - C.glowHint(gpHint, (C.GLenum)(target), (C.GLenum)(mode)) -} -func IsBuffer(buffer uint32) bool { - ret := C.glowIsBuffer(gpIsBuffer, (C.GLuint)(buffer)) - return ret == TRUE -} -func IsEnabled(cap uint32) bool { - ret := C.glowIsEnabled(gpIsEnabled, (C.GLenum)(cap)) - return ret == TRUE -} -func IsFramebuffer(framebuffer uint32) bool { - ret := C.glowIsFramebuffer(gpIsFramebuffer, (C.GLuint)(framebuffer)) - return ret == TRUE -} -func IsProgram(program uint32) bool { - ret := C.glowIsProgram(gpIsProgram, (C.GLuint)(program)) - return ret == TRUE -} -func IsRenderbuffer(renderbuffer uint32) bool { - ret := C.glowIsRenderbuffer(gpIsRenderbuffer, (C.GLuint)(renderbuffer)) - return ret == TRUE -} -func IsShader(shader uint32) bool { - ret := C.glowIsShader(gpIsShader, (C.GLuint)(shader)) - return ret == TRUE -} -func IsTexture(texture uint32) bool { - ret := C.glowIsTexture(gpIsTexture, (C.GLuint)(texture)) - return ret == TRUE -} -func LineWidth(width float32) { - C.glowLineWidth(gpLineWidth, (C.GLfloat)(width)) -} -func LinkProgram(program uint32) { - C.glowLinkProgram(gpLinkProgram, (C.GLuint)(program)) -} -func PixelStorei(pname uint32, param int32) { - C.glowPixelStorei(gpPixelStorei, (C.GLenum)(pname), (C.GLint)(param)) -} -func PolygonOffset(factor float32, units float32) { - C.glowPolygonOffset(gpPolygonOffset, (C.GLfloat)(factor), (C.GLfloat)(units)) -} -func ReadPixels(x int32, y int32, width int32, height int32, format uint32, xtype uint32, pixels unsafe.Pointer) { - C.glowReadPixels(gpReadPixels, (C.GLint)(x), (C.GLint)(y), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLenum)(format), (C.GLenum)(xtype), pixels) -} -func RenderbufferStorage(target uint32, internalformat uint32, width int32, height int32) { - C.glowRenderbufferStorage(gpRenderbufferStorage, (C.GLenum)(target), (C.GLenum)(internalformat), (C.GLsizei)(width), (C.GLsizei)(height)) -} -func SampleCoverage(value float32, invert bool) { - C.glowSampleCoverage(gpSampleCoverage, (C.GLfloat)(value), (C.GLboolean)(boolToInt(invert))) -} -func Scissor(x int32, y int32, width int32, height int32) { - C.glowScissor(gpScissor, (C.GLint)(x), (C.GLint)(y), (C.GLsizei)(width), (C.GLsizei)(height)) -} -func ShaderSource(shader uint32, count int32, xstring **uint8, length *int32) { - C.glowShaderSource(gpShaderSource, (C.GLuint)(shader), (C.GLsizei)(count), (**C.GLchar)(unsafe.Pointer(xstring)), (*C.GLint)(unsafe.Pointer(length))) -} -func StencilFunc(xfunc uint32, ref int32, mask uint32) { - C.glowStencilFunc(gpStencilFunc, (C.GLenum)(xfunc), (C.GLint)(ref), (C.GLuint)(mask)) -} -func StencilFuncSeparate(face uint32, xfunc uint32, ref int32, mask uint32) { - C.glowStencilFuncSeparate(gpStencilFuncSeparate, (C.GLenum)(face), (C.GLenum)(xfunc), (C.GLint)(ref), (C.GLuint)(mask)) -} -func StencilMask(mask uint32) { - C.glowStencilMask(gpStencilMask, (C.GLuint)(mask)) -} -func StencilMaskSeparate(face uint32, mask uint32) { - C.glowStencilMaskSeparate(gpStencilMaskSeparate, (C.GLenum)(face), (C.GLuint)(mask)) -} -func StencilOp(fail uint32, zfail uint32, zpass uint32) { - C.glowStencilOp(gpStencilOp, (C.GLenum)(fail), (C.GLenum)(zfail), (C.GLenum)(zpass)) -} -func StencilOpSeparate(face uint32, sfail uint32, dpfail uint32, dppass uint32) { - C.glowStencilOpSeparate(gpStencilOpSeparate, (C.GLenum)(face), (C.GLenum)(sfail), (C.GLenum)(dpfail), (C.GLenum)(dppass)) -} -func TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, border int32, format uint32, xtype uint32, pixels unsafe.Pointer) { - C.glowTexImage2D(gpTexImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLint)(internalformat), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLint)(border), (C.GLenum)(format), (C.GLenum)(xtype), pixels) -} -func TexParameterf(target uint32, pname uint32, param float32) { - C.glowTexParameterf(gpTexParameterf, (C.GLenum)(target), (C.GLenum)(pname), (C.GLfloat)(param)) -} -func TexParameterfv(target uint32, pname uint32, params *float32) { - C.glowTexParameterfv(gpTexParameterfv, (C.GLenum)(target), (C.GLenum)(pname), (*C.GLfloat)(unsafe.Pointer(params))) -} -func TexParameteri(target uint32, pname uint32, param int32) { - C.glowTexParameteri(gpTexParameteri, (C.GLenum)(target), (C.GLenum)(pname), (C.GLint)(param)) -} -func TexParameteriv(target uint32, pname uint32, params *int32) { - C.glowTexParameteriv(gpTexParameteriv, (C.GLenum)(target), (C.GLenum)(pname), (*C.GLint)(unsafe.Pointer(params))) -} -func TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels unsafe.Pointer) { - C.glowTexSubImage2D(gpTexSubImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLint)(xoffset), (C.GLint)(yoffset), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLenum)(format), (C.GLenum)(xtype), pixels) -} -func Uniform1f(location int32, v0 float32) { - C.glowUniform1f(gpUniform1f, (C.GLint)(location), (C.GLfloat)(v0)) -} -func Uniform1fv(location int32, count int32, value *float32) { - C.glowUniform1fv(gpUniform1fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value))) -} -func Uniform1i(location int32, v0 int32) { - C.glowUniform1i(gpUniform1i, (C.GLint)(location), (C.GLint)(v0)) -} -func Uniform1iv(location int32, count int32, value *int32) { - C.glowUniform1iv(gpUniform1iv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLint)(unsafe.Pointer(value))) -} -func Uniform2f(location int32, v0 float32, v1 float32) { - C.glowUniform2f(gpUniform2f, (C.GLint)(location), (C.GLfloat)(v0), (C.GLfloat)(v1)) -} -func Uniform2fv(location int32, count int32, value *float32) { - C.glowUniform2fv(gpUniform2fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value))) -} -func Uniform2i(location int32, v0 int32, v1 int32) { - C.glowUniform2i(gpUniform2i, (C.GLint)(location), (C.GLint)(v0), (C.GLint)(v1)) -} -func Uniform2iv(location int32, count int32, value *int32) { - C.glowUniform2iv(gpUniform2iv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLint)(unsafe.Pointer(value))) -} -func Uniform3f(location int32, v0 float32, v1 float32, v2 float32) { - C.glowUniform3f(gpUniform3f, (C.GLint)(location), (C.GLfloat)(v0), (C.GLfloat)(v1), (C.GLfloat)(v2)) -} -func Uniform3fv(location int32, count int32, value *float32) { - C.glowUniform3fv(gpUniform3fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value))) -} -func Uniform3i(location int32, v0 int32, v1 int32, v2 int32) { - C.glowUniform3i(gpUniform3i, (C.GLint)(location), (C.GLint)(v0), (C.GLint)(v1), (C.GLint)(v2)) -} -func Uniform3iv(location int32, count int32, value *int32) { - C.glowUniform3iv(gpUniform3iv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLint)(unsafe.Pointer(value))) -} -func Uniform4f(location int32, v0 float32, v1 float32, v2 float32, v3 float32) { - C.glowUniform4f(gpUniform4f, (C.GLint)(location), (C.GLfloat)(v0), (C.GLfloat)(v1), (C.GLfloat)(v2), (C.GLfloat)(v3)) -} -func Uniform4fv(location int32, count int32, value *float32) { - C.glowUniform4fv(gpUniform4fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value))) -} -func Uniform4i(location int32, v0 int32, v1 int32, v2 int32, v3 int32) { - C.glowUniform4i(gpUniform4i, (C.GLint)(location), (C.GLint)(v0), (C.GLint)(v1), (C.GLint)(v2), (C.GLint)(v3)) -} -func Uniform4iv(location int32, count int32, value *int32) { - C.glowUniform4iv(gpUniform4iv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLint)(unsafe.Pointer(value))) -} -func UniformMatrix2fv(location int32, count int32, transpose bool, value *float32) { - C.glowUniformMatrix2fv(gpUniformMatrix2fv, (C.GLint)(location), (C.GLsizei)(count), (C.GLboolean)(boolToInt(transpose)), (*C.GLfloat)(unsafe.Pointer(value))) -} -func UniformMatrix3fv(location int32, count int32, transpose bool, value *float32) { - C.glowUniformMatrix3fv(gpUniformMatrix3fv, (C.GLint)(location), (C.GLsizei)(count), (C.GLboolean)(boolToInt(transpose)), (*C.GLfloat)(unsafe.Pointer(value))) -} -func UniformMatrix4fv(location int32, count int32, transpose bool, value *float32) { - C.glowUniformMatrix4fv(gpUniformMatrix4fv, (C.GLint)(location), (C.GLsizei)(count), (C.GLboolean)(boolToInt(transpose)), (*C.GLfloat)(unsafe.Pointer(value))) -} -func UseProgram(program uint32) { - C.glowUseProgram(gpUseProgram, (C.GLuint)(program)) -} -func ValidateProgram(program uint32) { - C.glowValidateProgram(gpValidateProgram, (C.GLuint)(program)) -} -func VertexAttrib1f(index uint32, x float32) { - C.glowVertexAttrib1f(gpVertexAttrib1f, (C.GLuint)(index), (C.GLfloat)(x)) -} -func VertexAttrib1fv(index uint32, v *float32) { - C.glowVertexAttrib1fv(gpVertexAttrib1fv, (C.GLuint)(index), (*C.GLfloat)(unsafe.Pointer(v))) -} -func VertexAttrib2f(index uint32, x float32, y float32) { - C.glowVertexAttrib2f(gpVertexAttrib2f, (C.GLuint)(index), (C.GLfloat)(x), (C.GLfloat)(y)) -} -func VertexAttrib2fv(index uint32, v *float32) { - C.glowVertexAttrib2fv(gpVertexAttrib2fv, (C.GLuint)(index), (*C.GLfloat)(unsafe.Pointer(v))) -} -func VertexAttrib3f(index uint32, x float32, y float32, z float32) { - C.glowVertexAttrib3f(gpVertexAttrib3f, (C.GLuint)(index), (C.GLfloat)(x), (C.GLfloat)(y), (C.GLfloat)(z)) -} -func VertexAttrib3fv(index uint32, v *float32) { - C.glowVertexAttrib3fv(gpVertexAttrib3fv, (C.GLuint)(index), (*C.GLfloat)(unsafe.Pointer(v))) -} -func VertexAttrib4f(index uint32, x float32, y float32, z float32, w float32) { - C.glowVertexAttrib4f(gpVertexAttrib4f, (C.GLuint)(index), (C.GLfloat)(x), (C.GLfloat)(y), (C.GLfloat)(z), (C.GLfloat)(w)) -} -func VertexAttrib4fv(index uint32, v *float32) { - C.glowVertexAttrib4fv(gpVertexAttrib4fv, (C.GLuint)(index), (*C.GLfloat)(unsafe.Pointer(v))) -} -func VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, pointer unsafe.Pointer) { - C.glowVertexAttribPointer(gpVertexAttribPointer, (C.GLuint)(index), (C.GLint)(size), (C.GLenum)(xtype), (C.GLboolean)(boolToInt(normalized)), (C.GLsizei)(stride), pointer) -} -func Viewport(x int32, y int32, width int32, height int32) { - C.glowViewport(gpViewport, (C.GLint)(x), (C.GLint)(y), (C.GLsizei)(width), (C.GLsizei)(height)) -} - -// Init initializes the OpenGL bindings by loading the function pointers (for -// each OpenGL function) from the active OpenGL context. -// -// It must be called under the presence of an active OpenGL context, e.g., -// always after calling window.MakeContextCurrent() and always before calling -// any OpenGL functions exported by this package. -// -// On Windows, Init loads pointers that are context-specific (and hence you -// must re-init if switching between OpenGL contexts, although not calling Init -// again after switching between OpenGL contexts may work if the contexts belong -// to the same graphics driver/device). -// -// On macOS and the other POSIX systems, the behavior is different, but code -// written compatible with the Windows behavior is compatible with macOS and the -// other POSIX systems. That is, always Init under an active OpenGL context, and -// always re-init after switching graphics contexts. -// -// For information about caveats of Init, you should read the "Platform Specific -// Function Retrieval" section of https://www.opengl.org/wiki/Load_OpenGL_Functions. -func Init() error { - return InitWithProcAddrFunc(getProcAddress) -} - -// InitWithProcAddrFunc intializes the package using the specified OpenGL -// function pointer loading function. For more cases Init should be used -// instead. -func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error { - gpActiveTexture = (C.GPACTIVETEXTURE)(getProcAddr("glActiveTexture")) - if gpActiveTexture == nil { - return errors.New("glActiveTexture") - } - gpAttachShader = (C.GPATTACHSHADER)(getProcAddr("glAttachShader")) - if gpAttachShader == nil { - return errors.New("glAttachShader") - } - gpBindAttribLocation = (C.GPBINDATTRIBLOCATION)(getProcAddr("glBindAttribLocation")) - if gpBindAttribLocation == nil { - return errors.New("glBindAttribLocation") - } - gpBindBuffer = (C.GPBINDBUFFER)(getProcAddr("glBindBuffer")) - if gpBindBuffer == nil { - return errors.New("glBindBuffer") - } - gpBindFramebuffer = (C.GPBINDFRAMEBUFFER)(getProcAddr("glBindFramebuffer")) - if gpBindFramebuffer == nil { - return errors.New("glBindFramebuffer") - } - gpBindRenderbuffer = (C.GPBINDRENDERBUFFER)(getProcAddr("glBindRenderbuffer")) - if gpBindRenderbuffer == nil { - return errors.New("glBindRenderbuffer") - } - gpBindTexture = (C.GPBINDTEXTURE)(getProcAddr("glBindTexture")) - if gpBindTexture == nil { - return errors.New("glBindTexture") - } - gpBlendColor = (C.GPBLENDCOLOR)(getProcAddr("glBlendColor")) - if gpBlendColor == nil { - return errors.New("glBlendColor") - } - gpBlendEquation = (C.GPBLENDEQUATION)(getProcAddr("glBlendEquation")) - if gpBlendEquation == nil { - return errors.New("glBlendEquation") - } - gpBlendEquationSeparate = (C.GPBLENDEQUATIONSEPARATE)(getProcAddr("glBlendEquationSeparate")) - if gpBlendEquationSeparate == nil { - return errors.New("glBlendEquationSeparate") - } - gpBlendFunc = (C.GPBLENDFUNC)(getProcAddr("glBlendFunc")) - if gpBlendFunc == nil { - return errors.New("glBlendFunc") - } - gpBlendFuncSeparate = (C.GPBLENDFUNCSEPARATE)(getProcAddr("glBlendFuncSeparate")) - if gpBlendFuncSeparate == nil { - return errors.New("glBlendFuncSeparate") - } - gpBufferData = (C.GPBUFFERDATA)(getProcAddr("glBufferData")) - if gpBufferData == nil { - return errors.New("glBufferData") - } - gpBufferSubData = (C.GPBUFFERSUBDATA)(getProcAddr("glBufferSubData")) - if gpBufferSubData == nil { - return errors.New("glBufferSubData") - } - gpCheckFramebufferStatus = (C.GPCHECKFRAMEBUFFERSTATUS)(getProcAddr("glCheckFramebufferStatus")) - if gpCheckFramebufferStatus == nil { - return errors.New("glCheckFramebufferStatus") - } - gpClear = (C.GPCLEAR)(getProcAddr("glClear")) - if gpClear == nil { - return errors.New("glClear") - } - gpClearColor = (C.GPCLEARCOLOR)(getProcAddr("glClearColor")) - if gpClearColor == nil { - return errors.New("glClearColor") - } - gpClearStencil = (C.GPCLEARSTENCIL)(getProcAddr("glClearStencil")) - if gpClearStencil == nil { - return errors.New("glClearStencil") - } - gpColorMask = (C.GPCOLORMASK)(getProcAddr("glColorMask")) - if gpColorMask == nil { - return errors.New("glColorMask") - } - gpCompileShader = (C.GPCOMPILESHADER)(getProcAddr("glCompileShader")) - if gpCompileShader == nil { - return errors.New("glCompileShader") - } - gpCompressedTexImage2D = (C.GPCOMPRESSEDTEXIMAGE2D)(getProcAddr("glCompressedTexImage2D")) - if gpCompressedTexImage2D == nil { - return errors.New("glCompressedTexImage2D") - } - gpCompressedTexSubImage2D = (C.GPCOMPRESSEDTEXSUBIMAGE2D)(getProcAddr("glCompressedTexSubImage2D")) - if gpCompressedTexSubImage2D == nil { - return errors.New("glCompressedTexSubImage2D") - } - gpCopyTexImage2D = (C.GPCOPYTEXIMAGE2D)(getProcAddr("glCopyTexImage2D")) - if gpCopyTexImage2D == nil { - return errors.New("glCopyTexImage2D") - } - gpCopyTexSubImage2D = (C.GPCOPYTEXSUBIMAGE2D)(getProcAddr("glCopyTexSubImage2D")) - if gpCopyTexSubImage2D == nil { - return errors.New("glCopyTexSubImage2D") - } - gpCreateProgram = (C.GPCREATEPROGRAM)(getProcAddr("glCreateProgram")) - if gpCreateProgram == nil { - return errors.New("glCreateProgram") - } - gpCreateShader = (C.GPCREATESHADER)(getProcAddr("glCreateShader")) - if gpCreateShader == nil { - return errors.New("glCreateShader") - } - gpCullFace = (C.GPCULLFACE)(getProcAddr("glCullFace")) - if gpCullFace == nil { - return errors.New("glCullFace") - } - gpDeleteBuffers = (C.GPDELETEBUFFERS)(getProcAddr("glDeleteBuffers")) - if gpDeleteBuffers == nil { - return errors.New("glDeleteBuffers") - } - gpDeleteFramebuffers = (C.GPDELETEFRAMEBUFFERS)(getProcAddr("glDeleteFramebuffers")) - if gpDeleteFramebuffers == nil { - return errors.New("glDeleteFramebuffers") - } - gpDeleteProgram = (C.GPDELETEPROGRAM)(getProcAddr("glDeleteProgram")) - if gpDeleteProgram == nil { - return errors.New("glDeleteProgram") - } - gpDeleteRenderbuffers = (C.GPDELETERENDERBUFFERS)(getProcAddr("glDeleteRenderbuffers")) - if gpDeleteRenderbuffers == nil { - return errors.New("glDeleteRenderbuffers") - } - gpDeleteShader = (C.GPDELETESHADER)(getProcAddr("glDeleteShader")) - if gpDeleteShader == nil { - return errors.New("glDeleteShader") - } - gpDeleteTextures = (C.GPDELETETEXTURES)(getProcAddr("glDeleteTextures")) - if gpDeleteTextures == nil { - return errors.New("glDeleteTextures") - } - gpDepthFunc = (C.GPDEPTHFUNC)(getProcAddr("glDepthFunc")) - if gpDepthFunc == nil { - return errors.New("glDepthFunc") - } - gpDepthMask = (C.GPDEPTHMASK)(getProcAddr("glDepthMask")) - if gpDepthMask == nil { - return errors.New("glDepthMask") - } - gpDetachShader = (C.GPDETACHSHADER)(getProcAddr("glDetachShader")) - if gpDetachShader == nil { - return errors.New("glDetachShader") - } - gpDisable = (C.GPDISABLE)(getProcAddr("glDisable")) - if gpDisable == nil { - return errors.New("glDisable") - } - gpDisableVertexAttribArray = (C.GPDISABLEVERTEXATTRIBARRAY)(getProcAddr("glDisableVertexAttribArray")) - if gpDisableVertexAttribArray == nil { - return errors.New("glDisableVertexAttribArray") - } - gpDrawArrays = (C.GPDRAWARRAYS)(getProcAddr("glDrawArrays")) - if gpDrawArrays == nil { - return errors.New("glDrawArrays") - } - gpDrawElements = (C.GPDRAWELEMENTS)(getProcAddr("glDrawElements")) - if gpDrawElements == nil { - return errors.New("glDrawElements") - } - gpEnable = (C.GPENABLE)(getProcAddr("glEnable")) - if gpEnable == nil { - return errors.New("glEnable") - } - gpEnableVertexAttribArray = (C.GPENABLEVERTEXATTRIBARRAY)(getProcAddr("glEnableVertexAttribArray")) - if gpEnableVertexAttribArray == nil { - return errors.New("glEnableVertexAttribArray") - } - gpFinish = (C.GPFINISH)(getProcAddr("glFinish")) - if gpFinish == nil { - return errors.New("glFinish") - } - gpFlush = (C.GPFLUSH)(getProcAddr("glFlush")) - if gpFlush == nil { - return errors.New("glFlush") - } - gpFramebufferRenderbuffer = (C.GPFRAMEBUFFERRENDERBUFFER)(getProcAddr("glFramebufferRenderbuffer")) - if gpFramebufferRenderbuffer == nil { - return errors.New("glFramebufferRenderbuffer") - } - gpFramebufferTexture2D = (C.GPFRAMEBUFFERTEXTURE2D)(getProcAddr("glFramebufferTexture2D")) - if gpFramebufferTexture2D == nil { - return errors.New("glFramebufferTexture2D") - } - gpFrontFace = (C.GPFRONTFACE)(getProcAddr("glFrontFace")) - if gpFrontFace == nil { - return errors.New("glFrontFace") - } - gpGenBuffers = (C.GPGENBUFFERS)(getProcAddr("glGenBuffers")) - if gpGenBuffers == nil { - return errors.New("glGenBuffers") - } - gpGenFramebuffers = (C.GPGENFRAMEBUFFERS)(getProcAddr("glGenFramebuffers")) - if gpGenFramebuffers == nil { - return errors.New("glGenFramebuffers") - } - gpGenRenderbuffers = (C.GPGENRENDERBUFFERS)(getProcAddr("glGenRenderbuffers")) - if gpGenRenderbuffers == nil { - return errors.New("glGenRenderbuffers") - } - gpGenTextures = (C.GPGENTEXTURES)(getProcAddr("glGenTextures")) - if gpGenTextures == nil { - return errors.New("glGenTextures") - } - gpGenerateMipmap = (C.GPGENERATEMIPMAP)(getProcAddr("glGenerateMipmap")) - if gpGenerateMipmap == nil { - return errors.New("glGenerateMipmap") - } - gpGetActiveAttrib = (C.GPGETACTIVEATTRIB)(getProcAddr("glGetActiveAttrib")) - if gpGetActiveAttrib == nil { - return errors.New("glGetActiveAttrib") - } - gpGetActiveUniform = (C.GPGETACTIVEUNIFORM)(getProcAddr("glGetActiveUniform")) - if gpGetActiveUniform == nil { - return errors.New("glGetActiveUniform") - } - gpGetAttachedShaders = (C.GPGETATTACHEDSHADERS)(getProcAddr("glGetAttachedShaders")) - if gpGetAttachedShaders == nil { - return errors.New("glGetAttachedShaders") - } - gpGetAttribLocation = (C.GPGETATTRIBLOCATION)(getProcAddr("glGetAttribLocation")) - if gpGetAttribLocation == nil { - return errors.New("glGetAttribLocation") - } - gpGetBooleanv = (C.GPGETBOOLEANV)(getProcAddr("glGetBooleanv")) - if gpGetBooleanv == nil { - return errors.New("glGetBooleanv") - } - gpGetBufferParameteriv = (C.GPGETBUFFERPARAMETERIV)(getProcAddr("glGetBufferParameteriv")) - if gpGetBufferParameteriv == nil { - return errors.New("glGetBufferParameteriv") - } - gpGetError = (C.GPGETERROR)(getProcAddr("glGetError")) - if gpGetError == nil { - return errors.New("glGetError") - } - gpGetFloatv = (C.GPGETFLOATV)(getProcAddr("glGetFloatv")) - if gpGetFloatv == nil { - return errors.New("glGetFloatv") - } - gpGetFramebufferAttachmentParameteriv = (C.GPGETFRAMEBUFFERATTACHMENTPARAMETERIV)(getProcAddr("glGetFramebufferAttachmentParameteriv")) - if gpGetFramebufferAttachmentParameteriv == nil { - return errors.New("glGetFramebufferAttachmentParameteriv") - } - gpGetIntegerv = (C.GPGETINTEGERV)(getProcAddr("glGetIntegerv")) - if gpGetIntegerv == nil { - return errors.New("glGetIntegerv") - } - gpGetProgramInfoLog = (C.GPGETPROGRAMINFOLOG)(getProcAddr("glGetProgramInfoLog")) - if gpGetProgramInfoLog == nil { - return errors.New("glGetProgramInfoLog") - } - gpGetProgramiv = (C.GPGETPROGRAMIV)(getProcAddr("glGetProgramiv")) - if gpGetProgramiv == nil { - return errors.New("glGetProgramiv") - } - gpGetRenderbufferParameteriv = (C.GPGETRENDERBUFFERPARAMETERIV)(getProcAddr("glGetRenderbufferParameteriv")) - if gpGetRenderbufferParameteriv == nil { - return errors.New("glGetRenderbufferParameteriv") - } - gpGetShaderInfoLog = (C.GPGETSHADERINFOLOG)(getProcAddr("glGetShaderInfoLog")) - if gpGetShaderInfoLog == nil { - return errors.New("glGetShaderInfoLog") - } - gpGetShaderSource = (C.GPGETSHADERSOURCE)(getProcAddr("glGetShaderSource")) - if gpGetShaderSource == nil { - return errors.New("glGetShaderSource") - } - gpGetShaderiv = (C.GPGETSHADERIV)(getProcAddr("glGetShaderiv")) - if gpGetShaderiv == nil { - return errors.New("glGetShaderiv") - } - gpGetString = (C.GPGETSTRING)(getProcAddr("glGetString")) - if gpGetString == nil { - return errors.New("glGetString") - } - gpGetTexParameterfv = (C.GPGETTEXPARAMETERFV)(getProcAddr("glGetTexParameterfv")) - if gpGetTexParameterfv == nil { - return errors.New("glGetTexParameterfv") - } - gpGetTexParameteriv = (C.GPGETTEXPARAMETERIV)(getProcAddr("glGetTexParameteriv")) - if gpGetTexParameteriv == nil { - return errors.New("glGetTexParameteriv") - } - gpGetUniformLocation = (C.GPGETUNIFORMLOCATION)(getProcAddr("glGetUniformLocation")) - if gpGetUniformLocation == nil { - return errors.New("glGetUniformLocation") - } - gpGetUniformfv = (C.GPGETUNIFORMFV)(getProcAddr("glGetUniformfv")) - if gpGetUniformfv == nil { - return errors.New("glGetUniformfv") - } - gpGetUniformiv = (C.GPGETUNIFORMIV)(getProcAddr("glGetUniformiv")) - if gpGetUniformiv == nil { - return errors.New("glGetUniformiv") - } - gpGetVertexAttribPointerv = (C.GPGETVERTEXATTRIBPOINTERV)(getProcAddr("glGetVertexAttribPointerv")) - if gpGetVertexAttribPointerv == nil { - return errors.New("glGetVertexAttribPointerv") - } - gpGetVertexAttribfv = (C.GPGETVERTEXATTRIBFV)(getProcAddr("glGetVertexAttribfv")) - if gpGetVertexAttribfv == nil { - return errors.New("glGetVertexAttribfv") - } - gpGetVertexAttribiv = (C.GPGETVERTEXATTRIBIV)(getProcAddr("glGetVertexAttribiv")) - if gpGetVertexAttribiv == nil { - return errors.New("glGetVertexAttribiv") - } - gpHint = (C.GPHINT)(getProcAddr("glHint")) - if gpHint == nil { - return errors.New("glHint") - } - gpIsBuffer = (C.GPISBUFFER)(getProcAddr("glIsBuffer")) - if gpIsBuffer == nil { - return errors.New("glIsBuffer") - } - gpIsEnabled = (C.GPISENABLED)(getProcAddr("glIsEnabled")) - if gpIsEnabled == nil { - return errors.New("glIsEnabled") - } - gpIsFramebuffer = (C.GPISFRAMEBUFFER)(getProcAddr("glIsFramebuffer")) - if gpIsFramebuffer == nil { - return errors.New("glIsFramebuffer") - } - gpIsProgram = (C.GPISPROGRAM)(getProcAddr("glIsProgram")) - if gpIsProgram == nil { - return errors.New("glIsProgram") - } - gpIsRenderbuffer = (C.GPISRENDERBUFFER)(getProcAddr("glIsRenderbuffer")) - if gpIsRenderbuffer == nil { - return errors.New("glIsRenderbuffer") - } - gpIsShader = (C.GPISSHADER)(getProcAddr("glIsShader")) - if gpIsShader == nil { - return errors.New("glIsShader") - } - gpIsTexture = (C.GPISTEXTURE)(getProcAddr("glIsTexture")) - if gpIsTexture == nil { - return errors.New("glIsTexture") - } - gpLineWidth = (C.GPLINEWIDTH)(getProcAddr("glLineWidth")) - if gpLineWidth == nil { - return errors.New("glLineWidth") - } - gpLinkProgram = (C.GPLINKPROGRAM)(getProcAddr("glLinkProgram")) - if gpLinkProgram == nil { - return errors.New("glLinkProgram") - } - gpPixelStorei = (C.GPPIXELSTOREI)(getProcAddr("glPixelStorei")) - if gpPixelStorei == nil { - return errors.New("glPixelStorei") - } - gpPolygonOffset = (C.GPPOLYGONOFFSET)(getProcAddr("glPolygonOffset")) - if gpPolygonOffset == nil { - return errors.New("glPolygonOffset") - } - gpReadPixels = (C.GPREADPIXELS)(getProcAddr("glReadPixels")) - if gpReadPixels == nil { - return errors.New("glReadPixels") - } - gpRenderbufferStorage = (C.GPRENDERBUFFERSTORAGE)(getProcAddr("glRenderbufferStorage")) - if gpRenderbufferStorage == nil { - return errors.New("glRenderbufferStorage") - } - gpSampleCoverage = (C.GPSAMPLECOVERAGE)(getProcAddr("glSampleCoverage")) - if gpSampleCoverage == nil { - return errors.New("glSampleCoverage") - } - gpScissor = (C.GPSCISSOR)(getProcAddr("glScissor")) - if gpScissor == nil { - return errors.New("glScissor") - } - gpShaderSource = (C.GPSHADERSOURCE)(getProcAddr("glShaderSource")) - if gpShaderSource == nil { - return errors.New("glShaderSource") - } - gpStencilFunc = (C.GPSTENCILFUNC)(getProcAddr("glStencilFunc")) - if gpStencilFunc == nil { - return errors.New("glStencilFunc") - } - gpStencilFuncSeparate = (C.GPSTENCILFUNCSEPARATE)(getProcAddr("glStencilFuncSeparate")) - if gpStencilFuncSeparate == nil { - return errors.New("glStencilFuncSeparate") - } - gpStencilMask = (C.GPSTENCILMASK)(getProcAddr("glStencilMask")) - if gpStencilMask == nil { - return errors.New("glStencilMask") - } - gpStencilMaskSeparate = (C.GPSTENCILMASKSEPARATE)(getProcAddr("glStencilMaskSeparate")) - if gpStencilMaskSeparate == nil { - return errors.New("glStencilMaskSeparate") - } - gpStencilOp = (C.GPSTENCILOP)(getProcAddr("glStencilOp")) - if gpStencilOp == nil { - return errors.New("glStencilOp") - } - gpStencilOpSeparate = (C.GPSTENCILOPSEPARATE)(getProcAddr("glStencilOpSeparate")) - if gpStencilOpSeparate == nil { - return errors.New("glStencilOpSeparate") - } - gpTexImage2D = (C.GPTEXIMAGE2D)(getProcAddr("glTexImage2D")) - if gpTexImage2D == nil { - return errors.New("glTexImage2D") - } - gpTexParameterf = (C.GPTEXPARAMETERF)(getProcAddr("glTexParameterf")) - if gpTexParameterf == nil { - return errors.New("glTexParameterf") - } - gpTexParameterfv = (C.GPTEXPARAMETERFV)(getProcAddr("glTexParameterfv")) - if gpTexParameterfv == nil { - return errors.New("glTexParameterfv") - } - gpTexParameteri = (C.GPTEXPARAMETERI)(getProcAddr("glTexParameteri")) - if gpTexParameteri == nil { - return errors.New("glTexParameteri") - } - gpTexParameteriv = (C.GPTEXPARAMETERIV)(getProcAddr("glTexParameteriv")) - if gpTexParameteriv == nil { - return errors.New("glTexParameteriv") - } - gpTexSubImage2D = (C.GPTEXSUBIMAGE2D)(getProcAddr("glTexSubImage2D")) - if gpTexSubImage2D == nil { - return errors.New("glTexSubImage2D") - } - gpUniform1f = (C.GPUNIFORM1F)(getProcAddr("glUniform1f")) - if gpUniform1f == nil { - return errors.New("glUniform1f") - } - gpUniform1fv = (C.GPUNIFORM1FV)(getProcAddr("glUniform1fv")) - if gpUniform1fv == nil { - return errors.New("glUniform1fv") - } - gpUniform1i = (C.GPUNIFORM1I)(getProcAddr("glUniform1i")) - if gpUniform1i == nil { - return errors.New("glUniform1i") - } - gpUniform1iv = (C.GPUNIFORM1IV)(getProcAddr("glUniform1iv")) - if gpUniform1iv == nil { - return errors.New("glUniform1iv") - } - gpUniform2f = (C.GPUNIFORM2F)(getProcAddr("glUniform2f")) - if gpUniform2f == nil { - return errors.New("glUniform2f") - } - gpUniform2fv = (C.GPUNIFORM2FV)(getProcAddr("glUniform2fv")) - if gpUniform2fv == nil { - return errors.New("glUniform2fv") - } - gpUniform2i = (C.GPUNIFORM2I)(getProcAddr("glUniform2i")) - if gpUniform2i == nil { - return errors.New("glUniform2i") - } - gpUniform2iv = (C.GPUNIFORM2IV)(getProcAddr("glUniform2iv")) - if gpUniform2iv == nil { - return errors.New("glUniform2iv") - } - gpUniform3f = (C.GPUNIFORM3F)(getProcAddr("glUniform3f")) - if gpUniform3f == nil { - return errors.New("glUniform3f") - } - gpUniform3fv = (C.GPUNIFORM3FV)(getProcAddr("glUniform3fv")) - if gpUniform3fv == nil { - return errors.New("glUniform3fv") - } - gpUniform3i = (C.GPUNIFORM3I)(getProcAddr("glUniform3i")) - if gpUniform3i == nil { - return errors.New("glUniform3i") - } - gpUniform3iv = (C.GPUNIFORM3IV)(getProcAddr("glUniform3iv")) - if gpUniform3iv == nil { - return errors.New("glUniform3iv") - } - gpUniform4f = (C.GPUNIFORM4F)(getProcAddr("glUniform4f")) - if gpUniform4f == nil { - return errors.New("glUniform4f") - } - gpUniform4fv = (C.GPUNIFORM4FV)(getProcAddr("glUniform4fv")) - if gpUniform4fv == nil { - return errors.New("glUniform4fv") - } - gpUniform4i = (C.GPUNIFORM4I)(getProcAddr("glUniform4i")) - if gpUniform4i == nil { - return errors.New("glUniform4i") - } - gpUniform4iv = (C.GPUNIFORM4IV)(getProcAddr("glUniform4iv")) - if gpUniform4iv == nil { - return errors.New("glUniform4iv") - } - gpUniformMatrix2fv = (C.GPUNIFORMMATRIX2FV)(getProcAddr("glUniformMatrix2fv")) - if gpUniformMatrix2fv == nil { - return errors.New("glUniformMatrix2fv") - } - gpUniformMatrix3fv = (C.GPUNIFORMMATRIX3FV)(getProcAddr("glUniformMatrix3fv")) - if gpUniformMatrix3fv == nil { - return errors.New("glUniformMatrix3fv") - } - gpUniformMatrix4fv = (C.GPUNIFORMMATRIX4FV)(getProcAddr("glUniformMatrix4fv")) - if gpUniformMatrix4fv == nil { - return errors.New("glUniformMatrix4fv") - } - gpUseProgram = (C.GPUSEPROGRAM)(getProcAddr("glUseProgram")) - if gpUseProgram == nil { - return errors.New("glUseProgram") - } - gpValidateProgram = (C.GPVALIDATEPROGRAM)(getProcAddr("glValidateProgram")) - if gpValidateProgram == nil { - return errors.New("glValidateProgram") - } - gpVertexAttrib1f = (C.GPVERTEXATTRIB1F)(getProcAddr("glVertexAttrib1f")) - if gpVertexAttrib1f == nil { - return errors.New("glVertexAttrib1f") - } - gpVertexAttrib1fv = (C.GPVERTEXATTRIB1FV)(getProcAddr("glVertexAttrib1fv")) - if gpVertexAttrib1fv == nil { - return errors.New("glVertexAttrib1fv") - } - gpVertexAttrib2f = (C.GPVERTEXATTRIB2F)(getProcAddr("glVertexAttrib2f")) - if gpVertexAttrib2f == nil { - return errors.New("glVertexAttrib2f") - } - gpVertexAttrib2fv = (C.GPVERTEXATTRIB2FV)(getProcAddr("glVertexAttrib2fv")) - if gpVertexAttrib2fv == nil { - return errors.New("glVertexAttrib2fv") - } - gpVertexAttrib3f = (C.GPVERTEXATTRIB3F)(getProcAddr("glVertexAttrib3f")) - if gpVertexAttrib3f == nil { - return errors.New("glVertexAttrib3f") - } - gpVertexAttrib3fv = (C.GPVERTEXATTRIB3FV)(getProcAddr("glVertexAttrib3fv")) - if gpVertexAttrib3fv == nil { - return errors.New("glVertexAttrib3fv") - } - gpVertexAttrib4f = (C.GPVERTEXATTRIB4F)(getProcAddr("glVertexAttrib4f")) - if gpVertexAttrib4f == nil { - return errors.New("glVertexAttrib4f") - } - gpVertexAttrib4fv = (C.GPVERTEXATTRIB4FV)(getProcAddr("glVertexAttrib4fv")) - if gpVertexAttrib4fv == nil { - return errors.New("glVertexAttrib4fv") - } - gpVertexAttribPointer = (C.GPVERTEXATTRIBPOINTER)(getProcAddr("glVertexAttribPointer")) - if gpVertexAttribPointer == nil { - return errors.New("glVertexAttribPointer") - } - gpViewport = (C.GPVIEWPORT)(getProcAddr("glViewport")) - if gpViewport == nil { - return errors.New("glViewport") - } - return nil -} diff --git a/backend/goglbackend/gl/procaddr.go b/backend/goglbackend/gl/procaddr.go deleted file mode 100644 index 4190c9b..0000000 --- a/backend/goglbackend/gl/procaddr.go +++ /dev/null @@ -1,72 +0,0 @@ -// +build !android,!ios -// Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. - -// This file implements GlowGetProcAddress for every supported platform. The -// correct version is chosen automatically based on build tags: -// -// windows: WGL -// darwin: CGL -// linux freebsd: GLX -// -// Use of EGL instead of the platform's default (listed above) is made possible -// via the "egl" build tag. -// -// It is also possible to install your own function outside this package for -// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc. - -package gl - -/* -#cgo windows CFLAGS: -DTAG_WINDOWS -#cgo windows LDFLAGS: -lopengl32 -#cgo darwin CFLAGS: -DTAG_DARWIN -#cgo darwin,!ios LDFLAGS: -framework OpenGL -#cgo linux freebsd CFLAGS: -DTAG_POSIX -#cgo linux freebsd LDFLAGS: -lGL -#cgo egl CFLAGS: -DTAG_EGL -#cgo egl LDFLAGS: -lEGL -// Check the EGL tag first as it takes priority over the platform's default -// configuration of WGL/GLX/CGL. -#if defined(TAG_EGL) - #include - #include - void* GlowGetProcAddress_glglesunion(const char* name) { - return eglGetProcAddress(name); - } -#elif defined(TAG_WINDOWS) - #define WIN32_LEAN_AND_MEAN 1 - #include - #include - static HMODULE ogl32dll = NULL; - void* GlowGetProcAddress_glglesunion(const char* name) { - void* pf = wglGetProcAddress((LPCSTR) name); - if (pf) { - return pf; - } - if (ogl32dll == NULL) { - ogl32dll = LoadLibraryA("opengl32.dll"); - } - return GetProcAddress(ogl32dll, (LPCSTR) name); - } -#elif defined(TAG_DARWIN) - #include - #include - void* GlowGetProcAddress_glglesunion(const char* name) { - return dlsym(RTLD_DEFAULT, name); - } -#elif defined(TAG_POSIX) - #include - #include - void* GlowGetProcAddress_glglesunion(const char* name) { - return glXGetProcAddress((const GLubyte *) name); - } -#endif -*/ -import "C" -import "unsafe" - -func getProcAddress(namea string) unsafe.Pointer { - cname := C.CString(namea) - defer C.free(unsafe.Pointer(cname)) - return C.GlowGetProcAddress_glglesunion(cname) -} diff --git a/backend/goglbackend/gl/procaddr_mobile.go b/backend/goglbackend/gl/procaddr_mobile.go deleted file mode 100644 index 129e863..0000000 --- a/backend/goglbackend/gl/procaddr_mobile.go +++ /dev/null @@ -1,312 +0,0 @@ -// +build android ios - -// Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. - -// This file implements GlowGetProcAddress for every supported platform. The -// correct version is chosen automatically based on build tags: -// -// windows: WGL -// darwin: CGL -// linux freebsd: GLX -// -// Use of EGL instead of the platform's default (listed above) is made possible -// via the "egl" build tag. -// -// It is also possible to install your own function outside this package for -// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc. - -package gl - -/* -#cgo android LDFLAGS: -lGLESv2 -#cgo android CFLAGS: -DANDROID -#cgo ios CFLAGS: -DIOS -#ifdef ANDROID - #include -#endif -#ifdef IOS - #include -#endif -*/ -import "C" -import "unsafe" - -func getProcAddress(namea string) unsafe.Pointer { - switch namea { - case "glActiveTexture": - return unsafe.Pointer(C.glActiveTexture) - case "glAttachShader": - return unsafe.Pointer(C.glAttachShader) - case "glBindAttribLocation": - return unsafe.Pointer(C.glBindAttribLocation) - case "glBindBuffer": - return unsafe.Pointer(C.glBindBuffer) - case "glBindFramebuffer": - return unsafe.Pointer(C.glBindFramebuffer) - case "glBindRenderbuffer": - return unsafe.Pointer(C.glBindRenderbuffer) - case "glBindTexture": - return unsafe.Pointer(C.glBindTexture) - case "glBlendColor": - return unsafe.Pointer(C.glBlendColor) - case "glBlendEquation": - return unsafe.Pointer(C.glBlendEquation) - case "glBlendEquationSeparate": - return unsafe.Pointer(C.glBlendEquationSeparate) - case "glBlendFunc": - return unsafe.Pointer(C.glBlendFunc) - case "glBlendFuncSeparate": - return unsafe.Pointer(C.glBlendFuncSeparate) - case "glBufferData": - return unsafe.Pointer(C.glBufferData) - case "glBufferSubData": - return unsafe.Pointer(C.glBufferSubData) - case "glCheckFramebufferStatus": - return unsafe.Pointer(C.glCheckFramebufferStatus) - case "glClear": - return unsafe.Pointer(C.glClear) - case "glClearColor": - return unsafe.Pointer(C.glClearColor) - case "glClearStencil": - return unsafe.Pointer(C.glClearStencil) - case "glColorMask": - return unsafe.Pointer(C.glColorMask) - case "glCompileShader": - return unsafe.Pointer(C.glCompileShader) - case "glCompressedTexImage2D": - return unsafe.Pointer(C.glCompressedTexImage2D) - case "glCompressedTexSubImage2D": - return unsafe.Pointer(C.glCompressedTexSubImage2D) - case "glCopyTexImage2D": - return unsafe.Pointer(C.glCopyTexImage2D) - case "glCopyTexSubImage2D": - return unsafe.Pointer(C.glCopyTexSubImage2D) - case "glCreateProgram": - return unsafe.Pointer(C.glCreateProgram) - case "glCreateShader": - return unsafe.Pointer(C.glCreateShader) - case "glCullFace": - return unsafe.Pointer(C.glCullFace) - case "glDeleteBuffers": - return unsafe.Pointer(C.glDeleteBuffers) - case "glDeleteFramebuffers": - return unsafe.Pointer(C.glDeleteFramebuffers) - case "glDeleteProgram": - return unsafe.Pointer(C.glDeleteProgram) - case "glDeleteRenderbuffers": - return unsafe.Pointer(C.glDeleteRenderbuffers) - case "glDeleteShader": - return unsafe.Pointer(C.glDeleteShader) - case "glDeleteTextures": - return unsafe.Pointer(C.glDeleteTextures) - case "glDepthFunc": - return unsafe.Pointer(C.glDepthFunc) - case "glDepthMask": - return unsafe.Pointer(C.glDepthMask) - case "glDetachShader": - return unsafe.Pointer(C.glDetachShader) - case "glDisable": - return unsafe.Pointer(C.glDisable) - case "glDisableVertexAttribArray": - return unsafe.Pointer(C.glDisableVertexAttribArray) - case "glDrawArrays": - return unsafe.Pointer(C.glDrawArrays) - case "glDrawElements": - return unsafe.Pointer(C.glDrawElements) - case "glEnable": - return unsafe.Pointer(C.glEnable) - case "glEnableVertexAttribArray": - return unsafe.Pointer(C.glEnableVertexAttribArray) - case "glFinish": - return unsafe.Pointer(C.glFinish) - case "glFlush": - return unsafe.Pointer(C.glFlush) - case "glFramebufferRenderbuffer": - return unsafe.Pointer(C.glFramebufferRenderbuffer) - case "glFramebufferTexture2D": - return unsafe.Pointer(C.glFramebufferTexture2D) - case "glFrontFace": - return unsafe.Pointer(C.glFrontFace) - case "glGenBuffers": - return unsafe.Pointer(C.glGenBuffers) - case "glGenFramebuffers": - return unsafe.Pointer(C.glGenFramebuffers) - case "glGenRenderbuffers": - return unsafe.Pointer(C.glGenRenderbuffers) - case "glGenTextures": - return unsafe.Pointer(C.glGenTextures) - case "glGenerateMipmap": - return unsafe.Pointer(C.glGenerateMipmap) - case "glGetActiveAttrib": - return unsafe.Pointer(C.glGetActiveAttrib) - case "glGetActiveUniform": - return unsafe.Pointer(C.glGetActiveUniform) - case "glGetAttachedShaders": - return unsafe.Pointer(C.glGetAttachedShaders) - case "glGetAttribLocation": - return unsafe.Pointer(C.glGetAttribLocation) - case "glGetBooleanv": - return unsafe.Pointer(C.glGetBooleanv) - case "glGetBufferParameteriv": - return unsafe.Pointer(C.glGetBufferParameteriv) - case "glGetError": - return unsafe.Pointer(C.glGetError) - case "glGetFloatv": - return unsafe.Pointer(C.glGetFloatv) - case "glGetFramebufferAttachmentParameteriv": - return unsafe.Pointer(C.glGetFramebufferAttachmentParameteriv) - case "glGetIntegerv": - return unsafe.Pointer(C.glGetIntegerv) - case "glGetProgramInfoLog": - return unsafe.Pointer(C.glGetProgramInfoLog) - case "glGetProgramiv": - return unsafe.Pointer(C.glGetProgramiv) - case "glGetRenderbufferParameteriv": - return unsafe.Pointer(C.glGetRenderbufferParameteriv) - case "glGetShaderInfoLog": - return unsafe.Pointer(C.glGetShaderInfoLog) - case "glGetShaderSource": - return unsafe.Pointer(C.glGetShaderSource) - case "glGetShaderiv": - return unsafe.Pointer(C.glGetShaderiv) - case "glGetString": - return unsafe.Pointer(C.glGetString) - case "glGetTexParameterfv": - return unsafe.Pointer(C.glGetTexParameterfv) - case "glGetTexParameteriv": - return unsafe.Pointer(C.glGetTexParameteriv) - case "glGetUniformLocation": - return unsafe.Pointer(C.glGetUniformLocation) - case "glGetUniformfv": - return unsafe.Pointer(C.glGetUniformfv) - case "glGetUniformiv": - return unsafe.Pointer(C.glGetUniformiv) - case "glGetVertexAttribPointerv": - return unsafe.Pointer(C.glGetVertexAttribPointerv) - case "glGetVertexAttribfv": - return unsafe.Pointer(C.glGetVertexAttribfv) - case "glGetVertexAttribiv": - return unsafe.Pointer(C.glGetVertexAttribiv) - case "glHint": - return unsafe.Pointer(C.glHint) - case "glIsBuffer": - return unsafe.Pointer(C.glIsBuffer) - case "glIsEnabled": - return unsafe.Pointer(C.glIsEnabled) - case "glIsFramebuffer": - return unsafe.Pointer(C.glIsFramebuffer) - case "glIsProgram": - return unsafe.Pointer(C.glIsProgram) - case "glIsRenderbuffer": - return unsafe.Pointer(C.glIsRenderbuffer) - case "glIsShader": - return unsafe.Pointer(C.glIsShader) - case "glIsTexture": - return unsafe.Pointer(C.glIsTexture) - case "glLineWidth": - return unsafe.Pointer(C.glLineWidth) - case "glLinkProgram": - return unsafe.Pointer(C.glLinkProgram) - case "glPixelStorei": - return unsafe.Pointer(C.glPixelStorei) - case "glPolygonOffset": - return unsafe.Pointer(C.glPolygonOffset) - case "glReadPixels": - return unsafe.Pointer(C.glReadPixels) - case "glRenderbufferStorage": - return unsafe.Pointer(C.glRenderbufferStorage) - case "glSampleCoverage": - return unsafe.Pointer(C.glSampleCoverage) - case "glScissor": - return unsafe.Pointer(C.glScissor) - case "glShaderSource": - return unsafe.Pointer(C.glShaderSource) - case "glStencilFunc": - return unsafe.Pointer(C.glStencilFunc) - case "glStencilFuncSeparate": - return unsafe.Pointer(C.glStencilFuncSeparate) - case "glStencilMask": - return unsafe.Pointer(C.glStencilMask) - case "glStencilMaskSeparate": - return unsafe.Pointer(C.glStencilMaskSeparate) - case "glStencilOp": - return unsafe.Pointer(C.glStencilOp) - case "glStencilOpSeparate": - return unsafe.Pointer(C.glStencilOpSeparate) - case "glTexImage2D": - return unsafe.Pointer(C.glTexImage2D) - case "glTexParameterf": - return unsafe.Pointer(C.glTexParameterf) - case "glTexParameterfv": - return unsafe.Pointer(C.glTexParameterfv) - case "glTexParameteri": - return unsafe.Pointer(C.glTexParameteri) - case "glTexParameteriv": - return unsafe.Pointer(C.glTexParameteriv) - case "glTexSubImage2D": - return unsafe.Pointer(C.glTexSubImage2D) - case "glUniform1f": - return unsafe.Pointer(C.glUniform1f) - case "glUniform1fv": - return unsafe.Pointer(C.glUniform1fv) - case "glUniform1i": - return unsafe.Pointer(C.glUniform1i) - case "glUniform1iv": - return unsafe.Pointer(C.glUniform1iv) - case "glUniform2f": - return unsafe.Pointer(C.glUniform2f) - case "glUniform2fv": - return unsafe.Pointer(C.glUniform2fv) - case "glUniform2i": - return unsafe.Pointer(C.glUniform2i) - case "glUniform2iv": - return unsafe.Pointer(C.glUniform2iv) - case "glUniform3f": - return unsafe.Pointer(C.glUniform3f) - case "glUniform3fv": - return unsafe.Pointer(C.glUniform3fv) - case "glUniform3i": - return unsafe.Pointer(C.glUniform3i) - case "glUniform3iv": - return unsafe.Pointer(C.glUniform3iv) - case "glUniform4f": - return unsafe.Pointer(C.glUniform4f) - case "glUniform4fv": - return unsafe.Pointer(C.glUniform4fv) - case "glUniform4i": - return unsafe.Pointer(C.glUniform4i) - case "glUniform4iv": - return unsafe.Pointer(C.glUniform4iv) - case "glUniformMatrix2fv": - return unsafe.Pointer(C.glUniformMatrix2fv) - case "glUniformMatrix3fv": - return unsafe.Pointer(C.glUniformMatrix3fv) - case "glUniformMatrix4fv": - return unsafe.Pointer(C.glUniformMatrix4fv) - case "glUseProgram": - return unsafe.Pointer(C.glUseProgram) - case "glValidateProgram": - return unsafe.Pointer(C.glValidateProgram) - case "glVertexAttrib1f": - return unsafe.Pointer(C.glVertexAttrib1f) - case "glVertexAttrib1fv": - return unsafe.Pointer(C.glVertexAttrib1fv) - case "glVertexAttrib2f": - return unsafe.Pointer(C.glVertexAttrib2f) - case "glVertexAttrib2fv": - return unsafe.Pointer(C.glVertexAttrib2fv) - case "glVertexAttrib3f": - return unsafe.Pointer(C.glVertexAttrib3f) - case "glVertexAttrib3fv": - return unsafe.Pointer(C.glVertexAttrib3fv) - case "glVertexAttrib4f": - return unsafe.Pointer(C.glVertexAttrib4f) - case "glVertexAttrib4fv": - return unsafe.Pointer(C.glVertexAttrib4fv) - case "glVertexAttribPointer": - return unsafe.Pointer(C.glVertexAttribPointer) - case "glViewport": - return unsafe.Pointer(C.glViewport) - } - return nil -} diff --git a/backend/goglbackend/gogl.go b/backend/goglbackend/gogl.go deleted file mode 100644 index e6338bd..0000000 --- a/backend/goglbackend/gogl.go +++ /dev/null @@ -1,400 +0,0 @@ -package goglbackend - -import ( - "fmt" - - "github.com/tfriedel6/canvas/backend/backendbase" - "github.com/tfriedel6/canvas/backend/goglbackend/gl" -) - -const alphaTexSize = 2048 - -var zeroes [alphaTexSize]byte - -// GLContext is a context that contains all the -// shaders and buffers necessary for rendering -type GLContext struct { - buf uint32 - shadowBuf uint32 - alphaTex uint32 - - shd unifiedShader - - offscr1 offscreenBuffer - offscr2 offscreenBuffer - - imageBufTex uint32 - imageBuf []byte - - ptsBuf []float32 -} - -// NewGLContext creates all the necessary GL resources, -// like shaders and buffers -func NewGLContext() (*GLContext, error) { - ctx := &GLContext{ - ptsBuf: make([]float32, 0, 4096), - } - - err := gl.Init() - if err != nil { - return nil, err - } - - gl.GetError() // clear error state - - err = loadShader(unifiedVS, unifiedFS, &ctx.shd.shaderProgram) - if err != nil { - return nil, err - } - ctx.shd.shaderProgram.mustLoadLocations(&ctx.shd) - if err = glError(); err != nil { - return nil, err - } - - gl.GenBuffers(1, &ctx.buf) - if err = glError(); err != nil { - return nil, err - } - - gl.GenBuffers(1, &ctx.shadowBuf) - if err = glError(); err != nil { - return nil, err - } - - gl.ActiveTexture(gl.TEXTURE0) - gl.GenTextures(1, &ctx.alphaTex) - gl.BindTexture(gl.TEXTURE_2D, ctx.alphaTex) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, alphaTexSize, alphaTexSize, 0, gl.ALPHA, gl.UNSIGNED_BYTE, nil) - // todo should use gl.RED on OpenGL, gl.ALPHA on OpenGL ES - - gl.Enable(gl.BLEND) - gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - gl.Enable(gl.STENCIL_TEST) - gl.StencilMask(0xFF) - gl.Clear(gl.STENCIL_BUFFER_BIT) - gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) - gl.StencilFunc(gl.EQUAL, 0, 0xFF) - - gl.Disable(gl.SCISSOR_TEST) - - return ctx, nil -} - -// GoGLBackend is a canvas backend using Go-GL -type GoGLBackend struct { - x, y, w, h int - fx, fy, fw, fh float64 - - *GLContext - - activateFn func() - disableTextureRenderTarget func() -} - -type offscreenBuffer struct { - tex uint32 - w int - h int - renderStencilBuf uint32 - frameBuf uint32 - alpha bool -} - -// New returns a new canvas backend. x, y, w, h define the target -// rectangle in the window. ctx is a GLContext created with -// NewGLContext, but can be nil for a default one. It makes sense -// to pass one in when using for example an onscreen and an -// offscreen backend using the same GL context. -func New(x, y, w, h int, ctx *GLContext) (*GoGLBackend, error) { - if ctx == nil { - var err error - ctx, err = NewGLContext() - if err != nil { - return nil, err - } - } - - b := &GoGLBackend{ - w: w, - h: h, - fw: float64(w), - fh: float64(h), - GLContext: ctx, - } - - b.activateFn = func() { - gl.BindFramebuffer(gl.FRAMEBUFFER, 0) - gl.Viewport(int32(b.x), int32(b.y), int32(b.w), int32(b.h)) - // todo reapply clipping since another application may have used the stencil buffer - } - b.disableTextureRenderTarget = func() { - gl.BindFramebuffer(gl.FRAMEBUFFER, 0) - gl.Viewport(int32(b.x), int32(b.y), int32(b.w), int32(b.h)) - } - - return b, nil -} - -// GoGLBackendOffscreen is a canvas backend using an offscreen -// texture -type GoGLBackendOffscreen struct { - GoGLBackend - - TextureID uint32 - - offscrBuf offscreenBuffer - offscrImg Image -} - -// NewOffscreen returns a new offscreen canvas backend. w, h define -// the size of the offscreen texture. ctx is a GLContext created -// with NewGLContext, but can be nil for a default one. It makes -// sense to pass one in when using for example an onscreen and an -// offscreen backend using the same GL context. -func NewOffscreen(w, h int, alpha bool, ctx *GLContext) (*GoGLBackendOffscreen, error) { - b, err := New(0, 0, w, h, ctx) - if err != nil { - return nil, err - } - bo := &GoGLBackendOffscreen{GoGLBackend: *b} - bo.offscrBuf.alpha = alpha - bo.offscrImg.flip = true - - bo.activateFn = func() { - bo.enableTextureRenderTarget(&bo.offscrBuf) - gl.Viewport(0, 0, int32(bo.w), int32(bo.h)) - bo.offscrImg.w = bo.offscrBuf.w - bo.offscrImg.h = bo.offscrBuf.h - bo.offscrImg.tex = bo.offscrBuf.tex - bo.TextureID = bo.offscrBuf.tex - } - bo.disableTextureRenderTarget = func() { - bo.enableTextureRenderTarget(&bo.offscrBuf) - } - - return bo, nil -} - -// SetBounds updates the bounds of the canvas. This would -// usually be called for example when the window is resized -func (b *GoGLBackend) SetBounds(x, y, w, h int) { - b.x, b.y = x, y - b.fx, b.fy = float64(x), float64(y) - b.w, b.h = w, h - b.fw, b.fh = float64(w), float64(h) - if b == activeContext { - gl.Viewport(0, 0, int32(b.w), int32(b.h)) - gl.Clear(gl.STENCIL_BUFFER_BIT) - } -} - -// SetSize updates the size of the offscreen texture -func (b *GoGLBackendOffscreen) SetSize(w, h int) { - b.GoGLBackend.SetBounds(0, 0, w, h) - b.offscrImg.w = b.offscrBuf.w - b.offscrImg.h = b.offscrBuf.h -} - -// Size returns the size of the window or offscreen -// texture -func (b *GoGLBackend) Size() (int, int) { - return b.w, b.h -} - -func glError() error { - glErr := gl.GetError() - if glErr != gl.NO_ERROR { - return fmt.Errorf("GL Error: %x", glErr) - } - return nil -} - -// Activate only needs to be called if there is other -// code also using the GL state -func (b *GoGLBackend) Activate() { - b.activate() -} - -var activeContext *GoGLBackend - -func (b *GoGLBackend) activate() { - if activeContext != b { - activeContext = b - b.activateFn() - } -} - -// Delete deletes the offscreen texture. After calling this -// the backend can no longer be used -func (b *GoGLBackendOffscreen) Delete() { - gl.DeleteTextures(1, &b.offscrBuf.tex) - gl.DeleteFramebuffers(1, &b.offscrBuf.frameBuf) - gl.DeleteRenderbuffers(1, &b.offscrBuf.renderStencilBuf) -} - -// CanUseAsImage returns true if the given backend can be -// directly used by this backend to avoid a conversion. -// Used internally -func (b *GoGLBackend) CanUseAsImage(b2 backendbase.Backend) bool { - _, ok := b2.(*GoGLBackendOffscreen) - return ok -} - -// AsImage returns nil, since this backend cannot be directly -// used as an image. Used internally -func (b *GoGLBackend) AsImage() backendbase.Image { - return nil -} - -// AsImage returns an implementation of the Image interface -// that can be used to render this offscreen texture -// directly. Used internally -func (b *GoGLBackendOffscreen) AsImage() backendbase.Image { - return &b.offscrImg -} - -func (b *GoGLBackend) useShader(style *backendbase.FillStyle, tf [9]float32, useAlpha bool, alphaTexSlot int32) (vertexLoc, alphaTexCoordLoc uint32) { - gl.UseProgram(b.shd.ID) - gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) - gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &tf[0]) - if useAlpha { - gl.Uniform1i(b.shd.UseAlphaTex, 1) - gl.Uniform1i(b.shd.AlphaTex, alphaTexSlot) - } else { - gl.Uniform1i(b.shd.UseAlphaTex, 0) - } - gl.Uniform1f(b.shd.GlobalAlpha, float32(style.Color.A)/255) - - if lg := style.LinearGradient; lg != nil { - lg := lg.(*LinearGradient) - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, lg.tex) - from := backendbase.Vec{style.Gradient.X0, style.Gradient.Y0} - to := backendbase.Vec{style.Gradient.X1, style.Gradient.Y1} - dir := to.Sub(from) - length := dir.Len() - dir = dir.Mulf(1 / length) - gl.Uniform2f(b.shd.From, float32(from[0]), float32(from[1])) - gl.Uniform2f(b.shd.Dir, float32(dir[0]), float32(dir[1])) - gl.Uniform1f(b.shd.Len, float32(length)) - gl.Uniform1i(b.shd.Gradient, 0) - gl.Uniform1i(b.shd.Func, shdFuncLinearGradient) - return b.shd.Vertex, b.shd.TexCoord - } - if rg := style.RadialGradient; rg != nil { - rg := rg.(*RadialGradient) - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, rg.tex) - gl.Uniform2f(b.shd.From, float32(style.Gradient.X0), float32(style.Gradient.Y0)) - gl.Uniform2f(b.shd.To, float32(style.Gradient.X1), float32(style.Gradient.Y1)) - gl.Uniform1f(b.shd.RadFrom, float32(style.Gradient.RadFrom)) - gl.Uniform1f(b.shd.RadTo, float32(style.Gradient.RadTo)) - gl.Uniform1i(b.shd.Gradient, 0) - gl.Uniform1i(b.shd.Func, shdFuncRadialGradient) - return b.shd.Vertex, b.shd.TexCoord - } - if ip := style.ImagePattern; ip != nil { - ipd := ip.(*ImagePattern).data - img := ipd.Image.(*Image) - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, img.tex) - gl.Uniform2f(b.shd.ImageSize, float32(img.w), float32(img.h)) - gl.Uniform1i(b.shd.Image, 0) - var f32mat [9]float32 - for i, v := range ipd.Transform { - f32mat[i] = float32(v) - } - gl.UniformMatrix3fv(b.shd.ImageTransform, 1, false, &f32mat[0]) - switch ipd.Repeat { - case backendbase.Repeat: - gl.Uniform2f(b.shd.Repeat, 1, 1) - case backendbase.RepeatX: - gl.Uniform2f(b.shd.Repeat, 1, 0) - case backendbase.RepeatY: - gl.Uniform2f(b.shd.Repeat, 0, 1) - case backendbase.NoRepeat: - gl.Uniform2f(b.shd.Repeat, 0, 0) - } - gl.Uniform1i(b.shd.Func, shdFuncImagePattern) - return b.shd.Vertex, b.shd.TexCoord - } - - cr := float32(style.Color.R) / 255 - cg := float32(style.Color.G) / 255 - cb := float32(style.Color.B) / 255 - ca := float32(style.Color.A) / 255 - gl.Uniform4f(b.shd.Color, cr, cg, cb, ca) - gl.Uniform1f(b.shd.GlobalAlpha, 1) - gl.Uniform1i(b.shd.Func, shdFuncSolid) - return b.shd.Vertex, b.shd.TexCoord -} - -func (b *GoGLBackend) enableTextureRenderTarget(offscr *offscreenBuffer) { - if offscr.w == b.w && offscr.h == b.h { - gl.BindFramebuffer(gl.FRAMEBUFFER, offscr.frameBuf) - return - } - - if b.w == 0 || b.h == 0 { - return - } - - if offscr.w != 0 && offscr.h != 0 { - gl.DeleteTextures(1, &offscr.tex) - gl.DeleteFramebuffers(1, &offscr.frameBuf) - gl.DeleteRenderbuffers(1, &offscr.renderStencilBuf) - } - offscr.w = b.w - offscr.h = b.h - - gl.ActiveTexture(gl.TEXTURE0) - gl.GenTextures(1, &offscr.tex) - gl.BindTexture(gl.TEXTURE_2D, offscr.tex) - // todo do non-power-of-two textures work everywhere? - if offscr.alpha { - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(b.w), int32(b.h), 0, gl.RGBA, gl.UNSIGNED_BYTE, nil) - } else { - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(b.w), int32(b.h), 0, gl.RGB, gl.UNSIGNED_BYTE, nil) - } - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - - gl.GenFramebuffers(1, &offscr.frameBuf) - gl.BindFramebuffer(gl.FRAMEBUFFER, offscr.frameBuf) - - gl.GenRenderbuffers(1, &offscr.renderStencilBuf) - gl.BindRenderbuffer(gl.RENDERBUFFER, offscr.renderStencilBuf) - gl.RenderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, int32(b.w), int32(b.h)) - gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, offscr.renderStencilBuf) - - gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, offscr.tex, 0) - - if err := gl.CheckFramebufferStatus(gl.FRAMEBUFFER); err != gl.FRAMEBUFFER_COMPLETE { - // todo this should maybe not panic - panic(fmt.Sprintf("Failed to set up framebuffer for offscreen texture: %x", err)) - } - - gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) -} - -func mat3(m backendbase.Mat) (m3 [9]float32) { - m3[0] = float32(m[0]) - m3[1] = float32(m[1]) - m3[2] = 0 - m3[3] = float32(m[2]) - m3[4] = float32(m[3]) - m3[5] = 0 - m3[6] = float32(m[4]) - m3[7] = float32(m[5]) - m3[8] = 1 - return -} - -var mat3identity = [9]float32{1, 0, 0, 0, 1, 0, 0, 0, 1} diff --git a/backend/goglbackend/gradients.go b/backend/goglbackend/gradients.go deleted file mode 100644 index bc94978..0000000 --- a/backend/goglbackend/gradients.go +++ /dev/null @@ -1,90 +0,0 @@ -package goglbackend - -import ( - "github.com/tfriedel6/canvas/backend/backendbase" - "github.com/tfriedel6/canvas/backend/goglbackend/gl" -) - -// LinearGradient is a gradient with any number of -// stops and any number of colors. The gradient will -// be drawn such that each point on the gradient -// will correspond to a straight line -type LinearGradient struct { - gradient -} - -// RadialGradient is a gradient with any number of -// stops and any number of colors. The gradient will -// be drawn such that each point on the gradient -// will correspond to a circle -type RadialGradient struct { - gradient -} - -type gradient struct { - b *GoGLBackend - tex uint32 -} - -func (b *GoGLBackend) LoadLinearGradient(data backendbase.Gradient) backendbase.LinearGradient { - b.activate() - - lg := &LinearGradient{ - gradient: gradient{b: b}, - } - gl.GenTextures(1, &lg.tex) - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, lg.tex) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - lg.load(data) - return lg -} - -func (b *GoGLBackend) LoadRadialGradient(data backendbase.Gradient) backendbase.RadialGradient { - b.activate() - - rg := &RadialGradient{ - gradient: gradient{b: b}, - } - gl.GenTextures(1, &rg.tex) - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, rg.tex) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - rg.load(data) - return rg -} - -// Delete explicitly deletes the gradient -func (g *gradient) Delete() { - g.b.activate() - - gl.DeleteTextures(1, &g.tex) -} - -func (lg *LinearGradient) Replace(data backendbase.Gradient) { lg.load(data) } -func (rg *RadialGradient) Replace(data backendbase.Gradient) { rg.load(data) } - -func (g *gradient) load(stops backendbase.Gradient) { - g.b.activate() - - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, g.tex) - var pixels [2048 * 4]byte - pp := 0 - for i := 0; i < 2048; i++ { - c := stops.ColorAt(float64(i) / 2047) - pixels[pp] = c.R - pixels[pp+1] = c.G - pixels[pp+2] = c.B - pixels[pp+3] = c.A - pp += 4 - } - - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2048, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&pixels[0])) -} diff --git a/backend/goglbackend/imagedata.go b/backend/goglbackend/imagedata.go deleted file mode 100644 index 2027a05..0000000 --- a/backend/goglbackend/imagedata.go +++ /dev/null @@ -1,102 +0,0 @@ -package goglbackend - -import ( - "image" - "image/color" - "unsafe" - - "github.com/tfriedel6/canvas/backend/goglbackend/gl" -) - -// GetImageData returns an RGBA image of the current image -func (b *GoGLBackend) GetImageData(x, y, w, h int) *image.RGBA { - b.activate() - - if x < 0 { - w += x - x = 0 - } - if y < 0 { - h += y - y = 0 - } - if w > b.w { - w = b.w - } - if h > b.h { - h = b.h - } - - var vp [4]int32 - gl.GetIntegerv(gl.VIEWPORT, &vp[0]) - - size := int(vp[2] * vp[3] * 3) - if len(b.imageBuf) < size { - b.imageBuf = make([]byte, size) - } - gl.ReadPixels(vp[0], vp[1], vp[2], vp[3], gl.RGB, gl.UNSIGNED_BYTE, gl.Ptr(&b.imageBuf[0])) - - rgba := image.NewRGBA(image.Rect(x, y, x+w, y+h)) - for cy := y; cy < y+h; cy++ { - bp := (int(vp[3])-h+cy)*int(vp[2])*3 + x*3 - for cx := x; cx < x+w; cx++ { - rgba.SetRGBA(cx, y+h-1-cy, color.RGBA{R: b.imageBuf[bp], G: b.imageBuf[bp+1], B: b.imageBuf[bp+2], A: 255}) - bp += 3 - } - } - return rgba -} - -// PutImageData puts the given image at the given x/y coordinates -func (b *GoGLBackend) PutImageData(img *image.RGBA, x, y int) { - b.activate() - - gl.ActiveTexture(gl.TEXTURE0) - if b.imageBufTex == 0 { - gl.GenTextures(1, &b.imageBufTex) - gl.BindTexture(gl.TEXTURE_2D, b.imageBufTex) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - } else { - gl.BindTexture(gl.TEXTURE_2D, b.imageBufTex) - } - - w, h := img.Bounds().Dx(), img.Bounds().Dy() - - if img.Stride == img.Bounds().Dx()*4 { - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(w), int32(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&img.Pix[0])) - } else { - data := make([]uint8, 0, w*h*4) - for cy := 0; cy < h; cy++ { - start := cy * img.Stride - end := start + w*4 - data = append(data, img.Pix[start:end]...) - } - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(w), int32(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&data[0])) - } - - dx, dy := float32(x), float32(y) - dw, dh := float32(w), float32(h) - - gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) - data := [16]float32{dx, dy, dx + dw, dy, dx + dw, dy + dh, dx, dy + dh, - 0, 0, 1, 0, 1, 1, 0, 1} - gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) - - gl.UseProgram(b.shd.ID) - gl.Uniform1i(b.shd.Image, 0) - gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) - gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) - gl.Uniform1f(b.shd.GlobalAlpha, 1) - gl.Uniform1i(b.shd.UseAlphaTex, 0) - gl.Uniform1i(b.shd.Func, shdFuncImage) - gl.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, gl.PtrOffset(8*4)) - gl.EnableVertexAttribArray(b.shd.Vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) - gl.DisableVertexAttribArray(b.shd.Vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) -} diff --git a/backend/goglbackend/images.go b/backend/goglbackend/images.go deleted file mode 100644 index 5199eef..0000000 --- a/backend/goglbackend/images.go +++ /dev/null @@ -1,221 +0,0 @@ -package goglbackend - -import ( - "errors" - "image" - "unsafe" - - "github.com/tfriedel6/canvas/backend/backendbase" - "github.com/tfriedel6/canvas/backend/goglbackend/gl" -) - -// Image represents a loaded image that can be used in various drawing functions -type Image struct { - b *GoGLBackend - w, h int - tex uint32 - flip bool -} - -func (b *GoGLBackend) LoadImage(src image.Image) (backendbase.Image, error) { - b.activate() - - var tex uint32 - gl.GenTextures(1, &tex) - if tex == 0 { - return nil, errors.New("glGenTextures failed") - } - - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, tex) - if src == nil { - return &Image{tex: tex}, nil - } - - img, err := loadImage(src, tex) - if err != nil { - return nil, err - } - img.b = b - - return img, nil -} - -func loadImage(src image.Image, tex uint32) (*Image, error) { - var img *Image - var err error - switch v := src.(type) { - case *image.RGBA: - img, err = loadImageRGBA(v, tex) - if err != nil { - return nil, err - } - case image.Image: - img, err = loadImageConverted(v, tex) - if err != nil { - return nil, err - } - default: - return nil, errors.New("Unsupported source type") - } - return img, nil -} - -func loadImageRGBA(src *image.RGBA, tex uint32) (*Image, error) { - img := &Image{tex: tex, w: src.Bounds().Dx(), h: src.Bounds().Dy()} - - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - if err := glError(); err != nil { - return nil, err - } - if src.Stride == img.w*4 { - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(img.w), int32(img.h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&src.Pix[0])) - } else { - data := make([]uint8, 0, img.w*img.h*4) - for y := 0; y < img.h; y++ { - start := y * src.Stride - end := start + img.w*4 - data = append(data, src.Pix[start:end]...) - } - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(img.w), int32(img.h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&data[0])) - } - if err := glError(); err != nil { - return nil, err - } - gl.GenerateMipmap(gl.TEXTURE_2D) - if err := glError(); err != nil { - return nil, err - } - return img, nil -} - -func loadImageConverted(src image.Image, tex uint32) (*Image, error) { - img := &Image{tex: tex, w: src.Bounds().Dx(), h: src.Bounds().Dy()} - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - if err := glError(); err != nil { - return nil, err - } - data := make([]uint8, 0, img.w*img.h*4) - for y := 0; y < img.h; y++ { - for x := 0; x < img.w; x++ { - ir, ig, ib, ia := src.At(x, y).RGBA() - r, g, b, a := uint8(ir>>8), uint8(ig>>8), uint8(ib>>8), uint8(ia>>8) - data = append(data, r, g, b, a) - } - } - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(img.w), int32(img.h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&data[0])) - if err := glError(); err != nil { - return nil, err - } - gl.GenerateMipmap(gl.TEXTURE_2D) - if err := glError(); err != nil { - return nil, err - } - return img, nil -} - -// Width returns the width of the image -func (img *Image) Width() int { return img.w } - -// Height returns the height of the image -func (img *Image) Height() int { return img.h } - -// Size returns the width and height of the image -func (img *Image) Size() (int, int) { return img.w, img.h } - -// Delete deletes the image from memory. Any draw calls -// with a deleted image will not do anything -func (img *Image) Delete() { - img.b.activate() - - gl.DeleteTextures(1, &img.tex) -} - -// Replace replaces the image with the new one -func (img *Image) Replace(src image.Image) error { - img.b.activate() - - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, img.tex) - newImg, err := loadImage(src, img.tex) - if err != nil { - return err - } - newImg.b = img.b - *img = *newImg - return nil -} - -func (b *GoGLBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh float64, pts [4]backendbase.Vec, alpha float64) { - b.activate() - - img := dimg.(*Image) - - sx /= float64(img.w) - sy /= float64(img.h) - sw /= float64(img.w) - sh /= float64(img.h) - - if img.flip { - sy += sh - sh = -sh - } - - var buf [16]float32 - data := buf[:0] - for _, pt := range pts { - data = append(data, float32(pt[0]), float32(pt[1])) - } - data = append(data, - float32(sx), float32(sy), - float32(sx), float32(sy+sh), - float32(sx+sw), float32(sy+sh), - float32(sx+sw), float32(sy), - ) - - gl.StencilFunc(gl.EQUAL, 0, 0xFF) - - gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) - gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) - - gl.ActiveTexture(gl.TEXTURE0) - gl.BindTexture(gl.TEXTURE_2D, img.tex) - - gl.UseProgram(b.shd.ID) - gl.Uniform1i(b.shd.Image, 0) - gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) - gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) - gl.Uniform1f(b.shd.GlobalAlpha, float32(alpha)) - gl.Uniform1i(b.shd.UseAlphaTex, 0) - gl.Uniform1i(b.shd.Func, shdFuncImage) - gl.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, nil) - gl.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, gl.PtrOffset(8*4)) - gl.EnableVertexAttribArray(b.shd.Vertex) - gl.EnableVertexAttribArray(b.shd.TexCoord) - gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) - gl.DisableVertexAttribArray(b.shd.Vertex) - gl.DisableVertexAttribArray(b.shd.TexCoord) - - gl.StencilFunc(gl.ALWAYS, 0, 0xFF) -} - -type ImagePattern struct { - b *GoGLBackend - data backendbase.ImagePatternData -} - -func (b *GoGLBackend) LoadImagePattern(data backendbase.ImagePatternData) backendbase.ImagePattern { - return &ImagePattern{ - b: b, - data: data, - } -} - -func (ip *ImagePattern) Delete() {} -func (ip *ImagePattern) Replace(data backendbase.ImagePatternData) { ip.data = data } diff --git a/backend/goglbackend/shader.go b/backend/goglbackend/shader.go deleted file mode 100644 index c1c0172..0000000 --- a/backend/goglbackend/shader.go +++ /dev/null @@ -1,202 +0,0 @@ -package goglbackend - -import ( - "errors" - "fmt" - "reflect" - "strings" - "unicode" - "unicode/utf8" - - "github.com/tfriedel6/canvas/backend/goglbackend/gl" -) - -type shaderProgram struct { - ID, vs, fs uint32 - - attribs map[string]uint32 - uniforms map[string]int32 -} - -func loadShader(vs, fs string, sp *shaderProgram) error { - glError() // clear the current error - - // compile vertex shader - { - sp.vs = gl.CreateShader(gl.VERTEX_SHADER) - csrc, freeFunc := gl.Strs(vs + "\x00") - defer freeFunc() - gl.ShaderSource(sp.vs, 1, csrc, nil) - gl.CompileShader(sp.vs) - - var status int32 - gl.GetShaderiv(sp.vs, gl.COMPILE_STATUS, &status) - if status != gl.TRUE { - var buf [65536]byte - var length int32 - gl.GetShaderInfoLog(sp.vs, int32(len(buf)), &length, &buf[0]) - clog := string(buf[:length]) - gl.DeleteShader(sp.vs) - return fmt.Errorf("failed to compile vertex shader:\n\n%s", clog) - } - if err := glError(); err != nil { - return fmt.Errorf("gl error after compiling vertex shader: %v", err) - } - } - - // compile fragment shader - { - sp.fs = gl.CreateShader(gl.FRAGMENT_SHADER) - csrc, freeFunc := gl.Strs(fs + "\x00") - defer freeFunc() - gl.ShaderSource(sp.fs, 1, csrc, nil) - gl.CompileShader(sp.fs) - - var status int32 - gl.GetShaderiv(sp.fs, gl.COMPILE_STATUS, &status) - if status != gl.TRUE { - var buf [65536]byte - var length int32 - gl.GetShaderInfoLog(sp.fs, int32(len(buf)), &length, &buf[0]) - clog := string(buf[:length]) - gl.DeleteShader(sp.fs) - return fmt.Errorf("failed to compile fragment shader:\n\n%s", clog) - } - if err := glError(); err != nil { - return fmt.Errorf("gl error after compiling fragment shader: %v", err) - } - } - - // link shader program - { - sp.ID = gl.CreateProgram() - gl.AttachShader(sp.ID, sp.vs) - gl.AttachShader(sp.ID, sp.fs) - gl.LinkProgram(sp.ID) - - var status int32 - gl.GetProgramiv(sp.ID, gl.LINK_STATUS, &status) - if status != gl.TRUE { - var buf [65536]byte - var length int32 - gl.GetProgramInfoLog(sp.ID, int32(len(buf)), &length, &buf[0]) - clog := string(buf[:length]) - gl.DeleteProgram(sp.ID) - gl.DeleteShader(sp.vs) - gl.DeleteShader(sp.fs) - return fmt.Errorf("failed to link shader program:\n\n%s", clog) - } - if err := glError(); err != nil { - return fmt.Errorf("gl error after linking shader: %v", err) - } - } - - gl.UseProgram(sp.ID) - var nameBuf [256]byte - var length, size int32 - var xtype uint32 - var count int32 - - // load the attributes - gl.GetProgramiv(sp.ID, gl.ACTIVE_ATTRIBUTES, &count) - sp.attribs = make(map[string]uint32, int(count)) - for i := int32(0); i < count; i++ { - gl.GetActiveAttrib(sp.ID, uint32(i), int32(len(nameBuf)), &length, &size, &xtype, &nameBuf[0]) - name := string(nameBuf[:length]) - loc := gl.GetAttribLocation(sp.ID, &nameBuf[0]) - sp.attribs[name] = uint32(loc) - } - - // load the uniforms - gl.GetProgramiv(sp.ID, gl.ACTIVE_UNIFORMS, &count) - sp.uniforms = make(map[string]int32, int(count)) - for i := int32(0); i < count; i++ { - gl.GetActiveUniform(sp.ID, uint32(i), int32(len(nameBuf)), &length, &size, &xtype, &nameBuf[0]) - name := string(nameBuf[:length]) - loc := gl.GetUniformLocation(sp.ID, &nameBuf[0]) - sp.uniforms[name] = loc - } - - return nil -} - -func (sp *shaderProgram) use() { - gl.UseProgram(sp.ID) -} - -func (sp *shaderProgram) delete() { - gl.DeleteProgram(sp.ID) - gl.DeleteShader(sp.vs) - gl.DeleteShader(sp.fs) -} - -func (sp *shaderProgram) loadLocations(target interface{}) error { - val := reflect.ValueOf(target) - if val.Kind() != reflect.Ptr { - panic("target must be a pointer to a struct") - } - val = val.Elem() - if val.Kind() != reflect.Struct { - panic("target must be a pointer to a struct") - } - - gl.UseProgram(sp.ID) - - var errs strings.Builder - - for name, loc := range sp.attribs { - field := val.FieldByName(sp.structName(name)) - if field == (reflect.Value{}) { - fmt.Fprintf(&errs, "field for attribute \"%s\" not found; ", name) - } else if field.Type() != reflect.TypeOf(uint32(0)) { - fmt.Fprintf(&errs, "field for attribute \"%s\" must have type uint32; ", name) - } else { - field.Set(reflect.ValueOf(uint32(loc))) - } - } - - for name, loc := range sp.uniforms { - field := val.FieldByName(sp.structName(name)) - if field == (reflect.Value{}) { - fmt.Fprintf(&errs, "field for uniform \"%s\" not found; ", name) - } else if field.Type() != reflect.TypeOf(int32(0)) { - fmt.Fprintf(&errs, "field for uniform \"%s\" must have type int32; ", name) - } else { - field.Set(reflect.ValueOf(int32(loc))) - } - } - - if errs.Len() > 0 { - return errors.New(strings.TrimSpace(errs.String())) - } - return nil -} - -func (sp *shaderProgram) structName(name string) string { - rn, sz := utf8.DecodeRuneInString(name) - name = fmt.Sprintf("%c%s", unicode.ToUpper(rn), name[sz:]) - idx := strings.IndexByte(name, '[') - if idx > 0 { - name = name[:idx] - } - return name -} - -func (sp *shaderProgram) mustLoadLocations(target interface{}) { - err := sp.loadLocations(target) - if err != nil { - panic(err) - } -} - -func (sp *shaderProgram) enableAllVertexAttribArrays() { - for _, loc := range sp.attribs { - gl.EnableVertexAttribArray(loc) - } -} - -func (sp *shaderProgram) disableAllVertexAttribArrays() { - for _, loc := range sp.attribs { - gl.DisableVertexAttribArray(loc) - } -} diff --git a/backend/goglbackend/shaders.go b/backend/goglbackend/shaders.go deleted file mode 100755 index 3541189..0000000 --- a/backend/goglbackend/shaders.go +++ /dev/null @@ -1,158 +0,0 @@ -package goglbackend - -var unifiedVS = ` -attribute vec2 vertex, texCoord; - -uniform vec2 canvasSize; -uniform mat3 matrix; - -varying vec2 v_cp, v_tc; - -void main() { - v_tc = texCoord; - vec3 v = matrix * vec3(vertex.xy, 1.0); - vec2 tf = v.xy / v.z; - v_cp = tf; - vec2 glp = tf * 2.0 / canvasSize - 1.0; - gl_Position = vec4(glp.x, -glp.y, 0.0, 1.0); -} -` -var unifiedFS = ` -#ifdef GL_ES -precision mediump float; -#endif - -varying vec2 v_cp, v_tc; - -uniform int func; - -uniform vec4 color; -uniform float globalAlpha; - -uniform sampler2D gradient; -uniform vec2 from, dir, to; -uniform float len, radFrom, radTo; - -uniform vec2 imageSize; -uniform sampler2D image; -uniform mat3 imageTransform; -uniform vec2 repeat; - -uniform bool useAlphaTex; -uniform sampler2D alphaTex; - -uniform int boxSize; -uniform bool boxVertical; -uniform float boxScale; -uniform float boxOffset; - -bool isNaN(float v) { - return v < 0.0 || 0.0 < v || v == 0.0 ? false : true; -} - -void main() { - vec4 col = color; - - if (func == 5) { - vec4 sum = vec4(0.0); - if (boxVertical) { - vec2 start = v_tc - vec2(0.0, (float(boxSize) * 0.5 + boxOffset) * boxScale); - for (int i=0; i <= boxSize; i++) { - sum += texture2D(image, start + vec2(0.0, float(i) * boxScale)); - } - } else { - vec2 start = v_tc - vec2((float(boxSize) * 0.5 + boxOffset) * boxScale, 0.0); - for (int i=0; i <= boxSize; i++) { - sum += texture2D(image, start + vec2(float(i) * boxScale, 0.0)); - } - } - gl_FragColor = sum / float(boxSize+1); - return; - } - - if (func == 1) { - vec2 v = v_cp - from; - float r = dot(v, dir) / len; - r = clamp(r, 0.0, 1.0); - col = texture2D(gradient, vec2(r, 0.0)); - } else if (func == 2) { - float o_a = 0.5 * sqrt( - pow(-2.0*from.x*from.x+2.0*from.x*to.x+2.0*from.x*v_cp.x-2.0*to.x*v_cp.x-2.0*from.y*from.y+2.0*from.y*to.y+2.0*from.y*v_cp.y-2.0*to.y*v_cp.y+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0) - -4.0*(from.x*from.x-2.0*from.x*v_cp.x+v_cp.x*v_cp.x+from.y*from.y-2.0*from.y*v_cp.y+v_cp.y*v_cp.y-radFrom*radFrom) - *(from.x*from.x-2.0*from.x*to.x+to.x*to.x+from.y*from.y-2.0*from.y*to.y+to.y*to.y-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo) - ); - float o_b = (from.x*from.x-from.x*to.x-from.x*v_cp.x+to.x*v_cp.x+from.y*from.y-from.y*to.y-from.y*v_cp.y+to.y*v_cp.y-radFrom*radFrom+radFrom*radTo); - float o_c = (from.x*from.x-2.0*from.x*to.x+to.x*to.x+from.y*from.y-2.0*from.y*to.y+to.y*to.y-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo); - float o1 = (-o_a + o_b) / o_c; - float o2 = (o_a + o_b) / o_c; - if (isNaN(o1) && isNaN(o2)) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); - return; - } - float o = max(o1, o2); - o = clamp(o, 0.0, 1.0); - col = texture2D(gradient, vec2(o, 0.0)); - } else if (func == 3) { - vec3 tfpt = vec3(v_cp, 1.0) * imageTransform; - vec2 imgpt = tfpt.xy / imageSize; - col = texture2D(image, mod(imgpt, 1.0)); - if (imgpt.x < 0.0 || imgpt.x > 1.0) { - col *= repeat.x; - } - if (imgpt.y < 0.0 || imgpt.y > 1.0) { - col *= repeat.y; - } - } else if (func == 4) { - col = texture2D(image, v_tc); - } - - if (useAlphaTex) { - col.a *= texture2D(alphaTex, v_tc).a * globalAlpha; - } else { - col.a *= globalAlpha; - } - - gl_FragColor = col; -} -` - -const ( - shdFuncSolid int32 = iota - shdFuncLinearGradient - shdFuncRadialGradient - shdFuncImagePattern - shdFuncImage - shdFuncBoxBlur -) - -type unifiedShader struct { - shaderProgram - - Vertex uint32 - TexCoord uint32 - - CanvasSize int32 - Matrix int32 - Color int32 - GlobalAlpha int32 - - Func int32 - - UseAlphaTex int32 - AlphaTex int32 - - Gradient int32 - From, To, Dir int32 - Len int32 - RadFrom, RadTo int32 - - ImageSize int32 - Image int32 - ImageTransform int32 - Repeat int32 - - BoxSize int32 - BoxVertical int32 - BoxScale int32 - BoxOffset int32 -} diff --git a/canvas_test.go b/canvas_test.go deleted file mode 100644 index 6d1d7d5..0000000 --- a/canvas_test.go +++ /dev/null @@ -1,657 +0,0 @@ -package canvas_test - -import ( - "fmt" - "image" - _ "image/jpeg" - "image/png" - "math" - "os" - "runtime" - "strings" - "testing" - - "github.com/go-gl/gl/v3.2-core/gl" - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/softwarebackend" - "github.com/tfriedel6/canvas/sdlcanvas" -) - -var usesw = false - -func run(t *testing.T, fn func(cv *canvas.Canvas)) { - var img *image.RGBA - if !usesw { - wnd, cv, err := sdlcanvas.CreateWindow(100, 100, "test") - if err != nil { - t.Fatalf("Failed to create window: %v", err) - return - } - defer wnd.Destroy() - - gl.Disable(gl.MULTISAMPLE) - - wnd.StartFrame() - - cv.ClearRect(0, 0, 100, 100) - fn(cv) - img = cv.GetImageData(0, 0, 100, 100) - } else { - backend := softwarebackend.New(100, 100) - cv := canvas.New(backend) - - cv.SetFillStyle("#000") - cv.FillRect(0, 0, 100, 100) - fn(cv) - img = cv.GetImageData(0, 0, 100, 100) - } - - caller, _, _, ok := runtime.Caller(1) - if !ok { - t.Fatal("Failed to get caller") - } - - callerFunc := runtime.FuncForPC(caller) - if callerFunc == nil { - t.Fatal("Failed to get caller function") - } - - const prefix = "canvas_test.Test" - callerFuncName := callerFunc.Name() - callerFuncName = callerFuncName[strings.Index(callerFuncName, prefix)+len(prefix):] - - fileName := fmt.Sprintf("testdata/%s.png", callerFuncName) - - _, err := os.Stat(fileName) - if err != nil && !os.IsNotExist(err) { - t.Fatalf("Failed to stat file \"%s\": %v", fileName, err) - } - - if os.IsNotExist(err) { - err = writeImage(img, fileName) - if err != nil { - t.Fatal(err) - } - return - } - - f, err := os.Open(fileName) - if err != nil { - t.Fatalf("Failed to open file \"%s\": %v", fileName, err) - } - defer f.Close() - - refImg, err := png.Decode(f) - if err != nil { - t.Fatalf("Failed to decode file \"%s\": %v", fileName, err) - } - - if b := img.Bounds(); b.Min.X != 0 || b.Min.Y != 0 || b.Max.X != 100 || b.Max.Y != 100 { - t.Fatalf("Image bounds must be 0,0,100,100") - } - if b := refImg.Bounds(); b.Min.X != 0 || b.Min.Y != 0 || b.Max.X != 100 || b.Max.Y != 100 { - t.Fatalf("Image bounds must be 0,0,100,100") - } - - for y := 0; y < 100; y++ { - for x := 0; x < 100; x++ { - r1, g1, b1, a1 := img.At(x, y).RGBA() - r2, g2, b2, a2 := refImg.At(x, y).RGBA() - if r1 != r2 || g1 != g2 || b1 != b2 || a1 != a2 { - writeImage(img, fmt.Sprintf("testdata/%s_fail.png", callerFuncName)) - t.FailNow() - } - } - } -} - -func writeImage(img *image.RGBA, fileName string) error { - f, err := os.OpenFile(fileName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777) - if err != nil { - return fmt.Errorf("Failed to create file \"%s\"", fileName) - } - defer f.Close() - - err = png.Encode(f, img) - if err != nil { - return fmt.Errorf("Failed to encode PNG") - } - return nil -} - -func TestFillRect(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFillStyle("#F00") - cv.FillRect(10, 10, 10, 10) - - cv.SetFillStyle("#F008") - cv.FillRect(30, 10, 10, 10) - - cv.SetFillStyle(64, 96, 128, 160) - cv.FillRect(50, 10, 10, 10) - - cv.SetFillStyle(0.5, 0.7, 0.2, 0.8) - cv.FillRect(70, 10, 10, 10) - }) -} - -func TestFillConvexPath(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFillStyle("#0F0") - cv.BeginPath() - cv.MoveTo(20, 20) - cv.LineTo(60, 20) - cv.LineTo(80, 80) - cv.LineTo(40, 80) - cv.ClosePath() - cv.Fill() - }) -} -func TestFillConcavePath(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFillStyle("#0F0") - cv.BeginPath() - cv.MoveTo(20, 20) - cv.LineTo(60, 20) - cv.LineTo(60, 60) - cv.LineTo(50, 60) - cv.LineTo(50, 40) - cv.LineTo(20, 40) - cv.ClosePath() - cv.Fill() - }) -} - -func TestFillHammer(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFillStyle("#0F0") - cv.BeginPath() - cv.Translate(50, 50) - cv.Scale(0.7, 0.7) - cv.MoveTo(-6, 60) - cv.LineTo(-6, -50) - cv.LineTo(-25, -50) - cv.LineTo(-12, -60) - cv.LineTo(25, -60) - cv.LineTo(25, -50) - cv.LineTo(6, -50) - cv.LineTo(6, 60) - cv.ClosePath() - cv.Fill() - }) -} - -func TestDrawPath(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#00F") - cv.SetLineJoin(canvas.Miter) - cv.SetLineWidth(8) - cv.BeginPath() - cv.MoveTo(10, 10) - cv.LineTo(30, 10) - cv.LineTo(30, 30) - cv.LineTo(10, 30) - cv.ClosePath() - cv.Stroke() - - cv.SetLineJoin(canvas.Round) - cv.BeginPath() - cv.MoveTo(40, 10) - cv.LineTo(60, 10) - cv.LineTo(60, 30) - cv.LineTo(40, 30) - cv.ClosePath() - cv.Stroke() - - cv.SetLineJoin(canvas.Bevel) - cv.BeginPath() - cv.MoveTo(70, 10) - cv.LineTo(90, 10) - cv.LineTo(90, 30) - cv.LineTo(70, 30) - cv.ClosePath() - cv.Stroke() - - cv.SetLineCap(canvas.Butt) - cv.BeginPath() - cv.MoveTo(10, 40) - cv.LineTo(30, 40) - cv.LineTo(30, 60) - cv.LineTo(10, 60) - cv.Stroke() - - cv.SetLineCap(canvas.Round) - cv.BeginPath() - cv.MoveTo(40, 40) - cv.LineTo(60, 40) - cv.LineTo(60, 60) - cv.LineTo(40, 60) - cv.Stroke() - - cv.SetLineCap(canvas.Square) - cv.BeginPath() - cv.MoveTo(70, 40) - cv.LineTo(90, 40) - cv.LineTo(90, 60) - cv.LineTo(70, 60) - cv.Stroke() - }) -} - -func TestMiterLimit(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#0F0") - cv.SetLineJoin(canvas.Miter) - cv.SetLineWidth(2.5) - cv.SetMiterLimit(30) - y, step := 20.0, 4.0 - for i := 0; i < 20; i++ { - cv.LineTo(20, y) - y += step - cv.LineTo(80, y) - y += step - step *= 0.9 - } - cv.Stroke() - }) -} - -func TestLineDash(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#0F0") - cv.SetLineWidth(2.5) - cv.SetLineDash([]float64{4, 6, 8}) - cv.BeginPath() - cv.MoveTo(20, 20) - cv.LineTo(80, 20) - cv.LineTo(80, 80) - cv.LineTo(50, 80) - cv.LineTo(50, 50) - cv.LineTo(20, 50) - cv.ClosePath() - cv.MoveTo(30, 30) - cv.LineTo(70, 30) - cv.LineTo(70, 70) - cv.LineTo(60, 70) - cv.LineTo(60, 40) - cv.LineTo(30, 40) - cv.ClosePath() - cv.Stroke() - ld := cv.GetLineDash() - if ld[0] != 4 || ld[1] != 6 || ld[2] != 8 || ld[3] != 4 || ld[4] != 6 || ld[5] != 8 { - t.Fail() - } - }) -} - -func TestLineDashOffset(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#0F0") - cv.SetLineWidth(2.5) - cv.SetLineDash([]float64{4, 6, 8}) - cv.SetLineDashOffset(5) - cv.BeginPath() - cv.MoveTo(20, 20) - cv.LineTo(80, 20) - cv.LineTo(80, 80) - cv.LineTo(50, 80) - cv.LineTo(50, 50) - cv.LineTo(20, 50) - cv.ClosePath() - cv.MoveTo(30, 30) - cv.LineTo(70, 30) - cv.LineTo(70, 70) - cv.LineTo(60, 70) - cv.LineTo(60, 40) - cv.LineTo(30, 40) - cv.ClosePath() - cv.Stroke() - ld := cv.GetLineDash() - if ld[0] != 4 || ld[1] != 6 || ld[2] != 8 || ld[3] != 4 || ld[4] != 6 || ld[5] != 8 { - t.Fail() - } - }) -} - -func TestCurves(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#00F") - cv.SetLineWidth(2.5) - cv.BeginPath() - cv.Arc(30, 30, 15, 0, 4, false) - cv.ClosePath() - cv.MoveTo(30, 70) - cv.LineTo(40, 70) - cv.ArcTo(50, 70, 50, 55, 5) - cv.ArcTo(50, 40, 55, 40, 5) - cv.QuadraticCurveTo(70, 40, 80, 60) - cv.BezierCurveTo(70, 80, 60, 80, 50, 90) - cv.Stroke() - }) -} - -func TestAlpha(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#F00") - cv.SetLineWidth(2.5) - cv.BeginPath() - cv.Arc(30, 30, 15, 0, 4, false) - cv.ClosePath() - cv.MoveTo(30, 70) - cv.LineTo(40, 70) - cv.ArcTo(50, 70, 50, 55, 5) - cv.ArcTo(50, 40, 55, 40, 5) - cv.QuadraticCurveTo(70, 40, 80, 60) - cv.BezierCurveTo(70, 80, 60, 80, 50, 90) - cv.Stroke() - - cv.SetStrokeStyle("#0F08") - cv.SetLineWidth(5) - cv.BeginPath() - cv.MoveTo(10, 10) - cv.LineTo(90, 90) - cv.LineTo(90, 10) - cv.LineTo(10, 90) - cv.ClosePath() - cv.Stroke() - - cv.SetGlobalAlpha(0.5) - cv.SetStrokeStyle("#FFF8") - cv.SetLineWidth(8) - cv.BeginPath() - cv.MoveTo(50, 10) - cv.LineTo(50, 90) - cv.Stroke() - }) -} - -func TestClosePath(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#0F0") - cv.SetLineWidth(2.5) - cv.BeginPath() - cv.MoveTo(20, 20) - cv.LineTo(40, 20) - cv.LineTo(40, 40) - cv.LineTo(20, 40) - cv.ClosePath() - cv.MoveTo(60, 20) - cv.LineTo(80, 20) - cv.LineTo(80, 40) - cv.LineTo(60, 40) - cv.ClosePath() - cv.Stroke() - - cv.SetFillStyle("#00F") - cv.BeginPath() - cv.MoveTo(20, 60) - cv.LineTo(40, 60) - cv.LineTo(40, 80) - cv.LineTo(20, 80) - cv.ClosePath() - cv.MoveTo(60, 60) - cv.LineTo(80, 60) - cv.LineTo(80, 80) - cv.LineTo(60, 80) - cv.ClosePath() - cv.Fill() - }) -} - -func TestLineDash2(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#0F0") - cv.SetLineWidth(2.5) - cv.BeginPath() - cv.MoveTo(20, 20) - cv.LineTo(40, 20) - cv.LineTo(40, 40) - cv.LineTo(20, 40) - cv.ClosePath() - cv.MoveTo(60, 20) - cv.LineTo(80, 20) - cv.LineTo(80, 40) - cv.LineTo(60, 40) - cv.ClosePath() - cv.SetLineDash([]float64{4, 4}) - cv.MoveTo(20, 60) - cv.LineTo(40, 60) - cv.LineTo(40, 80) - cv.LineTo(20, 80) - cv.ClosePath() - cv.MoveTo(60, 60) - cv.LineTo(80, 60) - cv.LineTo(80, 80) - cv.LineTo(60, 80) - cv.ClosePath() - cv.Stroke() - }) -} -func TestText(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFont("testdata/Roboto-Light.ttf", 48) - cv.SetFillStyle("#F00") - cv.FillText("A BC", 0, 46) - cv.SetStrokeStyle("#0F0") - cv.SetLineWidth(1) - cv.StrokeText("D EF", 0, 90) - }) -} - -func TestConvex(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFillStyle("#F00") - cv.BeginPath() - cv.MoveTo(10, 10) - cv.LineTo(20, 10) - cv.LineTo(20, 20) - cv.LineTo(10, 20) - cv.LineTo(10, 10) - cv.ClosePath() - cv.Fill() - - cv.SetFillStyle("#0F0") - cv.BeginPath() - cv.MoveTo(30, 10) - cv.LineTo(40, 10) - cv.LineTo(40, 15) - cv.LineTo(35, 15) - cv.LineTo(35, 20) - cv.LineTo(40, 20) - cv.LineTo(40, 25) - cv.LineTo(30, 25) - cv.ClosePath() - cv.Fill() - - cv.SetFillStyle("#00F") - cv.BeginPath() - cv.MoveTo(50, 10) - cv.LineTo(50, 25) - cv.LineTo(60, 25) - cv.LineTo(60, 20) - cv.LineTo(55, 20) - cv.LineTo(55, 15) - cv.LineTo(60, 15) - cv.LineTo(60, 10) - cv.ClosePath() - cv.Fill() - - cv.SetFillStyle("#FFF") - cv.BeginPath() - cv.MoveTo(20, 35) - cv.LineTo(80, 35) - cv.ArcTo(90, 35, 90, 45, 10) - cv.LineTo(90, 80) - cv.ArcTo(90, 90, 80, 90, 10) - cv.LineTo(20, 90) - cv.ArcTo(10, 90, 10, 80, 10) - cv.LineTo(10, 45) - cv.ArcTo(10, 35, 20, 35, 10) - cv.ClosePath() - cv.Fill() - }) -} - -func TestConvexSelfIntersecting(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFillStyle("#F00") - cv.BeginPath() - cv.MoveTo(33.7, 31.5) - cv.LineTo(35.4, 55.0) - cv.LineTo(53.0, 33.5) - cv.LineTo(56.4, 62.4) - cv.ClosePath() - cv.Fill() - }) -} - -func TestTransform(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - path := cv.NewPath2D() - path.MoveTo(-10, -10) - path.LineTo(10, -10) - path.LineTo(0, 10) - path.ClosePath() - - cv.Translate(40, 20) - cv.BeginPath() - cv.LineTo(10, 10) - cv.LineTo(30, 10) - cv.LineTo(20, 30) - cv.ClosePath() - cv.SetStrokeStyle("#F00") - cv.Stroke() - cv.SetStrokeStyle("#0F0") - cv.StrokePath(path) - cv.Translate(20, 0) - cv.SetStrokeStyle("#00F") - cv.StrokePath(path) - cv.Translate(-40, 30) - cv.BeginPath() - cv.LineTo(10, 10) - cv.LineTo(30, 10) - cv.LineTo(20, 30) - cv.ClosePath() - cv.Translate(20, 0) - cv.SetStrokeStyle("#FF0") - cv.Stroke() - cv.Translate(20, 0) - cv.SetStrokeStyle("#F0F") - cv.StrokePath(path) - }) -} - -func TestTransform2(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetStrokeStyle("#FFF") - cv.SetLineWidth(16) - cv.MoveTo(20, 20) - cv.LineTo(20, 50) - cv.Scale(2, 1) - cv.LineTo(45, 80) - cv.SetLineJoin(canvas.Round) - cv.SetLineCap(canvas.Round) - cv.Stroke() - }) -} - -func TestImage(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.DrawImage("testdata/cat.jpg", 5, 5, 40, 40) - cv.DrawImage("testdata/cat.jpg", 100, 100, 100, 100, 55, 55, 40, 40) - cv.Save() - cv.Translate(75, 25) - cv.Rotate(math.Pi / 2) - cv.Translate(-20, -20) - cv.DrawImage("testdata/cat.jpg", 0, 0, 40, 40) - cv.Restore() - cv.SetTransform(1, 0, 0.2, 1, 0, 0) - cv.DrawImage("testdata/cat.jpg", -8, 55, 40, 40) - }) -} - -func TestGradient(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.Translate(50, 50) - cv.Scale(0.8, 0.7) - cv.Rotate(math.Pi * 0.1) - cv.Translate(-50, -50) - - lg := cv.CreateLinearGradient(10, 10, 40, 20) - lg.AddColorStop(0, 0.5, 0, 0) - lg.AddColorStop(0.5, "#008000") - lg.AddColorStop(1, 0, 0, 128) - cv.SetFillStyle(lg) - cv.FillRect(0, 0, 50, 100) - - rg := cv.CreateRadialGradient(75, 15, 10, 75, 75, 20) - rg.AddColorStop(0, 1.0, 0, 0, 0.5) - rg.AddColorStop(0.5, "#00FF0080") - rg.AddColorStop(1, 0, 0, 255, 128) - cv.SetFillStyle(rg) - cv.FillRect(50, 0, 50, 100) - }) -} - -func TestImagePattern(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.Translate(50, 50) - cv.Scale(0.95, 1.05) - cv.Rotate(-math.Pi * 0.1) - - cv.SetFillStyle("testdata/cat.jpg") - cv.FillRect(-40, -40, 80, 80) - }) -} - -func TestImagePattern2(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - ptrn := cv.CreatePattern("testdata/cat.jpg", canvas.NoRepeat) - ptrn.SetTransform([6]float64{0, 0.1, 0.1, 0, 0, 0}) - - cv.Translate(50, 50) - cv.Scale(0.95, 1.05) - cv.Rotate(-math.Pi * 0.1) - - cv.SetFillStyle(ptrn) - cv.FillRect(-40, -40, 80, 80) - }) -} - -func TestShadow(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - cv.SetFillStyle("#800") - cv.SetShadowColor("#00F") - cv.SetShadowOffset(6, 6) - cv.FillRect(10, 10, 60, 25) - cv.SetShadowBlur(6) - cv.FillRect(10, 55, 60, 25) - cv.SetFillStyle("#0F0") - cv.SetShadowColor("#F0F") - cv.SetGlobalAlpha(0.5) - cv.FillRect(50, 15, 30, 60) - }) -} - -func TestReadme(t *testing.T) { - run(t, func(cv *canvas.Canvas) { - w, h := 100.0, 100.0 - cv.SetFillStyle("#000") - cv.FillRect(0, 0, w, h) - - for r := 0.0; r < math.Pi*2; r += math.Pi * 0.1 { - cv.SetFillStyle(int(r*10), int(r*20), int(r*40)) - cv.BeginPath() - cv.MoveTo(w*0.5, h*0.5) - cv.Arc(w*0.5, h*0.5, math.Min(w, h)*0.4, r, r+0.1*math.Pi, false) - cv.ClosePath() - cv.Fill() - } - - cv.SetStrokeStyle("#FFF") - cv.SetLineWidth(10) - cv.BeginPath() - cv.Arc(w*0.5, h*0.5, math.Min(w, h)*0.4, 0, math.Pi*2, false) - cv.Stroke() - }) -} diff --git a/examples/android/CanvasAndroidExample/.gitignore b/examples/android/CanvasAndroidExample/.gitignore deleted file mode 100644 index 5edb4ee..0000000 --- a/examples/android/CanvasAndroidExample/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -.DS_Store -/build -/captures -.externalNativeBuild diff --git a/examples/android/CanvasAndroidExample/.idea/caches/build_file_checksums.ser b/examples/android/CanvasAndroidExample/.idea/caches/build_file_checksums.ser deleted file mode 100644 index 1ddb89481ae9584a857940ab3c4ca02377a1799b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 534 zcmZ4UmVvdnh`~NNKUXg?FQq6yGexf?KR>5fFEb@IQ7^qHF(oHeub?PDD>b=9F91S2 zm1gFoxMk*~I%lLNXBU^|7Q2L-Ts|(GuF1r}Dy7ofWYL2`N^IX#cW;tZfX zEBmd3hs6>uGBYr_F>vMNC#JY1CYR(Fc`|U8WE7RMT=5I{ zxS%!bmA_V8QCw4h)!}vtgQ|W;er~FM36MzDhZ?Sr2yYA%uE_S>>}S}-^0I+*#+x5b zbtMdfcvK7QE( - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/.idea/encodings.xml b/examples/android/CanvasAndroidExample/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/examples/android/CanvasAndroidExample/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/.idea/gradle.xml b/examples/android/CanvasAndroidExample/.idea/gradle.xml deleted file mode 100644 index 7ac24c7..0000000 --- a/examples/android/CanvasAndroidExample/.idea/gradle.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/.idea/misc.xml b/examples/android/CanvasAndroidExample/.idea/misc.xml deleted file mode 100644 index dc34569..0000000 --- a/examples/android/CanvasAndroidExample/.idea/misc.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/.idea/runConfigurations.xml b/examples/android/CanvasAndroidExample/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/examples/android/CanvasAndroidExample/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/.idea/vcs.xml b/examples/android/CanvasAndroidExample/.idea/vcs.xml deleted file mode 100644 index c2365ab..0000000 --- a/examples/android/CanvasAndroidExample/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/app/.gitignore b/examples/android/CanvasAndroidExample/app/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/examples/android/CanvasAndroidExample/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/examples/android/CanvasAndroidExample/app/build.gradle b/examples/android/CanvasAndroidExample/app/build.gradle deleted file mode 100644 index 540fa7d..0000000 --- a/examples/android/CanvasAndroidExample/app/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 26 - defaultConfig { - applicationId "com.example.canvasandroidexample" - minSdkVersion 15 - targetSdkVersion 26 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation fileTree(dir: 'libs', include: ['*.aar']) - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' -} diff --git a/examples/android/CanvasAndroidExample/app/proguard-rules.pro b/examples/android/CanvasAndroidExample/app/proguard-rules.pro deleted file mode 100644 index f1b4245..0000000 --- a/examples/android/CanvasAndroidExample/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/examples/android/CanvasAndroidExample/app/src/androidTest/java/com/example/canvasandroidexample/ExampleInstrumentedTest.java b/examples/android/CanvasAndroidExample/app/src/androidTest/java/com/example/canvasandroidexample/ExampleInstrumentedTest.java deleted file mode 100644 index 39b7560..0000000 --- a/examples/android/CanvasAndroidExample/app/src/androidTest/java/com/example/canvasandroidexample/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.canvasandroidexample; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.example.canvasandroidexample", appContext.getPackageName()); - } -} diff --git a/examples/android/CanvasAndroidExample/app/src/main/AndroidManifest.xml b/examples/android/CanvasAndroidExample/app/src/main/AndroidManifest.xml deleted file mode 100644 index ab15940..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/app/src/main/java/com/example/canvasandroidexample/MainActivity.java b/examples/android/CanvasAndroidExample/app/src/main/java/com/example/canvasandroidexample/MainActivity.java deleted file mode 100644 index c6c10fb..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/java/com/example/canvasandroidexample/MainActivity.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.example.canvasandroidexample; - -import android.app.Activity; -import android.opengl.*; -import android.os.Bundle; -import android.view.MotionEvent; -import android.view.View; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import canvasandroidexample.Canvasandroidexample; - -public class MainActivity extends Activity implements GLSurfaceView.Renderer { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - GLSurfaceView view = new GLSurfaceView(this); - view.setEGLContextClientVersion(2); - view.setEGLConfigChooser(8, 8, 8, 8, 0, 8); - view.setRenderer(this); - view.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - int x = Math.round(event.getX()); - int y = Math.round(event.getY()); - if (event.getAction() == MotionEvent.ACTION_DOWN) { - Canvasandroidexample.touchEvent("down", x, y); - } else if (event.getAction() == MotionEvent.ACTION_UP) { - Canvasandroidexample.touchEvent("up", x, y); - } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - Canvasandroidexample.touchEvent("move", x, y); - } - return true; - } - }); - setContentView(view); - } - - @Override - protected void onResume() { - super.onResume(); - } - - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - Canvasandroidexample.onSurfaceCreated(); - } - - @Override - public void onSurfaceChanged(GL10 gl, int width, int height) { - Canvasandroidexample.onSurfaceChanged(width, height); - } - - @Override - public void onDrawFrame(GL10 gl) { - Canvasandroidexample.onDrawFrame(); - } -} diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/examples/android/CanvasAndroidExample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c3903ed..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/drawable/ic_launcher_background.xml b/examples/android/CanvasAndroidExample/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 5713f34..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index bbd3e02..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index bbd3e02..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f5908281d070150700378b64a84c7db1f97aa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3056 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 axPAxe%7rDusX+w*00006jj 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⁣ zwiG+x#%j}{0gU~J8;<|!B1@-XaB@{KORFwrYg_8rOv({b0EO#DbeQRm;B6_9=mXGf z-x|VL{zd`)#@yN}HkCSJbjbNlE|zL3Wm9Q8HY`sV)}3%pgN>cL^67{Z;PPL(*wT8N zUjXU{@|*hvm}({wsAC=x0^ok0%UAz0;sogW{B!nDqk|JJ5x~4NfTDgP49^zeu`csl?5mY@JdQdISc zFs!E{^grmkLnUk9 zny~m)1vws@5BFI<-0Tuo2JWX(0v`W|t(wg;s--L47WTvTMz-8l#TL^=OJNRS2?_Qj z3AKT+gvbyBi#H*-tJ%tWD|>EV3wy|8qxfzS!5RW;Jpl5*zo&^UBU=fG#2}UvRyNkK zA06Dy9;K1ca@r2T>yThYgI!ont$(G{6q#2QT+00r_x0(b)gsE`lBB?2gr55gq^D3Fi&p%E(p9>U%bv zkg1Jco(RbyTX7FDHOnl7-O@ zI$AaIl?9NJKPm(WiBP`1-#CB1QzU>&hKm)fpa5DKE{2$X0hGz-0uZ?cyTk(YC!Y&| zL=1VrNERSA5NA2jq7FACfX4JfPyj5XXl1yv0>~s;eF7L2$>&oMqeTFT2m$y7FlkON z_yurD1yIOvA;5C6016pyxBznGUt0kJ&k5r#;&>Jow`r)sp9R~PmK~lz$3xH%LT*1U zJdOyABZ3!FvNoR*vN$5ykHS8f`jA4zV+|L}i1C4`B2c{R0;UdYxaU|H)2avz@ z=mEYc|2S<+(B2Tj+FkX+2D+yFI!k9lWMA61DJ{)e;lum$(;O87?vGJJe!KtK04+N_ zI*P~t@dUb>9Xh{dbyl{-ZQ(UMgz7$|QfL5XSPkskt^NgctYC#;4WcZB1@%@wy@2t3 z2z0DI7&%b$*Aw~abe?GxE`ez@+6hOh-6*8fHRV{1os$EL@}uUZeG4h1&Be`98q*7j z=3-v+lhIjfWVo12!<>%V^a6lTgW3+_#W6n|p*~==zOH7z$0{LSZk(Tpd7EaD04hnA zL;#fxS0aD{`5^&D`}>0Uq?byDD-l2=!wm_bLcUl4gc(% za1p|itVANvFF>hghAS07Im1;IK;|b*W)}VDyI;BIp2=K*yu2a)j?B|f<44NI$NbmJ z#dE0>jI$fMr&@>4kN8MLFb4&2O9fEKaQg%(QO$4_1rVQywG^CmBLh#}_7gKW3vd?| z2?1^&KWq8}8I^_S0|)MowU_pw$q@nl@Nkn$z>BQq_KA^9yaR`(R3u{{Ig;cwt z@AJ^{ODQCm^neroM9nKNUAXi9RCK`OsP_LuR0PUR(YZCCX5dNF6VzcoK&=b^r`W?ltt|*F zpkoae%ZT{C1h~EcFui~b7fF`vb<<~j_VquuUA$}QqIKYELPp#;{u?q8Dz}WAG-(3; zjrm$i%7UbyZMM(Y{>!uJ#vNB?R~B{6Htp=>e*<{fQQ5W7V(1coCWlOON!MzZxhum| ztZBQpGR z;~#ur^&PockKdV{Q6R>o`Pl{0x!DEbpZ7y9Y;*ZvE!*gU`V1W3znva{f=?WO5I&>B z&hw6}tjECtaghm5z|C#%M;Yf_*pI^};h}Vl=^r9EN=tVDj86D;C$jIJ?K7VP+00000NkvXXu0mjf D5i!M* diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d3ae0d3943ab44cdc27feef9256dc6d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7098 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 diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe024be86e868d14e91120a6902f8e88ac6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6464 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 B0*L?s diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a1b15ff180f3dacac19395fe3046cdec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10676 zcmV;lDNELgP)um}xpNhCM7m0FQ}4}N1loz9~lvx)@N$zJd<6*u{W9aHJztU)8d8y;?3WdPz&A7QJeFUv+{E$_OFb457DPov zKYK{O^DFs{ApSuA{FLNz6?vik@>8e5x#1eBfU?k4&SP;lt`%BTxnkw{sDSls^$yvr#7NA*&s?gZVd_>Rv*NEb*6Zkcn zTpQm5+>7kJN$=MTQ_~#;5b!%>j&UU=HX-HtFNaj*ZO3v3%R?+kD&@Hn5iL5pzkc<} z!}Vjz^MoN~xma>UAg`3?HmDQH_r$-+6~29-ynfB8BlXkvm55}{k7TadH<~V$bhW)OZXK@1)CrIKcRnSY`tG*oX}4YC&HgKz~^u7 zD?#%P?L~p~dt3#y(89y}P;ij|-Z#KC;98PvlJCjf6TQbsznsL8#78n~B_kaQl}nsm zLHr7z%-FAGd=-!e?C{q62x5i4g4hNuh)LeqTa4ynfC4h(k*e>okrBlLv;YG%yf8!6 zcN)a^5>rp^4L+myO70z(0m`D}$C(eqfV1GpzM+%$6s6$?xF>~%Gzx|$BUZ$=;f)B8 zoQUrc!zB4kT!wqSvJ=ywY-W)3364w!`U>J+49ZE`H~+{!gaM)zFV!?!H+)k8BnOj3 zGvU93auN}g?X^8c`+PFv|EH=R%m)iUN7gssWyTD~uv7prl1iRfRaCFeJUuA@$(p&K z?D+cmhxf`n9B~!?S#d*TeLb^(q~VYS$3KhjfwfMWtZx&PlTZ(i@5HJ?of_Q)0YX99 z35b?W>?=vlb6gtK1ydcF4<@aH|Hgj8r?~QNOPx(YoKT^Xn=?Q%=1uA&-G(}mXdtsT zQuKACS|@G@uBW(SY(cH%% zq+xr%bpGqOGHyw3=8K7;J&hp^g1UsyG zYT24BGeGQukP?&TlOBE2H$2oH>U#E>GtI-fmc)17uc`7FRxJ3A!c%ADN^Z^oi6tYp zjzE+a{r&jt6z^scbd(feWPVEE!lV1I4lfdLhQ|yLdx&1IEV%l1erB&H8X}3=8lIcc zCNPUis-KRbCC z20@WYl&vVEZo!fLXxXs?{|<|Z=>0^-iX;y6{DT$lSo8b|@FZM3U$+W37(A_9<)fnq zP~11?(AKlHI-Lh(`?-@S?(1{t16bc7ESX->9twFP@t8_XK$XxuSFF#R(g7H(U%XvWa zm}J>%4-suYL=gX7-_MsjD27o?I!G888fxV$koLCfOv+Da&OVTG*@(aC9lz_e>*UGS zrX6f-45hd55ya-p_O{FbHEG%Ee9~i(H-B3RZkv`0ZDn$!>MigMZX06&y3RSk-WnL-{cM1 z1TZr|rc*Xaf|_^y&YLc4KK3<@aWfge2jARbRRg1DfJ~%pV9L_@$UADw3EXC_n%p0v zQO*{=88K@W{T?$wCR#S!M!e+R$aDL~EzovN7pbOBvrk&&ASS=Z43No|jrc>}aXXO5 zrd1<|Qypq-h#J*iORN@8YRc&`17u=lqo&L&YV%p#hL%P*WfIfH%ZUC^o#`?IWWr?w zQ^?EgP7!lqlq}ZM}d*sSVz(mqeQrA_huV@M4iwXa>k+%O-ZHW44JrRxLJy zLoHTuEqw(sMcO38n*lQ6ve97<&+Y50NNmVpW{hed@5EgrWfI~ITFJ0D(<|k)ag-~cV z0@-#S9z8&EUfBL7C_53YJ$)2ix^)vhsH;Q&KDdwe{q{2oJ#~b@#Qr?YGHrh;`rz<> z)F&rNr}J@}p8^N(8hLRH`=jpeT@y z2v7WETpnG{qixxkWWyK7(3QJ)RF-$=`O^k3+oY;O;rNnl^kVc*(j(Jb_99(Dw1w;T z4K8fsKDzn|epoWT|5{~*3bCC1>nd5;@=5lApq%3>^U_gQD>5j-O@WH;uEG+4MSBjJkdgtP;JG2`S&&Sa#_w33(yyAux~lnp7>wMXzD4yy_2#Vh+7&WMkWFl9Ohq06ifTiMWIC(|1Fe(3n}U_0(+jGC_(1c@X4vzk6y`)qzH+WXtj>dhI3=)~1Oi0Omh z^vp^i61ge1rO8;F~ncj_=tk zIvnwqFB-?)jER5LdQ?Hi=Kv5dgPZx%XSjc8VLCd4yYK4E88pIi4AGWzwdmrFf6&AF zI-`N3cpnf!Klj%)afJEC-x{^po?kDKD0@>6(}1f2xkCOMS49E?+5^EenLUrqK%EANgiQdAy8BW0e}Fvw`>)CTcvBeX6ZgjWC~(KdFE9hv+M6*t z?loxF7N3yv+}r*v(>9DX;0V1TP3G)L5r}m~e)RO*pc zv#tyehrK*U7ilRPA zk!aAmm9v3`z|hH7+WJ41!*h~g<2G1sUubFoL9b?dbp>%)pHzUZ-n)Z)W(6jh>jY-3 zUq&n%9=y?`ajN7rr3`t68sL^H^MG_rUDQw2$gj4Jb8MXgAW99^EbKmu9*Pv4Rh3=;vUVF30sUrdj!_n0*+m?WCbo^8q2fo|;?vH3OFh4__< zyaqNQdP4&Q+6R)%gv|^b#b|oW*XMMKLhEgy7(3D!poW*Tk`Qn4f*HUBD@U4+eOL|4 zh+hT+hl`Hx6+v(dZi=hGf|lF9JV};bs&Bm{THmunMOu))>8UdnTYV%TFdKB!dzN+?+5S+WYI><_z_6eDC z+WvMv78tB-j%G_;_de;{^Q7!t>Khj7gp^izaCK?7PmUiHevBXbk=s8{114AjWHDj{ z_(0ZvDUl`5mu8_cWw}Ba6$W+4RbZ4H97I^qQrq9Yd$5A!1wSqDNaUXf_sQ%GF7*wX zXFhfrz!d7zZiDhtgk#HcP(aukNVacB**=V7u3*Xwp&aR_R8vnbd1PGG6$}j(F_VMA?KUK~Jd?J)TjC!h3~KL|i&IYtL40AFtv zb_DC5Vt8aT6JhF5fEI0_FM#^zCX2>a=A#}FVOKjnH_(#+q}Ggy0kU*_?=3Ifjr+H$ z0D{~ZO<8+Sll*k^U-Y6DvsCpBP|v8XH*H@U(US~mumH%)dBJRde1f|G&@1J+MvVi( zla}?vMV%}C?xRQOryKvG8`v3bs)mPaL*v7}=z1;z?uq)tAg6HwY9Ihbhu^awAJU&S zK#m{H4)PVmJ!}eqpy%MRP$Pe(&D;?N7($!Oz=8uTxRyl1Wg*V=gE z5PBge1q~I%qmY6Ol#1^O?u~P=44?CDh*GEXjSmoi`y;!_V+I2o>H!jms@u4HII9l^ z=&`W@f)v#1KQ8O!bY@+=fC3VBA@A7jQt^q~fz}*7i0(grY=jujW3=vAHS&qyN!B3* z;l=MjJrW~O7Sz5xp2Z?EtA`naLM239gw8Ub=%IHPY<00fb5 zozf%j+(s|urpUn~5r5pE7yi0taDcx4`#K81u*kwAk(cvQ$vx_F{wd}8h=eKDCE$M(iD9_QGJh zr0e(Z>QuRZ+`ff^GZPu%;bA#_^$&vsboSa6V!jmN0SV4dBKN4v`C)aESBtZV7J~U( zOc3e47Zx3Ux67y(o?#7;!=y1jxEueEF#$^c_PoxG_pq)GZLU2`d>%!3rdJjkrAK!2 z!2>jNPceo_9v)xpmu)_EgxsU9*GT^QoERVik+LSzH$Z{Ax7_GFY+!HA0MSfDyXT(k z?vob%yRiU**{7No8PKK&w77Z?8j#9IJ#hv1O^!lS%kt0n7@x79#}+R-TuINbiBfotv)O^y=kD0AkUNhrP$U_@qXE zYpkIR$Zgi=#6Os0^$m7rt1kV3&R~;r&xn%>8xzDHk!yob^vyrl^*R$4R_u5eYdHc> zk}^bkAIjLe{t{-Q8+D@9&dz9Q;o$+RGT7l8sx<~c5IBs*Dp_bAwqQRM2olfEe}Vk4 zc9Vt3hx$Z%0|;xNF=aW(Z*%CEmg_ z-riR#1Wjb9t+D^_K$%|E`_m#&XHzQ*&~vzFCzYIJB6Ieap%urgb=%UsC<9^hC4{(B z(3+*N>|JNdhT54KE$HT~okqq-teADE3Vn9^sA!>%+fb|98XIO zePvP!J8>9Ao~cC(u@>UqZhO(v+C!ob_m!fdtCwsACbR*lqtAwwQ@{hCy1%pm)*>|2 z*4U}vUNFO;Lw9~?Rw9)osm$D4f)?XmUvN$e8eWjjsm+Gr-@$~6iMgqWH+%YAV1gAu z7NbW)FU+RvtZ75ADtlW83vAW@YkP-BMr{8tV}A+L9?({@=u8(K9O&F z4CiS*&nHDa>J}36GR;VAs~I41Kfit308jVeg0#zIVj;(cr8EHqE6<OP0C9kbOl`)daY)$O<0J;;?A%Ve z&#H!_rNfB84*1o6aD2oLL(Ywd^#ZTmyK9Dlqg=at2TjDGCcH@qymjUqbf4FvGxc*ap|#6x@}Ug@+NK z6j_PV43T(wmxf+(J5kT~r++|VKw>6X0o1~R#{);Yll!>QeP1cfzTvOK0-Ndpf;nGz znqZirxrk&)Llzz-fKnnEL_I{Lt#O<8-0}IX?!m#sfdv{wY{3p7aF*=sI^w@wUdl;1 zOaQ`8mA(OjeI_2&*O_79989c3v-g+F!6OGyYBVD}5>W|JMvMsd5c6BV0+zUQBP_6V zpc@@&KR+A%>NFy5N0^}idafWHEjUnt=I<|KC5!NPqrW(T!j9Ll{*5Zxa^f&K*Ftjr zawS=CfJrKpWc85)DE8bbv=YBAz#5gkRLaSR_+g6q@-*6f>L^-JT`4CEtE*JX@Z1zF z0E&{AR0fE|??ogjZqfU3(3!I1@j9|~pd0<5UcI0vX5Z_hd1HMA@j|Yv)N2|G^GS;q zXYi@WB9s-#b)He4kH+MtvHHF`8K0kl-oxkemC0RJl}RX;os2R(GXc%6Dn>&D@rZ}- zPb!J(Btl-2B2W+9n6vkmpjV4Bl?F&viUK%NfXXmH_#u%8D2iDWAcFW0m@khVp9{N9 z7&DbP(1Gk7XhlD$GZqiugk2XTu>nJ*bAY;J1CcQR(gq#?Wq4+yGC*3wqY5A{@Bl2z z0I7yYB2tLJe5Lb|+h?DCkK5jdFd$~3g?0d0ShVgG6l4p2kXQKH?S=$M3{jLui1Y>! zz77*W+QP#K5C?de0OAUdGC-Q)A%ZOd%_kz}%W2+>L}>etfq`~pMyi$o5kJUY><4vq zdT;7z-}KnW2H$K&gE`X+Kok~5fVjY;1Q17f6amr&9##OQG7B#?nzXIwwheWiM!)a| zv^^L9r_m3B3^W^?E?~yI`Qf!(wU9Ow3)Pu3odJ?DRk8qag@-*r>fw?ty;X?M?5GeGW6VdRS@X}kbfC>Ph0tSHC!=o7> zcJP1%;)e#h-i!cg0S|z}2#|Ws1LjKvukP!X{cY{zF$mh+!rtD7tND^MV;y)-ur`c4 zFKkU>&&+tOw*1y*YwVu5X8==z0UVItNs(wyMIoAiwTI+0%@V;VuNP&ZIh92y2&-(k zMi0;exUrZe67@)CmgjR)(0ttRFy~A9c}gUif~+K|%mVQAO^-$M_Lq|w4!my^J_<}z zA?b<|Lu5*2A)0rv67|lAMLqF*s7KWjivr(f4{^A5$f4qjg zmxyepp;Y!W2-Y|f2|IZNMV_rib8+3xIZ#3BP@Ul4G|a88M6V}A)%k~vnh0%eYirwy zYwt@rDs5q5-M(vANBrvba>DMCi52-;ZT+q5*4X2*N*nu4*&?uY&0IEM1_>fN{*6zdU!wDfFIgPxZWn<9+^rhhu0i5u{>8eHa7)5yJ`s} z&wJ6fw${~r$vM*&uCCxryLOp0cDzs0u6k{{^!ivQ8f-O~8dg3KgU_SbRiA)C08Qiv zzKj+=kD{M5JWJLGV(;@P`ZkfJkBl^sz+u>GVaJz7K;+rg z!o@{r=UEY;R%DelCy0#G3URLBevOL)`* zqy;>(0F74#5KDMKCSwZ$ri&3ES$H7!lg1Z%!6v&4XYGNurEM%p9@7gz5@*`VqGLzU zLT+15_Xc^?TikPBx22wj=^SZ zs}Z0G&hW4Wh|SoR5uCl&CJhu&k`der5ui5sCU4Xu6TeIXd)x3=z%U;RBc ztv*7s+cIP7jSY}0h}ev6NdZcX;0%u}Krp$FD?Ca7=>U&BKrt%d;n#!acKLYTY21bZ zv@JUu!uL_#BXe+Yf|!Brh+$)}DSJRnnTjC}Ljoio_TWn)VmmNO0IF00kQSrrFee?R z7Bc~)&8WJ1fTFY-RVM%)WCnDP(H}A& zhBl&Y)kS8&w1q_z9gU_85|G-ofg9`TvUE|dcg!}aDQgOV5Q)DNUCuQ)WYLDoh0la$WgJ4Rotv zl73SGB!!5ft4;u_0)Tewlu1aIlv4$e7NhEr2*wDImhcdODhmiee(7;S&)u7m^TJuj zaGUfdZDVciLfWbcO&60EYDq)jov~-{4mK7`pYEYc&w@icvLv$}mP~63fQaCyo2Ss* zQVo!HDH$pO(lRB35g-omfawMe^nP_^y$^poa`|Z9SFjm3X%lhVbe0*eXklR@hpazj z*S1q9FNjjxxVQ}d->$7c!mNdD=TFtot*O#!`|xS|OHuf_lO(fI+uy#9pUO$a*#sOA z$Rylwv>Hv8d{!)xY^h8tQ6spaLFVi$MVo35lV#;3pFwgMqm(I19?9JSfizUeB!pxz zcn=V0Ex3&Ey6Qwt{o0znXyk^^eztLT9tLee+r-Wk{2opI5JWWXJ32UktqpML9XRs6 z#MobUojQtE)E=tWWgF@baOJ{w)?sH(aQZ!{b=ZagG!MYD6E_&Z4eyD-|6~MGQ5j`# z30VOQ`vMH%@f}La~!CD6da+o0vbz|)znwna{EC?cc;6-Qy+!o+g*weOYZHn;7XD^B!GzUq~%s$X>)e$w?x< z)Z{%y9JjKLLjf7F$S-*}(L4YTB*B9jlapkLL@J3tktnH*$W0;n%wWo3O+r{wMM+Xs z312FZ01r9LkcJA*uaczmNv}$!;O~IX;}g9Njo7gI5`{<7<8q*FVrk0oC=PXy=|H#u zKz|QgXXl|oYge50=7$rDoC!A zwmuJZ)k$wFA`CfyIQN20w{F8JJU+C?)xnrU75an-ynV+u_V&K`HPF)1vY*SRA5?qo z4wJ-*MB1#|r!Rm&z+V6}B?l0Pe4bzc2%Dl|*~vO(62cT4m?6OkkScgmqa{JY29NC< zP`3p$kKj5U0CjC6u5(A)29~DgG_&oQS$!%!~kOnUbLrAa(Fytpgg!eRC*soc&G_uG_vu^N8!(Nuj&` z#K5BpB1am;3cv;J?KETBHutTeLYRx~!*UT%eFH@HlYnR~Xd#ZtV2l89$md}MNCP~) z#NEhk{c@q>)Yl@QPDyT$xQ-p4baOh=17y<6kArSxF%WmxdX1ad1CA`8-MhaZCnN0!T$BAvIYd$Ypk2y6B4Si@|dVJW!`?+j>!lxq~SM z3ias|wWr-lH!C{=QINH>!!YMh<{ktaPS&W&jIB2|K;l(L3bab7U{MCX3JClZr|>x|SL)ShO73*>(Um3?TLG`qsoXZfidM1G@Xto|+)Gp=VaS;Q^9D6v=9A zD>#=4Ano&cVAicz1Lcqje*g}Ec0HrKfAs*ZXNAq1<|_lpmo==DKZL81tN)a z-G$7_Zqvrk!pe$hqqYtX!@JFyp6HMtm!DR zlY%zt)46}pc&GU@O5HcDdK3`1gJ_^hRfR&SkCYK(7=R>uMx>}8RhI`yOL*WM)W?DK zd0>f^Fa5DbD2!_Kr?c<^^IC=K{kB<@x5 zk$1vQb~leE3UKtFT;Jvph*;*-lWW8bLCF!qLW$cXy+TXr@ad&Qi)bp0anoS zpc={A)@G=~8PB3aVN#6)WyEEr;5gAbX#X_(I$X6; zYpSX{&_t+i#6PmJ^0%_Jm6*0ZSo(JyIABWG_ol_VE?acLZPV(9(0h|=CK;f}D(n=h zH}=5R*n3cbAWn;2{Pym{R zy1w&fY{!B9--3Im@f>2Rti&3}gO=5fmc5Nk_uLGR9zYUnB;q6423g?ViKSTj!bo(N z;35C#KI82u-qJ4{Gf19eyVUlUW%|^ zZnCIfP7;y+_-`g5|IbPi^%ca4`U?_-{WBAUA;nq3Pmb&tjVjJW{j(BKKdjOErbeS) zu{%)Dotu!~`sIJ|mMlEx{_fPMF3&yt4!*}{=)Lxad&l5N;yDtHBLSza865qC)RtDR zEzNTQ$I=Twxjl$hva*tBC1{|2c0A9QyeEzMpx1&~aRXK^t{J*{-KFPtZ@v9|LL_>( zFq5pc7*d#lFa&5!Sq>Ugk%wTXYPEvD6H=0eMi-=`m$Q@5wh937R(}&TIUbMRpz@FH=p^muMS&k8rPW&v5Uw3|(oN%o@i?AX(9{eMj0e z=|;zbye%X!HEJd)P*|Sr9279#aqQ@Y0n?{$9=Lcxs@J0TE4-I}RLfhl^rG*&<(K_F zUwy@Y^V+`y!q?sCv2DYDAOYd)Z}@Ln_qX4s&#w5cTltGm=(3C6OBdC;FPKx|J8x!c z@AsyKx#Dxexm&kxJ(ymrFTJ)z(*WQ-$UTbhwHv+nPP8mmW^jxPQY+dck!Yn(GBCl| zkS7UDcIeQPG+ujYNI(&)epEv|1C8I--hO0z57$xcyu3ne{CQ(R;BWX0{zm~B2aNYrwV0HSx8{J;1$)?@1OKiJ7vbWif-(1RyDDC0Urd(C)7@ec}NqAJW4iP}%mf zbm-iNbeE}?u#}fR3L^cV^!xa?mYqBIAtni6fpfz(#K5@GYdg|=k%dN4+nB*IQJC7% zz*}ePoH|fP)rD#VciPxq#I!);i-%JJsPv!`K;iJCfOym2c+zupr{{E{*RZ44w4wK4 zhUN){sTFNBOX{3j)0j#J>OV=q>OxJ619fN}DGajWNdM=ZG3C0HJC*5|F-luRx+T-!eR#IDS=86u9ga*$qLhV6wmY2 a9sdtN6eHRrdyqB&0000AvglfA9NypXa{#=A1b*&&-_9nK?6&dOB)k#LUD105bLa$_BV6=HEq#kGmWEawY(P zYgJuY!N_}RGo8TO$oTXsB$&89>#C*cCdYLmNX~ke#Hv9KA93kET{$`$PbI2&f<=QO zbYEuG&fq#8;U|Hp%+iMX($XltD84sh%`HcA9=yrw*x5Rd?dw|aj_wW|b=kga#C;uk zY)LO?99@%_7kX6dzR(&*!tnq4;>`zco!?9(Az&zTo|L_j^WL&gF7wJuI**)H&y&sO z9l;NhRvPV@eM$C25(Y1oLfTY%Qu06J{1!LY%l6`?e{u8in|(1@!4MJk2$1+uIsPqnf+k()k8h#rg7tMJHVtWaqYT zq|_R>T}xsUyk)<9e2b1o1pB702Pc9ve?7kQpF2}x}2=dBPVaUdm7-ZjF+bUL0vak))KQnKW)qx!vgbJE?)QXqi+7Po!iYjGEI9xeX+3}trhX=ZOA z6m<4$ajUa5?TbuamQOsfYFx!_%v5Pca-z3$eHCN9QVeZN0(`DY*CwYcn=Z{IwS{|W zMVA?tHKL`t<(1kV)n+5idi^{`iXLpvnO=;Rx{T4}wriDGR@79T*3GDl#qU(VPNH?_ z+WNh=8;jQwV zM#imv9eB3r+LQaLX%UgUmS$Q-V|+Ygp>ovUbJ{jiX~_q+go2a38CD$M(o|A(oS*f( zh?L!-@KukR?4c%)OIZBg${L2g5L6Pa=XF(yBP@&9b|agsWh)uYDy{MN@*W9zbE^QG zPZ8wOAg?zDskn|*wf&j@!i7Pbw6fw_Jr}n|+l>O-_8a2*TEQA7y+XU@NUD_gnXUKG z2}$1=_w*$M6~;^rw4#*yT22U!%e#`&t(A(xyf|-T(y3T1sVLvn_}AGKzdo!w)-*Uq z)`#%}qna5)jZjh2p>&4DK;ogEbdo#F?UZ%H>ljUbLLNV;50EQ$-zmX5OZ~Oiu>6ZIQR6g&! zPTyC(E=$qrR?zuYogtRne89+%HynZlT2P=QPE)k~RavpYct9<_leX;S(cUYWmJ%5i zw<#|0L;Epc1diZ!djsOtxXCrexN0iPy+W$%xrf_3!-ktsYsF?BfO_-+rz;1%p|X0Z z`xS4h<)pP{yf5Y2%`K?M%L1lRyQRhGg2R@R1BO$0TUeSMPUR$cJ)j;QyWQ-2SYJ1? z%~^ILTzh8y5rPT)29-&Qo@%PiVei|f)aGz{7xO>5>77{OmMi}>lo?rwpOta_aN2a} zZ_L3$CVhl%C4|)F%yc_!V?s)E@;~94fP)o1CTwgW@3F@BcS<{+x8_h1m|gj-8eT8~ z{P{;v_nE3QwfJ#=Vz7jq`qgMV1n|+2J0HNKgTY17#cGz07^gpi;87-UU+o*XC;A3g zg??@@etFPbu_%d$CSm+feh%;vd6_sgJ6ydmIB8OZ2ObCNBuk-&Tg}J-dX|>uJe}kmEmBH)Q7uAac~6f=i$joy zJK0c6OM9t_Ef1k*Ry3>%RVQV4P_zwS5s^T+u`MbCH zd6?wSSFRIE`|C9((s}H4ZYxc^RT{P)UbYCc^d0IW&aSPITSpqAIQF6g6&D^@VVnrOzTa^&s3buD4Zh79z^>7JLQH+- zqYS8QcLF8+03Y|4eD30R)L9O+_7gvyxH&uXehWGsGF8ox(YPKFj0 zeO}1^(}~=Cb++)WmDI6QeKp!MtupG%f{wZCy1$n!&RIBjUrS~HF0dp*p%w3uW|XYcuU?@&lSpJS-nf;@|F$`Umi_6zQo)P* zAN?|yXKv+GF@wL}{Z@+e2fPCrPyKWP%8JnsD4{x0N4};B4)_O}kwrPV3fK?Wi2^1> z9|==dt|saLUjuoB-9|amKlwXh1UO#${B=k&OyF9&!@HCh^(P1Z!t`T$%9BxBE^)o# zrb+Lsi5i*!ebE*rcxuhl)knhZ#ON)wO$oi@$3X1Yo6{S=udP&GmK4bkq;tb{^J~U4q82PKlFy7~0oQfA>1ZE&nMwI&x>vEc6U6l>WUM9Dh&x=`RU*Gbxx! zkNtRQF;b=RUB91-eD(xJv`D~Lmt+aUbpk*|itL0+z!SP00+|E6y z`uA#y)}Obo8;y%<&n3om?p6xzZJ%th-0j>wzfmi#6_%M|?B;=zSIm6DyAoM_apC>I zXM6D8M09ojEP0;(Tm6=+iv(2Opx(Oj#^^AOYqkBr2bn&rSZqFl_g%UyrartZl7oXX z-sf{fs&@{EPIHwb9qDY_<^%-#3soQ%QDuSy?jsU+(Fip2|+_ zGrN|zd*<~MKX{Lbhj???lU_IhSOdz4)6#L*Ah zm&9^`M`a&%BRsm}7gG3v#DiB;WAYz|2o$)P`>;wKw>@5~1xl# znaLk1Gsg9W+FM2frk6^A_#Vca3W3`Oq!4wV08%sw2(tG4QPdzk%6LE|<#%m44u|qJ zyU?M#nQ?*VpSqw3iYXL4`rl88NPi0HtH8TIb5i9co;}~0@H+On_0OFWps8>3b*XNL zROE5^A`ad4h3;CKVSt1Kz|T<$S=!5XFZ%6Vi5u+l>6fg(<F3On}Towx%MlobtMeV$xN86aA@wyIsb zpySR3MZYr<`22Zdh0P(}B+{cDNL&Y~SPHU}if;!Las3k+eLw;apzg$Cn=31tX!;`8 zY=|5HvpA^g-d!i?nHGr%`~;Flh)u-a91db%jAcig`GW_KWahiTTh z{}^LvD}yhSsCAb|MoLE2G})=@*?##ViZEif4M<3V`i@tM!^>(*Rgr=M9E%|@2gR-B zJV|}j_)t9!JI+t<`3J6z`iNgqpaz#UNv`wl%dOPql&jUOM&>{9=QR^_l&7V4>`hsJ z^G|jS@;l#xw>et_W*DeS$UNv7$Yq?LHspOA%H3LWvgs9kgq*9fx_t)_w4AYf&erE; zoUk${(?)h)eonZuyEw`pl=f#;ELYvr!4*#ks>oM})C*(SuXf}-zfb9s0fYSo3g&C* zV=nfhl#iZHZ8A?c#4g7pM_Rrg?|bjeon~Ou(U2Voz^zl1+IZQ!G&%DZFh62aK+ek- zIo}{Z&X;+Mut%Mj>T@fUL(+){SDfT6!du|ddt5){zl^BJmNK30o-LWDrxIFSRRt+6 z!mYbqyWs;|mm8gb++|aKrJtx9R=#Vi=s69%I$3gH4DJ(vBFLcl7y^(vnPL2npvJ^j?o{T3??tCz0EKI&uu8tndn zkP*E{3i=Q?WeHe^H6*-O16$ApV$=)$Nqz3J%o|%deE091F8ElmB!tV*#0J2#d^I^`4ktA5yK?Q)z|RG`a?V z6vH1jHr#*xxAsihWpi)FEq@|s`QcppDIGpfxROKBu0<7Fy{apE5|3#IrOxK5OZfiT zjAMJ0KGV~$kv@fkjt4!>L}(9#^U%fwjj7Soc36XR)nDkQ3%8O)y;4K2VSi!6N4Mh@ zw62zp(^}TOjuhC^j`!miC0|X$=v@bbB+t5$f4<4>B;>4L-dJnDu>0!J6a6@}jJN&h z5e^#-V!s9Wub&ovQDiBRQH|Uc+sDm4EBsD^hoLp{bH0m|`La@aQ;Ug8XOExRXK|8f z^?z9pD!y^tS<2~MSIn4a7XMfypgzG#m*nQ%dM@^@iK_bUx$*elFco$VW}e6F=)=J* z3o<(tO11GJCk*0owwI(!QK`Ukf9T;Pd{7*GdM=q|Klu8W#Ibn*K754KV1q`FWw!Tu zep>9~)rzk~X|!cCM0wh46KQ1GO>+TU8SrsBIj*FPcmY7D$cXZ;q6s*Vh)z%o(t;vn zx!K|qj$8j0+q9$yyXv#dz}`dy+B*;=H54B~0IEX%s9R#o6}K@lXi@`Zn-ymH++KpSwT zEpq>t59b$ORT?+07%Qzh8*}&0C2m>=7z55P?UqIjx=Nd z5_RT#G>kXWDMf$`cv#^@V6=CmHr$UfeA!pUv;qQtHbiC6i2y8QN z_e#fn4t6ytGgXu;d7vVGdnkco*$$)h)0U9bYF(y!vQMeBp4HNebA$vCuS3f%VZdk< zA0N@-iIRCci*VNggbxTXO(${yjlZp>R|r93&dmU$WQz=7>t!z_gTUtPbjoj2-X{Rs zrTA$5Jtrt~@cao#5|vM$p+l3M_HC0Ykiw9@7935K_wf*-^|GKh$%+opV7&;?rh9&P zh@9}XUqp-`JNnPs3e9~OrZBIJ1eel)hsimyfZSIAKa-_e!~q3^y@G=z;FN<65|y#S zIBWtzFv3n-*Aa|5F3Z9=zMs!RG6&8j!J;3)knD|vHy=yM(L#G}?m=jXNQ08rzG{Q? z03L8v^?3q`cxQdd42Z9RVo{e%Ga$C`=^7nqlxSf^lZhCTfwJB*!vD&M6QLv2g3NcE zlLNNSl;_UR5*{d}Kf!uIIF!i1cJDS7fMI##KSPmi=TR$DWZKb=cLBWJrF7#XGuhG7 zjcL@fyIHYDII3IRrCBTavFc^BM=uYdvN&GWBrcfogytsZ#mNX@9K+}pNp_= zk9AV-B>m?U~{NIbky_m^|J@%P=#HgBe^ zDfz`6g|`gOJpKE@q~4TH!vrHVNVb%n^e@&ALm85qj|xaBT5I90Ycp`;(u*rwGoyp? zo42?p->1XHi@SD&m=D5+6}|bUFWFw^Ue~(Ns1WQdWg=ux{zyH+AM91|XPZ%d*fiP0agmU%;tlV*!A{7y5(|3pSIw`dLqLknHv_PQBq$*|@+K4(r z(nO>@f;?%pkIO4xr70*Nk#eL*y7x+_=)8hsToX389#3w1KYRW> z*jT10YzQG%=Q$~Vd?jE*NFJ3Q_1xC`bl#coS5x4+(w)Pk{J+G z!)n>NlV4dtbN2@K)QdPtA{jC87jPU@hGv_JS3`DM&#QrL5o|v9pZ!u|C7l8Y!06X} zo>&23nPdehmmoN^p|A!0tiUTr`CHa7lrfP~sQnxYB!UG1e(yGzf9ed??k|R+753Jl z7|p%-Z;}uZWB`691Y{;z%fht0EQ5I=Q=xM!$55sB}?14LLaJP!Sh9=o6Ct`HH&OJAVuCgBpm0G_>L zLgPblVMON9`^+|EfPcuK*NO!3l?TlBFPGtQ7{6XmmBfL}Lk{{Mr*gyq842232l)y! z&EGfE9#VdjQO(a$U8DtYD6#;quA5M_q9pjqqG3-3XgR=iH5haYfFOE#7*m*WlW+;p z?*(QB<`&=?VN8b*zDdAXk|0u&ChUKnuK~u}^00YLP@tffpKM40h@>0qAv>J$ zJrJO6LoW6nQ;Lt_8TqG$3|&uIySi8pIQWB_=t1;Ew5BRl7J?W_#P#Q!jsiS1)t)R& zBm=TT1+G!Pc}xbIpGmNXV5B}zM2aE|pbfY#^zg<53DRF@)}T12BMzF0(fIJ0A+3Z) zF(FCSsFO`ljPqMasO-{OJsw6GD$89qiidf9!om$onI10;i?xPp_7Zxa02^=nHJfV2 zo}1Yu%99UK)~|dQR05$flJ_LP@??KD=@6^q3rd&zl=sq`D155z=wL0%C|=Gl`rS`{ zw-3XN{PCKN>`Mx4Uux^yLNOaIrkrs#Bqr1f%w1cG$Fdo;T7H<^$r|;|#mdi$cevZ* zdUc9(`eHt8@K+4=->Qr*HrT(({2Uj)Bl+GPr7ru{us3&!JKUzXmE_(`3UuU4d?;JL zc1X3KSL^U^==r@m)sd2}-$!fwYMO+)%E6|CLIK_ z##nHbe&&rMSDpx}2%+?FJ^shJ8yjE97(vftaucYh>*)KEqRD9|NrLKH=hV$e9A!~^ z4bADay5RL!GXeJ2_zHiwLYIYD#U!gVUX?0lWn6r52N(6LN{Xi9iK=_HO>X!U%Sq@l zh^!p)kHb1d(Ot9To5AfPe}~eD)OZ0MoXW((BIk$hb?gir611I2@D$KJ^VOg zT4fSfiCU#LYYL*CDCFNS4@bFDJa-HD&yA+x-IPQdMe7%+($&f?mC=n) z%&EO|+G#XLeHlo%(5I?7ol`ugo-_s0FL0#nkfTIT>6E9z50T3{?rk#sL>rRnNM~|9 zbq!>`l)R){K{#)v-}J)R27GTgA_f4XfzXn2${0y<*>7Svs39Rgf5ulzf}LmgT3Eqn z8G!%JRL1Gwj7k#Zh=Le=U`Dd4zH#;|o}L#6L-c(Lz=^Dm0-V6?8-?W5q)|w-V8|R@XK0f;$q`9@OmGmQp4JO_0Zgzau^3zjqT)q;CKx|;eNzuf>j1twm zQVhYEF@QgguW{CYFS%U=FfSW|H*CE2A+vuEH66-Q#2iU|Hp8DbO&^njfDi(!U@PIK z7gKGe-eQ+t4rUUtOnfvN87~ND%ab5b!x8Kexv=DeQHV%lmmMLXSRR33V1Aty75xeT&9+VL0)Pz zHpe~F;-a3{`62`|2n#wq#ktiRT;Lh?1diJGf-G(W%QRhQ=!Jr8$ZYk3OReu(4&Gvg zpl?-6>j!|kPL7>&DkSoxD|)&8W{jZ2fm<;ybWp=h-n|lrVTDs2KpsZq8Q@_M%r>_G z6KCrGAXxq8UNzXk`cExGjmaZsNdrw!&Z+iI)D|i}mo;laGQ-M%`}Lv&JJzx${Fd2` zs~^QJGpsDcGk=sm8SeA2z~=GbR9j%8fE@kpnk59Gk8>W2JHBvC&t8y~%f9?sa~*MT zzP9Q8+4`#QlH>2jX$MYd!H45&7r$Jq^`E!@tm|Bu+=?c(yux?!x_X7iET(66!RFDJ zzB?@ffQNcw6D-yOq*Rav4dB9dVs+0RBr5E*p3whI*rE4%-H25JcTOP^)Sh)#sZzJ+ z$IbOD+T^K=`N6CDCpfKHwv%aj}rTaikoks1a4O*+M}j{W)R#K&nzKm zPg7psVmbDEy1VO-r#xCjVwX&}+zKNECBJ!QguJUSSN_kOkv4T&}pz(^z6}X zGCV=1#|a(xlOI`HtWV8dgfuF4s$*LghD`Amxfcq5mblTfRr+m0tzen&#b|xUxLu~H zK~RBt!`&v4%R?`#kjuBJ$opo+D?{Uaa{a2hC;Ka(&ON7#V0K>#_J%#LVtBRt)u}`s z=j4Xe0jY2@p+RHv*#26?%g93kteo0Q@0;`x2ZCw zUn4`&W-e{5P}Q($ccv`W$#ILg_$6+&?B*0cJk#%;d`QzBB`qy)(UxZZ&Ov}Yokd3N zj~ERapEhGwAMEX1`=zw)*qz1io2i_F)DBjWB|*PHvd4MRPX+%d*|}3CF{@tXNmMe6 zAljfg2r$`|z9qsViLaWuOHk$mb2UHh%?~=#HPf2CPQh;AUrYWW~ zvTV9=)lS#UB-`B5)Kb!Ylg0RA){o3e`19Jl&hb@~zS>>vrFR-^youk^@6>0S` zToim7wzkY|Yt*;aGUy!o{yxd8=*L;orYQC!H#=|pjn&hO>o9B$tJu8TBHmxPPsm-) zM#T(;Z9_uvy1xq;yeeWQV6|}+=O;1%) zGZyIq}2>crU3z2ri)(ut%F~+%S>FR4^Xw()Y-+~&Xp*Ns z$?%1aydpzNIz2aN98}oth>3boYSifQ)J81Of>6k)!`WQWrB;xxXccBzrWe5V*>oMh zon)MEw$@-*!>L`CK}u@x^9-4gfvepI0b8q5QYVXr96{4Q#s2ZelHXxHv~G{GymRer zqyj7m)3yn3z5i4koiIJ!-u=p6QeL|BN+pWd>}TOFOVi01q839$NZ&I_quqb(n~9Wk id-{KKnnu*>l46e`&P3zgUlQEeAE2(Hqg<+p4E|raIYd(c diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/examples/android/CanvasAndroidExample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c239cb67b8a2134ddd5f325db1d2d5bee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15523 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 BIP(Ai diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/values/colors.xml b/examples/android/CanvasAndroidExample/app/src/main/res/values/colors.xml deleted file mode 100644 index 3ab3e9c..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #3F51B5 - #303F9F - #FF4081 - diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/values/strings.xml b/examples/android/CanvasAndroidExample/app/src/main/res/values/strings.xml deleted file mode 100644 index d8603ef..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - CanvasAndroidExample - diff --git a/examples/android/CanvasAndroidExample/app/src/main/res/values/styles.xml b/examples/android/CanvasAndroidExample/app/src/main/res/values/styles.xml deleted file mode 100644 index ff6c9d2..0000000 --- a/examples/android/CanvasAndroidExample/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/examples/android/CanvasAndroidExample/app/src/test/java/com/example/canvasandroidexample/ExampleUnitTest.java b/examples/android/CanvasAndroidExample/app/src/test/java/com/example/canvasandroidexample/ExampleUnitTest.java deleted file mode 100644 index 11d000b..0000000 --- a/examples/android/CanvasAndroidExample/app/src/test/java/com/example/canvasandroidexample/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.canvasandroidexample; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/examples/android/CanvasAndroidExample/build.gradle b/examples/android/CanvasAndroidExample/build.gradle deleted file mode 100644 index 1a3d812..0000000 --- a/examples/android/CanvasAndroidExample/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - - repositories { - google() - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.1.2' - - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/examples/android/CanvasAndroidExample/gradle.properties b/examples/android/CanvasAndroidExample/gradle.properties deleted file mode 100644 index 743d692..0000000 --- a/examples/android/CanvasAndroidExample/gradle.properties +++ /dev/null @@ -1,13 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true diff --git a/examples/android/CanvasAndroidExample/gradle/wrapper/gradle-wrapper.jar b/examples/android/CanvasAndroidExample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54708 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

_x$+l{{cH8$W#CT diff --git a/examples/android/CanvasAndroidExample/gradle/wrapper/gradle-wrapper.properties b/examples/android/CanvasAndroidExample/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 759c3fa..0000000 --- a/examples/android/CanvasAndroidExample/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu May 10 15:38:02 CEST 2018 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/examples/android/CanvasAndroidExample/gradlew b/examples/android/CanvasAndroidExample/gradlew deleted file mode 100755 index cccdd3d..0000000 --- a/examples/android/CanvasAndroidExample/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/examples/android/CanvasAndroidExample/gradlew.bat b/examples/android/CanvasAndroidExample/gradlew.bat deleted file mode 100644 index e95643d..0000000 --- a/examples/android/CanvasAndroidExample/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/examples/android/CanvasAndroidExample/settings.gradle b/examples/android/CanvasAndroidExample/settings.gradle deleted file mode 100644 index e7b4def..0000000 --- a/examples/android/CanvasAndroidExample/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/examples/android/README.md b/examples/android/README.md deleted file mode 100644 index a83c7bd..0000000 --- a/examples/android/README.md +++ /dev/null @@ -1,3 +0,0 @@ -As of this writing, gomobile does not support go modules. In this case this project can only be compiled while it is in the GOPATH/src directory. - -The go bindings are generated with the ```gomobile bind -target android``` command, which results in a .aar and a .jar file. These should be placed in the CanvasAndroidExample/app/libs directory, and then the project should compile. diff --git a/examples/android/android.go b/examples/android/android.go deleted file mode 100644 index 4c29fa7..0000000 --- a/examples/android/android.go +++ /dev/null @@ -1,42 +0,0 @@ -package canvasandroidexample - -import ( - "math" - - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/goglbackend" -) - -var cv *canvas.Canvas -var mx, my float64 - -func TouchEvent(typ string, x, y int) { - mx, my = float64(x), float64(y) -} - -func OnSurfaceCreated() { -} - -func OnSurfaceChanged(w, h int) { - backend, err := goglbackend.New(0, 0, w, h, nil) - if err != nil { - panic(err) - } - cv = canvas.New(backend) -} - -func OnDrawFrame() { - if cv == nil { - return - } - w, h := float64(cv.Width()), float64(cv.Height()) - - cv.SetFillStyle("#000") - cv.FillRect(0, 0, w, h) - cv.SetFillStyle("#0F0") - cv.FillRect(w*0.25, h*0.25, w*0.5, h*0.5) - cv.SetLineWidth(6) - sqrSize := math.Min(w, h) * 0.1 - cv.SetStrokeStyle("#F00") - cv.StrokeRect(mx-sqrSize/2, my-sqrSize/2, sqrSize, sqrSize) -} diff --git a/examples/drawing/Righteous-Regular.ttf b/examples/drawing/Righteous-Regular.ttf deleted file mode 100644 index 07fc0b45132b1d7039c202e6d09c91b1a137ec26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43104 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 diff --git a/examples/drawing/cat.jpg b/examples/drawing/cat.jpg deleted file mode 100755 index 27bcece7c1ada345524c89474a780824c12ae675..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135161 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 diff --git a/examples/drawing/drawing.go b/examples/drawing/drawing.go deleted file mode 100644 index bee02d4..0000000 --- a/examples/drawing/drawing.go +++ /dev/null @@ -1,134 +0,0 @@ -package main - -import ( - "image/color" - "log" - "math" - - "github.com/tfriedel6/canvas/sdlcanvas" -) - -func main() { - wnd, cv, err := sdlcanvas.CreateWindow(1280, 720, "Canvas Example") - if err != nil { - log.Println(err) - return - } - defer wnd.Destroy() - - lg := cv.CreateLinearGradient(320, 200, 480, 520) - lg.AddColorStop(0, "#ff000040") - lg.AddColorStop(1, "#00ff0040") - lg.AddColorStop(0.5, "#0000ff40") - - rg := cv.CreateRadialGradient(540, 300, 80, 740, 300, 100) - rg.AddColorStop(0, "#ff0000") - rg.AddColorStop(1, "#00ff00") - rg.AddColorStop(0.5, "#0000ff") - - wnd.MainLoop(func() { - w, h := float64(cv.Width()), float64(cv.Height()) - - // Clear the screen - cv.SetFillStyle("#000") - cv.FillRect(0, 0, w, h) - - // Estimated size used for scaling - const ( - contentWidth = 1000 - contentHeight = 350 - ) - - // Calculate scaling - sx := w / contentWidth - sy := h / contentHeight - scale := math.Min(sx, sy) - cv.Save() - defer cv.Restore() - cv.Scale(scale, scale) - - // Draw lines with different colors and line thickness - for x := 1.0; x < 10.5; x += 1.0 { - cv.SetStrokeStyle(int(x*25), 255, 255) - cv.SetLineWidth(x) - cv.BeginPath() - cv.MoveTo(x*10+20, 20) - cv.LineTo(x*10+20, 120) - cv.Stroke() - } - - // Draw a path - cv.BeginPath() - cv.MoveTo(160, 20) - cv.LineTo(180, 20) - cv.LineTo(180, 40) - cv.LineTo(200, 40) - cv.LineTo(200, 60) - cv.LineTo(220, 60) - cv.LineTo(220, 80) - cv.LineTo(240, 80) - cv.LineTo(240, 100) - cv.LineTo(260, 100) - cv.LineTo(260, 120) - cv.ArcTo(160, 120, 160, 100, 20) - cv.ClosePath() - cv.SetStrokeStyle(color.RGBA{R: 255, G: 128, B: 128, A: 255}) - cv.SetLineWidth(4) - cv.Stroke() - - // Fill a polygon - cv.BeginPath() - cv.MoveTo(300, 20) - cv.LineTo(340, 20) - cv.QuadraticCurveTo(370, 20, 370, 50) - cv.QuadraticCurveTo(370, 80, 400, 80) - cv.LineTo(400, 80) - cv.LineTo(400, 120) - cv.LineTo(360, 120) - cv.BezierCurveTo(330, 120, 330, 80, 300, 80) - cv.ClosePath() - cv.SetFillStyle(color.RGBA{R: 128, G: 255, B: 128, A: 255}) - cv.Fill() - - // Draw with alpha - cv.SetGlobalAlpha(0.5) - cv.SetFillStyle("#FF0000") - cv.BeginPath() - cv.Arc(100, 275, 60, 0, math.Pi*2, false) - cv.Fill() - cv.SetFillStyle("#00FF00") - cv.BeginPath() - cv.Arc(140, 210, 60, 0, math.Pi*2, false) - cv.Fill() - cv.SetFillStyle("#0000FF") - cv.BeginPath() - cv.Arc(180, 275, 60, 0, math.Pi*2, false) - cv.Fill() - cv.SetGlobalAlpha(1) - - // Clipped drawing - cv.Save() - cv.BeginPath() - cv.Arc(340, 240, 80, 0, math.Pi*2, true) - cv.Clip() - cv.SetStrokeStyle(0, 255, 0) - for x := 1.0; x < 12.5; x += 1.0 { - cv.BeginPath() - cv.MoveTo(260, 140+16*x) - cv.LineTo(420, 140+16*x) - cv.Stroke() - } - cv.SetFillStyle(0, 0, 255) - for x := 1.0; x < 12.5; x += 1.0 { - cv.FillRect(246+x*14, 150, 6, 180) - } - cv.Restore() - - // Draw images - cv.DrawImage("cat.jpg", 480, 40, 320, 265) - - // Draw text - cv.SetFont("Righteous-Regular.ttf", 40) - cv.FillText("<-- Cat", 820, 180) - }) -} diff --git a/examples/events/events.go b/examples/events/events.go deleted file mode 100644 index 9ce47d0..0000000 --- a/examples/events/events.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "log" - "math" - "time" - - "github.com/tfriedel6/canvas/sdlcanvas" -) - -type circle struct { - x, y float64 - color string -} - -func main() { - wnd, cv, err := sdlcanvas.CreateWindow(1280, 720, "Canvas Example") - if err != nil { - log.Println(err) - return - } - defer wnd.Destroy() - - var mx, my, action float64 - circles := make([]circle, 0, 100) - - wnd.MouseMove = func(x, y int) { - mx, my = float64(x), float64(y) - } - wnd.MouseDown = func(button, x, y int) { - action = 1 - circles = append(circles, circle{x: mx, y: my, color: "#F00"}) - } - wnd.KeyDown = func(scancode int, rn rune, name string) { - switch name { - case "Escape": - wnd.Close() - case "Space": - action = 1 - circles = append(circles, circle{x: mx, y: my, color: "#0F0"}) - case "Enter": - action = 1 - circles = append(circles, circle{x: mx, y: my, color: "#00F"}) - } - } - - lastTime := time.Now() - - wnd.MainLoop(func() { - now := time.Now() - diff := now.Sub(lastTime) - lastTime = now - action -= diff.Seconds() * 3 - action = math.Max(0, action) - - w, h := float64(cv.Width()), float64(cv.Height()) - - // Clear the screen - cv.SetFillStyle("#000") - cv.FillRect(0, 0, w, h) - - // Draw a circle around the cursor - cv.SetStrokeStyle("#F00") - cv.SetLineWidth(6) - cv.BeginPath() - cv.Arc(mx, my, 24+action*24, 0, math.Pi*2, false) - cv.Stroke() - - // Draw circles where the user has clicked - for _, circle := range circles { - cv.SetFillStyle(circle.color) - cv.BeginPath() - cv.Arc(circle.x, circle.y, 24, 0, math.Pi*2, false) - cv.Fill() - } - }) -} diff --git a/examples/glfw/glfw.go b/examples/glfw/glfw.go deleted file mode 100644 index e0d2e60..0000000 --- a/examples/glfw/glfw.go +++ /dev/null @@ -1,89 +0,0 @@ -package main - -import ( - "log" - "runtime" - - "github.com/go-gl/gl/v3.2-core/gl" - "github.com/go-gl/glfw/v3.3/glfw" - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/goglbackend" -) - -func main() { - runtime.LockOSThread() - - // init GLFW - err := glfw.Init() - if err != nil { - log.Fatalf("Error initializing GLFW: %v", err) - } - defer glfw.Terminate() - - // the stencil size setting is required for the canvas to work - glfw.WindowHint(glfw.StencilBits, 8) - glfw.WindowHint(glfw.DepthBits, 0) - - // create window - window, err := glfw.CreateWindow(1280, 720, "GLFW Test", nil, nil) - if err != nil { - log.Fatalf("Error creating window: %v", err) - } - window.MakeContextCurrent() - - // init GL - err = gl.Init() - if err != nil { - log.Fatalf("Error initializing GL: %v", err) - } - - // set vsync on, enable multisample (if available) - glfw.SwapInterval(1) - gl.Enable(gl.MULTISAMPLE) - - // load GL backend - backend, err := goglbackend.New(0, 0, 0, 0, nil) - if err != nil { - log.Fatalf("Error loading canvas GL assets: %v", err) - } - - var sx, sy float64 = 1, 1 - window.SetCursorPosCallback(func(w *glfw.Window, xpos, ypos float64) { - mx, my = xpos*sx, ypos*sy - }) - - // initialize canvas with zero size, since size is set in main loop - cv := canvas.New(backend) - - for !window.ShouldClose() { - window.MakeContextCurrent() - - // find window size and scaling - ww, wh := window.GetSize() - fbw, fbh := window.GetFramebufferSize() - sx = float64(fbw) / float64(ww) - sy = float64(fbh) / float64(wh) - - glfw.PollEvents() - - // set canvas size - backend.SetBounds(0, 0, fbw, fbh) - - // call the run function to do all the drawing - run(cv, float64(fbw), float64(fbh)) - - // swap back and front buffer - window.SwapBuffers() - } -} - -var mx, my float64 - -func run(cv *canvas.Canvas, w, h float64) { - cv.SetFillStyle("#000") - cv.FillRect(0, 0, w, h) - cv.SetFillStyle("#00F") - cv.FillRect(w*0.25, h*0.25, w*0.5, h*0.5) - cv.SetStrokeStyle("#0F0") - cv.StrokeRect(mx-32, my-32, 64, 64) -} diff --git a/examples/gomobile/gomobile.go b/examples/gomobile/gomobile.go deleted file mode 100644 index a434515..0000000 --- a/examples/gomobile/gomobile.go +++ /dev/null @@ -1,71 +0,0 @@ -package main - -import ( - "log" - "math" - "time" - - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/xmobilebackend" - "golang.org/x/mobile/app" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/gl" -) - -func main() { - app.Main(func(a app.App) { - var cv, painter *canvas.Canvas - var cvb *xmobilebackend.XMobileBackendOffscreen - var painterb *xmobilebackend.XMobileBackend - var w, h int - - var glctx gl.Context - for e := range a.Events() { - switch e := a.Filter(e).(type) { - case lifecycle.Event: - switch e.Crosses(lifecycle.StageVisible) { - case lifecycle.CrossOn: - var err error - glctx = e.DrawContext.(gl.Context) - ctx, err := xmobilebackend.NewGLContext(glctx) - if err != nil { - log.Fatal(err) - } - cvb, err = xmobilebackend.NewOffscreen(0, 0, false, ctx) - if err != nil { - log.Fatalln(err) - } - painterb, err = xmobilebackend.New(0, 0, 0, 0, ctx) - if err != nil { - log.Fatalln(err) - } - cv = canvas.New(cvb) - painter = canvas.New(painterb) - a.Send(paint.Event{}) - case lifecycle.CrossOff: - cvb.Delete() - glctx = nil - } - case size.Event: - w, h = e.WidthPx, e.HeightPx - case paint.Event: - if glctx != nil { - fw, fh := float64(w), float64(h) - color := math.Sin(float64(time.Now().UnixNano())*0.000000002)*0.3 + 0.7 - - cvb.SetSize(w, h) - cv.SetFillStyle(color*0.2, color*0.2, color*0.8) - cv.FillRect(fw*0.25, fh*0.25, fw*0.5, fh*0.5) - - painterb.SetBounds(0, 0, w, h) - painter.DrawImage(cv) - - a.Publish() - a.Send(paint.Event{}) - } - } - } - }) -} diff --git a/examples/ios/CanvasIOSExample/.gitignore b/examples/ios/CanvasIOSExample/.gitignore deleted file mode 100644 index d9349d6..0000000 --- a/examples/ios/CanvasIOSExample/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -xcuserdata -project.xcworkspace -Example.framework - diff --git a/examples/ios/CanvasIOSExample/CanvasIOSExample.xcodeproj/project.pbxproj b/examples/ios/CanvasIOSExample/CanvasIOSExample.xcodeproj/project.pbxproj deleted file mode 100644 index 066fe37..0000000 --- a/examples/ios/CanvasIOSExample/CanvasIOSExample.xcodeproj/project.pbxproj +++ /dev/null @@ -1,325 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - A02D492720AB3AA900E68C35 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02D492620AB3AA900E68C35 /* MainViewController.swift */; }; - A094B52520AB3D0C000BCEA6 /* Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A094B52420AB3D0C000BCEA6 /* Example.framework */; }; - A0F2843E20AAD80F0049BD39 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F2843D20AAD80F0049BD39 /* AppDelegate.swift */; }; - A0F2844520AAD8100049BD39 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0F2844420AAD8100049BD39 /* Assets.xcassets */; }; - A0F2844820AAD8100049BD39 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A0F2844620AAD8100049BD39 /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - A02D492620AB3AA900E68C35 /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; - A094B52420AB3D0C000BCEA6 /* Example.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Example.framework; sourceTree = ""; }; - A0F2843A20AAD80F0049BD39 /* CanvasIOSExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CanvasIOSExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A0F2843D20AAD80F0049BD39 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - A0F2844420AAD8100049BD39 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - A0F2844720AAD8100049BD39 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - A0F2844920AAD8100049BD39 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - A0F2843720AAD80F0049BD39 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A094B52520AB3D0C000BCEA6 /* Example.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - A0F2843120AAD80F0049BD39 = { - isa = PBXGroup; - children = ( - A0F2843C20AAD80F0049BD39 /* CanvasIOSExample */, - A0F2843B20AAD80F0049BD39 /* Products */, - ); - sourceTree = ""; - }; - A0F2843B20AAD80F0049BD39 /* Products */ = { - isa = PBXGroup; - children = ( - A0F2843A20AAD80F0049BD39 /* CanvasIOSExample.app */, - ); - name = Products; - sourceTree = ""; - }; - A0F2843C20AAD80F0049BD39 /* CanvasIOSExample */ = { - isa = PBXGroup; - children = ( - A0F2843D20AAD80F0049BD39 /* AppDelegate.swift */, - A02D492620AB3AA900E68C35 /* MainViewController.swift */, - A0F2844420AAD8100049BD39 /* Assets.xcassets */, - A0F2844620AAD8100049BD39 /* LaunchScreen.storyboard */, - A0F2844920AAD8100049BD39 /* Info.plist */, - A094B52420AB3D0C000BCEA6 /* Example.framework */, - ); - path = CanvasIOSExample; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - A0F2843920AAD80F0049BD39 /* CanvasIOSExample */ = { - isa = PBXNativeTarget; - buildConfigurationList = A0F2844C20AAD8100049BD39 /* Build configuration list for PBXNativeTarget "CanvasIOSExample" */; - buildPhases = ( - A0F2843620AAD80F0049BD39 /* Sources */, - A0F2843720AAD80F0049BD39 /* Frameworks */, - A0F2843820AAD80F0049BD39 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = CanvasIOSExample; - productName = CanvasIOSExample; - productReference = A0F2843A20AAD80F0049BD39 /* CanvasIOSExample.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - A0F2843220AAD80F0049BD39 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0910; - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = example; - TargetAttributes = { - A0F2843920AAD80F0049BD39 = { - CreatedOnToolsVersion = 9.1; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = A0F2843520AAD80F0049BD39 /* Build configuration list for PBXProject "CanvasIOSExample" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = A0F2843120AAD80F0049BD39; - productRefGroup = A0F2843B20AAD80F0049BD39 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - A0F2843920AAD80F0049BD39 /* CanvasIOSExample */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - A0F2843820AAD80F0049BD39 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A0F2844820AAD8100049BD39 /* LaunchScreen.storyboard in Resources */, - A0F2844520AAD8100049BD39 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - A0F2843620AAD80F0049BD39 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A0F2843E20AAD80F0049BD39 /* AppDelegate.swift in Sources */, - A02D492720AB3AA900E68C35 /* MainViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - A0F2844620AAD8100049BD39 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - A0F2844720AAD8100049BD39 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - A0F2844A20AAD8100049BD39 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - A0F2844B20AAD8100049BD39 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.1; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - A0F2844D20AAD8100049BD39 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/CanvasIOSExample", - ); - INFOPLIST_FILE = CanvasIOSExample/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.CanvasIOSExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - A0F2844E20AAD8100049BD39 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/CanvasIOSExample", - ); - INFOPLIST_FILE = CanvasIOSExample/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.CanvasIOSExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - A0F2843520AAD80F0049BD39 /* Build configuration list for PBXProject "CanvasIOSExample" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A0F2844A20AAD8100049BD39 /* Debug */, - A0F2844B20AAD8100049BD39 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - A0F2844C20AAD8100049BD39 /* Build configuration list for PBXNativeTarget "CanvasIOSExample" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A0F2844D20AAD8100049BD39 /* Debug */, - A0F2844E20AAD8100049BD39 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = A0F2843220AAD80F0049BD39 /* Project object */; -} diff --git a/examples/ios/CanvasIOSExample/CanvasIOSExample/AppDelegate.swift b/examples/ios/CanvasIOSExample/CanvasIOSExample/AppDelegate.swift deleted file mode 100644 index cfaf6cc..0000000 --- a/examples/ios/CanvasIOSExample/CanvasIOSExample/AppDelegate.swift +++ /dev/null @@ -1,38 +0,0 @@ -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - - window = UIWindow(frame: UIScreen.main.bounds) - window?.rootViewController = MainViewController() - self.window?.makeKeyAndVisible() - - return true - } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } -} diff --git a/examples/ios/CanvasIOSExample/CanvasIOSExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/ios/CanvasIOSExample/CanvasIOSExample/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 1d060ed..0000000 --- a/examples/ios/CanvasIOSExample/CanvasIOSExample/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios/CanvasIOSExample/CanvasIOSExample/Base.lproj/LaunchScreen.storyboard b/examples/ios/CanvasIOSExample/CanvasIOSExample/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f83f6fd..0000000 --- a/examples/ios/CanvasIOSExample/CanvasIOSExample/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios/CanvasIOSExample/CanvasIOSExample/Info.plist b/examples/ios/CanvasIOSExample/CanvasIOSExample/Info.plist deleted file mode 100644 index 4222ac2..0000000 --- a/examples/ios/CanvasIOSExample/CanvasIOSExample/Info.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios/CanvasIOSExample/CanvasIOSExample/MainViewController.swift b/examples/ios/CanvasIOSExample/CanvasIOSExample/MainViewController.swift deleted file mode 100644 index 09f8ab4..0000000 --- a/examples/ios/CanvasIOSExample/CanvasIOSExample/MainViewController.swift +++ /dev/null @@ -1,54 +0,0 @@ -import UIKit -import GLKit -import Example - -class MainViewController : UIViewController, GLKViewDelegate { - var loaded:Bool? - - override func viewDidLoad() { - loaded = false - let view = GLKView(frame: UIScreen.main.bounds) - let context : EAGLContext? = EAGLContext(api: .openGLES2) - view.context = context! - view.drawableColorFormat = .RGBA8888 - view.drawableDepthFormat = .formatNone - view.drawableStencilFormat = .format8 - view.drawableMultisample = .multisample4X - view.delegate = self - self.view = view - } - - func glkView(_ view: GLKView, drawIn rect: CGRect) { - if loaded == nil || !loaded! { - loaded = true - let scale = UIScreen.main.nativeScale - ExampleLoadGL(Int(rect.width * scale), Int(rect.height * scale)) - } - - ExampleDrawFrame() - DispatchQueue.main.async { - view.setNeedsDisplay() - } - } - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - let scale = UIScreen.main.nativeScale - let touch = touches.first! - let loc = touch.location(in: self.view) - ExampleTouchEvent("down", Int(loc.x*scale), Int(loc.y*scale)) - } - - override func touchesMoved(_ touches: Set, with event: UIEvent?) { - let scale = UIScreen.main.nativeScale - let touch = touches.first! - let loc = touch.location(in: self.view) - ExampleTouchEvent("move", Int(loc.x*scale), Int(loc.y*scale)) - } - - override func touchesEnded(_ touches: Set, with event: UIEvent?) { - let scale = UIScreen.main.nativeScale - let touch = touches.first! - let loc = touch.location(in: self.view) - ExampleTouchEvent("up", Int(loc.x*scale), Int(loc.y*scale)) - } -} diff --git a/examples/ios/README.md b/examples/ios/README.md deleted file mode 100644 index 4ccd0fe..0000000 --- a/examples/ios/README.md +++ /dev/null @@ -1,7 +0,0 @@ -As of this writing, gomobile does not support go modules. In this case this project can only be compiled while it is in the GOPATH/src directory. - -Run this command: - -gomobile bind -target ios -tags ios - -Then add the resulting Example.framework into the Xcode project, and it should compile and run from there diff --git a/examples/ios/ios.go b/examples/ios/ios.go deleted file mode 100644 index 89b4630..0000000 --- a/examples/ios/ios.go +++ /dev/null @@ -1,39 +0,0 @@ -package example - -import ( - "math" - - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/goglbackend" -) - -var cv *canvas.Canvas -var mx, my float64 - -func TouchEvent(typ string, x, y int) { - mx, my = float64(x), float64(y) -} - -func LoadGL(w, h int) { - backend, err := goglbackend.New(0, 0, w, h, nil) - if err != nil { - panic(err) - } - cv = canvas.New(backend) -} - -func DrawFrame() { - if cv == nil { - return - } - w, h := float64(cv.Width()), float64(cv.Height()) - - cv.SetFillStyle("#000") - cv.FillRect(0, 0, w, h) - cv.SetFillStyle("#0F0") - cv.FillRect(w*0.25, h*0.25, w*0.5, h*0.5) - cv.SetLineWidth(6) - sqrSize := math.Min(w, h) * 0.1 - cv.SetStrokeStyle("#F00") - cv.StrokeRect(mx-sqrSize/2, my-sqrSize/2, sqrSize, sqrSize) -} diff --git a/examples/sdl/sdl.go b/examples/sdl/sdl.go deleted file mode 100644 index a1014de..0000000 --- a/examples/sdl/sdl.go +++ /dev/null @@ -1,130 +0,0 @@ -package main - -import ( - "log" - "runtime" - "time" - - "github.com/go-gl/gl/v3.2-core/gl" - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/goglbackend" - "github.com/veandco/go-sdl2/sdl" -) - -func main() { - runtime.LockOSThread() - - // init SDL - err := sdl.Init(sdl.INIT_VIDEO) - if err != nil { - log.Fatalf("Error initializing SDL: %v", err) - } - defer sdl.Quit() - - // the stencil size setting is required for the canvas to work - sdl.GLSetAttribute(sdl.GL_RED_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_GREEN_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_BLUE_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_ALPHA_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_DEPTH_SIZE, 0) - sdl.GLSetAttribute(sdl.GL_STENCIL_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1) - sdl.GLSetAttribute(sdl.GL_MULTISAMPLEBUFFERS, 1) - sdl.GLSetAttribute(sdl.GL_MULTISAMPLESAMPLES, 4) - - // create window - const title = "SDL Test" - window, err := sdl.CreateWindow(title, sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, 1280, 720, sdl.WINDOW_RESIZABLE|sdl.WINDOW_OPENGL|sdl.WINDOW_ALLOW_HIGHDPI) - if err != nil { - // fallback in case multisample is not available - sdl.GLSetAttribute(sdl.GL_MULTISAMPLEBUFFERS, 0) - sdl.GLSetAttribute(sdl.GL_MULTISAMPLESAMPLES, 0) - window, err = sdl.CreateWindow(title, sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, 1280, 720, sdl.WINDOW_RESIZABLE|sdl.WINDOW_OPENGL|sdl.WINDOW_ALLOW_HIGHDPI) - if err != nil { - log.Fatalf("Error creating window: %v", err) - } - } - defer window.Destroy() - - // create GL context - glContext, err := window.GLCreateContext() - if err != nil { - log.Fatalf("Error creating GL context: %v", err) - } - - // init GL - err = gl.Init() - if err != nil { - log.Fatalf("Error initializing GL: %v", err) - } - - // enable vsync and multisample (if available) - sdl.GLSetSwapInterval(1) - gl.Enable(gl.MULTISAMPLE) - - // load GL backend - backend, err := goglbackend.New(0, 0, 0, 0, nil) - if err != nil { - log.Fatalf("Error loading canvas GL assets: %v", err) - } - - // initialize canvas with zero size, since size is set in main loop - cv := canvas.New(backend) - - for running := true; running; { - err := window.GLMakeCurrent(glContext) - if err != nil { - time.Sleep(10 * time.Millisecond) - continue - } - - // find window size and scaling - ww, wh := window.GetSize() - fbw, fbh := window.GLGetDrawableSize() - sx := float64(fbw) / float64(ww) - sy := float64(fbh) / float64(wh) - - // handle events - for { - event := sdl.PollEvent() - if event == nil { - break - } - - switch e := event.(type) { - case *sdl.KeyboardEvent: - if e.Type == sdl.KEYDOWN && e.Keysym.Scancode == sdl.SCANCODE_ESCAPE { - running = false - } - case *sdl.MouseMotionEvent: - mx, my = float64(e.X)*sx, float64(e.Y)*sy - case *sdl.QuitEvent: - running = false - case *sdl.WindowEvent: - if e.Type == sdl.WINDOWEVENT_CLOSE { - running = false - } - } - } - - // set canvas size - backend.SetBounds(0, 0, int(fbw), int(fbh)) - - // call the run function to do all the drawing - run(cv, float64(fbw), float64(fbh)) - - // swap back and front buffer - window.GLSwap() - } -} - -var mx, my float64 - -func run(cv *canvas.Canvas, w, h float64) { - cv.SetFillStyle("#000") - cv.FillRect(0, 0, w, h) - cv.SetFillStyle("#0F0") - cv.FillRect(w*0.25, h*0.25, w*0.5, h*0.5) - cv.SetStrokeStyle("#00F") - cv.StrokeRect(mx-32, my-32, 64, 64) -} diff --git a/examples/shiny/shiny.go b/examples/shiny/shiny.go deleted file mode 100644 index 99bd521..0000000 --- a/examples/shiny/shiny.go +++ /dev/null @@ -1,58 +0,0 @@ -package main - -import ( - "log" - - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/xmobilebackend" - "golang.org/x/exp/shiny/driver/gldriver" - "golang.org/x/exp/shiny/screen" - "golang.org/x/exp/shiny/widget" - "golang.org/x/exp/shiny/widget/glwidget" - "golang.org/x/exp/shiny/widget/node" -) - -var cv *canvas.Canvas -var sheet *widget.Sheet - -func main() { - gldriver.Main(func(s screen.Screen) { - glw := glwidget.NewGL(draw) - sheet = widget.NewSheet(glw) - ctx, err := xmobilebackend.NewGLContext(glw.Ctx) - if err != nil { - log.Fatal(err) - } - backend, err := xmobilebackend.New(0, 0, 600, 600, ctx) - if err != nil { - log.Fatal(err) - } - cv = canvas.New(backend) - - err = widget.RunWindow(s, sheet, &widget.RunWindowOptions{ - NewWindowOptions: screen.NewWindowOptions{ - Title: "Shiny Canvas Example", - Width: 600, - Height: 600, - }, - }) - if err != nil { - log.Fatal(err) - } - }) -} - -func draw(w *glwidget.GL) { - cv.Save() - defer cv.Restore() - - cv.Translate(0, 600) - cv.Scale(1, -1) - - cv.ClearRect(0, 0, 600, 600) - cv.SetFillStyle("#FF00FF") - cv.FillRect(100, 100, 200, 200) - - w.Publish() - w.Mark(node.MarkNeedsPaintBase) -} diff --git a/glfwcanvas/glfwcanvas.go b/glfwcanvas/glfwcanvas.go deleted file mode 100644 index 07c73c2..0000000 --- a/glfwcanvas/glfwcanvas.go +++ /dev/null @@ -1,184 +0,0 @@ -package glfwcanvas - -import ( - "fmt" - _ "image/gif" // Imported here so that applications based on this package support these formats by default - _ "image/jpeg" - _ "image/png" - "math" - "runtime" - "time" - - "github.com/go-gl/gl/v3.2-core/gl" - "github.com/go-gl/glfw/v3.3/glfw" - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/goglbackend" -) - -// Window represents the opened window with GL context. The Mouse* and Key* -// functions can be set for callbacks -type Window struct { - Window *glfw.Window - canvas *canvas.Canvas - frameTimes [10]time.Time - frameIndex int - frameCount int - fps float32 - close bool - MouseDown func(button, x, y int) - MouseMove func(x, y int) - MouseUp func(button, x, y int) - MouseWheel func(x, y int) - KeyDown func(scancode int, rn rune, name string) - KeyUp func(scancode int, rn rune, name string) - KeyChar func(rn rune) - SizeChange func(w, h int) -} - -// CreateWindow creates a window using SDL and initializes the OpenGL context -func CreateWindow(w, h int, title string) (*Window, *canvas.Canvas, error) { - runtime.LockOSThread() - - // init GLFW - err := glfw.Init() - if err != nil { - return nil, nil, fmt.Errorf("Error initializing GLFW: %v", err) - } - - // the stencil size setting is required for the canvas to work - glfw.WindowHint(glfw.StencilBits, 8) - glfw.WindowHint(glfw.DepthBits, 0) - - // create window - window, err := glfw.CreateWindow(w, h, title, nil, nil) - if err != nil { - return nil, nil, fmt.Errorf("Error creating window: %v", err) - } - window.MakeContextCurrent() - - // init GL - err = gl.Init() - if err != nil { - return nil, nil, fmt.Errorf("Error initializing GL: %v", err) - } - - // set vsync on, enable multisample (if available) - glfw.SwapInterval(1) - gl.Enable(gl.MULTISAMPLE) - - // load canvas GL backend - fbw, fbh := window.GetFramebufferSize() - backend, err := goglbackend.New(0, 0, fbw, fbh, nil) - if err != nil { - return nil, nil, fmt.Errorf("Error loading GoGL backend: %v", err) - } - - cv := canvas.New(backend) - wnd := &Window{ - Window: window, - canvas: cv, - } - - var mx, my int - - window.SetMouseButtonCallback(func(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) { - if action == glfw.Press && wnd.MouseDown != nil { - wnd.MouseDown(int(button), mx, my) - } else if action == glfw.Release && wnd.MouseUp != nil { - wnd.MouseUp(int(button), mx, my) - } - }) - window.SetCursorPosCallback(func(w *glfw.Window, xpos, ypos float64) { - mx, my = int(math.Round(xpos)), int(math.Round(ypos)) - if wnd.MouseMove != nil { - wnd.MouseMove(mx, my) - } - }) - window.SetScrollCallback(func(w *glfw.Window, xoff, yoff float64) { - if wnd.MouseWheel != nil { - wnd.MouseWheel(int(math.Round(xoff)), int(math.Round(yoff))) - } - }) - window.SetKeyCallback(func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) { - if action == glfw.Press && wnd.KeyDown != nil { - wnd.KeyDown(scancode, keyRune(key), keyName(key)) - } else if action == glfw.Release && wnd.KeyUp != nil { - wnd.KeyUp(scancode, keyRune(key), keyName(key)) - } - }) - window.SetCharCallback(func(w *glfw.Window, char rune) { - if wnd.KeyChar != nil { - wnd.KeyChar(char) - } - }) - window.SetSizeCallback(func(w *glfw.Window, width, height int) { - if wnd.SizeChange != nil { - wnd.SizeChange(width, height) - } else { - fbw, fbh := window.GetFramebufferSize() - backend.SetBounds(0, 0, fbw, fbh) - } - }) - window.SetCloseCallback(func(w *glfw.Window) { - wnd.Close() - }) - - return wnd, cv, nil -} - -// FPS returns the frames per second (averaged over 10 frames) -func (wnd *Window) FPS() float32 { - return wnd.fps -} - -// Close can be used to end a call to MainLoop -func (wnd *Window) Close() { - wnd.close = true -} - -// StartFrame handles events and gets the window ready for rendering -func (wnd *Window) StartFrame() { - wnd.Window.MakeContextCurrent() - glfw.PollEvents() -} - -// FinishFrame updates the FPS count and displays the frame -func (wnd *Window) FinishFrame() { - now := time.Now() - wnd.frameTimes[wnd.frameIndex] = now - wnd.frameIndex++ - wnd.frameIndex %= len(wnd.frameTimes) - if wnd.frameCount < len(wnd.frameTimes) { - wnd.frameCount++ - } else { - diff := now.Sub(wnd.frameTimes[wnd.frameIndex]).Seconds() - wnd.fps = float32(wnd.frameCount-1) / float32(diff) - } - - wnd.Window.SwapBuffers() -} - -// MainLoop runs a main loop and calls run on every frame -func (wnd *Window) MainLoop(run func()) { - for !wnd.close { - wnd.StartFrame() - run() - wnd.FinishFrame() - } -} - -// Size returns the current width and height of the window. -// Note that this size may not be the same as the size of the -// framebuffer, since some operating systems scale the window. -// Use the Width/Height/Size function on Canvas to determine -// the drawing size -func (wnd *Window) Size() (int, int) { - return wnd.Window.GetSize() -} - -// FramebufferSize returns the current width and height of -// the framebuffer, which is also the internal size of the -// canvas -func (wnd *Window) FramebufferSize() (int, int) { - return wnd.Window.GetFramebufferSize() -} diff --git a/glfwcanvas/keynames.go b/glfwcanvas/keynames.go deleted file mode 100644 index fcc0670..0000000 --- a/glfwcanvas/keynames.go +++ /dev/null @@ -1,216 +0,0 @@ -package glfwcanvas - -import "github.com/go-gl/glfw/v3.3/glfw" - -var keyNameMap [347]string -var keyRuneMap [347]rune - -func init() { - keyNameMap[glfw.KeyEscape] = "Escape" - keyNameMap[glfw.Key0] = "Digit0" - keyNameMap[glfw.Key1] = "Digit1" - keyNameMap[glfw.Key2] = "Digit2" - keyNameMap[glfw.Key3] = "Digit3" - keyNameMap[glfw.Key4] = "Digit4" - keyNameMap[glfw.Key5] = "Digit5" - keyNameMap[glfw.Key6] = "Digit6" - keyNameMap[glfw.Key7] = "Digit7" - keyNameMap[glfw.Key8] = "Digit8" - keyNameMap[glfw.Key9] = "Digit9" - keyNameMap[glfw.KeyMinus] = "Minus" - keyNameMap[glfw.KeyEqual] = "Equal" - keyNameMap[glfw.KeyBackspace] = "Backspace" - keyNameMap[glfw.KeyTab] = "Tab" - keyNameMap[glfw.KeyQ] = "KeyQ" - keyNameMap[glfw.KeyW] = "KeyW" - keyNameMap[glfw.KeyE] = "KeyE" - keyNameMap[glfw.KeyR] = "KeyR" - keyNameMap[glfw.KeyT] = "KeyT" - keyNameMap[glfw.KeyY] = "KeyY" - keyNameMap[glfw.KeyU] = "KeyU" - keyNameMap[glfw.KeyI] = "KeyI" - keyNameMap[glfw.KeyO] = "KeyO" - keyNameMap[glfw.KeyP] = "KeyP" - keyNameMap[glfw.KeyLeftBracket] = "BracketLeft" - keyNameMap[glfw.KeyRightBracket] = "BracketRight" - keyNameMap[glfw.KeyEnter] = "Enter" - keyNameMap[glfw.KeyLeftControl] = "ControlLeft" - keyNameMap[glfw.KeyA] = "KeyA" - keyNameMap[glfw.KeyS] = "KeyS" - keyNameMap[glfw.KeyD] = "KeyD" - keyNameMap[glfw.KeyF] = "KeyF" - keyNameMap[glfw.KeyG] = "KeyG" - keyNameMap[glfw.KeyH] = "KeyH" - keyNameMap[glfw.KeyJ] = "KeyJ" - keyNameMap[glfw.KeyK] = "KeyK" - keyNameMap[glfw.KeyL] = "KeyL" - keyNameMap[glfw.KeySemicolon] = "Semicolon" - keyNameMap[glfw.KeyApostrophe] = "Quote" - keyNameMap[glfw.KeyGraveAccent] = "Backquote" - keyNameMap[glfw.KeyLeftShift] = "ShiftLeft" - keyNameMap[glfw.KeyBackslash] = "Backslash" - keyNameMap[glfw.KeyZ] = "KeyZ" - keyNameMap[glfw.KeyX] = "KeyX" - keyNameMap[glfw.KeyC] = "KeyC" - keyNameMap[glfw.KeyV] = "KeyV" - keyNameMap[glfw.KeyB] = "KeyB" - keyNameMap[glfw.KeyN] = "KeyN" - keyNameMap[glfw.KeyM] = "KeyM" - keyNameMap[glfw.KeyComma] = "Comma" - keyNameMap[glfw.KeyPeriod] = "Period" - keyNameMap[glfw.KeySlash] = "Slash" - keyNameMap[glfw.KeyRightShift] = "ShiftRight" - keyNameMap[glfw.KeyKPMultiply] = "NumpadMultiply" - keyNameMap[glfw.KeyLeftAlt] = "AltLeft" - keyNameMap[glfw.KeySpace] = "Space" - keyNameMap[glfw.KeyCapsLock] = "CapsLock" - keyNameMap[glfw.KeyF1] = "F1" - keyNameMap[glfw.KeyF2] = "F2" - keyNameMap[glfw.KeyF3] = "F3" - keyNameMap[glfw.KeyF4] = "F4" - keyNameMap[glfw.KeyF5] = "F5" - keyNameMap[glfw.KeyF6] = "F6" - keyNameMap[glfw.KeyF7] = "F7" - keyNameMap[glfw.KeyF8] = "F8" - keyNameMap[glfw.KeyF9] = "F9" - keyNameMap[glfw.KeyF10] = "F10" - keyNameMap[glfw.KeyPause] = "Pause" - keyNameMap[glfw.KeyScrollLock] = "ScrollLock" - keyNameMap[glfw.KeyKP7] = "Numpad7" - keyNameMap[glfw.KeyKP8] = "Numpad8" - keyNameMap[glfw.KeyKP9] = "Numpad9" - keyNameMap[glfw.KeyKPSubtract] = "NumpadSubtract" - keyNameMap[glfw.KeyKP4] = "Numpad4" - keyNameMap[glfw.KeyKP5] = "Numpad5" - keyNameMap[glfw.KeyKP6] = "Numpad6" - keyNameMap[glfw.KeyKPAdd] = "NumpadAdd" - keyNameMap[glfw.KeyKP1] = "Numpad1" - keyNameMap[glfw.KeyKP2] = "Numpad2" - keyNameMap[glfw.KeyKP3] = "Numpad3" - keyNameMap[glfw.KeyKP0] = "Numpad0" - keyNameMap[glfw.KeyKPDecimal] = "NumpadDecimal" - keyNameMap[glfw.KeyPrintScreen] = "PrintScreen" - // keyNameMap[glfw.KeyNonUSBackslash] = "IntlBackslash" - keyNameMap[glfw.KeyF11] = "F11" - keyNameMap[glfw.KeyF12] = "F12" - keyNameMap[glfw.KeyKPEqual] = "NumpadEqual" - keyNameMap[glfw.KeyF13] = "F13" - keyNameMap[glfw.KeyF14] = "F14" - keyNameMap[glfw.KeyF15] = "F15" - keyNameMap[glfw.KeyF16] = "F16" - keyNameMap[glfw.KeyF17] = "F17" - keyNameMap[glfw.KeyF18] = "F18" - keyNameMap[glfw.KeyF19] = "F19" - // keyNameMap[glfw.KeyUndo] = "Undo" - // keyNameMap[glfw.KeyPaste] = "Paste" - // keyNameMap[glfw.KeyAudioNext] = "MediaTrackPrevious" - // keyNameMap[glfw.KeyCut] = "Cut" - // keyNameMap[glfw.KeyCopy] = "Copy" - // keyNameMap[glfw.KeyAudioNext] = "MediaTrackNext" - keyNameMap[glfw.KeyKPEnter] = "NumpadEnter" - keyNameMap[glfw.KeyRightControl] = "ControlRight" - // keyNameMap[glfw.KeyMute] = "AudioVolumeMute" - // keyNameMap[glfw.KeyAudioPlay] = "MediaPlayPause" - // keyNameMap[glfw.KeyAudioStop] = "MediaStop" - // keyNameMap[glfw.KeyVolumeDown] = "AudioVolumeDown" - // keyNameMap[glfw.KeyVolumeUp] = "AudioVolumeUp" - keyNameMap[glfw.KeyKPDivide] = "NumpadDivide" - keyNameMap[glfw.KeyRightAlt] = "AltRight" - // keyNameMap[glfw.KeyHelp] = "Help" - keyNameMap[glfw.KeyHome] = "Home" - keyNameMap[glfw.KeyUp] = "ArrowUp" - keyNameMap[glfw.KeyPageUp] = "PageUp" - keyNameMap[glfw.KeyLeft] = "ArrowLeft" - keyNameMap[glfw.KeyRight] = "ArrowRight" - keyNameMap[glfw.KeyEnd] = "End" - keyNameMap[glfw.KeyDown] = "ArrowDown" - keyNameMap[glfw.KeyInsert] = "Insert" - keyNameMap[glfw.KeyDelete] = "Delete" - // keyNameMap[glfw.KeyApplication] = "ContextMenu" - - keyRuneMap[glfw.Key0] = '0' - keyRuneMap[glfw.Key1] = '1' - keyRuneMap[glfw.Key2] = '2' - keyRuneMap[glfw.Key3] = '3' - keyRuneMap[glfw.Key4] = '4' - keyRuneMap[glfw.Key5] = '5' - keyRuneMap[glfw.Key6] = '6' - keyRuneMap[glfw.Key7] = '7' - keyRuneMap[glfw.Key8] = '8' - keyRuneMap[glfw.Key9] = '9' - keyRuneMap[glfw.KeyMinus] = '-' - keyRuneMap[glfw.KeyEqual] = '=' - keyRuneMap[glfw.KeyTab] = '\t' - keyRuneMap[glfw.KeyQ] = 'Q' - keyRuneMap[glfw.KeyW] = 'W' - keyRuneMap[glfw.KeyE] = 'E' - keyRuneMap[glfw.KeyR] = 'R' - keyRuneMap[glfw.KeyT] = 'T' - keyRuneMap[glfw.KeyY] = 'Y' - keyRuneMap[glfw.KeyU] = 'U' - keyRuneMap[glfw.KeyI] = 'I' - keyRuneMap[glfw.KeyO] = 'O' - keyRuneMap[glfw.KeyP] = 'P' - keyRuneMap[glfw.KeyLeftBracket] = '[' - keyRuneMap[glfw.KeyRightBracket] = ']' - keyRuneMap[glfw.KeyEnter] = '\n' - keyRuneMap[glfw.KeyA] = 'A' - keyRuneMap[glfw.KeyS] = 'S' - keyRuneMap[glfw.KeyD] = 'D' - keyRuneMap[glfw.KeyF] = 'F' - keyRuneMap[glfw.KeyG] = 'G' - keyRuneMap[glfw.KeyH] = 'H' - keyRuneMap[glfw.KeyJ] = 'J' - keyRuneMap[glfw.KeyK] = 'K' - keyRuneMap[glfw.KeyL] = 'L' - keyRuneMap[glfw.KeySemicolon] = ';' - keyRuneMap[glfw.KeyApostrophe] = '\'' - keyRuneMap[glfw.KeyGraveAccent] = '`' - keyRuneMap[glfw.KeyBackslash] = '\\' - keyRuneMap[glfw.KeyZ] = 'Z' - keyRuneMap[glfw.KeyX] = 'X' - keyRuneMap[glfw.KeyC] = 'C' - keyRuneMap[glfw.KeyV] = 'V' - keyRuneMap[glfw.KeyB] = 'B' - keyRuneMap[glfw.KeyN] = 'N' - keyRuneMap[glfw.KeyM] = 'M' - keyRuneMap[glfw.KeyComma] = ',' - keyRuneMap[glfw.KeyPeriod] = '.' - keyRuneMap[glfw.KeySlash] = '/' - keyRuneMap[glfw.KeyKPMultiply] = '*' - keyRuneMap[glfw.KeySpace] = ' ' - keyRuneMap[glfw.KeyKP7] = '7' - keyRuneMap[glfw.KeyKP8] = '8' - keyRuneMap[glfw.KeyKP9] = '9' - keyRuneMap[glfw.KeyKPSubtract] = '-' - keyRuneMap[glfw.KeyKP4] = '4' - keyRuneMap[glfw.KeyKP5] = '5' - keyRuneMap[glfw.KeyKP6] = '6' - keyRuneMap[glfw.KeyKPAdd] = '+' - keyRuneMap[glfw.KeyKP1] = '1' - keyRuneMap[glfw.KeyKP2] = '2' - keyRuneMap[glfw.KeyKP3] = '3' - keyRuneMap[glfw.KeyKP0] = '0' - keyRuneMap[glfw.KeyKPDecimal] = '.' - keyRuneMap[glfw.KeyKPEqual] = '=' - keyRuneMap[glfw.KeyKPEnter] = '\n' - keyRuneMap[glfw.KeyKPDivide] = '/' -} - -func keyName(key glfw.Key) string { - if int(key) >= len(keyNameMap) { - return "Unidentified" - } - name := keyNameMap[key] - if name == "" { - return "Unidentified" - } - return name -} - -func keyRune(key glfw.Key) rune { - if int(key) >= len(keyNameMap) { - return 0 - } - return keyRuneMap[key] -} diff --git a/sdlcanvas/keynames.go b/sdlcanvas/keynames.go deleted file mode 100644 index 348a7df..0000000 --- a/sdlcanvas/keynames.go +++ /dev/null @@ -1,216 +0,0 @@ -package sdlcanvas - -import "github.com/veandco/go-sdl2/sdl" - -var keyNameMap [262]string -var keyRuneMap [262]rune - -func init() { - keyNameMap[sdl.SCANCODE_ESCAPE] = "Escape" - keyNameMap[sdl.SCANCODE_0] = "Digit0" - keyNameMap[sdl.SCANCODE_1] = "Digit1" - keyNameMap[sdl.SCANCODE_2] = "Digit2" - keyNameMap[sdl.SCANCODE_3] = "Digit3" - keyNameMap[sdl.SCANCODE_4] = "Digit4" - keyNameMap[sdl.SCANCODE_5] = "Digit5" - keyNameMap[sdl.SCANCODE_6] = "Digit6" - keyNameMap[sdl.SCANCODE_7] = "Digit7" - keyNameMap[sdl.SCANCODE_8] = "Digit8" - keyNameMap[sdl.SCANCODE_9] = "Digit9" - keyNameMap[sdl.SCANCODE_MINUS] = "Minus" - keyNameMap[sdl.SCANCODE_EQUALS] = "Equal" - keyNameMap[sdl.SCANCODE_BACKSPACE] = "Backspace" - keyNameMap[sdl.SCANCODE_TAB] = "Tab" - keyNameMap[sdl.SCANCODE_Q] = "KeyQ" - keyNameMap[sdl.SCANCODE_W] = "KeyW" - keyNameMap[sdl.SCANCODE_E] = "KeyE" - keyNameMap[sdl.SCANCODE_R] = "KeyR" - keyNameMap[sdl.SCANCODE_T] = "KeyT" - keyNameMap[sdl.SCANCODE_Y] = "KeyY" - keyNameMap[sdl.SCANCODE_U] = "KeyU" - keyNameMap[sdl.SCANCODE_I] = "KeyI" - keyNameMap[sdl.SCANCODE_O] = "KeyO" - keyNameMap[sdl.SCANCODE_P] = "KeyP" - keyNameMap[sdl.SCANCODE_LEFTBRACKET] = "BracketLeft" - keyNameMap[sdl.SCANCODE_RIGHTBRACKET] = "BracketRight" - keyNameMap[sdl.SCANCODE_RETURN] = "Enter" - keyNameMap[sdl.SCANCODE_LCTRL] = "ControlLeft" - keyNameMap[sdl.SCANCODE_A] = "KeyA" - keyNameMap[sdl.SCANCODE_S] = "KeyS" - keyNameMap[sdl.SCANCODE_D] = "KeyD" - keyNameMap[sdl.SCANCODE_F] = "KeyF" - keyNameMap[sdl.SCANCODE_G] = "KeyG" - keyNameMap[sdl.SCANCODE_H] = "KeyH" - keyNameMap[sdl.SCANCODE_J] = "KeyJ" - keyNameMap[sdl.SCANCODE_K] = "KeyK" - keyNameMap[sdl.SCANCODE_L] = "KeyL" - keyNameMap[sdl.SCANCODE_SEMICOLON] = "Semicolon" - keyNameMap[sdl.SCANCODE_APOSTROPHE] = "Quote" - keyNameMap[sdl.SCANCODE_GRAVE] = "Backquote" - keyNameMap[sdl.SCANCODE_LSHIFT] = "ShiftLeft" - keyNameMap[sdl.SCANCODE_BACKSLASH] = "Backslash" - keyNameMap[sdl.SCANCODE_Z] = "KeyZ" - keyNameMap[sdl.SCANCODE_X] = "KeyX" - keyNameMap[sdl.SCANCODE_C] = "KeyC" - keyNameMap[sdl.SCANCODE_V] = "KeyV" - keyNameMap[sdl.SCANCODE_B] = "KeyB" - keyNameMap[sdl.SCANCODE_N] = "KeyN" - keyNameMap[sdl.SCANCODE_M] = "KeyM" - keyNameMap[sdl.SCANCODE_COMMA] = "Comma" - keyNameMap[sdl.SCANCODE_PERIOD] = "Period" - keyNameMap[sdl.SCANCODE_SLASH] = "Slash" - keyNameMap[sdl.SCANCODE_RSHIFT] = "ShiftRight" - keyNameMap[sdl.SCANCODE_KP_MULTIPLY] = "NumpadMultiply" - keyNameMap[sdl.SCANCODE_LALT] = "AltLeft" - keyNameMap[sdl.SCANCODE_SPACE] = "Space" - keyNameMap[sdl.SCANCODE_CAPSLOCK] = "CapsLock" - keyNameMap[sdl.SCANCODE_F1] = "F1" - keyNameMap[sdl.SCANCODE_F2] = "F2" - keyNameMap[sdl.SCANCODE_F3] = "F3" - keyNameMap[sdl.SCANCODE_F4] = "F4" - keyNameMap[sdl.SCANCODE_F5] = "F5" - keyNameMap[sdl.SCANCODE_F6] = "F6" - keyNameMap[sdl.SCANCODE_F7] = "F7" - keyNameMap[sdl.SCANCODE_F8] = "F8" - keyNameMap[sdl.SCANCODE_F9] = "F9" - keyNameMap[sdl.SCANCODE_F10] = "F10" - keyNameMap[sdl.SCANCODE_PAUSE] = "Pause" - keyNameMap[sdl.SCANCODE_SCROLLLOCK] = "ScrollLock" - keyNameMap[sdl.SCANCODE_KP_7] = "Numpad7" - keyNameMap[sdl.SCANCODE_KP_8] = "Numpad8" - keyNameMap[sdl.SCANCODE_KP_9] = "Numpad9" - keyNameMap[sdl.SCANCODE_KP_MINUS] = "NumpadSubtract" - keyNameMap[sdl.SCANCODE_KP_4] = "Numpad4" - keyNameMap[sdl.SCANCODE_KP_5] = "Numpad5" - keyNameMap[sdl.SCANCODE_KP_6] = "Numpad6" - keyNameMap[sdl.SCANCODE_KP_PLUS] = "NumpadAdd" - keyNameMap[sdl.SCANCODE_KP_1] = "Numpad1" - keyNameMap[sdl.SCANCODE_KP_2] = "Numpad2" - keyNameMap[sdl.SCANCODE_KP_3] = "Numpad3" - keyNameMap[sdl.SCANCODE_KP_0] = "Numpad0" - keyNameMap[sdl.SCANCODE_KP_DECIMAL] = "NumpadDecimal" - keyNameMap[sdl.SCANCODE_PRINTSCREEN] = "PrintScreen" - keyNameMap[sdl.SCANCODE_NONUSBACKSLASH] = "IntlBackslash" - keyNameMap[sdl.SCANCODE_F11] = "F11" - keyNameMap[sdl.SCANCODE_F12] = "F12" - keyNameMap[sdl.SCANCODE_KP_EQUALS] = "NumpadEqual" - keyNameMap[sdl.SCANCODE_F13] = "F13" - keyNameMap[sdl.SCANCODE_F14] = "F14" - keyNameMap[sdl.SCANCODE_F15] = "F15" - keyNameMap[sdl.SCANCODE_F16] = "F16" - keyNameMap[sdl.SCANCODE_F17] = "F17" - keyNameMap[sdl.SCANCODE_F18] = "F18" - keyNameMap[sdl.SCANCODE_F19] = "F19" - keyNameMap[sdl.SCANCODE_UNDO] = "Undo" - keyNameMap[sdl.SCANCODE_PASTE] = "Paste" - keyNameMap[sdl.SCANCODE_AUDIOPREV] = "MediaTrackPrevious" - keyNameMap[sdl.SCANCODE_CUT] = "Cut" - keyNameMap[sdl.SCANCODE_COPY] = "Copy" - keyNameMap[sdl.SCANCODE_AUDIONEXT] = "MediaTrackNext" - keyNameMap[sdl.SCANCODE_KP_ENTER] = "NumpadEnter" - keyNameMap[sdl.SCANCODE_RCTRL] = "ControlRight" - keyNameMap[sdl.SCANCODE_MUTE] = "AudioVolumeMute" - keyNameMap[sdl.SCANCODE_AUDIOPLAY] = "MediaPlayPause" - keyNameMap[sdl.SCANCODE_AUDIOSTOP] = "MediaStop" - keyNameMap[sdl.SCANCODE_VOLUMEDOWN] = "AudioVolumeDown" - keyNameMap[sdl.SCANCODE_VOLUMEUP] = "AudioVolumeUp" - keyNameMap[sdl.SCANCODE_KP_DIVIDE] = "NumpadDivide" - keyNameMap[sdl.SCANCODE_RALT] = "AltRight" - keyNameMap[sdl.SCANCODE_HELP] = "Help" - keyNameMap[sdl.SCANCODE_HOME] = "Home" - keyNameMap[sdl.SCANCODE_UP] = "ArrowUp" - keyNameMap[sdl.SCANCODE_PAGEUP] = "PageUp" - keyNameMap[sdl.SCANCODE_LEFT] = "ArrowLeft" - keyNameMap[sdl.SCANCODE_RIGHT] = "ArrowRight" - keyNameMap[sdl.SCANCODE_END] = "End" - keyNameMap[sdl.SCANCODE_DOWN] = "ArrowDown" - keyNameMap[sdl.SCANCODE_INSERT] = "Insert" - keyNameMap[sdl.SCANCODE_DELETE] = "Delete" - keyNameMap[sdl.SCANCODE_APPLICATION] = "ContextMenu" - - keyRuneMap[sdl.SCANCODE_0] = '0' - keyRuneMap[sdl.SCANCODE_1] = '1' - keyRuneMap[sdl.SCANCODE_2] = '2' - keyRuneMap[sdl.SCANCODE_3] = '3' - keyRuneMap[sdl.SCANCODE_4] = '4' - keyRuneMap[sdl.SCANCODE_5] = '5' - keyRuneMap[sdl.SCANCODE_6] = '6' - keyRuneMap[sdl.SCANCODE_7] = '7' - keyRuneMap[sdl.SCANCODE_8] = '8' - keyRuneMap[sdl.SCANCODE_9] = '9' - keyRuneMap[sdl.SCANCODE_MINUS] = '-' - keyRuneMap[sdl.SCANCODE_EQUALS] = '=' - keyRuneMap[sdl.SCANCODE_TAB] = '\t' - keyRuneMap[sdl.SCANCODE_Q] = 'Q' - keyRuneMap[sdl.SCANCODE_W] = 'W' - keyRuneMap[sdl.SCANCODE_E] = 'E' - keyRuneMap[sdl.SCANCODE_R] = 'R' - keyRuneMap[sdl.SCANCODE_T] = 'T' - keyRuneMap[sdl.SCANCODE_Y] = 'Y' - keyRuneMap[sdl.SCANCODE_U] = 'U' - keyRuneMap[sdl.SCANCODE_I] = 'I' - keyRuneMap[sdl.SCANCODE_O] = 'O' - keyRuneMap[sdl.SCANCODE_P] = 'P' - keyRuneMap[sdl.SCANCODE_LEFTBRACKET] = '[' - keyRuneMap[sdl.SCANCODE_RIGHTBRACKET] = ']' - keyRuneMap[sdl.SCANCODE_RETURN] = '\n' - keyRuneMap[sdl.SCANCODE_A] = 'A' - keyRuneMap[sdl.SCANCODE_S] = 'S' - keyRuneMap[sdl.SCANCODE_D] = 'D' - keyRuneMap[sdl.SCANCODE_F] = 'F' - keyRuneMap[sdl.SCANCODE_G] = 'G' - keyRuneMap[sdl.SCANCODE_H] = 'H' - keyRuneMap[sdl.SCANCODE_J] = 'J' - keyRuneMap[sdl.SCANCODE_K] = 'K' - keyRuneMap[sdl.SCANCODE_L] = 'L' - keyRuneMap[sdl.SCANCODE_SEMICOLON] = ';' - keyRuneMap[sdl.SCANCODE_APOSTROPHE] = '\'' - keyRuneMap[sdl.SCANCODE_GRAVE] = '`' - keyRuneMap[sdl.SCANCODE_BACKSLASH] = '\\' - keyRuneMap[sdl.SCANCODE_Z] = 'Z' - keyRuneMap[sdl.SCANCODE_X] = 'X' - keyRuneMap[sdl.SCANCODE_C] = 'C' - keyRuneMap[sdl.SCANCODE_V] = 'V' - keyRuneMap[sdl.SCANCODE_B] = 'B' - keyRuneMap[sdl.SCANCODE_N] = 'N' - keyRuneMap[sdl.SCANCODE_M] = 'M' - keyRuneMap[sdl.SCANCODE_COMMA] = ',' - keyRuneMap[sdl.SCANCODE_PERIOD] = '.' - keyRuneMap[sdl.SCANCODE_SLASH] = '/' - keyRuneMap[sdl.SCANCODE_KP_MULTIPLY] = '*' - keyRuneMap[sdl.SCANCODE_SPACE] = ' ' - keyRuneMap[sdl.SCANCODE_KP_7] = '7' - keyRuneMap[sdl.SCANCODE_KP_8] = '8' - keyRuneMap[sdl.SCANCODE_KP_9] = '9' - keyRuneMap[sdl.SCANCODE_KP_MINUS] = '-' - keyRuneMap[sdl.SCANCODE_KP_4] = '4' - keyRuneMap[sdl.SCANCODE_KP_5] = '5' - keyRuneMap[sdl.SCANCODE_KP_6] = '6' - keyRuneMap[sdl.SCANCODE_KP_PLUS] = '+' - keyRuneMap[sdl.SCANCODE_KP_1] = '1' - keyRuneMap[sdl.SCANCODE_KP_2] = '2' - keyRuneMap[sdl.SCANCODE_KP_3] = '3' - keyRuneMap[sdl.SCANCODE_KP_0] = '0' - keyRuneMap[sdl.SCANCODE_KP_DECIMAL] = '.' - keyRuneMap[sdl.SCANCODE_KP_EQUALS] = '=' - keyRuneMap[sdl.SCANCODE_KP_ENTER] = '\n' - keyRuneMap[sdl.SCANCODE_KP_DIVIDE] = '/' -} - -func keyName(s sdl.Scancode) string { - if int(s) >= len(keyNameMap) { - return "Unidentified" - } - name := keyNameMap[s] - if name == "" { - return "Unidentified" - } - return name -} - -func keyRune(s sdl.Scancode) rune { - if int(s) >= len(keyNameMap) { - return 0 - } - return keyRuneMap[s] -} diff --git a/sdlcanvas/sdlcanvas.go b/sdlcanvas/sdlcanvas.go deleted file mode 100644 index d67d26e..0000000 --- a/sdlcanvas/sdlcanvas.go +++ /dev/null @@ -1,275 +0,0 @@ -package sdlcanvas - -import ( - "fmt" - _ "image/gif" // Imported here so that applications based on this package support these formats by default - _ "image/jpeg" - _ "image/png" - "runtime" - "time" - "unicode/utf8" - - "github.com/go-gl/gl/v3.2-core/gl" - "github.com/tfriedel6/canvas" - "github.com/tfriedel6/canvas/backend/goglbackend" - "github.com/veandco/go-sdl2/sdl" -) - -// Window represents the opened window with GL context. The Mouse* and Key* -// functions can be set for callbacks -type Window struct { - Window *sdl.Window - WindowID uint32 - GLContext sdl.GLContext - Backend *goglbackend.GoGLBackend - canvas *canvas.Canvas - frameTimes [10]time.Time - frameIndex int - frameCount int - fps float32 - close bool - events []sdl.Event - Event func(event sdl.Event) - MouseDown func(button, x, y int) - MouseMove func(x, y int) - MouseUp func(button, x, y int) - MouseWheel func(x, y int) - KeyDown func(scancode int, rn rune, name string) - KeyUp func(scancode int, rn rune, name string) - KeyChar func(rn rune) - SizeChange func(w, h int) -} - -// CreateWindow creates a window using SDL and initializes the OpenGL context -func CreateWindow(w, h int, title string) (*Window, *canvas.Canvas, error) { - runtime.LockOSThread() - - // init SDL - err := sdl.Init(sdl.INIT_VIDEO) - if err != nil { - return nil, nil, fmt.Errorf("Error initializing SDL: %v", err) - } - - sdl.GLSetAttribute(sdl.GL_RED_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_GREEN_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_BLUE_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_ALPHA_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_DEPTH_SIZE, 0) - sdl.GLSetAttribute(sdl.GL_STENCIL_SIZE, 8) - sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1) - sdl.GLSetAttribute(sdl.GL_MULTISAMPLEBUFFERS, 1) - sdl.GLSetAttribute(sdl.GL_MULTISAMPLESAMPLES, 4) - - // create window - window, err := sdl.CreateWindow(title, sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, int32(w), int32(h), sdl.WINDOW_RESIZABLE|sdl.WINDOW_OPENGL|sdl.WINDOW_ALLOW_HIGHDPI) - if err != nil { - sdl.GLSetAttribute(sdl.GL_MULTISAMPLEBUFFERS, 0) - sdl.GLSetAttribute(sdl.GL_MULTISAMPLESAMPLES, 0) - window, err = sdl.CreateWindow(title, sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, int32(w), int32(h), sdl.WINDOW_RESIZABLE|sdl.WINDOW_OPENGL|sdl.WINDOW_ALLOW_HIGHDPI) - if err != nil { - return nil, nil, fmt.Errorf("Error creating window: %v", err) - } - } - windowID, err := window.GetID() - if err != nil { - return nil, nil, fmt.Errorf("Error getting window ID: %v", err) - } - - // create GL context - glContext, err := window.GLCreateContext() - if err != nil { - return nil, nil, fmt.Errorf("Error creating GL context: %v", err) - } - - // init GL - err = gl.Init() - if err != nil { - return nil, nil, fmt.Errorf("Error initializing GL: %v", err) - } - - // load canvas GL backend - fbw, fbh := window.GLGetDrawableSize() - backend, err := goglbackend.New(0, 0, int(fbw), int(fbh), nil) - if err != nil { - return nil, nil, fmt.Errorf("Error loading GoGL backend: %v", err) - } - - sdl.GLSetSwapInterval(1) - gl.Enable(gl.MULTISAMPLE) - - cv := canvas.New(backend) - wnd := &Window{ - Window: window, - WindowID: windowID, - GLContext: glContext, - Backend: backend, - canvas: cv, - events: make([]sdl.Event, 0, 100), - } - - return wnd, cv, nil -} - -// Destroy destroys the GL context and the window -func (wnd *Window) Destroy() { - sdl.GLDeleteContext(wnd.GLContext) - wnd.Window.Destroy() -} - -// FPS returns the frames per second (averaged over 10 frames) -func (wnd *Window) FPS() float32 { - return wnd.fps -} - -// Close can be used to end a call to MainLoop -func (wnd *Window) Close() { - wnd.close = true -} - -// StartFrame handles events and gets the window ready for rendering -func (wnd *Window) StartFrame() error { - err := wnd.Window.GLMakeCurrent(wnd.GLContext) - if err != nil { - return err - } - - wnd.events = wnd.events[:0] - for { - event := sdl.PollEvent() - if event == nil { - break - } - - handled := false - switch e := event.(type) { - case *sdl.MouseButtonEvent: - if e.Type == sdl.MOUSEBUTTONDOWN { - if wnd.MouseDown != nil { - wnd.MouseDown(int(e.Button), int(e.X), int(e.Y)) - handled = true - } - } else if e.Type == sdl.MOUSEBUTTONUP { - if wnd.MouseUp != nil { - wnd.MouseUp(int(e.Button), int(e.X), int(e.Y)) - handled = true - } - } - case *sdl.MouseMotionEvent: - if wnd.MouseMove != nil { - wnd.MouseMove(int(e.X), int(e.Y)) - handled = true - } - case *sdl.MouseWheelEvent: - if wnd.MouseWheel != nil { - wnd.MouseWheel(int(e.X), int(e.Y)) - handled = true - } - case *sdl.KeyboardEvent: - if e.Type == sdl.KEYDOWN { - if wnd.KeyDown != nil { - wnd.KeyDown(int(e.Keysym.Scancode), keyRune(e.Keysym.Scancode), keyName(e.Keysym.Scancode)) - handled = true - } - } else if e.Type == sdl.KEYUP { - if wnd.KeyUp != nil { - wnd.KeyUp(int(e.Keysym.Scancode), keyRune(e.Keysym.Scancode), keyName(e.Keysym.Scancode)) - handled = true - } - } - case *sdl.TextInputEvent: - if wnd.KeyChar != nil { - rn, _ := utf8.DecodeRune(e.Text[:]) - wnd.KeyChar(rn) - handled = true - } - case *sdl.WindowEvent: - if e.WindowID == wnd.WindowID { - if e.Event == sdl.WINDOWEVENT_SIZE_CHANGED { - fbw, fbh := wnd.Window.GLGetDrawableSize() - if wnd.SizeChange != nil { - wnd.SizeChange(int(e.Data1), int(e.Data2)) - handled = true - } else { - wnd.Backend.SetBounds(0, 0, int(fbw), int(fbh)) - } - } - } - } - - if !handled && wnd.Event != nil { - wnd.Event(event) - handled = true - } - - if !handled { - wnd.events = append(wnd.events, event) - } - } - - return nil -} - -// FinishFrame updates the FPS count and displays the frame -func (wnd *Window) FinishFrame() { - now := time.Now() - wnd.frameTimes[wnd.frameIndex] = now - wnd.frameIndex++ - wnd.frameIndex %= len(wnd.frameTimes) - if wnd.frameCount < len(wnd.frameTimes) { - wnd.frameCount++ - } else { - diff := now.Sub(wnd.frameTimes[wnd.frameIndex]).Seconds() - wnd.fps = float32(wnd.frameCount-1) / float32(diff) - } - - wnd.Window.GLSwap() -} - -// MainLoop runs a main loop and calls run on every frame -func (wnd *Window) MainLoop(run func()) { - // main loop - for !wnd.close { - err := wnd.StartFrame() - if err != nil { - time.Sleep(10 * time.Millisecond) - continue - } - - for _, event := range wnd.events { - switch e := event.(type) { - case *sdl.WindowEvent: - if e.Event == sdl.WINDOWEVENT_CLOSE { - wnd.close = true - } - case *sdl.QuitEvent: - wnd.close = true - case *sdl.KeyboardEvent: - if e.Type == sdl.KEYDOWN && e.Keysym.Scancode == sdl.SCANCODE_ESCAPE { - wnd.close = true - } - } - } - - run() - - wnd.FinishFrame() - } -} - -// Size returns the current width and height of the window. -// Note that this size may not be the same as the size of the -// framebuffer, since some operating systems scale the window. -// Use the Width/Height/Size function on Canvas to determine -// the drawing size -func (wnd *Window) Size() (int, int) { - w, h := wnd.Window.GetSize() - return int(w), int(h) -} - -// FramebufferSize returns the current width and height of -// the framebuffer, which is also the internal size of the -// canvas -func (wnd *Window) FramebufferSize() (int, int) { - w, h := wnd.Window.GLGetDrawableSize() - return int(w), int(h) -}