gioui.org/ui@v0.0.0-20190926171558-ce74bc0cbaea/app/gl_ios.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 // +build darwin,ios 4 5 package app 6 7 /* 8 #cgo CFLAGS: -fmodules -fobjc-arc -x objective-c 9 10 #include <CoreFoundation/CoreFoundation.h> 11 #include <OpenGLES/ES2/gl.h> 12 #include <OpenGLES/ES2/glext.h> 13 #include "gl_ios.h" 14 */ 15 import "C" 16 17 import ( 18 "errors" 19 "fmt" 20 21 "gioui.org/ui/app/internal/gl" 22 ) 23 24 type context struct { 25 owner *window 26 c *gl.Functions 27 ctx C.CFTypeRef 28 layer C.CFTypeRef 29 init bool 30 frameBuffer gl.Framebuffer 31 colorBuffer, depthBuffer gl.Renderbuffer 32 } 33 34 func init() { 35 layerFactory = func() uintptr { 36 return uintptr(C.gio_createGLLayer()) 37 } 38 } 39 40 func newContext(w *window) (*context, error) { 41 ctx := C.gio_createContext() 42 if ctx == 0 { 43 return nil, fmt.Errorf("failed to create EAGLContext") 44 } 45 c := &context{ 46 ctx: ctx, 47 owner: w, 48 layer: C.CFTypeRef(w.contextLayer()), 49 c: new(gl.Functions), 50 } 51 return c, nil 52 } 53 54 func (c *context) Functions() *gl.Functions { 55 return c.c 56 } 57 58 func (c *context) Release() { 59 if c.ctx == 0 { 60 return 61 } 62 C.gio_renderbufferStorage(c.ctx, 0, C.GLenum(gl.RENDERBUFFER)) 63 c.c.DeleteFramebuffer(c.frameBuffer) 64 c.c.DeleteRenderbuffer(c.colorBuffer) 65 c.c.DeleteRenderbuffer(c.depthBuffer) 66 C.gio_makeCurrent(0) 67 C.CFRelease(c.ctx) 68 c.ctx = 0 69 } 70 71 func (c *context) Present() error { 72 if c.layer == 0 { 73 panic("context is not active") 74 } 75 // Discard depth buffer as recommended in 76 // https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html 77 c.c.BindFramebuffer(gl.FRAMEBUFFER, c.frameBuffer) 78 c.c.InvalidateFramebuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT) 79 c.c.BindRenderbuffer(gl.RENDERBUFFER, c.colorBuffer) 80 if C.gio_presentRenderbuffer(c.ctx, C.GLenum(gl.RENDERBUFFER)) == 0 { 81 return errors.New("presentRenderBuffer failed") 82 } 83 return nil 84 } 85 86 func (c *context) Lock() {} 87 88 func (c *context) Unlock() {} 89 90 func (c *context) MakeCurrent() error { 91 if C.gio_makeCurrent(c.ctx) == 0 { 92 C.CFRelease(c.ctx) 93 c.ctx = 0 94 return errors.New("[EAGLContext setCurrentContext] failed") 95 } 96 if !c.init { 97 c.init = true 98 c.frameBuffer = c.c.CreateFramebuffer() 99 c.colorBuffer = c.c.CreateRenderbuffer() 100 c.depthBuffer = c.c.CreateRenderbuffer() 101 } 102 if !c.owner.isVisible() { 103 // Make sure any in-flight GL commands are complete. 104 c.c.Finish() 105 return nil 106 } 107 currentRB := gl.Renderbuffer{uint(c.c.GetInteger(gl.RENDERBUFFER_BINDING))} 108 c.c.BindRenderbuffer(gl.RENDERBUFFER, c.colorBuffer) 109 if C.gio_renderbufferStorage(c.ctx, c.layer, C.GLenum(gl.RENDERBUFFER)) == 0 { 110 return errors.New("renderbufferStorage failed") 111 } 112 w := c.c.GetRenderbufferParameteri(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH) 113 h := c.c.GetRenderbufferParameteri(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT) 114 c.c.BindRenderbuffer(gl.RENDERBUFFER, c.depthBuffer) 115 c.c.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h) 116 c.c.BindRenderbuffer(gl.RENDERBUFFER, currentRB) 117 c.c.BindFramebuffer(gl.FRAMEBUFFER, c.frameBuffer) 118 c.c.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, c.colorBuffer) 119 c.c.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, c.depthBuffer) 120 if st := c.c.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE { 121 return fmt.Errorf("framebuffer incomplete, status: %#x\n", st) 122 } 123 return nil 124 }