OpenGL context sharing
This commit is contained in:
parent
6642c114f7
commit
0562755be9
|
@ -70,6 +70,9 @@
|
||||||
(class orig-gl-context%
|
(class orig-gl-context%
|
||||||
(init-field agl)
|
(init-field agl)
|
||||||
|
|
||||||
|
(define/override (get-handle)
|
||||||
|
agl)
|
||||||
|
|
||||||
(define/override (do-call-as-current t)
|
(define/override (do-call-as-current t)
|
||||||
(dynamic-wind
|
(dynamic-wind
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
@ -107,7 +110,9 @@
|
||||||
bitmap%))
|
bitmap%))
|
||||||
|
|
||||||
(define (create-gl-bitmap w h conf)
|
(define (create-gl-bitmap w h conf)
|
||||||
(let ([fmt (aglChoosePixelFormat
|
(let* ([share-context (send conf get-share-context)]
|
||||||
|
[context-handle (if share-context (send share-context get-handle) #f)]
|
||||||
|
[fmt (aglChoosePixelFormat
|
||||||
#f
|
#f
|
||||||
0
|
0
|
||||||
(append
|
(append
|
||||||
|
@ -132,9 +137,9 @@
|
||||||
AGL_SAMPLES_ARB ms)))
|
AGL_SAMPLES_ARB ms)))
|
||||||
(list AGL_NONE)))])
|
(list AGL_NONE)))])
|
||||||
(and fmt
|
(and fmt
|
||||||
(let ([agl (aglCreateContext fmt #f)]
|
(let ([agl (aglCreateContext fmt context-handle)]
|
||||||
[d-agl (or dummy-agl
|
[d-agl (or dummy-agl
|
||||||
(let ([d (aglCreateContext fmt #f)])
|
(let ([d (aglCreateContext fmt context-handle)])
|
||||||
(when d
|
(when d
|
||||||
(set! dummy-agl d)
|
(set! dummy-agl d)
|
||||||
d)))])
|
d)))])
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
(import-class NSView NSGraphicsContext NSScroller NSComboBox NSWindow
|
(import-class NSView NSGraphicsContext NSScroller NSComboBox NSWindow
|
||||||
NSImageView NSTextFieldCell
|
NSImageView NSTextFieldCell
|
||||||
NSOpenGLView NSOpenGLPixelFormat)
|
NSOpenGLView NSOpenGLContext NSOpenGLPixelFormat)
|
||||||
|
|
||||||
(import-protocol NSComboBoxDelegate)
|
(import-protocol NSComboBoxDelegate)
|
||||||
|
|
||||||
|
@ -354,12 +354,25 @@
|
||||||
(tell (tell (if is-combo? RacketComboBox RacketView)
|
(tell (tell (if is-combo? RacketComboBox RacketView)
|
||||||
alloc)
|
alloc)
|
||||||
initWithFrame: #:type _NSRect r)
|
initWithFrame: #:type _NSRect r)
|
||||||
(let ([pf (gl-config->pixel-format gl-config)])
|
(let* ([share-context (send gl-config get-share-context)]
|
||||||
(begin0
|
[context-handle (and share-context (send share-context get-handle))]
|
||||||
(tell (tell RacketGLView alloc)
|
[pf (gl-config->pixel-format gl-config)]
|
||||||
|
[new-context (and
|
||||||
|
context-handle
|
||||||
|
(tell (tell NSOpenGLContext alloc)
|
||||||
|
initWithFormat: pf
|
||||||
|
shareContext: context-handle))]
|
||||||
|
[gl-view (tell (tell RacketGLView alloc)
|
||||||
initWithFrame: #:type _NSRect r
|
initWithFrame: #:type _NSRect r
|
||||||
pixelFormat: pf)
|
pixelFormat: pf)])
|
||||||
(tellv pf release)))))))
|
(when new-context
|
||||||
|
(tellv gl-view setOpenGLContext: new-context)
|
||||||
|
;; We're supposed to sync via `setView:' but it fails,
|
||||||
|
;; perhaps because the view isn't yet visible:
|
||||||
|
;; (tellv new-context setView: gl-view)
|
||||||
|
(tellv new-context release))
|
||||||
|
(tellv pf release)
|
||||||
|
gl-view)))))
|
||||||
(tell #:type _void cocoa addSubview: content-cocoa)
|
(tell #:type _void cocoa addSubview: content-cocoa)
|
||||||
(set-ivar! content-cocoa wxb (->wxb this))
|
(set-ivar! content-cocoa wxb (->wxb this))
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
(let ([gl-ctx (tell (send canvas get-cocoa-content) openGLContext)])
|
(let ([gl-ctx (tell (send canvas get-cocoa-content) openGLContext)])
|
||||||
(or gl
|
(or gl
|
||||||
(let ([g (new (class gl-context%
|
(let ([g (new (class gl-context%
|
||||||
|
(define/override (get-handle) gl-ctx)
|
||||||
(define/override (do-call-as-current t)
|
(define/override (do-call-as-current t)
|
||||||
(dynamic-wind
|
(dynamic-wind
|
||||||
(lambda () (tellv gl-ctx makeCurrentContext))
|
(lambda () (tellv gl-ctx makeCurrentContext))
|
||||||
|
|
|
@ -123,6 +123,8 @@
|
||||||
(init-field [gl gl]
|
(init-field [gl gl]
|
||||||
[drawable drawable])
|
[drawable drawable])
|
||||||
|
|
||||||
|
(define/override (get-handle) gl)
|
||||||
|
|
||||||
(define/override (draw:do-call-as-current t)
|
(define/override (draw:do-call-as-current t)
|
||||||
(dynamic-wind
|
(dynamic-wind
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
@ -146,14 +148,17 @@
|
||||||
|
|
||||||
(define (prepare-widget-gl-context gtk config)
|
(define (prepare-widget-gl-context gtk config)
|
||||||
(init!)
|
(init!)
|
||||||
(let ([config (config->GdkGLConfig #f ; (gtk_widget_get_screen gtk)
|
(let ([share-context (send config get-share-context)]
|
||||||
|
[config (config->GdkGLConfig #f ; (gtk_widget_get_screen gtk)
|
||||||
(or config
|
(or config
|
||||||
(new gl-config%))
|
(new gl-config%))
|
||||||
#t)])
|
#t)])
|
||||||
(when config
|
(when config
|
||||||
(gtk_widget_set_gl_capability gtk
|
(gtk_widget_set_gl_capability gtk
|
||||||
config
|
config
|
||||||
#f
|
(if share-context
|
||||||
|
(send share-context get-handle)
|
||||||
|
#f)
|
||||||
#t
|
#t
|
||||||
0))))
|
0))))
|
||||||
|
|
||||||
|
@ -172,7 +177,9 @@
|
||||||
|
|
||||||
(define (create-and-install-gl-context bm config)
|
(define (create-and-install-gl-context bm config)
|
||||||
(init!)
|
(init!)
|
||||||
(let ([config (config->GdkGLConfig #f config #f)])
|
(let* ([share-context (send config get-share-context)]
|
||||||
|
[context-handle (if share-context (send share-context get-handle) #f)]
|
||||||
|
[config (config->GdkGLConfig #f config #f)])
|
||||||
(when config
|
(when config
|
||||||
(let ([gdkpx (send bm get-gdk-pixmap)])
|
(let ([gdkpx (send bm get-gdk-pixmap)])
|
||||||
(let ([glpx (gdk_pixmap_set_gl_capability gdkpx config #f)])
|
(let ([glpx (gdk_pixmap_set_gl_capability gdkpx config #f)])
|
||||||
|
@ -180,7 +187,7 @@
|
||||||
(let ([gl
|
(let ([gl
|
||||||
;; currently uses "indirect" mode --- can we
|
;; currently uses "indirect" mode --- can we
|
||||||
;; reliably use direct in some environments?
|
;; reliably use direct in some environments?
|
||||||
(gdk_gl_context_new glpx #f #f GDK_GL_RGBA_TYPE)])
|
(gdk_gl_context_new glpx context-handle #f GDK_GL_RGBA_TYPE)])
|
||||||
(and gl
|
(and gl
|
||||||
(send bm install-gl-context
|
(send bm install-gl-context
|
||||||
(new gl-context%
|
(new gl-context%
|
||||||
|
|
|
@ -71,6 +71,9 @@
|
||||||
(define tried-multisample? #f)
|
(define tried-multisample? #f)
|
||||||
(define wglChoosePixelFormatARB #f)
|
(define wglChoosePixelFormatARB #f)
|
||||||
|
|
||||||
|
(define looked-for-createcontextattribs? #f)
|
||||||
|
(define wglCreateContextAttribsARB #f)
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
(define gl-context%
|
(define gl-context%
|
||||||
|
@ -78,6 +81,8 @@
|
||||||
(init-field [hglrc hglrc]
|
(init-field [hglrc hglrc]
|
||||||
[hdc hdc])
|
[hdc hdc])
|
||||||
|
|
||||||
|
(define/override (get-handle) hglrc)
|
||||||
|
|
||||||
(define/override (draw:do-call-as-current t)
|
(define/override (draw:do-call-as-current t)
|
||||||
(dynamic-wind
|
(dynamic-wind
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
@ -119,6 +124,7 @@
|
||||||
(define (create-gl-context hdc config offscreen?
|
(define (create-gl-context hdc config offscreen?
|
||||||
#:try-ms? [try-ms? (not offscreen?)])
|
#:try-ms? [try-ms? (not offscreen?)])
|
||||||
(when try-ms? (unless tried-multisample? (init-multisample! config)))
|
(when try-ms? (unless tried-multisample? (init-multisample! config)))
|
||||||
|
(unless looked-for-createcontextattribs? (init-createcontextattribs! config))
|
||||||
(let* ([config (or config (new gl-config%))]
|
(let* ([config (or config (new gl-config%))]
|
||||||
[accum (send config get-accum-size)]
|
[accum (send config get-accum-size)]
|
||||||
[pfd
|
[pfd
|
||||||
|
@ -156,7 +162,9 @@
|
||||||
wglChoosePixelFormatARB
|
wglChoosePixelFormatARB
|
||||||
(or (choose-multisample hdc config offscreen? ms)
|
(or (choose-multisample hdc config offscreen? ms)
|
||||||
(choose-multisample hdc config offscreen? 2)))
|
(choose-multisample hdc config offscreen? 2)))
|
||||||
(ChoosePixelFormat hdc pfd))])
|
(ChoosePixelFormat hdc pfd))]
|
||||||
|
[share-context (send config get-share-context)]
|
||||||
|
[context-handle (if share-context (send share-context get-handle) #f)])
|
||||||
(and (not (zero? pixelFormat))
|
(and (not (zero? pixelFormat))
|
||||||
(and (SetPixelFormat hdc pixelFormat pfd)
|
(and (SetPixelFormat hdc pixelFormat pfd)
|
||||||
(begin
|
(begin
|
||||||
|
@ -164,20 +172,18 @@
|
||||||
(when (not (zero? (bitwise-and (PIXELFORMATDESCRIPTOR-dwFlags pfd)
|
(when (not (zero? (bitwise-and (PIXELFORMATDESCRIPTOR-dwFlags pfd)
|
||||||
PFD_NEED_PALETTE)))
|
PFD_NEED_PALETTE)))
|
||||||
(log-error "don't know how to create a GL palette, yet"))
|
(log-error "don't know how to create a GL palette, yet"))
|
||||||
(let ([hglrc (wglCreateContext hdc)])
|
(let ([hglrc (if wglCreateContextAttribsARB
|
||||||
|
(wglCreateContextAttribsARB hdc context-handle (vector 0))
|
||||||
|
(wglCreateContext hdc))])
|
||||||
(and hglrc
|
(and hglrc
|
||||||
(new gl-context% [hglrc hglrc] [hdc hdc]))))))))
|
(new gl-context% [hglrc hglrc] [hdc hdc]))))))))
|
||||||
|
|
||||||
(define (init-multisample! config)
|
(define (with-dummy-context config thunk)
|
||||||
;; To create a multisampled context, we need
|
|
||||||
;; wglChoosePixelFormatARB().
|
|
||||||
;; To look up wglChoosePixelFormatARB(), we need
|
|
||||||
;; an existing gl context.
|
|
||||||
;; To create a gl context, we need a separate window
|
;; To create a gl context, we need a separate window
|
||||||
;; (because you can't change a window's pixel format
|
;; (because you can't change a window's pixel format
|
||||||
;; after it is set).
|
;; after it is set).
|
||||||
;; So, create a dummy window to make a context to
|
;; So, create a dummy window to make a context to
|
||||||
;; try to get wglChoosePixelFormatARB().
|
;; try to do whatever needs doing.
|
||||||
(let ([hwnd (CreateWindowExW 0
|
(let ([hwnd (CreateWindowExW 0
|
||||||
"PLTFrame"
|
"PLTFrame"
|
||||||
""
|
""
|
||||||
|
@ -194,6 +200,30 @@
|
||||||
(call-with-context
|
(call-with-context
|
||||||
(get-field hdc c)
|
(get-field hdc c)
|
||||||
(get-field hglrc c)
|
(get-field hglrc c)
|
||||||
|
thunk)))
|
||||||
|
(ReleaseDC hwnd hdc)))))
|
||||||
|
|
||||||
|
(define (init-createcontextattribs! config)
|
||||||
|
;; look for wglCreateContextAttribsARB which is a beefed
|
||||||
|
;; up version of wglCreateContext
|
||||||
|
(set! looked-for-createcontextattribs? #t)
|
||||||
|
(with-dummy-context config
|
||||||
|
(lambda ()
|
||||||
|
(set! wglCreateContextAttribsARB
|
||||||
|
(let ([f (wglGetProcAddress "wglCreateContextAttribsARB")])
|
||||||
|
(and f
|
||||||
|
((allocator wglDeleteContext)
|
||||||
|
(function-ptr f (_wfun _HDC
|
||||||
|
_HGLRC
|
||||||
|
(_vector i _int)
|
||||||
|
-> _HGLRC)))))))))
|
||||||
|
|
||||||
|
(define (init-multisample! config)
|
||||||
|
;; To create a multisampled context, we need
|
||||||
|
;; wglChoosePixelFormatARB().
|
||||||
|
;; To look up wglChoosePixelFormatARB(), we need
|
||||||
|
;; an existing gl context.
|
||||||
|
(with-dummy-context config
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(set! wglChoosePixelFormatARB
|
(set! wglChoosePixelFormatARB
|
||||||
(let ([f (wglGetProcAddress "wglChoosePixelFormatARB")])
|
(let ([f (wglGetProcAddress "wglChoosePixelFormatARB")])
|
||||||
|
@ -206,8 +236,7 @@
|
||||||
(num-formats : (_ptr o _UINT))
|
(num-formats : (_ptr o _UINT))
|
||||||
-> (r : _BOOL)
|
-> (r : _BOOL)
|
||||||
-> (and r formats))))))
|
-> (and r formats))))))
|
||||||
(set! tried-multisample? #t)))))
|
(set! tried-multisample? #t))))
|
||||||
(ReleaseDC hwnd hdc)))))
|
|
||||||
|
|
||||||
(define GL_TRUE 1)
|
(define GL_TRUE 1)
|
||||||
(define GL_FALSE 0)
|
(define GL_FALSE 0)
|
||||||
|
|
|
@ -392,7 +392,8 @@
|
||||||
(set-double-buffered (->m any/c void?))
|
(set-double-buffered (->m any/c void?))
|
||||||
(set-multisample-size (->m (integer-in 0 256) void?))
|
(set-multisample-size (->m (integer-in 0 256) void?))
|
||||||
(set-stencil-size (->m (integer-in 0 256) void?))
|
(set-stencil-size (->m (integer-in 0 256) void?))
|
||||||
(set-stereo (->m any/c void?))))
|
(set-stereo (->m any/c void?))
|
||||||
|
(set-share-context (->m (or/c (is-a?/c gl-context%) #f) void?))))
|
||||||
|
|
||||||
(define bitmap%/c
|
(define bitmap%/c
|
||||||
(class/c
|
(class/c
|
||||||
|
|
|
@ -33,4 +33,9 @@
|
||||||
(define multisample-size 0)
|
(define multisample-size 0)
|
||||||
(define/public (get-multisample-size) multisample-size)
|
(define/public (get-multisample-size) multisample-size)
|
||||||
(define/public (set-multisample-size s)
|
(define/public (set-multisample-size s)
|
||||||
(set! multisample-size s)))
|
(set! multisample-size s))
|
||||||
|
|
||||||
|
(define share-context #f)
|
||||||
|
(define/public (get-share-context) share-context)
|
||||||
|
(define/public (set-share-context s)
|
||||||
|
(set! share-context s)))
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
(interface ()
|
(interface ()
|
||||||
[call-as-current (->*m [(-> any)] [evt? any/c] any)]
|
[call-as-current (->*m [(-> any)] [evt? any/c] any)]
|
||||||
[ok? (->m boolean?)]
|
[ok? (->m boolean?)]
|
||||||
[swap-buffers (->m any)]))
|
[swap-buffers (->m any)]
|
||||||
|
[get-handle (->m any)]))
|
||||||
|
|
||||||
;; Implemented by subclasses:
|
;; Implemented by subclasses:
|
||||||
(define gl-context%
|
(define gl-context%
|
||||||
|
@ -63,6 +64,9 @@
|
||||||
(channel-put ch #t))))))
|
(channel-put ch #t))))))
|
||||||
alternate-evt)))
|
alternate-evt)))
|
||||||
|
|
||||||
|
(define/public (get-handle)
|
||||||
|
#f)
|
||||||
|
|
||||||
(define/public (call-as-current t [alternate-evt never-evt] [enable-breaks? #f])
|
(define/public (call-as-current t [alternate-evt never-evt] [enable-breaks? #f])
|
||||||
(with-gl-lock
|
(with-gl-lock
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
|
|
@ -49,6 +49,18 @@ Reports the multisampling size that the configuration requests, where
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defmethod[(get-share-context)
|
||||||
|
(or/c #f (is-a?/c gl-context<%>))]{
|
||||||
|
|
||||||
|
Returns a @racket[gl-context<%>] object that shares certain objects
|
||||||
|
(textures, display lists, etc.) with newly created OpenGL drawing
|
||||||
|
contexts, or @racket[#f] is none is set.
|
||||||
|
|
||||||
|
See also @method[gl-config% set-share-context].
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@defmethod[(get-stencil-size)
|
@defmethod[(get-stencil-size)
|
||||||
(integer-in 0 256)]{
|
(integer-in 0 256)]{
|
||||||
|
|
||||||
|
@ -97,6 +109,27 @@ Adjusts the configuration to request a particular multisample size,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defmethod[(set-share-context [context (or/c #f (is-a?/c gl-context<%>))])
|
||||||
|
void?]{
|
||||||
|
|
||||||
|
Determines a @racket[gl-context<%>] object that shares certain objects
|
||||||
|
(textures, display lists, etc.) with newly created OpenGL drawing
|
||||||
|
contexts, where @racket[#f] indicates
|
||||||
|
that no sharing should occur.
|
||||||
|
|
||||||
|
When a context @racket[_B] shares objects with context @racket[_A], it
|
||||||
|
is also shares objects with every other context sharing with
|
||||||
|
@racket[_A], and vice versa.
|
||||||
|
|
||||||
|
If an OpenGL implementation does not support sharing, @racket[context]
|
||||||
|
is effectively ignored when a new context is created.
|
||||||
|
Sharing should be supported in all versions of Mac OS X.
|
||||||
|
On Windows and Linux, sharing is provided by the presence of the
|
||||||
|
@tt{WGL_ARB_create_context} and @tt{GLX_ARB_create_context} extensions,
|
||||||
|
respectively (and OpenGL 3.2 requires both).
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@defmethod[(set-stencil-size [on? (integer-in 0 256)])
|
@defmethod[(set-stencil-size [on? (integer-in 0 256)])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#lang scribble/doc
|
#lang scribble/doc
|
||||||
@(require "common.rkt")
|
@(require "common.rkt"
|
||||||
|
(for-label (only-in ffi/unsafe cpointer?)))
|
||||||
|
|
||||||
@definterface/title[gl-context<%> ()]{
|
@definterface/title[gl-context<%> ()]{
|
||||||
|
|
||||||
|
@ -76,6 +77,22 @@ If @racket[enable-breaks?] is true, then the method uses
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defmethod[(get-handle) cpointer?]{
|
||||||
|
|
||||||
|
Returns a handle to the platform's underlying context. The value that the
|
||||||
|
pointer represents depends on the platform:
|
||||||
|
|
||||||
|
@itemize[
|
||||||
|
@item{Windows: @tt{HGLRC}}
|
||||||
|
@item{Mac OS X: @tt{NSOpenGLContext}}
|
||||||
|
@item{Unix: @tt{GdkGLContext}}
|
||||||
|
]
|
||||||
|
|
||||||
|
Note that these values are not necessary the most ``low-level'' context objects,
|
||||||
|
but are instead the ones useful to Racket. A @tt{NSOpenGLContext} wraps a
|
||||||
|
@tt{CGLContextObj}, and a @tt{GdkGLContext} contains a @tt{GLXcontext}.
|
||||||
|
}
|
||||||
|
|
||||||
@defmethod[(ok?)
|
@defmethod[(ok?)
|
||||||
boolean?]{
|
boolean?]{
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user