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