~ubuntu-branches/ubuntu/precise/virtualbox/precise-updates

« back to all changes in this revision

Viewing changes to src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-07-04 13:02:31 UTC
  • mfrom: (3.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110704130231-l843es6wqhx614n7
Tags: 4.0.10-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Add the Modaliases control field manually for maximum backportability.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <iprt/mem.h>
27
27
#include <iprt/time.h>
28
28
 
 
29
/*
 
30
 * How this works:
 
31
 * In general it is not so easy like on the other platforms, cause Cocoa
 
32
 * doesn't support any clipping of already painted stuff. In Mac OS X there is
 
33
 * the concept of translucent canvas's e.g. windows and there it is just
 
34
 * painted what should be visible to the user. Unfortunately this isn't the
 
35
 * concept of chromium. Therefor I reroute all OpenGL operation from the guest
 
36
 * to a frame buffer object (FBO). This is a OpenGL extension, which is
 
37
 * supported by all OS X versions we support (AFAIC tell). Of course the guest
 
38
 * doesn't know that and we have to make sure that the OpenGL state always is
 
39
 * in the right state to paint into the FBO and not to the front/back buffer.
 
40
 * Several functions below (like cocoaBindFramebufferEXT, cocoaGetIntegerv,
 
41
 * ...) doing this. When a swap or finish is triggered by the guest, the
 
42
 * content (which is already bound to an texture) is painted on the screen
 
43
 * within a separate OpenGL context. This allows the usage of the same
 
44
 * resources (texture ids, buffers ...) but at the same time having an
 
45
 * different internal OpenGL state. Another advantage is that we can paint a
 
46
 * thumbnail of the current output in a much more smaller (GPU accelerated
 
47
 * scale) version on a third context and use glReadPixels to get the actual
 
48
 * data. glReadPixels is a very slow operation, but as we just use a much more
 
49
 * smaller image, we can handle it (anyway this is only done 5 times per
 
50
 * second).
 
51
 *
 
52
 * Other things to know:
 
53
 * - If the guest request double buffering, we have to make sure there are two
 
54
 *   buffers. We use the same FBO with 2 color attachments. Also glDrawBuffer
 
55
 *   and glReadBuffer is intercepted to make sure it is painted/read to/from
 
56
 *   the correct buffers. On swap our buffers are swapped and not the
 
57
 *   front/back buffer.
 
58
 * - If the guest request a depth/stencil buffer, a combined render buffer for
 
59
 *   this is created.
 
60
 * - If the size of the guest OpenGL window changes, all FBO's, textures, ...
 
61
 *   need to be recreated.
 
62
 * - We need to track any changes to the parent window
 
63
 *   (create/destroy/move/resize). The various classes like OverlayHelperView,
 
64
 *   OverlayWindow, ... are there for.
 
65
 * - The HGCM service runs on a other thread than the Main GUI. Keeps this
 
66
 *   always in mind (see e.g. performSelectorOnMainThread in renderFBOToView)
 
67
 * - We make heavy use of late binding. We can not be sure that the GUI (or any
 
68
 *   other third party GUI), overwrite our NSOpenGLContext. So we always ask if
 
69
 *   this is our own one, before use. Really neat concept of Objective-C/Cocoa
 
70
 *   ;)
 
71
 */
 
72
 
29
73
/* Debug macros */
30
74
#define FBO 1 /* Disable this to see how the output is without the FBO in the middle of the processing chain. */
31
 
//#define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
32
 
//#define DEBUG_VERBOSE /* Define this could get some debug info about the messages flow. */
 
75
#if 0
 
76
#define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
 
77
#define DEBUG_VERBOSE /* Define this to get some debug info about the messages flow. */
 
78
#endif
33
79
 
34
80
#ifdef DEBUG_poetzsch
35
81
#define DEBUG_MSG(text) \
62
108
            char *errStr;
63
109
            switch (g)
64
110
            {
65
 
                case GL_INVALID_ENUM: errStr = RTStrDup("GL_INVALID_ENUM"); break;
66
 
                case GL_INVALID_VALUE: errStr = RTStrDup("GL_INVALID_VALUE"); break;
 
111
                case GL_INVALID_ENUM:      errStr = RTStrDup("GL_INVALID_ENUM"); break;
 
112
                case GL_INVALID_VALUE:     errStr = RTStrDup("GL_INVALID_VALUE"); break;
67
113
                case GL_INVALID_OPERATION: errStr = RTStrDup("GL_INVALID_OPERATION"); break;
68
 
                case GL_STACK_OVERFLOW: errStr = RTStrDup("GL_STACK_OVERFLOW"); break;
69
 
                case GL_STACK_UNDERFLOW: errStr = RTStrDup("GL_STACK_UNDERFLOW"); break;
70
 
                case GL_OUT_OF_MEMORY: errStr = RTStrDup("GL_OUT_OF_MEMORY"); break;
71
 
                case GL_TABLE_TOO_LARGE: errStr = RTStrDup("GL_TABLE_TOO_LARGE"); break;
72
 
                default: errStr = RTStrDup("UNKNOWN"); break;
 
114
                case GL_STACK_OVERFLOW:    errStr = RTStrDup("GL_STACK_OVERFLOW"); break;
 
115
                case GL_STACK_UNDERFLOW:   errStr = RTStrDup("GL_STACK_UNDERFLOW"); break;
 
116
                case GL_OUT_OF_MEMORY:     errStr = RTStrDup("GL_OUT_OF_MEMORY"); break;
 
117
                case GL_TABLE_TOO_LARGE:   errStr = RTStrDup("GL_TABLE_TOO_LARGE"); break;
 
118
                default:                   errStr = RTStrDup("UNKNOWN"); break;
73
119
            }
74
120
            DEBUG_MSG(("%s:%d: glError %d (%s)\n", file, line, g, errStr));
75
121
            RTMemFree(errStr);
143
189
    NSOpenGLContext *m_pSharedGLCtx;
144
190
    RTTHREAD         mThread;
145
191
 
 
192
#ifdef FBO
 
193
    GLuint           m_FBOId;
146
194
    /* FBO handling */
147
 
    GLuint           m_FBOId;
148
 
    GLuint           m_FBOTexId;
 
195
    GLuint           m_FBOTexBackId;
 
196
    GLuint           m_FBOTexFrontId;
 
197
    GLuint           m_FBOAttBackId;
 
198
    GLuint           m_FBOAttFrontId;
 
199
    GLuint           m_FBODepthStencilPackedId;
149
200
    NSSize           m_FBOTexSize;
150
 
    GLuint           m_FBODepthStencilPackedId;
 
201
 
 
202
    bool             m_fFrontDrawing;
 
203
#endif
151
204
 
152
205
    /* The corresponding dock tile view of this OpenGL view & all helper
153
206
     * members. */
154
207
    DockOverlayView *m_DockTileView;
 
208
 
155
209
    GLuint           m_FBOThumbId;
156
210
    GLuint           m_FBOThumbTexId;
157
211
    GLfloat          m_FBOThumbScaleX;
188
242
- (void)createFBO;
189
243
- (void)deleteFBO;
190
244
 
 
245
- (bool)isCurrentFBO;
191
246
- (void)updateFBO;
192
247
- (void)makeCurrentFBO;
193
248
- (void)swapFBO;
194
249
- (void)flushFBO;
 
250
- (void)stateInfo:(GLenum)pname withParams:(GLint*)params;
195
251
- (void)finishFBO;
196
 
- (void)bindFBO;
 
252
- (void)bindFBO:(GLenum)target withFrameBuffer:(GLuint)framebuffer;
 
253
- (void)tryDraw;
197
254
- (void)renderFBOToView;
 
255
- (void)renderFBOToDockTile;
198
256
 
199
257
- (void)clearVisibleRegions;
200
258
- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects;
316
374
            hasAlpha:YES
317
375
            isPlanar:NO
318
376
            colorSpaceName:NSDeviceRGBColorSpace
 
377
            bitmapFormat:NSAlphaFirstBitmapFormat
319
378
            bytesPerRow:frame.size.width * 4
320
379
            bitsPerPixel:8 * 4];
321
380
        m_ThumbImage = [[NSImage alloc] initWithSize:[m_ThumbBitmap size]];
331
390
 
332
391
- (void)drawRect:(NSRect)aRect
333
392
{
 
393
    NSRect frame;
 
394
 
334
395
    [self lock];
335
396
#ifdef SHOW_WINDOW_BACKGROUND
336
397
    [[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7] set];
337
 
    NSRect frame = [self frame];
338
 
    [NSBezierPath fillRect:NSMakeRect(0, 0, frame.size.width, frame.size.height)]; 
 
398
    frame = [self frame];
 
399
    [NSBezierPath fillRect:NSMakeRect(0, 0, frame.size.width, frame.size.height)];
339
400
#endif /* SHOW_WINDOW_BACKGROUND */
340
401
    if (m_ThumbImage != nil)
341
402
        [m_ThumbImage drawAtPoint:NSMakePoint(0, 0) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
369
430
    if (self)
370
431
        m_pPixelFormat = format;
371
432
 
 
433
    DEBUG_MSG(("OCTX(%p): init OverlayOpenGLContext\n", (void*)self));
 
434
 
372
435
    return self;
373
436
}
374
 
    
 
437
 
375
438
- (void)dealloc
376
439
{
377
 
    DEBUG_MSG(("Dealloc context %X\n", (uint)self));
 
440
    DEBUG_MSG(("OCTX(%p): dealloc OverlayOpenGLContext\n", (void*)self));
378
441
 
379
442
    [m_pPixelFormat release];
380
443
 
390
453
 
391
454
-(void)setView:(NSView*)view
392
455
{
 
456
    DEBUG_MSG(("OCTX(%p): setView: new view: %p\n", (void*)self, (void*)view));
 
457
 
393
458
#ifdef FBO
394
459
    m_pView = view;;
395
460
#else
408
473
 
409
474
-(void)clearDrawable
410
475
{
 
476
    DEBUG_MSG(("OCTX(%p): clearDrawable\n", (void*)self));
 
477
 
411
478
    m_pView = NULL;;
412
479
    [super clearDrawable];
413
480
}
417
484
    return m_pPixelFormat;
418
485
}
419
486
 
420
 
@end;
 
487
@end
421
488
 
422
489
/********************************************************************************
423
490
*
432
499
 
433
500
    m_pOverlayWindow = pOverlayWindow;
434
501
 
 
502
    DEBUG_MSG(("OHVW(%p): init OverlayHelperView\n", (void*)self));
 
503
 
435
504
    return self;
436
505
}
437
506
 
438
507
-(void)viewDidMoveToWindow
439
508
{
 
509
    DEBUG_MSG(("OHVW(%p): viewDidMoveToWindow: new win: %p\n", (void*)self, (void*)[self window]));
 
510
 
440
511
    [m_pOverlayWindow parentWindowChanged:[self window]];
441
512
}
442
513
 
451
522
 
452
523
- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView
453
524
{
454
 
    if(self = [super initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
 
525
    NSWindow *pParentWin = nil;
 
526
 
 
527
    if((self = [super initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]))
455
528
    {
456
529
        m_pParentView = pParentView;
457
530
        m_pOverlayView = pOverlayView;
475
548
        /* Disable mouse events for this window */
476
549
        [self setIgnoresMouseEvents:YES];
477
550
 
478
 
        NSWindow *pParentWin = [m_pParentView window];
 
551
        pParentWin = [m_pParentView window];
479
552
 
480
553
        /* Initial set the position to the parents view top/left (Compiz fix). */
481
554
        [self setFrameOrigin:
487
560
 
488
561
        /* Add ourself as a child to the parent views window. Note: this has to
489
562
         * be done last so that everything else is setup in
490
 
         * parentWindowChanged. */ 
 
563
         * parentWindowChanged. */
491
564
        [pParentWin addChildWindow:self ordered:NSWindowAbove];
492
565
    }
 
566
    DEBUG_MSG(("OWIN(%p): init OverlayWindow\n", (void*)self));
 
567
 
493
568
    return self;
494
569
}
495
570
 
496
571
- (void)dealloc
497
572
{
498
 
    DEBUG_MSG(("Dealloc window %X\n", (uint)self));
 
573
    DEBUG_MSG(("OWIN(%p): dealloc OverlayWindow\n", (void*)self));
499
574
 
500
575
    [[NSNotificationCenter defaultCenter] removeObserver:self];
501
576
 
507
582
 
508
583
- (void)parentWindowFrameChanged:(NSNotification*)pNote
509
584
{
 
585
    DEBUG_MSG(("OWIN(%p): parentWindowFrameChanged\n", (void*)self));
 
586
 
510
587
    /* Reposition this window with the help of the OverlayView. Perform the
511
588
     * call in the OpenGL thread. */
512
 
//    [m_pOverlayView performSelector:@selector(reshape) onThread:m_Thread withObject:nil waitUntilDone:YES];
513
 
    DEBUG_MSG(("parentWindowFrameChanged\n"));
 
589
    /*
 
590
    [m_pOverlayView performSelector:@selector(reshape) onThread:m_Thread withObject:nil waitUntilDone:YES];
 
591
    */
 
592
 
514
593
    [m_pOverlayView reshape];
515
594
}
516
595
 
517
596
- (void)parentWindowChanged:(NSWindow*)pWindow
518
597
{
 
598
    DEBUG_MSG(("OWIN(%p): parentWindowChanged\n", (void*)self));
 
599
 
519
600
    [[NSNotificationCenter defaultCenter] removeObserver:self];
520
 
    DEBUG_MSG(("parentWindowChanged\n"));
 
601
 
521
602
    if(pWindow != nil)
522
603
    {
523
604
        /* Ask to get notifications when our parent window frame changes. */
530
611
        [pWindow addChildWindow:self ordered:NSWindowAbove];
531
612
        /* Reshape the overlay view after a short waiting time to let the main
532
613
         * window resize itself properly. */
533
 
//        [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
534
 
//        [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(reshape) userInfo:nil repeats:NO];
 
614
        /*
 
615
        [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
 
616
        [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(reshape) userInfo:nil repeats:NO];
 
617
        */
535
618
        [m_pOverlayView reshape];
536
619
    }
537
620
}
547
630
 
548
631
- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView
549
632
{
550
 
    m_pParentView = pParentView;
 
633
    m_pParentView             = pParentView;
551
634
    /* Make some reasonable defaults */
552
 
    m_pGLCtx = NULL;
553
 
    m_pSharedGLCtx = NULL;
554
 
    mThread = aThread;
555
 
    m_FBOId = 0;
556
 
    m_FBOTexId = 0;
557
 
    m_FBOTexSize = NSZeroSize;
 
635
    m_pGLCtx                  = nil;
 
636
    m_pSharedGLCtx            = nil;
 
637
    mThread                   = aThread;
 
638
#ifdef FBO
 
639
    m_FBOId                   = 0;
 
640
    m_FBOTexBackId            = 0;
 
641
    m_FBOTexFrontId           = 0;
 
642
    m_FBOAttBackId            = GL_COLOR_ATTACHMENT0_EXT;
 
643
    m_FBOAttFrontId           = GL_COLOR_ATTACHMENT1_EXT;
558
644
    m_FBODepthStencilPackedId = 0;
559
 
    m_FBOThumbId = 0;
560
 
    m_FBOThumbTexId = 0;
561
 
    m_cClipRects = 0;
562
 
    m_paClipRects = NULL;
563
 
    m_Pos = NSZeroPoint;
564
 
    m_Size = NSZeroSize;
565
 
    m_RootShift = NSZeroPoint;
 
645
    m_FBOTexSize              = NSZeroSize;
 
646
#endif
 
647
    m_FBOThumbId              = 0;
 
648
    m_FBOThumbTexId           = 0;
 
649
    m_cClipRects              = 0;
 
650
    m_paClipRects             = NULL;
 
651
    m_Pos                     = NSZeroPoint;
 
652
    m_Size                    = NSMakeSize(1, 1);
 
653
    m_RootShift               = NSZeroPoint;
566
654
 
567
 
    DEBUG_MSG(("Init view %X (%X)\n", (uint)self, (uint)mThread));
568
 
    
569
655
    self = [super initWithFrame:frame];
570
656
 
 
657
    DEBUG_MSG(("OVIW(%p): init OverlayView\n", (void*)self));
 
658
 
571
659
    return self;
572
660
}
573
661
 
574
662
- (void)dealloc
575
663
{
576
 
    DEBUG_MSG(("Dealloc view %X\n", (uint)self));
 
664
    DEBUG_MSG(("OVIW(%p): dealloc OverlayView\n", (void*)self));
577
665
 
578
666
    [self deleteFBO];
579
667
 
580
668
    if (m_pGLCtx)
581
669
    {
582
 
        if ([m_pGLCtx view] == self) 
 
670
        if ([m_pGLCtx view] == self)
583
671
            [m_pGLCtx clearDrawable];
584
672
    }
585
673
    if (m_pSharedGLCtx)
586
674
    {
587
 
        if ([m_pSharedGLCtx view] == self) 
 
675
        if ([m_pSharedGLCtx view] == self)
588
676
            [m_pSharedGLCtx clearDrawable];
589
677
 
590
678
        [m_pSharedGLCtx release];
597
685
 
598
686
- (void)drawRect:(NSRect)aRect
599
687
{
600
 
//    NSGraphicsContext*pC = [NSGraphicsContext currentContext];
601
 
//    [[NSColor blueColor] set];
602
 
//    NSBezierPath *p = [[NSBezierPath alloc] bezierPathWithOvalInRect:[self frame]];
603
 
//    [p fill];
604
 
//    [[NSColor greenColor] set];
605
 
//    [p stroke];
606
 
//    if ([self lockFocusIfCanDraw])
607
 
//    {
608
 
//        [self renderFBOToView];
609
 
//        [self unlockFocus];
610
 
//    }
 
688
    /* Do nothing */
611
689
}
612
690
 
613
691
- (void)setGLCtx:(NSOpenGLContext*)pCtx
614
692
{
 
693
    DEBUG_MSG(("OVIW(%p): setGLCtx: new ctx: %p\n", (void*)self, (void*)pCtx));
 
694
 
615
695
    m_pGLCtx = pCtx;
616
696
}
617
697
 
625
705
    return m_pParentView;
626
706
}
627
707
 
628
 
- (void)setParentView: (NSView*)view
 
708
- (void)setParentView:(NSView*)pView
629
709
{
630
 
    m_pParentView = view;
 
710
    DEBUG_MSG(("OVIW(%p): setParentView: new view: %p\n", (void*)self, (void*)pView));
 
711
 
 
712
    m_pParentView = pView;
631
713
}
632
714
 
633
 
- (void)setOverlayWin: (NSWindow*)win
 
715
- (void)setOverlayWin:(NSWindow*)pWin
634
716
{
635
 
    m_pOverlayWin = win;
 
717
    DEBUG_MSG(("OVIW(%p): setOverlayWin: new win: %p\n", (void*)self, (void*)pWin));
 
718
 
 
719
    m_pOverlayWin = pWin;
636
720
}
637
721
 
638
722
- (NSWindow*)overlayWin
642
726
 
643
727
- (void)setPos:(NSPoint)pos
644
728
{
 
729
    DEBUG_MSG(("OVIW(%p): setPos: new pos: %d, %d\n", (void*)self, (int)pos.x, (int)pos.y));
 
730
 
645
731
    m_Pos = pos;
 
732
 
646
733
    [self reshape];
647
734
}
648
735
 
654
741
- (void)setSize:(NSSize)size
655
742
{
656
743
    m_Size = size;
657
 
    
658
 
    if (!m_FBOId)
659
 
    {
660
 
        DEBUG_MSG(("Set size (no fbo) %p\n", self));
661
 
        [self reshape];
662
 
        [self updateFBO];
663
 
    }
664
 
    else
665
 
    {
666
 
        DEBUG_MSG(("Set size FBO %p\n", self));
 
744
 
 
745
#ifdef FBO
 
746
    if (m_FBOId)
 
747
    {
 
748
        DEBUG_MSG(("OVIW(%p): setSize: new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
667
749
        [self reshape];
668
750
        [self updateFBO];
669
751
        /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
670
752
        [self updateViewport];
671
753
    }
 
754
    else
 
755
#endif
 
756
    {
 
757
        DEBUG_MSG(("OVIW(%p): setSize (no FBO): new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
 
758
        [self reshape];
 
759
        [self updateFBO];
 
760
    }
672
761
}
673
762
 
674
763
- (NSSize)size
678
767
 
679
768
- (void)updateViewport
680
769
{
681
 
    DEBUG_MSG(("updateViewport %p\n", self));
 
770
    NSRect r;
 
771
 
 
772
    DEBUG_MSG(("OVIW(%p): updateViewport\n", (void*)self));
 
773
 
 
774
#ifdef FBO
682
775
    if (m_pSharedGLCtx)
683
776
    {
684
777
        /* Update the viewport for our OpenGL view */
685
 
        DEBUG_MSG(("MakeCurrent (shared) %X\n", m_pSharedGLCtx));
 
778
        DEBUG_MSG(("OVIW(%p): makeCurrent (shared) %p\n", (void*)self, (void*)m_pSharedGLCtx));
686
779
        [m_pSharedGLCtx makeCurrentContext];
687
780
        [m_pSharedGLCtx update];
688
781
 
689
 
        NSRect r = [self frame];
 
782
        r = [self frame];
690
783
        /* Setup all matrices */
691
784
        glMatrixMode(GL_PROJECTION);
692
785
        glLoadIdentity();
693
786
        glViewport(0, 0, r.size.width, r.size.height);
694
787
        glOrtho(0, r.size.width, 0, r.size.height, -1, 1);
695
 
        DEBUG_MSG_1(("frame[%i, %i, %i, %i]\n", (int)r.origin.x, (int)r.origin.x, (int)r.size.width, (int)r.size.height));
696
 
        DEBUG_MSG_1(("m_Pos(%i,%i) m_Size(%i,%i)\n", (int)m_Pos.x, (int)m_Pos.y, (int)m_Size.width, (int)m_Size.height));
697
 
        DEBUG_MSG_1(("m_RootShift(%i, %i)\n", (int)m_RootShift.x, (int)m_RootShift.y));
 
788
        DEBUG_MSG_1(("OVIW(%p): frame[%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.x, (int)r.size.width, (int)r.size.height));
 
789
        DEBUG_MSG_1(("OVIW(%p): m_Pos(%i,%i) m_Size(%i,%i)\n", (void*)self, (int)m_Pos.x, (int)m_Pos.y, (int)m_Size.width, (int)m_Size.height));
 
790
        DEBUG_MSG_1(("OVIW(%p): m_RootShift(%i, %i)\n", (void*)self, (int)m_RootShift.x, (int)m_RootShift.y));
698
791
        glMatrixMode(GL_TEXTURE);
699
792
        glLoadIdentity();
700
 
        glTranslatef(0.0f, m_RootShift.y, 0.0f);
701
793
        glMatrixMode(GL_MODELVIEW);
702
794
        glLoadIdentity();
703
 
        glTranslatef(-m_RootShift.x, 0.0f, 0.0f);
704
795
 
705
796
        /* Clear background to transparent */
706
797
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
707
798
 
708
 
        glEnable(GL_TEXTURE_RECTANGLE_ARB);
709
 
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
710
 
 
711
 
        DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
 
799
        DEBUG_MSG(("OVIW(%p): makeCurrent (non shared) %p\n", (void*)self, (void*)m_pGLCtx));
712
800
        [m_pGLCtx makeCurrentContext];
713
801
    }
 
802
#endif
714
803
}
715
804
 
716
805
- (void)reshape
717
806
{
718
 
    DEBUG_MSG(("(%p)reshape %p\n", RTThreadSelf(), self));
 
807
    NSRect parentFrame = NSZeroRect;
 
808
    NSPoint parentPos  = NSZeroPoint;
 
809
    NSPoint childPos   = NSZeroPoint;
 
810
    NSRect childFrame  = NSZeroRect;
 
811
    NSRect newFrame    = NSZeroRect;
 
812
 
 
813
    DEBUG_MSG(("OVIW(%p): reshape\n", (void*)self));
 
814
 
719
815
    /* Getting the right screen coordinates of the parents frame is a little bit
720
816
     * complicated. */
721
 
    NSRect parentFrame = [m_pParentView frame];
722
 
    NSPoint parentPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:NSMakePoint(parentFrame.origin.x, parentFrame.origin.y + parentFrame.size.height)]];
 
817
    parentFrame = [m_pParentView frame];
 
818
    parentPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:NSMakePoint(parentFrame.origin.x, parentFrame.origin.y + parentFrame.size.height)]];
723
819
    parentFrame.origin.x = parentPos.x;
724
820
    parentFrame.origin.y = parentPos.y;
725
821
 
726
822
    /* Calculate the new screen coordinates of the overlay window. */
727
 
    NSPoint childPos = NSMakePoint(m_Pos.x, m_Pos.y + m_Size.height);
 
823
    childPos = NSMakePoint(m_Pos.x, m_Pos.y + m_Size.height);
728
824
    childPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:childPos]];
729
825
 
730
826
    /* Make a frame out of it. */
731
 
    NSRect childFrame = NSMakeRect(childPos.x, childPos.y, m_Size.width, m_Size.height);
 
827
    childFrame = NSMakeRect(childPos.x, childPos.y, m_Size.width, m_Size.height);
732
828
 
733
829
    /* We have to make sure that the overlay window will not be displayed out
734
830
     * of the parent window. So intersect both frames & use the result as the new
735
831
     * frame for the window. */
736
 
    NSRect newFrame = NSIntersectionRect(parentFrame, childFrame);
 
832
    newFrame = NSIntersectionRect(parentFrame, childFrame);
737
833
 
738
834
    /* Later we have to correct the texture position in the case the window is
739
835
     * out of the parents window frame. So save the shift values for later use. */
746
842
    else
747
843
        m_RootShift.y = 0;
748
844
 
749
 
//    NSScrollView *pScrollView = [[[m_pParentView window] contentView] enclosingScrollView];
750
 
//    if (pScrollView)
751
 
//    {
752
 
//        NSRect scrollRect = [pScrollView documentVisibleRect];
753
 
//        NSRect scrollRect = [m_pParentView visibleRect];
754
 
//        printf ("sc rect: %d %d %d %d\n", (int) scrollRect.origin.x,(int) scrollRect.origin.y,(int) scrollRect.size.width,(int) scrollRect.size.height);
755
 
//        NSRect b = [[m_pParentView superview] bounds];
756
 
//        printf ("bound rect: %d %d %d %d\n", (int) b.origin.x,(int) b.origin.y,(int) b.size.width,(int) b.size.height);
757
 
//        newFrame.origin.x += scrollRect.origin.x;
758
 
//        newFrame.origin.y += scrollRect.origin.y;
759
 
//    }
 
845
    /*
 
846
    NSScrollView *pScrollView = [[[m_pParentView window] contentView] enclosingScrollView];
 
847
    if (pScrollView)
 
848
    {
 
849
        NSRect scrollRect = [pScrollView documentVisibleRect];
 
850
        NSRect scrollRect = [m_pParentView visibleRect];
 
851
        printf ("sc rect: %d %d %d %d\n", (int) scrollRect.origin.x,(int) scrollRect.origin.y,(int) scrollRect.size.width,(int) scrollRect.size.height);
 
852
        NSRect b = [[m_pParentView superview] bounds];
 
853
        printf ("bound rect: %d %d %d %d\n", (int) b.origin.x,(int) b.origin.y,(int) b.size.width,(int) b.size.height);
 
854
        newFrame.origin.x += scrollRect.origin.x;
 
855
        newFrame.origin.y += scrollRect.origin.y;
 
856
    }
 
857
    */
760
858
 
761
859
    /* Set the new frame. */
762
860
    [[self window] setFrame:newFrame display:YES];
770
868
 
771
869
- (void)createFBO
772
870
{
773
 
    GLint oldTexId;
774
 
    GLint oldFBId;
775
 
    
776
 
    DEBUG_MSG(("createFBO %p\n", self));
 
871
    GLint   oldTexId         = 0;
 
872
    GLint   oldFBId          = 0;
 
873
    NSView *pDockScreen      = nil;
 
874
    GLint   maxTexSize       = 0;
 
875
    GLfloat imageAspectRatio = 0;
 
876
    GLint   filter           = GL_NEAREST;
 
877
 
777
878
    [self deleteFBO];
778
879
 
779
 
    //GL_SAVE_STATE;
780
 
#if 0
781
 
    CHECK_GL_ERROR();
782
 
    glPushAttrib(GL_ACCUM_BUFFER_BIT);
783
 
    glPopAttrib();
784
 
    CHECK_GL_ERROR();
785
 
#endif
 
880
#ifdef FBO
 
881
    DEBUG_MSG(("OVIW(%p): createFBO\n", (void*)self));
786
882
 
787
883
    glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &oldTexId);
788
884
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldFBId);
799
895
        isFBO = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt);
800
896
        if (!isFBO)
801
897
        {
802
 
            DEBUG_MSG(("Your system does not support framebuffer extension\n"));
803
 
        }
804
 
        
 
898
            DEBUG_MSG(("Your system does not support the GL_EXT_framebuffer_object extension\n"));
 
899
        }
 
900
        isFBO = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_blit", strExt);
 
901
        if (!isFBO)
 
902
        {
 
903
            DEBUG_MSG(("Your system does not support the GL_EXT_framebuffer_blit extension\n"));
 
904
        }
 
905
 
805
906
        /* Create FBO object */
806
907
        glGenFramebuffersEXT(1, &m_FBOId);
807
908
        /* & the texture as well the depth/stencil render buffer */
808
 
        glGenTextures(1, &m_FBOTexId);
809
 
        DEBUG_MSG(("Create FBO %d %d\n", m_FBOId, m_FBOTexId));
 
909
        glGenTextures(1, &m_FBOTexBackId);
 
910
        glGenTextures(1, &m_FBOTexFrontId);
 
911
        DEBUG_MSG(("OVIW(%p): gen numbers: FBOId=%d FBOTexBackId=%d FBOTexFrontId=%d\n", (void*)self, m_FBOId, m_FBOTexBackId, m_FBOTexFrontId));
810
912
 
811
913
        glGenRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
812
914
    }
815
917
    /* Bind to FBO */
816
918
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
817
919
 
818
 
    /*glEnable(GL_TEXTURE_RECTANGLE_ARB);*/
819
 
    
820
 
    GLfloat imageAspectRatio = m_FBOTexSize.width / m_FBOTexSize.height;
 
920
    /*
 
921
    glEnable(GL_TEXTURE_RECTANGLE_ARB);
 
922
     */
 
923
 
 
924
    imageAspectRatio = m_FBOTexSize.width / m_FBOTexSize.height;
821
925
 
822
926
    /* Sanity check against maximum OpenGL texture size. If bigger adjust to
823
927
     * maximum possible size while maintain the aspect ratio. */
824
 
    GLint maxTexSize; 
825
928
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
826
 
//    maxTexSize = 150;
827
 
    GLint filter = GL_NEAREST;
828
 
    if (m_FBOTexSize.width > maxTexSize || m_FBOTexSize.height > maxTexSize) 
 
929
    if (m_FBOTexSize.width > maxTexSize || m_FBOTexSize.height > maxTexSize)
829
930
    {
830
931
        filter = GL_LINEAR;
831
932
        if (imageAspectRatio > 1)
832
933
        {
833
 
            m_FBOTexSize.width = maxTexSize; 
 
934
            m_FBOTexSize.width = maxTexSize;
834
935
            m_FBOTexSize.height = maxTexSize / imageAspectRatio;
835
936
        }
836
937
        else
837
938
        {
838
939
            m_FBOTexSize.width = maxTexSize * imageAspectRatio;
839
 
            m_FBOTexSize.height = maxTexSize; 
 
940
            m_FBOTexSize.height = maxTexSize;
840
941
        }
841
942
    }
842
 
    
843
 
    /* Initialize FBO Texture */
844
 
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
845
 
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, filter);
846
 
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, filter);
847
 
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
848
 
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
849
 
    
 
943
 
 
944
    DEBUG_MSG(("OVIW(%p): tex size is: %dx%d\n", (void*)self, (int)m_FBOTexSize.width, (int)m_FBOTexSize.height));
 
945
 
 
946
    /* Initialize FBO Textures */
850
947
    /* The GPUs like the GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV combination
851
948
     * others are also valid, but might incur a costly software translation. */
852
 
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width, m_FBOTexSize.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
853
 
    DEBUG_MSG(("m_FBOTexSize(%i,%i)\n", (int)m_FBOTexSize.width, (int)m_FBOTexSize.height));
854
 
        
855
 
    /* Now attach texture to the FBO as its color destination */
856
 
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId, 0);
 
949
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexBackId);
 
950
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width, m_FBOTexSize.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
 
951
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexFrontId);
 
952
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width, m_FBOTexSize.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
 
953
 
 
954
    /* Now attach the textures to the FBO as its color destinations */
 
955
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, m_FBOAttBackId,  GL_TEXTURE_RECTANGLE_ARB, m_FBOTexBackId, 0);
 
956
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, m_FBOAttFrontId, GL_TEXTURE_RECTANGLE_ARB, m_FBOTexFrontId, 0);
857
957
 
858
958
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
859
 
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, m_FBOTexSize.width, m_FBOTexSize.height);
860
 
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
861
 
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
 
959
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_FBOTexSize.width, m_FBOTexSize.height);
 
960
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
 
961
 
 
962
    /* Bind the FBOs for reading and drawing. */
 
963
    glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
 
964
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_FBOId);
 
965
 
 
966
    /* Explicitly clear the textures otherwise they would contain old memory stuff. */
 
967
    glDrawBuffer(m_FBOAttBackId);
 
968
    glClear(GL_COLOR_BUFFER_BIT);
 
969
    glDrawBuffer(m_FBOAttFrontId);
 
970
    glClear(GL_COLOR_BUFFER_BIT);
 
971
 
 
972
    /* Now initially reading/drawing to the back buffer. */
 
973
    glReadBuffer(m_FBOAttBackId);
 
974
    glDrawBuffer(m_FBOAttBackId);
862
975
 
863
976
    /* Make sure the FBO was created successfully. */
864
977
    if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
865
 
        DEBUG_MSG(("Framebuffer Object creation or update failed!\n"));
 
978
        DEBUG_MSG(("OVIW(%p): Framebuffer Object creation or update failed!\n", (void*)self));
866
979
 
 
980
//    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
867
981
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, oldTexId);
868
 
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFBId ? oldFBId:m_FBOId);
 
982
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)oldFBId ? (GLuint)oldFBId : m_FBOId);
869
983
 
870
984
    /* Is there a dock tile preview enabled in the GUI? If so setup a
871
985
     * additional thumbnail view for the dock tile. */
872
 
    NSView *dockScreen = [self dockTileScreen];
873
 
    if (dockScreen)
 
986
    pDockScreen = [self dockTileScreen];
 
987
    if (pDockScreen)
874
988
    {
875
989
        if (!m_FBOThumbId)
876
990
        {
885
999
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
886
1000
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
887
1001
        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
888
 
    
 
1002
 
889
1003
        /* The GPUs like the GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV combination
890
1004
         * others are also valid, but might incur a costly software translation. */
891
 
        glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, m_FBOTexSize.width * m_FBOThumbScaleX, m_FBOTexSize.height * m_FBOThumbScaleY, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
 
1005
        glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width * m_FBOThumbScaleX, m_FBOTexSize.height * m_FBOThumbScaleY, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
892
1006
 
893
1007
        /* Now attach texture to the FBO as its color destination */
894
1008
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOThumbTexId, 0);
895
1009
 
896
1010
        /* Make sure the FBO was created successfully. */
897
1011
        if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
898
 
            DEBUG_MSG(("Framebuffer Thumb Object creation or update failed!\n"));
 
1012
            DEBUG_MSG(("OVIW(%p): Framebuffer \"Thumb\" Object creation or update failed!\n", (void*)self));
899
1013
 
900
1014
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, oldTexId);
901
 
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFBId ? oldFBId:m_FBOId);
 
1015
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)oldFBId ? (GLuint)oldFBId : m_FBOId);
902
1016
 
903
1017
        m_DockTileView = [[DockOverlayView alloc] init];
904
1018
        [self reshapeDockTile];
905
 
        [dockScreen addSubview:m_DockTileView];
 
1019
        [pDockScreen addSubview:m_DockTileView];
906
1020
    }
907
1021
 
908
1022
    /* Initialize with one big visual region over the full size */
913
1027
    m_paClipRects[1] = 0;
914
1028
    m_paClipRects[2] = m_FBOTexSize.width;
915
1029
    m_paClipRects[3] = m_FBOTexSize.height;
916
 
    
917
 
    //GL_RESTORE_STATE;
 
1030
#endif
918
1031
}
919
1032
 
920
1033
- (void)deleteFBO
921
1034
{
922
 
    DEBUG_MSG(("deleteFBO %p\n", self));
 
1035
    DEBUG_MSG(("OVIW(%p): deleteFBO\n", (void*)self));
 
1036
 
923
1037
    if (m_pSharedGLCtx)
924
1038
    {
925
 
        DEBUG_MSG(("MakeCurrent (shared) %X\n", m_pSharedGLCtx));
 
1039
        DEBUG_MSG(("OVIW(%p): makeCurrent (shared) %p\n", (void*)self, (void*)m_pSharedGLCtx));
926
1040
        [m_pSharedGLCtx makeCurrentContext];
927
1041
        [m_pSharedGLCtx update];
928
1042
 
932
1046
 
933
1047
    if (m_pGLCtx)
934
1048
    {
935
 
        DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
 
1049
        DEBUG_MSG(("OVIW(%p): makeCurrent (non shared) %p\n", (void*)self, (void*)m_pGLCtx));
936
1050
        [m_pGLCtx makeCurrentContext];
937
1051
 
 
1052
#ifdef FBO
938
1053
        if (m_FBODepthStencilPackedId > 0)
939
1054
        {
940
1055
            glDeleteRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
941
1056
            m_FBODepthStencilPackedId = 0;
942
1057
        }
943
 
        if (m_FBOTexId > 0)
944
 
        {
945
 
            glDeleteTextures(1, &m_FBOTexId);
946
 
            m_FBOTexId = 0;
 
1058
        if (m_FBOTexBackId > 0)
 
1059
        {
 
1060
            glDeleteTextures(1, &m_FBOTexBackId);
 
1061
            m_FBOTexBackId = 0;
 
1062
        }
 
1063
        if (m_FBOTexFrontId > 0)
 
1064
        {
 
1065
            glDeleteTextures(1, &m_FBOTexFrontId);
 
1066
            m_FBOTexFrontId = 0;
947
1067
        }
948
1068
        if (m_FBOId > 0)
949
1069
        {
950
 
            GLint tmpFB;
951
 
            glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
952
 
 
953
 
            if (tmpFB == m_FBOId)
954
 
            {
 
1070
            if ([self isCurrentFBO])
955
1071
                glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
956
 
            }
957
 
            
 
1072
 
958
1073
            glDeleteFramebuffersEXT(1, &m_FBOId);
959
1074
            m_FBOId = 0;
960
1075
        }
 
1076
#endif
961
1077
    }
962
1078
 
963
1079
    if (m_DockTileView != nil)
970
1086
 
971
1087
- (void)updateFBO
972
1088
{
973
 
    DEBUG_MSG(("updateFBO %p\n", self));
 
1089
    DEBUG_MSG(("OVIW(%p): updateFBO\n", (void*)self));
 
1090
 
974
1091
    [self makeCurrentFBO];
975
 
    
 
1092
 
976
1093
    if (m_pGLCtx)
977
1094
    {
978
1095
#ifdef FBO
986
1103
 
987
1104
- (void)makeCurrentFBO
988
1105
{
989
 
    DEBUG_MSG_1(("MakeCurrent called %X\n", self));
 
1106
    DEBUG_MSG(("OVIW(%p): makeCurrentFBO\n", (void*)self));
990
1107
 
991
1108
#ifdef FBO
 
1109
    DEBUG_MSG(("OVIW(%p): FBOId=%d CTX=%p\n", (void*)self, m_FBOId, (void*)m_pGLCtx));
992
1110
    if([NSOpenGLContext currentContext] != 0)
993
1111
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
994
1112
#endif
995
1113
    if (m_pGLCtx)
996
1114
    {
997
 
        if ([m_pGLCtx view] != self) 
 
1115
        if ([m_pGLCtx view] != self)
998
1116
        {
999
1117
            /* We change the active view, so flush first */
1000
1118
            if([NSOpenGLContext currentContext] != 0)
1002
1120
            [m_pGLCtx setView: self];
1003
1121
            CHECK_GL_ERROR();
1004
1122
        }
1005
 
//        if ([NSOpenGLContext currentContext] != m_pGLCtx)
 
1123
        /*
 
1124
        if ([NSOpenGLContext currentContext] != m_pGLCtx)
 
1125
        */
1006
1126
        {
1007
 
            DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
1008
1127
            [m_pGLCtx makeCurrentContext];
1009
1128
            CHECK_GL_ERROR();
1010
 
//            [m_pGLCtx update];
 
1129
            /*
 
1130
            [m_pGLCtx update];
 
1131
            */
1011
1132
        }
1012
1133
    }
1013
1134
#ifdef FBO
1015
1136
#endif
1016
1137
}
1017
1138
 
 
1139
- (bool)isCurrentFBO
 
1140
{
 
1141
#ifdef FBO
 
1142
    GLint curFBOId = 0;
 
1143
 
 
1144
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &curFBOId);
 
1145
    DEBUG_MSG_1(("OVIW(%p): isCurrentFBO: curFBOId=%d FBOId=%d\n", (void*)self, curFBOId, m_FBOId));
 
1146
    return (GLuint)curFBOId == m_FBOId;
 
1147
#else
 
1148
    return false;
 
1149
#endif
 
1150
}
 
1151
 
 
1152
- (void)tryDraw
 
1153
{
 
1154
    if ([self lockFocusIfCanDraw])
 
1155
    {
 
1156
        [self renderFBOToView];
 
1157
        [self unlockFocus];
 
1158
    }
 
1159
}
 
1160
 
1018
1161
- (void)swapFBO
1019
1162
{
1020
 
    DEBUG_MSG_1(("SwapCurrent called %X\n", self));
 
1163
    GLint sw     = 0;
 
1164
    GLint readFBOId = 0;
 
1165
    GLint drawFBOId = 0;
 
1166
    GLint readId = 0;
 
1167
    GLint drawId = 0;
 
1168
 
 
1169
    DEBUG_MSG(("OVIW(%p): swapFBO\n", (void*)self));
1021
1170
 
1022
1171
#ifdef FBO
1023
 
    GLint tmpFB;
1024
 
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
1025
 
    DEBUG_MSG_1(("Swap GetINT %d\n", tmpFB));
1026
 
    /* Don't use flush buffers cause we are using FBOs here */
1027
 
//    [m_pGLCtx flushBuffer];
 
1172
    /* Don't use flush buffers cause we are using FBOs here! */
 
1173
 
 
1174
    /* Before we swap make sure everything is done (This is really
 
1175
     * important. Don't remove.) */
1028
1176
    glFlush();
1029
 
//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1030
 
    DEBUG_MSG_1(("swapFBO bound:%i, self:%i\n", tmpFB, m_FBOId));
1031
 
    if (tmpFB == m_FBOId)
1032
 
    {
1033
 
        if ([self lockFocusIfCanDraw])
1034
 
        {
1035
 
            [self renderFBOToView];
1036
 
            [self unlockFocus];
1037
 
        }
1038
 
    }
1039
 
//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
 
1177
 
 
1178
    /* Fetch the current used read and draw buffers. */
 
1179
    glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readFBOId);
 
1180
    glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBOId);
 
1181
    glGetIntegerv(GL_READ_BUFFER, &readId);
 
1182
    glGetIntegerv(GL_DRAW_BUFFER, &drawId);
 
1183
 
 
1184
    /* Do the swapping of our internal ids */
 
1185
    sw              = m_FBOTexFrontId;
 
1186
    m_FBOTexFrontId = m_FBOTexBackId;
 
1187
    m_FBOTexBackId  = sw;
 
1188
    sw              = m_FBOAttFrontId;
 
1189
    m_FBOAttFrontId = m_FBOAttBackId;
 
1190
    m_FBOAttBackId  = sw;
 
1191
 
 
1192
    DEBUG_MSG_1(("read FBO: %d draw FBO: %d readId: %d drawId: %d\n", readFBOId, drawFBOId, readId, drawId));
 
1193
    /* We also have to swap the real ids on the current context. */
 
1194
    if ((GLuint)readFBOId == m_FBOId)
 
1195
    {
 
1196
        if ((GLuint)readId == m_FBOAttFrontId)
 
1197
            glReadBuffer(m_FBOAttBackId);
 
1198
        if ((GLuint)readId == m_FBOAttBackId)
 
1199
            glReadBuffer(m_FBOAttFrontId);
 
1200
    }
 
1201
    if ((GLuint)drawFBOId == m_FBOId)
 
1202
    {
 
1203
        if ((GLuint)drawId == m_FBOAttFrontId)
 
1204
            glDrawBuffer(m_FBOAttBackId);
 
1205
        if ((GLuint)drawId == m_FBOAttBackId)
 
1206
            glDrawBuffer(m_FBOAttFrontId);
 
1207
    }
 
1208
 
 
1209
    [self tryDraw];
1040
1210
#else
1041
1211
    [m_pGLCtx flushBuffer];
1042
1212
#endif
1044
1214
 
1045
1215
- (void)flushFBO
1046
1216
{
1047
 
    GLint tmpFB;
1048
 
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
 
1217
    GLint drawId = 0;
 
1218
    GLint FBOId  = 0;
 
1219
 
 
1220
    DEBUG_MSG(("OVIW(%p): flushFBO\n", (void*)self));
 
1221
 
1049
1222
    glFlush();
1050
 
//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1051
 
    DEBUG_MSG_1 (("Flush GetINT %d\n", tmpFB));
1052
 
    if (tmpFB == m_FBOId)
 
1223
#ifdef FBO
 
1224
    /* If at any time OpenGl operations where done in the front buffer, we need
 
1225
     * to reflect this in the FBO as well. This is something which on real
 
1226
     * hardware happens and unfortunately some applications rely on it (grrr ... Compiz). */
 
1227
    if (   m_fFrontDrawing
 
1228
        && [self isCurrentFBO])
1053
1229
    {
1054
 
        if ([self lockFocusIfCanDraw])
1055
 
        {
1056
 
            [self renderFBOToView];
1057
 
            [self unlockFocus];
1058
 
        }
 
1230
        /* Only reset if we aren't currently front. */
 
1231
        glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &FBOId);
 
1232
        glGetIntegerv(GL_DRAW_BUFFER, &drawId);
 
1233
        if (!(   (GLuint)FBOId  == m_FBOId
 
1234
              && (GLuint)drawId == m_FBOAttFrontId))
 
1235
            m_fFrontDrawing = false;
 
1236
        [self tryDraw];
1059
1237
    }
1060
 
//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
 
1238
#endif
1061
1239
}
1062
1240
 
1063
1241
- (void)finishFBO
1064
1242
{
1065
 
    GLint tmpFB;
1066
 
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
 
1243
    DEBUG_MSG(("OVIW(%p): finishFBO\n", (void*)self));
 
1244
 
1067
1245
    glFinish();
1068
 
        //    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1069
 
    DEBUG_MSG_1 (("Finish GetINT %d\n", tmpFB));
1070
 
    if (tmpFB == m_FBOId)
1071
 
    {
1072
 
        if ([self lockFocusIfCanDraw])
1073
 
        {
1074
 
            [self renderFBOToView];
1075
 
            [self unlockFocus];
1076
 
        }
1077
 
    }
1078
 
//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
1079
 
}
1080
 
 
1081
 
- (void)bindFBO
1082
 
{
1083
 
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
 
1246
#ifdef FBO
 
1247
    if ([self isCurrentFBO])
 
1248
        [self tryDraw];
 
1249
#endif
 
1250
}
 
1251
 
 
1252
- (void)stateInfo:(GLenum)pname withParams:(GLint*)params
 
1253
{
 
1254
    GLint test;
 
1255
//    DEBUG_MSG_1(("StateInfo requested: %d\n", pname));
 
1256
 
 
1257
    glGetIntegerv(pname, params);
 
1258
#ifdef FBO
 
1259
    switch(pname)
 
1260
    {
 
1261
        case GL_FRAMEBUFFER_BINDING_EXT:
 
1262
        case GL_READ_FRAMEBUFFER_BINDING:
 
1263
        case GL_READ_FRAMEBUFFER_EXT:
 
1264
        case GL_DRAW_FRAMEBUFFER_EXT:
 
1265
        {
 
1266
            if ((GLuint)*params == m_FBOId)
 
1267
                *params = 0;
 
1268
            break;
 
1269
        }
 
1270
        case GL_READ_BUFFER:
 
1271
        {
 
1272
            glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &test);
 
1273
            if ((GLuint)test == m_FBOId)
 
1274
            {
 
1275
                if ((GLuint)*params == m_FBOAttFrontId)
 
1276
                    *params = GL_FRONT;
 
1277
                else
 
1278
                    if ((GLuint)*params == m_FBOAttBackId)
 
1279
                        *params = GL_BACK;
 
1280
            }
 
1281
            break;
 
1282
        }
 
1283
        case GL_DRAW_BUFFER:
 
1284
        {
 
1285
            glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &test);
 
1286
            if ((GLuint)test == m_FBOId)
 
1287
            {
 
1288
                if ((GLuint)*params == m_FBOAttFrontId)
 
1289
                    *params = GL_FRONT;
 
1290
                else
 
1291
                    if ((GLuint)*params == m_FBOAttBackId)
 
1292
                        *params = GL_BACK;
 
1293
            }
 
1294
            break;
 
1295
        }
 
1296
    }
 
1297
#endif
 
1298
}
 
1299
 
 
1300
- (void)readBuffer:(GLenum)mode
 
1301
{
 
1302
#ifdef FBO
 
1303
    /*
 
1304
    if ([self isCurrentFBO])
 
1305
    */
 
1306
    {
 
1307
        if (mode == GL_FRONT)
 
1308
        {
 
1309
            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
 
1310
            glReadBuffer(m_FBOAttFrontId);
 
1311
        }
 
1312
        else if (mode == GL_BACK)
 
1313
        {
 
1314
            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
 
1315
            glReadBuffer(m_FBOAttBackId);
 
1316
        }
 
1317
        else
 
1318
            glReadBuffer(mode);
 
1319
    }
 
1320
#else
 
1321
    glReadBuffer(mode);
 
1322
#endif
 
1323
}
 
1324
 
 
1325
- (void)drawBuffer:(GLenum)mode
 
1326
{
 
1327
#ifdef FBO
 
1328
    /*
 
1329
    if ([self isCurrentFBO])
 
1330
    */
 
1331
    {
 
1332
        if (mode == GL_FRONT)
 
1333
        {
 
1334
            DEBUG_MSG(("OVIW(%p): front\n", (void*)self));
 
1335
            glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_FBOId);
 
1336
            glDrawBuffer(m_FBOAttFrontId);
 
1337
            m_fFrontDrawing = true;
 
1338
        }
 
1339
        else if (mode == GL_BACK)
 
1340
        {
 
1341
            DEBUG_MSG(("OVIW(%p): back\n", (void*)self));
 
1342
            glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_FBOId);
 
1343
            glDrawBuffer(m_FBOAttBackId);
 
1344
        }
 
1345
        else
 
1346
        {
 
1347
            DEBUG_MSG(("OVIW(%p): other: %d\n", (void*)self, mode));
 
1348
            glDrawBuffer(mode);
 
1349
        }
 
1350
    }
 
1351
#else
 
1352
    glDrawBuffer(mode);
 
1353
#endif
 
1354
}
 
1355
 
 
1356
- (void)bindFBO:(GLenum)target withFrameBuffer:(GLuint)framebuffer
 
1357
{
 
1358
#ifdef FBO
 
1359
    if (framebuffer != 0)
 
1360
        glBindFramebufferEXT(target, framebuffer);
 
1361
    else
 
1362
        glBindFramebufferEXT(target, m_FBOId);
 
1363
#else
 
1364
    glBindFramebufferEXT(target, framebuffer);
 
1365
#endif
1084
1366
}
1085
1367
 
1086
1368
- (void)renderFBOToView
1087
1369
{
 
1370
    GLint opaque       = 0;
 
1371
    GLint i            = 0;
 
1372
    GLint oldReadFBOId = 0;
 
1373
    GLint oldDrawFBOId = 0;
 
1374
    GLint oldReadId    = 0;
 
1375
    GLint oldDrawId    = 0;
 
1376
 
 
1377
    DEBUG_MSG(("OVIW(%p): renderFBOToView\n", (void*)self));
 
1378
 
 
1379
#ifdef FBO
 
1380
 
 
1381
    /* Fetch the current used read and draw buffers. */
 
1382
    glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &oldReadFBOId);
 
1383
    glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &oldDrawFBOId);
 
1384
    glGetIntegerv(GL_READ_BUFFER, &oldReadId);
 
1385
    glGetIntegerv(GL_DRAW_BUFFER, &oldDrawId);
 
1386
 
1088
1387
    if (!m_pSharedGLCtx)
1089
1388
    {
1090
1389
        /* Create a shared context out of the main context. Use the same pixel format. */
1091
1390
        m_pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
1092
1391
 
1093
1392
        /* Set the new context as non opaque */
1094
 
        GLint opaque = 0;
1095
 
        [m_pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];        
1096
 
        /* Only swap on screen refresh */
1097
 
//        GLint swap = 1;
1098
 
//        [m_pSharedGLCtx setValues:&swap forParameter:NSOpenGLCPSwapInterval];        
 
1393
        [m_pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
1099
1394
        /* Set this view as the drawable for the new context */
1100
1395
        [m_pSharedGLCtx setView: self];
1101
1396
        [self updateViewport];
1104
1399
    if (m_pSharedGLCtx)
1105
1400
    {
1106
1401
        NSRect r = [self frame];
1107
 
        DEBUG_MSG_1(("rF2V frame[%i, %i, %i, %i]\n", (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
 
1402
        DEBUG_MSG(("OVIW(%p): rF2V frame: [%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
1108
1403
 
1109
 
        if (m_FBOTexId > 0)
 
1404
        if (m_FBOTexFrontId > 0)
1110
1405
        {
1111
1406
            if ([m_pSharedGLCtx view] != self)
1112
1407
            {
1113
 
                DEBUG_MSG(("renderFBOToView: not current view of shared ctx!"));
 
1408
                DEBUG_MSG(("OVIW(%p): not current view of shared ctx! Switching ...\n", (void*)self));
1114
1409
                [m_pSharedGLCtx setView: self];
1115
1410
                [self updateViewport];
1116
1411
            }
1117
1412
 
1118
 
            //DEBUG_MSG(("MakeCurrent (shared) %X\n", m_pSharedGLCtx));
1119
1413
            [m_pSharedGLCtx makeCurrentContext];
1120
 
       
1121
 
            if (m_FBOThumbTexId > 0 &&
1122
 
                [m_DockTileView thumbBitmap] != nil)
1123
 
            {
1124
 
                /* Only update after at least 200 ms, cause glReadPixels is
1125
 
                 * heavy performance wise. */
1126
 
                uint64_t uiNewTime = RTTimeMilliTS();
1127
 
                if (uiNewTime - m_uiDockUpdateTime > 200)
1128
 
                {
1129
 
                    m_uiDockUpdateTime = uiNewTime;
1130
 
#if 0
1131
 
                    /* todo: check this for optimization */
1132
 
                    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
1133
 
                    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE,
1134
 
                                    GL_STORAGE_SHARED_APPLE);
1135
 
                    glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1136
 
                    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
1137
 
                                 sizex, sizey, 0, GL_BGRA,
1138
 
                                 GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr);
1139
 
                    glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
1140
 
                                        0, 0, 0, 0, 0, image_width, image_height);
1141
 
                    glFlush();
1142
 
                    // Do other work processing here, using a double or triple buffer
1143
 
                    glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
1144
 
                                  GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
1145
 
#endif
1146
 
 
1147
 
                    GL_SAVE_STATE;
1148
 
                    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOThumbId);
1149
 
 
1150
 
                    /* We like to read from the primary color buffer */
1151
 
                    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1152
 
 
1153
 
                    NSRect rr = [m_DockTileView frame];
1154
 
 
1155
 
                    /* Setup all matrices */
1156
 
                    glMatrixMode(GL_PROJECTION);
1157
 
                    glLoadIdentity();
1158
 
                    glViewport(0, 0, rr.size.width, rr.size.height);
1159
 
                    glOrtho(0, rr.size.width, 0, rr.size.height, -1, 1);
1160
 
                    glScalef(m_FBOThumbScaleX, m_FBOThumbScaleY, 1.0f);
1161
 
                    glMatrixMode(GL_TEXTURE);
1162
 
                    glLoadIdentity();
1163
 
                    glTranslatef(0.0f, m_RootShift.y, 0.0f);
1164
 
                    glMatrixMode(GL_MODELVIEW);
1165
 
                    glLoadIdentity();
1166
 
 
1167
 
                    /* Clear background to transparent */
1168
 
                    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1169
 
                    glClear(GL_COLOR_BUFFER_BIT);
1170
 
 
1171
 
                    glEnable(GL_TEXTURE_RECTANGLE_ARB);
1172
 
                    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
1173
 
                    GLint i;
1174
 
                    for (i = 0; i < m_cClipRects; ++i)
1175
 
                    {
1176
 
                        GLint x1 = m_paClipRects[4*i];
1177
 
                        GLint y1 = (r.size.height - m_paClipRects[4*i+1]);
1178
 
                        GLint x2 = m_paClipRects[4*i+2];
1179
 
                        GLint y2 = (r.size.height - m_paClipRects[4*i+3]);
1180
 
                        glBegin(GL_QUADS);
1181
 
                        {
1182
 
                            glTexCoord2i(x1, y1); glVertex2i(x1, y1);
1183
 
                            glTexCoord2i(x1, y2); glVertex2i(x1, y2);
1184
 
                            glTexCoord2i(x2, y2); glVertex2i(x2, y2);
1185
 
                            glTexCoord2i(x2, y1); glVertex2i(x2, y1);
1186
 
                        }
1187
 
                        glEnd();
1188
 
                    }
1189
 
                    glFinish();
1190
 
 
1191
 
                    /* Here the magic of reading the FBO content in our own buffer
1192
 
                     * happens. We have to lock this access, in the case the dock
1193
 
                     * is updated currently. */
1194
 
                    [m_DockTileView lock];
1195
 
                    glReadPixels(0, 0, rr.size.width, rr.size.height,
1196
 
                                 GL_RGBA,
1197
 
                                 GL_UNSIGNED_BYTE,
1198
 
                                 [[m_DockTileView thumbBitmap] bitmapData]);
1199
 
                    [m_DockTileView unlock];
1200
 
 
1201
 
                    NSDockTile *pDT = [[NSApplication sharedApplication] dockTile];
1202
 
 
1203
 
                    /* Send a display message to the dock tile in the main thread */
1204
 
                    [[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
1205
 
 
1206
 
                    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1207
 
                    GL_RESTORE_STATE;
1208
 
                }
1209
 
            }
1210
 
 
 
1414
 
 
1415
            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
 
1416
            glReadBuffer(m_FBOAttFrontId);
 
1417
            glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
 
1418
            glDrawBuffer(GL_BACK);
 
1419
 
 
1420
            /* Render FBO content to the dock tile when necessary. */
 
1421
            [self renderFBOToDockTile];
 
1422
 
 
1423
#if 1 /* Set to 0 to see the docktile instead of the real output */
1211
1424
            /* Clear background to transparent */
1212
1425
            glClear(GL_COLOR_BUFFER_BIT);
1213
1426
 
1214
 
            glEnable(GL_TEXTURE_RECTANGLE_ARB);
1215
 
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
1216
 
 
1217
 
            /* Blit the content of the FBO to the screen. todo: check for
1218
 
             * optimization with display lists. */
1219
 
            GLint i;
 
1427
            /* Blit the content of the FBO to the screen. */
1220
1428
            for (i = 0; i < m_cClipRects; ++i)
1221
1429
            {
1222
1430
                GLint x1 = m_paClipRects[4*i];
1223
1431
                GLint y1 = r.size.height - m_paClipRects[4*i+1];
1224
1432
                GLint x2 = m_paClipRects[4*i+2];
1225
1433
                GLint y2 = r.size.height - m_paClipRects[4*i+3];
1226
 
                glBegin(GL_QUADS);
1227
 
                {
1228
 
                    glTexCoord2i(x1, y1); glVertex2i(x1, y1);
1229
 
                    glTexCoord2i(x1, y2); glVertex2i(x1, y2);
1230
 
                    glTexCoord2i(x2, y2); glVertex2i(x2, y2);
1231
 
                    glTexCoord2i(x2, y1); glVertex2i(x2, y1);
1232
 
                }
1233
 
                glEnd();
 
1434
                glBlitFramebufferEXT(x1, y1 + m_RootShift.y, x2, y2 + m_RootShift.y,
 
1435
                                     x1 - m_RootShift.x, y1, x2 - m_RootShift.x, y2,
 
1436
                                     GL_COLOR_BUFFER_BIT, GL_NEAREST);
1234
1437
            }
 
1438
#endif
 
1439
            /*
1235
1440
            glFinish();
 
1441
            */
 
1442
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1236
1443
            [m_pSharedGLCtx flushBuffer];
1237
 
            //DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
 
1444
 
1238
1445
            [m_pGLCtx makeCurrentContext];
1239
 
        }
1240
 
    }
 
1446
            /* Reset to previous buffer bindings. */
 
1447
            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oldReadFBOId);
 
1448
            glReadBuffer(oldReadId);
 
1449
            glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, oldDrawFBOId);
 
1450
            glDrawBuffer(oldDrawId);
 
1451
        }
 
1452
    }
 
1453
#else
 
1454
    [m_pGLCtx flushBuffer];
 
1455
#endif
 
1456
}
 
1457
 
 
1458
- (void)renderFBOToDockTile
 
1459
{
 
1460
    NSRect r        = [self frame];
 
1461
    NSRect rr       = NSZeroRect;
 
1462
    GLint i         = 0;
 
1463
    NSDockTile *pDT = nil;
 
1464
 
 
1465
#ifdef FBO
 
1466
    if (   m_FBOThumbId
 
1467
        && m_FBOThumbTexId
 
1468
        && [m_DockTileView thumbBitmap] != nil)
 
1469
    {
 
1470
        /* Only update after at least 200 ms, cause glReadPixels is
 
1471
         * heavy performance wise. */
 
1472
        uint64_t uiNewTime = RTTimeMilliTS();
 
1473
        if (uiNewTime - m_uiDockUpdateTime > 200)
 
1474
        {
 
1475
            m_uiDockUpdateTime = uiNewTime;
 
1476
#if 0
 
1477
            /* todo: check this for optimization */
 
1478
            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
 
1479
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE,
 
1480
                            GL_STORAGE_SHARED_APPLE);
 
1481
            glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
 
1482
            glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
 
1483
                         sizex, sizey, 0, GL_BGRA,
 
1484
                         GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr);
 
1485
            glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
 
1486
                                0, 0, 0, 0, 0, image_width, image_height);
 
1487
            glFlush();
 
1488
            /* Do other work processing here, using a double or triple buffer */
 
1489
            glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
 
1490
                          GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
 
1491
#endif
 
1492
            /* Clear background to transparent */
 
1493
            glClear(GL_COLOR_BUFFER_BIT);
 
1494
 
 
1495
            rr = [m_DockTileView frame];
 
1496
 
 
1497
            for (i = 0; i < m_cClipRects; ++i)
 
1498
            {
 
1499
                GLint x1 = m_paClipRects[4*i];
 
1500
                GLint y1 = r.size.height - m_paClipRects[4*i+1];
 
1501
                GLint x2 = m_paClipRects[4*i+2];
 
1502
                GLint y2 = r.size.height - m_paClipRects[4*i+3];
 
1503
 
 
1504
                glBlitFramebufferEXT(x1, y1 + m_RootShift.y, x2, y2 + m_RootShift.y,
 
1505
                                     x1 * m_FBOThumbScaleX, y1 * m_FBOThumbScaleY, x2 * m_FBOThumbScaleX, y2 * m_FBOThumbScaleY,
 
1506
                                     GL_COLOR_BUFFER_BIT, GL_LINEAR);
 
1507
            }
 
1508
            glFinish();
 
1509
 
 
1510
            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
 
1511
            glReadBuffer(GL_BACK);
 
1512
            /* Here the magic of reading the FBO content in our own buffer
 
1513
             * happens. We have to lock this access, in the case the dock
 
1514
             * is updated currently. */
 
1515
            [m_DockTileView lock];
 
1516
            glReadPixels(0, 0, rr.size.width, rr.size.height,
 
1517
                         GL_BGRA,
 
1518
                         GL_UNSIGNED_INT_8_8_8_8,
 
1519
                         [[m_DockTileView thumbBitmap] bitmapData]);
 
1520
            [m_DockTileView unlock];
 
1521
 
 
1522
            glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
 
1523
            glReadBuffer(m_FBOAttFrontId);
 
1524
 
 
1525
            pDT = [[NSApplication sharedApplication] dockTile];
 
1526
 
 
1527
            /* Send a display message to the dock tile in the main thread */
 
1528
            [[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
 
1529
 
 
1530
        }
 
1531
    }
 
1532
#endif
1241
1533
}
1242
1534
 
1243
1535
- (void)clearVisibleRegions
1252
1544
 
1253
1545
- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects
1254
1546
{
1255
 
    DEBUG_MSG_1(("New region received\n"));
 
1547
    DEBUG_MSG_1(("OVIW(%p): setVisibleRegions: cRects=%d\n", (void*)self, cRects));
1256
1548
 
1257
1549
    [self clearVisibleRegions];
1258
1550
 
1259
 
    if (cRects>0)
 
1551
    if (cRects > 0)
1260
1552
    {
1261
1553
        m_paClipRects = (GLint*)RTMemAlloc(sizeof(GLint) * 4 * cRects);
1262
1554
        m_cClipRects = cRects;
1280
1572
 
1281
1573
- (void)reshapeDockTile
1282
1574
{
 
1575
    NSRect newFrame = NSZeroRect;
 
1576
 
1283
1577
    NSView *pView = [self dockTileScreen];
1284
1578
    if (pView != nil)
1285
1579
    {
1288
1582
 
1289
1583
        m_FBOThumbScaleX = (float)dockFrame.size.width / parentFrame.size.width;
1290
1584
        m_FBOThumbScaleY = (float)dockFrame.size.height / parentFrame.size.height;
1291
 
        NSRect newFrame = NSMakeRect ((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_RootShift.y) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
1292
 
//    NSRect newFrame = NSMakeRect ((int)roundf(m_Pos.x * m_FBOThumbScaleX), (int)roundf(dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (int)roundf(m_Size.width * m_FBOThumbScaleX), (int)roundf(m_Size.height * m_FBOThumbScaleY));
1293
 
//      NSRect newFrame = NSMakeRect ((m_Pos.x * m_FBOThumbScaleX), (dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (m_Size.width * m_FBOThumbScaleX), (m_Size.height * m_FBOThumbScaleY));
1294
 
//    printf ("%f %f %f %f - %f %f\n", newFrame.origin.x, newFrame.origin.y, newFrame.size.width, newFrame.size.height, m_Size.height, m_FBOThumbScaleY);
 
1585
        newFrame = NSMakeRect((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_RootShift.y) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
 
1586
        /*
 
1587
        NSRect newFrame = NSMakeRect ((int)roundf(m_Pos.x * m_FBOThumbScaleX), (int)roundf(dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (int)roundf(m_Size.width * m_FBOThumbScaleX), (int)roundf(m_Size.height * m_FBOThumbScaleY));
 
1588
        NSRect newFrame = NSMakeRect ((m_Pos.x * m_FBOThumbScaleX), (dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (m_Size.width * m_FBOThumbScaleX), (m_Size.height * m_FBOThumbScaleY));
 
1589
        printf ("%f %f %f %f - %f %f\n", newFrame.origin.x, newFrame.origin.y, newFrame.size.width, newFrame.size.height, m_Size.height, m_FBOThumbScaleY);
 
1590
        */
1295
1591
        [m_DockTileView setFrame: newFrame];
1296
1592
    }
1297
1593
}
1305
1601
********************************************************************************/
1306
1602
void cocoaGLCtxCreate(NativeNSOpenGLContextRef *ppCtx, GLbitfield fVisParams)
1307
1603
{
 
1604
    NSOpenGLPixelFormat *pFmt = nil;
 
1605
 
1308
1606
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1309
1607
 
1310
 
    NSOpenGLPixelFormatAttribute attribs[24] = 
 
1608
    NSOpenGLPixelFormatAttribute attribs[24] =
1311
1609
    {
1312
1610
        NSOpenGLPFAWindow,
1313
1611
        NSOpenGLPFAAccelerated,
1314
1612
        NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24
1315
1613
    };
1316
 
    
 
1614
 
1317
1615
    int i = 4;
 
1616
 
1318
1617
    if (fVisParams & CR_ALPHA_BIT)
1319
1618
    {
1320
1619
        DEBUG_MSG(("CR_ALPHA_BIT requested\n"));
1333
1632
        attribs[i++] = NSOpenGLPFAStencilSize;
1334
1633
        attribs[i++] = 8;
1335
1634
    }
1336
 
    if (fVisParams & CR_ACCUM_BIT) 
 
1635
    if (fVisParams & CR_ACCUM_BIT)
1337
1636
    {
1338
1637
        DEBUG_MSG(("CR_ACCUM_BIT requested\n"));
1339
1638
        attribs[i++] = NSOpenGLPFAAccumSize;
1342
1641
        else
1343
1642
            attribs[i++] = 24;
1344
1643
    }
1345
 
    if (fVisParams & CR_MULTISAMPLE_BIT) 
 
1644
    if (fVisParams & CR_MULTISAMPLE_BIT)
1346
1645
    {
1347
1646
        DEBUG_MSG(("CR_MULTISAMPLE_BIT requested\n"));
1348
1647
        attribs[i++] = NSOpenGLPFASampleBuffers;
1357
1656
    }
1358
1657
    if (fVisParams & CR_STEREO_BIT)
1359
1658
    {
1360
 
        DEBUG_MSG(("CR_DOUBLE_BIT requested\n"));
 
1659
        /* We don't support that.
 
1660
        DEBUG_MSG(("CR_STEREO_BIT requested\n"));
1361
1661
        attribs[i++] = NSOpenGLPFAStereo;
 
1662
        */
1362
1663
    }
1363
 
    
 
1664
 
1364
1665
    /* Mark the end */
1365
1666
    attribs[i++] = 0;
1366
1667
 
1367
1668
    /* Choose a pixel format */
1368
 
    NSOpenGLPixelFormat* pFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
1369
 
    
 
1669
    pFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
 
1670
 
1370
1671
    if (pFmt)
1371
1672
    {
1372
1673
        *ppCtx = [[OverlayOpenGLContext alloc] initWithFormat:pFmt shareContext:nil];
1373
1674
 
1374
1675
        /* Enable multi threaded OpenGL engine */
1375
 
//        CGLContextObj cglCtx = [*ppCtx CGLContextObj];
1376
 
//        CGLError err = CGLEnable(cglCtx, kCGLCEMPEngine);
1377
 
//        if (err != kCGLNoError)
1378
 
//            printf ("Couldn't enable MT OpenGL engine!\n");
1379
 
    
 
1676
        /*
 
1677
        CGLContextObj cglCtx = [*ppCtx CGLContextObj];
 
1678
        CGLError err = CGLEnable(cglCtx, kCGLCEMPEngine);
 
1679
        if (err != kCGLNoError)
 
1680
            printf ("Couldn't enable MT OpenGL engine!\n");
 
1681
        */
 
1682
 
1380
1683
        DEBUG_MSG(("New context %X\n", (uint)*ppCtx));
1381
1684
    }
1382
1685
 
1387
1690
{
1388
1691
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1389
1692
 
1390
 
//    [pCtx release];
 
1693
    /*
 
1694
    [pCtx release];
 
1695
    */
1391
1696
 
1392
1697
    [pPool release];
1393
1698
}
1445
1750
 
1446
1751
void cocoaViewDestroy(NativeNSViewRef pView)
1447
1752
{
 
1753
    NSWindow *pWin = nil;
 
1754
 
1448
1755
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1449
1756
 
1450
1757
    /* Hide the view early */
1451
1758
    [pView setHidden: YES];
1452
1759
 
1453
 
    NSWindow *win = [pView window];
1454
 
    [[NSNotificationCenter defaultCenter] removeObserver:win];
1455
 
    [win setContentView: nil];
1456
 
    [[win parentWindow] removeChildWindow: win];
1457
 
    int b = [win retainCount];
1458
 
//    for (; b > 1; --b)
1459
 
//        [win performSelector:@selector(release)]
1460
 
    [win performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:YES];
1461
 
//        [win release];
 
1760
    pWin = [pView window];
 
1761
    [[NSNotificationCenter defaultCenter] removeObserver:pWin];
 
1762
    [pWin setContentView: nil];
 
1763
    [[pWin parentWindow] removeChildWindow: pWin];
 
1764
    /*
 
1765
    a = [pWin retainCount];
 
1766
    for (; a > 1; --a)
 
1767
        [pWin performSelector:@selector(release)]
 
1768
    */
 
1769
    [pWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:YES];
 
1770
    /*
 
1771
    [pWin release];
 
1772
    */
1462
1773
 
1463
1774
    /* There seems to be a bug in the performSelector method which is called in
1464
1775
     * parentWindowChanged above. The object is retained but not released. This
1465
1776
     * results in an unbalanced reference count, which is here manually
1466
1777
     * decremented. */
1467
 
    int a = [pView retainCount];
1468
 
//    for (; a > 1; --a)
 
1778
    /*
 
1779
    a = [pView retainCount];
 
1780
    for (; a > 1; --a)
 
1781
    */
1469
1782
    [pView performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:YES];
1470
 
//        [pView release];
 
1783
    /*
 
1784
    [pView release];
 
1785
    */
1471
1786
 
1472
1787
    [pPool release];
1473
1788
}
1482
1797
}
1483
1798
 
1484
1799
void cocoaViewDisplay(NativeNSViewRef pView)
1485
 
{    
 
1800
{
1486
1801
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1487
1802
 
1488
 
    DEBUG_MSG_1(("cocoaViewDisplay %p\n", pView));
 
1803
    DEBUG_MSG_1(("cocoaViewDisplay %p\n", (void*)pView));
1489
1804
    [(OverlayView*)pView swapFBO];
1490
1805
 
1491
1806
    [pPool release];
1528
1843
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1529
1844
 
1530
1845
    DEBUG_MSG(("cocoaViewMakeCurrentContext(%p, %p)\n", (void*)pView, (void*)pCtx));
1531
 
    
 
1846
 
1532
1847
    [(OverlayView*)pView setGLCtx:pCtx];
1533
1848
    [(OverlayView*)pView makeCurrentFBO];
1534
1849
 
1549
1864
* Additional OpenGL wrapper
1550
1865
*
1551
1866
********************************************************************************/
 
1867
static void performSelectorOnView(SEL selector)
 
1868
{
 
1869
    NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
 
1870
 
 
1871
    if (pCtx)
 
1872
    {
 
1873
        NSView *pView = [pCtx view];
 
1874
        if (pView)
 
1875
        {
 
1876
            if ([pView respondsToSelector:selector])
 
1877
                [pView performSelector:selector];
 
1878
        }
 
1879
    }
 
1880
}
 
1881
 
 
1882
static void performSelectorOnViewOneArg(SEL selector, id arg1)
 
1883
{
 
1884
    NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
 
1885
 
 
1886
    if (pCtx)
 
1887
    {
 
1888
        NSView *pView = [pCtx view];
 
1889
        if (pView)
 
1890
        {
 
1891
            if ([pView respondsToSelector:selector])
 
1892
                [pView performSelector:selector withObject:arg1];
 
1893
        }
 
1894
    }
 
1895
}
 
1896
 
 
1897
static void performSelectorOnViewTwoArgs(SEL selector, id arg1, id arg2)
 
1898
{
 
1899
    NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
 
1900
 
 
1901
    if (pCtx)
 
1902
    {
 
1903
        NSView *pView = [pCtx view];
 
1904
        if (pView)
 
1905
        {
 
1906
            if ([pView respondsToSelector:selector])
 
1907
                [pView performSelector:selector withObject:arg1 withObject:arg2];
 
1908
        }
 
1909
    }
 
1910
}
 
1911
 
1552
1912
void cocoaFlush(void)
1553
1913
{
 
1914
    NSOpenGLContext *pCtx = nil;
 
1915
 
1554
1916
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1555
1917
 
1556
 
//    glFlush();
1557
 
//    return;
1558
 
 
1559
1918
    DEBUG_MSG_1(("glFlush called\n"));
1560
1919
 
1561
 
#ifdef FBO
1562
 
    NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1563
 
    if (pCtx)
1564
 
    {
1565
 
        NSView *pView = [pCtx view];
1566
 
        if (pView)
1567
 
        {
1568
 
            if ([pView respondsToSelector:@selector(flushFBO)])
1569
 
                [pView performSelector:@selector(flushFBO)];
1570
 
        }
1571
 
    }
1572
 
#else
1573
 
    glFlush();
1574
 
#endif
 
1920
    performSelectorOnView(@selector(flushFBO));
1575
1921
 
1576
1922
    [pPool release];
1577
1923
}
1582
1928
 
1583
1929
    DEBUG_MSG_1(("glFinish called\n"));
1584
1930
 
1585
 
#ifdef FBO
1586
 
    NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1587
 
    if (pCtx)
1588
 
    {
1589
 
        NSView *pView = [pCtx view];
1590
 
        if (pView)
1591
 
        {
1592
 
            if ([pView respondsToSelector:@selector(finishFBO)])
1593
 
                [pView performSelector:@selector(finishFBO)];
1594
 
        }
1595
 
    }
1596
 
#else
1597
 
    glFinish();
1598
 
#endif
 
1931
    performSelectorOnView(@selector(finishFBO));
1599
1932
 
1600
1933
    [pPool release];
1601
1934
}
1604
1937
{
1605
1938
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1606
1939
 
1607
 
    DEBUG_MSG(("glRenderspuBindFramebufferEXT called %d\n", framebuffer));
 
1940
    DEBUG_MSG_1(("glBindFramebufferEXT called target: %d  fb: %d\n", target, framebuffer));
 
1941
 
 
1942
    performSelectorOnViewTwoArgs(@selector(bindFBO:withFrameBuffer:), (id)target, (id)framebuffer);
 
1943
 
 
1944
    [pPool release];
 
1945
}
 
1946
 
 
1947
void cocoaCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
 
1948
{
 
1949
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
 
1950
    GLbitfield mask = GL_COLOR_BUFFER_BIT;
 
1951
 
 
1952
    DEBUG_MSG_1(("glCopyPixels called: %d,%d-%dx%d type: %d\n", x, y, width, height, type));
1608
1953
 
1609
1954
#ifdef FBO
1610
 
    if (framebuffer != 0)
1611
 
        glBindFramebufferEXT(target, framebuffer);
1612
 
    else
1613
 
    {
1614
 
        NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1615
 
        if (pCtx)
1616
 
        {
1617
 
            NSView *pView = [pCtx view];
1618
 
            if (pView)
1619
 
            {
1620
 
                if ([pView respondsToSelector:@selector(bindFBO)])
1621
 
                    [pView performSelector:@selector(bindFBO)];
1622
 
            }
1623
 
        }
1624
 
    }
 
1955
    if (type == GL_DEPTH)
 
1956
        mask = GL_DEPTH_BUFFER_BIT;
 
1957
    else if (type == GL_STENCIL)
 
1958
        mask = GL_STENCIL_BUFFER_BIT;
 
1959
    glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, mask, GL_NEAREST);
1625
1960
#else
1626
 
    glBindFramebufferEXT(target, framebuffer);
 
1961
    glCopyPixels(x, y, width, height, type);
1627
1962
#endif
1628
1963
 
1629
1964
    [pPool release];
1630
1965
}
1631
1966
 
 
1967
void cocoaGetIntegerv(GLenum pname, GLint *params)
 
1968
{
 
1969
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
 
1970
 
 
1971
//    DEBUG_MSG_1(("getIntergerv called: %d\n", pname));
 
1972
 
 
1973
    performSelectorOnViewTwoArgs(@selector(stateInfo:withParams:), (id)pname, (id)params);
 
1974
 
 
1975
    [pPool release];
 
1976
}
 
1977
 
 
1978
void cocoaReadBuffer(GLenum mode)
 
1979
{
 
1980
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
 
1981
 
 
1982
    DEBUG_MSG_1(("glReadBuffer called: %d\n", mode));
 
1983
 
 
1984
    performSelectorOnViewOneArg(@selector(readBuffer:), (id)mode);
 
1985
 
 
1986
    [pPool release];
 
1987
}
 
1988
 
 
1989
void cocoaDrawBuffer(GLenum mode)
 
1990
{
 
1991
    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
 
1992
 
 
1993
    DEBUG_MSG_1(("glDrawBuffer called: %d\n", mode));
 
1994
 
 
1995
    performSelectorOnViewOneArg(@selector(drawBuffer:), (id)mode);
 
1996
 
 
1997
    [pPool release];
 
1998
}
 
1999