OpenGL Loop mit DisplayLink

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • OpenGL Loop mit DisplayLink

    Hallo,

    ich bin noch neu im Bereich der Grafikprogrammierung.
    Ich habe mal bei Apple gesucht, wie man eine einfache OpenGL Loop erstellt.
    Das Ergebnis war: developer.apple.com/library/mac/#qa/qa1385/_index.html

    Ich habe den Code kopiert und versucht auszuführen:

    Quellcode

    1. CVDisplayLinkSetOutputCallback(dlrDisplayLink, &MyDisplayLinkCallback, self);


    Bei den self kommt folgender Fehler:
    Implicit conversion of Objective-C pointer type 'MyOpenGLView *' to C pointer type 'void *' requires a bridged cast

    Was läuft falsch? Und warum?
  • Das mit dem bridge fasten habe ich jetzt hinbekommen.

    Quellcode

    1. #import "OpenGLView.h"
    2. @interface OpenGLView()
    3. - (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime;
    4. @end
    5. @implementation OpenGLView
    6. - (void)prepareOpenGL
    7. {
    8. GLint swapInt = 1;
    9. [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
    10. CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
    11. CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, (__bridge void *) self);
    12. CGLContextObj cglContext = [[self openGLContext] CGLContextObj];
    13. CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
    14. CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
    15. CVDisplayLinkStart(displayLink);
    16. }
    17. static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
    18. {
    19. return [(__bridge OpenGLView *)displayLinkContext getFrameForTime:outputTime];;
    20. }
    21. - (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
    22. {
    23. glClear(GL_COLOR_BUFFER_BIT);
    24. glColor3i(255, 0, 0);
    25. glBegin(GL_TRIANGLES);
    26. {
    27. glVertex3f(-3.0, -3.0, -3.0);
    28. glVertex3f( 0.0, 3.0, -3.0);
    29. glVertex3f( 3.0, -3.0, -3.0);
    30. }
    31. glEnd();
    32. glFlush();
    33. return kCVReturnSuccess;
    34. }
    35. @end
    Alles anzeigen


    Der Fehler kommt bei glClear "CVDisplayLink EXC_BAD_ACCESS".
  • Hmmm... vielleicht auch wieder ARC?
    in prepareOpenGL machst du einen Create DisplayLink. Wegen ARC könnte es sein, dass der am Ende der Methode verworfen wird und du daher im displayLink einen NULL Pointer oder einen dangling Pointer stehen hast.
    Kann aber auch sein, dass du mit glClear ja den ColorBuffer manipulierst, aber gar keine Buffers erstellt hast? glInit() finde ich auch nicht.
    Ich habe da auch mal was mit OpenGL gemacht und irgendwie sah das ganz anders aus... ist aber schon eine Weile her...
  • Wo hast du denn „ displayLink“ deklariert?
    CF Konstrukte werden nicht von ARC verwaltet! Deshalb im dealloc frei geben. Aber das ist nicht der Fehler, der zum Crash führt.
    Du benutzt vermutlich ein NSOpenGLView. Unter Cocoa kannst du nicht malen wann du willst. Sondern nur, wann ein View es für richtig hält.
    Deshalb bei Subclassen von NSView immer nur in - (void)drawRect:(NSRect)dirtyRect malen! Das steht aber so auch in der Docu und in den Guides.
    Im der DisplayLink Routine rufst du deshalb [myGLView setNeedsDisplay:YES] auf, und malst im drawRect: des Views.

    Gruß
  • Das ist so nicht richtig, Du zeichnest schon mit dem Displaylink (das ist ja auch Sinn und Zweck der Sache, denn Du möchtest eine Synchronisation auf den displayrefresh). Was aber in Deinem Fall fehlt, ist den Context zu locken, außerdem musst Du beachten, dass der Displaylink-Callback in einem eigenen Thread läuft. Ich bin gerade unterwegs und kann Dir keinen Code posten, schaue Dir mal das GLEssentials-Demo an, da wird das mit dem Displaylink gezeigt.
  • So, hier nochmal ein Codebeispiel, wichtig ist, einen autoreleasepool im display-link-callback zu benutzen. Das locking ist wichtig, da reshape und drawRect im mainthread aufgerufen werden können, siehe Kommentar.

    Quellcode

    1. - (CVReturn)getFrameForTime:( const CVTimeStamp* )outputTime
    2. {
    3. NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ];
    4. // Add your drawing codes here
    5. [ self renderScene ];
    6. [ pool drain ];
    7. return kCVReturnSuccess;
    8. }
    9. - (void)renderScene
    10. {
    11. [[self openGLContext] makeCurrentContext];
    12. // This method will be called on both the main thread (through -drawRect:) and a secondary thread (through the display link rendering loop)
    13. // Also, when resizing the view, -reshape is called on the main thread, but we may be drawing on a secondary thread
    14. // Add a mutex around to avoid the threads accessing the context simultaneously
    15. CGLLockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
    16. // render the scene
    17. CGLFlushDrawable((CGLContextObj)[[self openGLContext] CGLContextObj]);
    18. CGLUnlockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
    19. }
    Alles anzeigen
  • Ich hab mal MMs Code getestet, aber gleicher Fehler bei glClear(GL_COLOR_BUFFER_BIT) in renderScene.

    Zum Zeitpunkt des Aufrufes besteht ein gültiger CVDisplayLinkRef.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Vyax ()

  • Vyax: @autoreleasepool{ ... } ;)
    Markus:
    Funktionieren hier die Cocoa Methoden nicht? Bzw. wenn nicht, hast du da ne Dokustelle parat, wo ich mich da nochmal reinlesen kann?

    Quellcode

    1. [[self openGLContext] makeCurrentContext];
    2. [self lockFocus];
    3. // draw stuff
    4. [[self openGLContext] flushBuffer];
    5. [self unlockFocus];


    Gruß

    EDIT: Hab die stelle gefunden, in denen auf CGLLockContext und Co. eingegangen wird. Jedoch wird da nicht gesagt ob -lockFocus das selbe tut, bzw. warum nicht.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von lasergans ()

  • Ich hab das jetzt insgesamt so:

    Quellcode

    1. - (void)prepareOpenGL
    2. {
    3. GLint swapInt = 1;
    4. [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
    5. CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
    6. CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, (__bridge void *) self);
    7. CGLContextObj cglContext = [[self openGLContext] CGLContextObj];
    8. CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
    9. CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
    10. CVDisplayLinkStart(displayLink);
    11. }
    12. - (void)renderScene
    13. {
    14. [[self openGLContext] makeCurrentContext];
    15. CGLLockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
    16. CGLFlushDrawable((CGLContextObj)[[self openGLContext] CGLContextObj]);
    17. CGLUnlockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
    18. }
    19. static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
    20. {
    21. return [(__bridge OpenGLView *)displayLinkContext getFrameForTime:outputTime];;
    22. }
    23. - (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
    24. {
    25. //NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    26. @autoreleasepool
    27. {
    28. // Render - Start
    29. glClear(GL_COLOR_BUFFER_BIT);
    30. glColor3i(255, 0, 0);
    31. glLoadIdentity();
    32. glRotatef(fRotationTri, 1, 1, 0);
    33. glBegin(GL_TRIANGLES);
    34. {
    35. glVertex3f(-3.0, -3.0, -3.0);
    36. glVertex3f( 0.0, 3.0, -3.0);
    37. glVertex3f( 3.0, -3.0, -3.0);
    38. }
    39. glEnd();
    40. glFlush();
    41. fRotationTri += 0.05;
    42. // Render - Ende
    43. [self renderScene];
    44. }
    45. return kCVReturnSuccess;
    46. }
    Alles anzeigen


    Aber ich bekomme das EXC_BAD_ACCESS nicht weg?