2
0
mirror of synced 2025-02-21 22:18:05 +00:00

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>
This commit is contained in:
David Crawshaw 2016-06-06 18:13:45 -04:00
parent d6153aa12b
commit b8e0f58304
9 changed files with 128 additions and 6 deletions

View File

@ -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

View File

@ -23,6 +23,8 @@ type fnargs struct {
a5 uintptr
a6 uintptr
a7 uintptr
a8 uintptr
a9 uintptr
}
type glfn int
@ -41,6 +43,7 @@ const (
glfnBlendEquationSeparate
glfnBlendFunc
glfnBlendFuncSeparate
glfnBlitFramebuffer
glfnBufferData
glfnBufferSubData
glfnCheckFramebufferStatus

View File

@ -103,6 +103,13 @@ func main() {
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 @@ func main() {
)
// 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, ", ")

View File

@ -1679,3 +1679,21 @@ func (ctx *context) Viewport(x, y, width, height int) {
},
})
}
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(),
},
})
}

View File

@ -2858,3 +2858,25 @@ func (ctx *context) Viewport(x, y, width, height int) {
},
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})
}

View File

@ -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 @@ type Context interface {
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,

View File

@ -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 @@ uintptr_t processFn(struct fnargs* args, char* parg) {
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;

View File

@ -12,6 +12,7 @@ package gl
#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 @@ type context struct {
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 @@ func NewContext() (Context, Worker) {
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 {

View File

@ -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 @@ typedef enum {
glfnBlendEquationSeparate,
glfnBlendFunc,
glfnBlendFuncSeparate,
glfnBlitFramebuffer,
glfnBufferData,
glfnBufferSubData,
glfnCheckFramebufferStatus,
@ -173,6 +188,8 @@ struct fnargs {
uintptr_t a5;
uintptr_t a6;
uintptr_t a7;
uintptr_t a8;
uintptr_t a9;
};
extern uintptr_t processFn(struct fnargs* args, char* parg);