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  }