gl_macos.go raw

   1  // SPDX-License-Identifier: Unlicense OR MIT
   2  
   3  // +build darwin,!ios
   4  
   5  package wm
   6  
   7  import (
   8  	"github.com/p9c/p9/pkg/gel/gio/gpu"
   9  	"github.com/p9c/p9/pkg/gel/gio/internal/gl"
  10  )
  11  
  12  /*
  13  #include <CoreFoundation/CoreFoundation.h>
  14  #include <CoreGraphics/CoreGraphics.h>
  15  #include <AppKit/AppKit.h>
  16  #include <OpenGL/gl3.h>
  17  
  18  __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLView(void);
  19  __attribute__ ((visibility ("hidden"))) CFTypeRef gio_contextForView(CFTypeRef viewRef);
  20  __attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx);
  21  __attribute__ ((visibility ("hidden"))) void gio_flushContextBuffer(CFTypeRef ctx);
  22  __attribute__ ((visibility ("hidden"))) void gio_clearCurrentContext(void);
  23  __attribute__ ((visibility ("hidden"))) void gio_lockContext(CFTypeRef ctxRef);
  24  __attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef);
  25  */
  26  import "C"
  27  
  28  type context struct {
  29  	c    *gl.Functions
  30  	ctx  C.CFTypeRef
  31  	view C.CFTypeRef
  32  }
  33  
  34  func init() {
  35  	viewFactory = func() C.CFTypeRef {
  36  		return C.gio_createGLView()
  37  	}
  38  }
  39  
  40  func newContext(w *window) (*context, error) {
  41  	view := w.contextView()
  42  	ctx := C.gio_contextForView(view)
  43  	c := &context{
  44  		ctx:  ctx,
  45  		view: view,
  46  	}
  47  	return c, nil
  48  }
  49  
  50  func (c *context) API() gpu.API {
  51  	return gpu.OpenGL{}
  52  }
  53  
  54  func (c *context) Release() {
  55  	c.Lock()
  56  	defer c.Unlock()
  57  	C.gio_clearCurrentContext()
  58  	// We could release the context with [view clearGLContext]
  59  	// and rely on [view openGLContext] auto-creating a new context.
  60  	// However that second context is not properly set up by
  61  	// OpenGLContextView, so we'll stay on the safe side and keep
  62  	// the first context around.
  63  }
  64  
  65  func (c *context) Present() error {
  66  	// Assume the caller already locked the context.
  67  	C.glFlush()
  68  	return nil
  69  }
  70  
  71  func (c *context) Lock() {
  72  	C.gio_lockContext(c.ctx)
  73  }
  74  
  75  func (c *context) Unlock() {
  76  	C.gio_unlockContext(c.ctx)
  77  }
  78  
  79  func (c *context) MakeCurrent() error {
  80  	c.Lock()
  81  	defer c.Unlock()
  82  	C.gio_makeCurrentContext(c.ctx)
  83  	return nil
  84  }
  85  
  86  func (w *window) NewContext() (Context, error) {
  87  	return newContext(w)
  88  }
  89