gl: support for GL ES 3.0
This CL covers the basic structure for supporting ES 3.0 where the
platform provides it, and includes one ES 3.0 function as a
proof-of-concept. The rest of the functions and constant values will
follow in later CLs.
ES 3.0 is available everywhere except Android older than
version 4.3, approximately half of Android devices today:
https://developer.android.com/about/dashboards/index.html#OpenGL
Change-Id: Ief7714131227c447a0c603dadad0bd5285999bb3
Reviewed-on: https://go-review.googlesource.com/23821
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/gl/doc.go b/gl/doc.go
index 1ea6efb..1eb1d77 100644
--- a/gl/doc.go
+++ b/gl/doc.go
@@ -3,7 +3,15 @@
// license that can be found in the LICENSE file.
/*
-Package gl implements Go bindings for OpenGL ES 2.
+Package gl implements Go bindings for OpenGL ES 2.0 and ES 3.0.
+
+The GL functions are defined on a Context object that is responsible for
+tracking a GL context. Typically a windowing system package (such as
+golang.org/x/exp/shiny/screen) will call NewContext and provide
+a gl.Context for a user application.
+
+If the gl package is compiled on a platform capable of supporting ES 3.0,
+the gl.Context object also implements gl.Context3.
The bindings are deliberately minimal, staying as close the C API as
possible. The semantics of each function maps onto functions
diff --git a/gl/fn.go b/gl/fn.go
index b4de7d5..a3fe0a6 100644
--- a/gl/fn.go
+++ b/gl/fn.go
@@ -23,6 +23,8 @@
a5 uintptr
a6 uintptr
a7 uintptr
+ a8 uintptr
+ a9 uintptr
}
type glfn int
@@ -41,6 +43,7 @@
glfnBlendEquationSeparate
glfnBlendFunc
glfnBlendFuncSeparate
+ glfnBlitFramebuffer
glfnBufferData
glfnBufferSubData
glfnCheckFramebufferStatus
diff --git a/gl/gendebug.go b/gl/gendebug.go
index 861ca19..57b966e 100644
--- a/gl/gendebug.go
+++ b/gl/gendebug.go
@@ -103,6 +103,13 @@
if fn.Recv == nil || fn.Recv.List[0].Names[0].Name != "ctx" {
continue
}
+ tname := "<unknown>"
+ t := fn.Recv.List[0].Type
+ if star, ok := t.(*ast.StarExpr); ok {
+ tname = "*" + star.X.(*ast.Ident).Name
+ } else if t, ok := t.(*ast.Ident); ok {
+ tname = t.Name
+ }
var (
params []string
@@ -112,7 +119,7 @@
)
// Print function signature.
- fmt.Fprintf(buf, "func (ctx *context) %s(", fn.Name.Name)
+ fmt.Fprintf(buf, "func (ctx %s) %s(", tname, fn.Name.Name)
for i, p := range fn.Type.Params.List {
if i > 0 {
fmt.Fprint(buf, ", ")
diff --git a/gl/gl.go b/gl/gl.go
index 71b0ee3..d9d0184 100644
--- a/gl/gl.go
+++ b/gl/gl.go
@@ -1679,3 +1679,21 @@
},
})
}
+
+func (ctx context3) BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) {
+ ctx.enqueue(call{
+ args: fnargs{
+ fn: glfnBlitFramebuffer,
+ a0: uintptr(srcX0),
+ a1: uintptr(srcY0),
+ a2: uintptr(srcX1),
+ a3: uintptr(srcY1),
+ a4: uintptr(dstX0),
+ a5: uintptr(dstY0),
+ a6: uintptr(dstX1),
+ a7: uintptr(dstY1),
+ a8: uintptr(mask),
+ a9: filter.c(),
+ },
+ })
+}
diff --git a/gl/gldebug.go b/gl/gldebug.go
index 2c718ff..8dde6df 100644
--- a/gl/gldebug.go
+++ b/gl/gldebug.go
@@ -2858,3 +2858,25 @@
},
blocking: true})
}
+
+func (ctx context3) BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) {
+ defer func() {
+ errstr := ctx.errDrain()
+ log.Printf("gl.BlitFramebuffer(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v) %v", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, errstr)
+ }()
+ ctx.enqueueDebug(call{
+ args: fnargs{
+ fn: glfnBlitFramebuffer,
+ a0: uintptr(srcX0),
+ a1: uintptr(srcY0),
+ a2: uintptr(srcX1),
+ a3: uintptr(srcY1),
+ a4: uintptr(dstX0),
+ a5: uintptr(dstY0),
+ a6: uintptr(dstX1),
+ a7: uintptr(dstY1),
+ a8: uintptr(mask),
+ a9: filter.c(),
+ },
+ blocking: true})
+}
diff --git a/gl/interface.go b/gl/interface.go
index cf02587..8c93954 100644
--- a/gl/interface.go
+++ b/gl/interface.go
@@ -4,7 +4,15 @@
package gl
-// Context is an OpenGL context.
+// Context is an OpenGL ES context.
+//
+// A Context has a method for every GL function supported by ES 2 or later.
+// In a program compiled with ES 3 support, a Context is also a Context3.
+// For example, a program can:
+//
+// func f(glctx gl.Context) {
+// glctx.(gl.Context3).BlitFramebuffer(...)
+// }
//
// Calls are not safe for concurrent use. However calls can be made from
// any goroutine, the gl package removes the notion of thread-local
@@ -816,6 +824,19 @@
Viewport(x, y, width, height int)
}
+// Context3 is an OpenGL ES 3 context.
+//
+// When the gl package is compiled with GL ES 3 support, the produced
+// Context object also implements the Context3 interface.
+type Context3 interface {
+ Context
+
+ // BlitFramebuffer copies a block of pixels between framebuffers.
+ //
+ // https://www.khronos.org/opengles/sdk/docs/man3/html/glBlitFramebuffer.xhtml
+ BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum)
+}
+
// Worker is used by display driver code to execute OpenGL calls.
//
// Typically display driver code creates a gl.Context for an application,
diff --git a/gl/work.c b/gl/work.c
index 6e7f76d..8f259f7 100644
--- a/gl/work.c
+++ b/gl/work.c
@@ -8,6 +8,15 @@
#include "_cgo_export.h"
#include "work.h"
+#if defined(GL_ES_VERSION_3_0) && GL_ES_VERSION_3_0
+#else
+#include <stdio.h>
+void glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
+ printf("GLES3 function is missing\n");
+ exit(2);
+}
+#endif
+
uintptr_t processFn(struct fnargs* args, char* parg) {
uintptr_t ret = 0;
switch (args->fn) {
@@ -50,6 +59,9 @@
case glfnBlendFuncSeparate:
glBlendFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3);
break;
+ case glfnBlitFramebuffer:
+ glBlitFramebuffer((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7, (GLbitfield)args->a8, (GLenum)args->a9);
+ break;
case glfnBufferData:
glBufferData((GLenum)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg, (GLenum)args->a2);
break;
diff --git a/gl/work.go b/gl/work.go
index 65fdc42..b6b8c0d 100644
--- a/gl/work.go
+++ b/gl/work.go
@@ -12,6 +12,7 @@
#cgo darwin,arm64 LDFLAGS: -framework OpenGLES
#cgo linux LDFLAGS: -lGLESv2
+#cgo android CFLAGS: -Dos_android
#cgo darwin,amd64 CFLAGS: -Dos_osx
#cgo darwin,arm CFLAGS: -Dos_ios
#cgo darwin,arm64 CFLAGS: -Dos_ios
@@ -66,6 +67,10 @@
func (ctx *context) WorkAvailable() <-chan struct{} { return ctx.workAvailable }
+type context3 struct {
+ *context
+}
+
// NewContext creates a cgo OpenGL context.
//
// See the Worker interface for more details on how it is used.
@@ -75,7 +80,16 @@
work: make(chan call, workbufLen),
retvalue: make(chan C.uintptr_t),
}
- return glctx, glctx
+ if C.GLES_VERSION == "GL_ES_2_0" {
+ return glctx, glctx
+ }
+ return context3{glctx}, glctx
+}
+
+// Version returns a GL ES version string, either "GL_ES_2_0" or "GL_ES_3_0".
+// Future versions of the gl package may return "GL_ES_3_1".
+func Version() string {
+ return C.GLES_VERSION
}
func (ctx *context) enqueue(c call) uintptr {
diff --git a/gl/work.h b/gl/work.h
index 1a090f3..3d9a81b 100644
--- a/gl/work.h
+++ b/gl/work.h
@@ -2,16 +2,30 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#ifdef os_linux
-#include <GLES2/gl2.h> // install on Ubuntu with: sudo apt-get install libegl1-mesa-dev libgles2-mesa-dev libx11-dev
+#ifdef os_android
+// TODO(crawshaw): We could include <android/api-level.h> and
+// condition on __ANDROID_API__ to get GLES3 headers. However
+// we also need to add -lGLESv3 to LDFLAGS, which we cannot do
+// from inside an ifdef.
+#include <GLES2/gl2.h>
+#elif os_linux
+#include <GLES3/gl3.h> // install on Ubuntu with: sudo apt-get install libegl1-mesa-dev libgles2-mesa-dev libx11-dev
#endif
+
#ifdef os_ios
#include <OpenGLES/ES2/glext.h>
#endif
+
#ifdef os_osx
#include <OpenGL/gl3.h>
#endif
+#if defined(GL_ES_VERSION_3_0) && GL_ES_VERSION_3_0
+#define GLES_VERSION "GL_ES_3_0"
+#else
+#define GLES_VERSION "GL_ES_2_0"
+#endif
+
#include <stdint.h>
#include <stdlib.h>
@@ -31,6 +45,7 @@
glfnBlendEquationSeparate,
glfnBlendFunc,
glfnBlendFuncSeparate,
+ glfnBlitFramebuffer,
glfnBufferData,
glfnBufferSubData,
glfnCheckFramebufferStatus,
@@ -173,6 +188,8 @@
uintptr_t a5;
uintptr_t a6;
uintptr_t a7;
+ uintptr_t a8;
+ uintptr_t a9;
};
extern uintptr_t processFn(struct fnargs* args, char* parg);