Port Cocotron to the new EGL-based OpenGL.framework

See darlinghq/darling#365

TODO:
* Get rid of the few remaining glX calls
* Port CALayerContext
This commit is contained in:
Sergey Bugaev 2018-05-27 08:20:55 +03:00
parent 452ec7a16f
commit 50a571eb4b
11 changed files with 117 additions and 128 deletions

View File

@ -14,6 +14,9 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
find_package(X11 REQUIRED)
find_package(Freetype REQUIRED)
# We do not link to host's libGL (directly),
# but we still need to include its headers
find_package(OpenGL REQUIRED)
find_package(PkgConfig REQUIRED)
@ -297,7 +300,7 @@ set(AppKit_sources
X11.subproj/X11SubWindow.m
X11.subproj/KTFont_FT.m
# O2Font_FT.m is built in Onyx2D
# CGLContext.m is built in OpenGL
# CGLContext.m no longer used
# X11.subproj/NSOpenGLDrawable_X11.m
# X11.subproj/O2Context_cairo.m
X11.subproj/X11Display.m
@ -391,14 +394,12 @@ add_framework(AppKit
Onyx2D
CoreText
CoreData
OpenGL
QuartzCore
CoreGraphics
# native libraries
FreeType
fontconfig
X11
GL
jpeg png tiff
CIRCULAR_DEPENDENCIES
OpenGL
QuartzCore
CoreGraphics
)

View File

@ -64,9 +64,14 @@ static inline void _clearCurrentContext(){
if(_currentContext()==self)
_clearCurrentContext();
[_pixelFormat release];
if (_cglWindow != NULL) {
CGLDestroyWindow(_cglWindow);
}
[_subwindow release];
_view=nil;
CGLReleaseContext(_glContext);
[super dealloc];
}
@ -107,57 +112,47 @@ static inline void _clearCurrentContext(){
if([_view window]!=nil)
rect=[_view convertRect:rect toView:nil];
GLint size[2]={
rect.size.width,
rect.size.height };
GLint origin[2]={
rect.origin.x,
rect.origin.y };
GLint hidden[1]= {
[_view isHidden] ? 1 : 0
};
CGLSetParameter(_glContext,kCGLCPSurfaceBackingSize,size);
CGLSetParameter(_glContext,kCGLCPSurfaceBackingOrigin,origin);
CGLSetParameter(_glContext,kCGLCPSurfaceHidden,hidden);
if (_subwindow == nil) {
_subwindow = [[[_view window] _createSubWindowWithFrame: rect] retain];
_cglWindow = CGLGetWindow([_subwindow nativeWindow]);
} else {
[_subwindow setFrame: rect];
}
if ([_view isHidden]) {
[_subwindow hide];
} else {
[_subwindow show];
}
}
-(void)setView:(NSView *)view {
if(_view!=view)
_hasPrepared=NO;
_view=view;
CGLLockContext(_glContext);
GLint num[1]={[[_view window] windowNumber]};
CGLSetParameter(_glContext,kCGLCPSurfaceWindowNumber,num);
[self update];
if (_view == view) return;
CGLUnlockContext(_glContext);
_hasPrepared = NO;
_view = view;
if (_cglWindow != NULL) {
CGLDestroyWindow(_cglWindow);
_cglWindow = NULL;
}
[_subwindow release];
_subwindow = nil;
[self updateViewParameters];
}
-(void)makeCurrentContext {
CGLError error;
if((error=CGLSetCurrentContext(_glContext))!=kCGLNoError)
NSLog(@"CGLSetCurrentContext failed with %d in %s %d",error,__FILE__,__LINE__);
_setCurrentContext(self);
#if 0
/*
We need to reload the view values when becoming current because it may
have moved windows since the last make current
*/
// Possible this shouldnt be done here, especially on a non-main thread
// Don't do this here due to threading reason. Figure out where to do this when moving windows, view _setWindow ?
[self updateViewParameters];
#endif
[self performSelectorOnMainThread: @selector(updateViewParameters)
withObject: nil
waitUntilDone: YES];
if((error=CGLContextMakeCurrentAndAttachToWindow(_glContext, _cglWindow))!=kCGLNoError)
NSLog(@"CGLSetCurrentContext failed with %d in %s %d",error,__FILE__,__LINE__);
_setCurrentContext(self);
if(!_hasPrepared){
_hasPrepared=YES;

View File

@ -26,6 +26,9 @@
#import <AppKit/NSFontManager.h>
#import <AppKit/NSFontTypeface.h>
#import <AppKit/NSWindow.h>
#import <OpenGL/CGLInternal.h>
#import <fcntl.h>
#import <fontconfig/fontconfig.h>
#import <X11/Xutil.h>
@ -94,6 +97,8 @@ static void socketCallback(
};
_cfSocket = CFSocketCreateWithNative(kCFAllocatorDefault, _fileDescriptor, kCFSocketReadCallBack, socketCallback, &context);
_source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _cfSocket, 0);
CGLRegisterNativeDisplay(_display);
#endif
_windowsByID=[NSMutableDictionary new];

View File

@ -17,35 +17,7 @@
_parent = parent;
frame = [self convertFrame: frame];
X11Display *x11Display = (X11Display *) [NSDisplay currentDisplay];
_display = x11Display.display;
/*
static const GLint attrs[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DEPTH_SIZE, 4,
None
};
int screen = DefaultScreen(_display);
// TODO: get rid of glX here
XVisualInfo *visualInfo = glXChooseVisual(display, screen, attrs);
Colormap cmap = XCreateColormap(
_display,
RootWindow(_display, visualInfo->screen),
visualInfo->visual,
AllocNone
);
XSetWindowAttributes xattr = {0};
xattr.colormap = cmap;
xattr.border_pixel = 0;
xattr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
*/
_display = [(X11Display *) [NSDisplay currentDisplay] display];
_window = XCreateSimpleWindow(
_display, [parent windowHandle],

View File

@ -10,7 +10,7 @@
#import <Onyx2D/O2Geometry.h>
#import <X11/Xlib.h>
#import <GL/glx.h>
#import <OpenGL/OpenGL.h>
#import <OpenGL/CGLInternal.h>
@class O2Context_cairo, X11Display, CAWindowOpenGLContext;
@ -20,6 +20,7 @@
XVisualInfo *_visualInfo;
Window _window;
CGLContextObj _cglContext;
CGLWindowRef _cglWindow;
CAWindowOpenGLContext *_caContext;
id _delegate;

View File

@ -64,7 +64,7 @@ void CGNativeBorderFrameWidthsForStyle(unsigned styleMask,CGFloat *top,CGFloat *
_frame=[self transformFrame:frame];
if(isPanel && styleMask&NSDocModalWindowMask)
styleMask=NSBorderlessWindowMask;
// TODO: get rid of these glX calls
GLint att[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
@ -108,6 +108,8 @@ void CGNativeBorderFrameWidthsForStyle(unsigned styleMask,CGFloat *top,CGFloat *
XSetWMProtocols(_display, _window, &atm , 1);
XSetWindowBackgroundPixmap(_display, _window, None);
_cglWindow = CGLGetWindow(_window);
[(X11Display*)[NSDisplay currentDisplay] setWindow:self forID:_window];
@ -119,7 +121,6 @@ void CGNativeBorderFrameWidthsForStyle(unsigned styleMask,CGFloat *top,CGFloat *
-(void)dealloc {
[self invalidate];
[_context release];
[_deviceDictionary release];
[super dealloc];
}
@ -168,10 +169,26 @@ void CGNativeBorderFrameWidthsForStyle(unsigned styleMask,CGFloat *top,CGFloat *
return _delegate;
}
-(void)invalidate {
_delegate=nil;
[_context release];
_context=nil;
-(void) invalidate {
// This is essentially dealloc; we release our contexts
// and windows, but unlike dealloc, this method can be called
// several times, so set everything to nil/NULL/0.
_delegate = nil;
[_context release];
_context = nil;
[_caContext release];
_caContext = nil;
if (_cglContext != NULL) {
CGLReleaseContext(_cglContext);
_cglContext = NULL;
}
if (_cglWindow != NULL) {
CGLDestroyWindow(_cglWindow);
_cglWindow = NULL;
}
if(_window) {
[(X11Display*)[NSDisplay currentDisplay] setWindow:nil forID:_window];
@ -301,37 +318,37 @@ void CGNativeBorderFrameWidthsForStyle(unsigned styleMask,CGFloat *top,CGFloat *
return NO;
}
CGL_EXPORT CGLError CGLCreateContextForWindow(CGLPixelFormatObj pixelFormat,CGLContextObj share,CGLContextObj *resultp,Display *display,XVisualInfo *visualInfo,Window window);
-(void)createCGLContextObjIfNeeded {
if(_cglContext==NULL){
-(void) createCGLContextObjIfNeeded {
if (_cglContext==NULL) {
CGLError error;
if((error=CGLCreateContextForWindow(NULL,NULL,&_cglContext,_display,_visualInfo,_window))!=kCGLNoError)
NSLog(@"glXCreateContext failed at %s %d with error %d",__FILE__,__LINE__,error);
if ((error = CGLCreateContext(NULL, NULL, &_cglContext)) != kCGLNoError)
NSLog(@"CGLCreateContext failed at %s %d with error %d", __FILE__ , __LINE__, error);
if ((error = CGLContextMakeCurrentAndAttachToWindow(_cglContext, _cglWindow)) != kCGLNoError)
NSLog(@"CGLContextMakeCurrentAndAttachToWindow failed with error %d", error);
}
if(_cglContext!=NULL && _caContext==NULL){
_caContext=[[CAWindowOpenGLContext alloc] initWithCGLContext:_cglContext];
if (_cglContext != nil && _caContext == nil){
_caContext = [[CAWindowOpenGLContext alloc] initWithCGLContext:_cglContext];
NSLog(@"Create _caContext %p %@", _caContext, _caContext);
}
}
-(void)openGLFlushBuffer {
-(void) openGLFlushBuffer {
CGLError error;
[self createCGLContextObjIfNeeded];
if(_caContext==NULL)
if (_caContext == nil)
return;
O2Surface *surface = [_context surface];
size_t width=O2ImageGetWidth(surface);
size_t height=O2ImageGetHeight(surface);
size_t width = O2ImageGetWidth(surface);
size_t height = O2ImageGetHeight(surface);
[_caContext prepareViewportWidth: width height: height];
[_caContext renderSurface: surface];
[_caContext prepareViewportWidth:width height:height];
[_caContext renderSurface:surface];
glFlush();
glXSwapBuffers(_display,_window);
CGLSwapBuffers(_cglWindow);
}
-(void)flushBuffer {

View File

@ -7,7 +7,9 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#import <Foundation/NSObject.h>
#import <CoreGraphics/CGSubWindow.h>
#import <OpenGL/gl.h>
#import <OpenGL/CGLInternal.h>
@class NSOpenGLPixelFormat, NSOpenGLPixelBuffer, NSView;
@ -25,7 +27,8 @@ typedef enum {
NSOpenGLPixelFormat *_pixelFormat;
NSView *_view;
void *_glContext;
id __remove;
CGSubWindow *_subwindow;
CGLWindowRef _cglWindow;
BOOL _hasPrepared;
}

View File

@ -46,7 +46,7 @@
// 0's are silently ignored per spec.
if(_numberOfBuffers>0 && _bufferObjects!=NULL) // nVidia driver will crash if bufferObjects is NULL, does not conform to spec.
CGLDeleteBuffers(_numberOfBuffers,_bufferObjects);
glDeleteBuffers(_numberOfBuffers,_bufferObjects);
if(_bufferObjects!=NULL)
free(_bufferObjects);
@ -91,9 +91,9 @@
}
else {
_readPixels[i]=NULL;
CGLBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, _bufferObjects[i]);
CGLBufferData(GL_PIXEL_PACK_BUFFER_ARB, _width*_rowsPerBuffer*4, NULL,GL_STREAM_READ);
CGLBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, _bufferObjects[i]);
glBufferData(GL_PIXEL_PACK_BUFFER_ARB, _width*_rowsPerBuffer*4, NULL,GL_STREAM_READ);
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
}
row+=_rowsPerBuffer;
@ -177,7 +177,7 @@ static inline uint32_t premultiplyPixel(uint32_t value){
if(_bufferObjects[i]==0)
glReadPixels(0,row,_width,rowCount,PIXEL_FORMAT, GL_UNSIGNED_BYTE,_readPixels[i]);
else {
CGLBindBuffer(GL_PIXEL_PACK_BUFFER,_bufferObjects[i]);
glBindBuffer(GL_PIXEL_PACK_BUFFER,_bufferObjects[i]);
unbind=YES;
glReadPixels(0,row,_width,rowCount,PIXEL_FORMAT, GL_UNSIGNED_BYTE, 0);
@ -191,7 +191,7 @@ static inline uint32_t premultiplyPixel(uint32_t value){
}
if(unbind)
CGLBindBuffer(GL_PIXEL_PACK_BUFFER,0);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0);
row=0;
unbind=NO;
@ -205,8 +205,8 @@ static inline uint32_t premultiplyPixel(uint32_t value){
inputRow=_readPixels[i];
else {
unbind=YES;
CGLBindBuffer(GL_PIXEL_PACK_BUFFER,_bufferObjects[i]);
inputRow=(GLubyte*)CGLMapBuffer(GL_PIXEL_PACK_BUFFER,GL_READ_ONLY);
glBindBuffer(GL_PIXEL_PACK_BUFFER,_bufferObjects[i]);
inputRow=(GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER,GL_READ_ONLY);
}
if(_isOpaque){
@ -243,18 +243,18 @@ static inline uint32_t premultiplyPixel(uint32_t value){
}
if(_bufferObjects[i]!=0){
CGLUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
row+=rowCount;
}
if(unbind)
CGLBindBuffer(GL_PIXEL_PACK_BUFFER,0);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0);
#if 0
if(_usePixelBuffer){
CGLBindBuffer(GL_PIXEL_PACK_BUFFER,0);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0);
if(inputBytes!=NULL){
CGLUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}

View File

@ -87,8 +87,5 @@ add_framework(CoreGraphics
CoreFoundation
Foundation
Onyx2D
GL
CIRCULAR_DEPENDENCIES
AppKit
OpenGL
)

View File

@ -32,11 +32,12 @@
GLint backingOrigin[2]={rect.origin.x,rect.origin.y};
GLint backingSize[2]={width,height};
CGLSetParameter(_glContext,kCGLCPSurfaceBackingOrigin,backingOrigin);
CGLSetParameter(_glContext,kCGLCPSurfaceBackingSize,backingSize);
// FIXME: convert to CGSubWindow
//CGLSetParameter(_glContext,kCGLCPSurfaceBackingOrigin,backingOrigin);
//CGLSetParameter(_glContext,kCGLCPSurfaceBackingSize,backingSize);
GLint opacity=0;
CGLSetParameter(_glContext,kCGLCPSurfaceOpacity,&opacity);
//CGLSetParameter(_glContext,kCGLCPSurfaceOpacity,&opacity);
_renderer=[[CARenderer rendererWithCGLContext:_glContext options:nil] retain];
@ -58,8 +59,8 @@
GLint backingOrigin[2]={rect.origin.x,rect.origin.y};
GLint backingSize[2]={width,height};
CGLSetParameter(_glContext,kCGLCPSurfaceBackingOrigin,backingOrigin);
CGLSetParameter(_glContext,kCGLCPSurfaceBackingSize,backingSize);
// CGLSetParameter(_glContext,kCGLCPSurfaceBackingOrigin,backingOrigin);
// CGLSetParameter(_glContext,kCGLCPSurfaceBackingSize,backingSize);
}
-(void)setLayer:(CALayer *)layer {

View File

@ -77,9 +77,6 @@ add_framework(QuartzCore
CoreFoundation
Foundation
Onyx2D
# native libraries
GL
CIRCULAR_DEPENDENCIES
OpenGL
CoreGraphics
)