OpenGL on Mac

It really is a matter of architecture or โ€œhow does it workโ€ than a problem to solve.

Apple's documentation claims that CGL is the lowest level api for managing OpenGL contexts, but it does not have functionality that allows you to connect a context to a window. AGL and Cocoa can associate a context with a window without problems, although the question is: how do they do it if they are built on CGL?

The obvious way is that they use CGL to render for off-screen memory, and then can somehow compose this. If so, how does this happen?

+6
cocoa opengl macos
source share
3 answers

There is a private function CGLSetSurface that connects a surface that is part of a window to a GL context created using the CGLCreateContext. Both AGL and Cocoa use this function internally.

+6
source share

I have not returned to this question since then, this is what I was able to make of it: An undocumented api that floats over the network seems to be the missing block from all of this - I could CGLSetSurface without returning an error, however in the end it not so much. Apparently, there is still something that needs to be done so that everything works at such a low level.

Overall, there seems to be no reasonable way to control everything through CGL . The way to deal with everything, as everyone else does, apparently, is through Cocoa classes ( using CGL for all things except attaching to the window, although after this point ).

0
source share

Full example:

 /* mkdir -p build/test.app/Contents/MacOS clang++ --std=c++11 -fno-exceptions -fno-rtti -mmacosx-version-min=10.9 -Wno-writable-strings -Wno-deprecated-declarations -framework OpenGL -framework Carbon -g gui8.cpp -o build/test.app/Contents/MacOS/test */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <ApplicationServices/ApplicationServices.h> #include <Carbon/Carbon.h> #include <OpenGL/CGLTypes.h> #include <OpenGL/CGLCurrent.h> #include <OpenGL/OpenGL.h> #include <OpenGL/gl.h> typedef int CGSConnectionID; typedef int CGSWindowID; typedef int CGSSurfaceID; typedef uint32_t _CGWindowID; extern "C" { typedef int CGSConnection; typedef int CGSWindow; typedef int CGSValue; typedef enum _CGSWindowOrderingMode { kCGSOrderAbove = 1, // Window is ordered above target. kCGSOrderBelow = -1, // Window is ordered below target. kCGSOrderOut = 0 // Window is removed from the on-screen window list. } CGSWindowOrderingMode; typedef void *CGSRegion; typedef CGSRegion *CGSRegionRef; typedef CGSWindow *CGSWindowRef; extern CGError CGSNewWindow( CGSConnection cid, int, float, float, const CGSRegion, CGSWindowRef); extern CGError CGSNewRegionWithRect( const CGRect * rect, CGSRegionRef newRegion ); extern OSStatus CGSOrderWindow(CGSConnection cid, CGSWindow win, CGSWindowOrderingMode place, CGSWindow relativeToWindow /* nullable */); extern OSStatus CGSSetWindowProperty(const CGSConnection cid, CGSWindow wid, CGSValue key, CGSValue value); extern CGSConnectionID CGSMainConnectionID(void); extern CGError CGSAddSurface(CGSConnectionID cid, _CGWindowID wid, CGSSurfaceID *sid); extern CGError CGSSetSurfaceBounds(CGSConnectionID cid, _CGWindowID wid, CGSSurfaceID sid, CGRect rect); extern CGError CGSOrderSurface(CGSConnectionID cid, _CGWindowID wid, CGSSurfaceID sid, int a, int b); extern OSStatus CGSMoveWindow(const CGSConnection cid, const CGSWindow wid, CGPoint *point); extern CGLError CGLSetSurface(CGLContextObj gl, CGSConnectionID cid, CGSWindowID wid, CGSSurfaceID sid); } #define kCGSBufferedBackingType 2 int main () { CGLContextObj cgl_context = NULL; CGSWindow window = 0; int width = 500, height = 500; CGPoint window_pos = { .x = 200, .y = 200 }; bool quit = false; CGSConnectionID connection_id = CGSMainConnectionID(); assert(connection_id); { CGSRegion region = NULL; CGRect r = CGRectMake(0,0, width, height); auto err1 = CGSNewRegionWithRect(&r, &region); assert(region); auto err2 = CGSNewWindow(connection_id, kCGSBufferedBackingType, window_pos.x, window_pos.y, region, &window); assert(window); auto err3 = CGSOrderWindow(connection_id, window, kCGSOrderAbove, 0); assert (err3 == kCGErrorSuccess); CGLPixelFormatAttribute attributes[] = { kCGLPFADoubleBuffer, kCGLPFAAccelerated, // Hardware rendering // kCGLPFARendererID, (CGLPixelFormatAttribute) kCGLRendererGenericFloatID, // Software rendering (CGLPixelFormatAttribute)0 }; CGLPixelFormatObj pix; GLint num; auto err4 = CGLChoosePixelFormat(attributes, &pix, &num); assert(err4 == kCGLNoError); // CGLErrorString(err1) assert(pix); CGLCreateContext(pix, NULL, &cgl_context); assert(cgl_context); CGLDestroyPixelFormat(pix); CGLSetCurrentContext(cgl_context); GLint v_sync_enabled = 1; CGLSetParameter(cgl_context, kCGLCPSwapInterval, &v_sync_enabled); CGSSurfaceID surface_id = 0; auto err5 = CGSAddSurface(connection_id, window, &surface_id); assert(err5 == kCGErrorSuccess); auto err6 = CGSSetSurfaceBounds(connection_id, window, surface_id, CGRectMake(0, 0, width, height)); assert(err6 == kCGErrorSuccess); auto err7 = CGSOrderSurface(connection_id, window, surface_id, 1, 0); assert(err7 == kCGErrorSuccess); auto err8 = CGLSetSurface(cgl_context, connection_id, window, surface_id); assert(err8 == kCGLNoError); GLint drawable = 0; CGLGetParameter(cgl_context, kCGLCPHasDrawable, &drawable); assert(drawable == 1); } assert(glGetError() == GL_NO_ERROR); CGPoint drag_starting_position; bool drag_started = false; while (!quit) { glClearColor(1,1,0,1); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); static float a = 0; glRotatef(a * 1000, 0, 0, 1); // printf("a: %f\n", a); a= a + .001; glBegin(GL_QUADS); if (a>1.5) a=0; glColor4f(0,a,1,1); glVertex2f(0.25, 0.25); glVertex2f(0.75, 0.25); glVertex2f(0.75, 0.75); glVertex2f(0.25, 0.75); glEnd(); auto err1 = CGLFlushDrawable(cgl_context); assert(err1 == kCGLNoError); assert(glGetError() == GL_NO_ERROR); } CGLSetCurrentContext(NULL); CGLDestroyContext(cgl_context); } 
0
source share

All Articles