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  }