VirtualBox

Changeset 24377 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 5, 2009 11:18:52 AM (15 years ago)
Author:
vboxsync
Message:

crOpenGL-OSX: add support for realtime dock tile preview of OpenGL content in Cocoa

Location:
trunk/src/VBox
Files:
4 added
3 edited
1 copied
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r24108 r24377  
    464464        src/darwin/DarwinKeyboard.cpp \
    465465        src/darwin/VBoxUtils-darwin.cpp \
    466         src/darwin/VBoxDockIconPreview.cpp \
     466        src/darwin/AbstractDockIconPreview.cpp \
    467467        src/VBoxFBQuartz2D.cpp
    468468
     
    478478        src/darwin/VBoxUtils-darwin-cocoa.mm \
    479479        src/darwin/VBoxCocoaSpecialControls.mm \
    480         src/darwin/VBoxDockIconPreview-cocoa.mm
     480        src/darwin/CocoaDockIconPreview.mm
    481481 VirtualBox_QT_MOCHDRS.darwin = \
    482482        include/VBoxCocoaSpecialControls.h
     
    484484else
    485485 VirtualBox_SOURCES.darwin += \
    486         src/darwin/VBoxUtils-darwin-carbon.cpp
     486        src/darwin/VBoxUtils-darwin-carbon.cpp \
     487        src/darwin/CarbonDockIconPreview.cpp
    487488endif
    488489
  • trunk/src/VBox/Frontends/VirtualBox/include/DockIconPreview.h

    r23589 r24377  
     1/* $Id$ */
    12/** @file
    23 *
     
    2425#define ___VBoxDockIconPreview_h___
    2526
    26 #include "VBoxUtils-darwin.h"
     27#ifdef QT_MAC_USE_COCOA
    2728
    28 RT_C_DECLS_BEGIN
    29 void darwinCreateVBoxDockIconTileView (void);
    30 void darwinDestroyVBoxDockIconTileView (void);
    31 
    32 CGContextRef darwinBeginCGContextForApplicationDockTile (void);
    33 void darwinEndCGContextForApplicationDockTile (CGContextRef aContext);
    34 
    35 void darwinOverlayApplicationDockTileImage (CGImageRef pImage);
    36 void darwinRestoreApplicationDockTileImage (void);
    37 RT_C_DECLS_END
    38 
    39 #ifndef __OBJC__
    40 class VBoxConsoleWnd;
    41 class VBoxFrameBuffer;
    42 
    43 class QPixmap;
    44 
    45 class VBoxDockIconPreview
     29#include "CocoaDockIconPreview.h"
     30class VBoxDockIconPreview: public CocoaDockIconPreview
    4631{
    4732public:
    48     VBoxDockIconPreview (VBoxConsoleWnd *aMainWnd, const QPixmap& aOverlayImage);
    49     ~VBoxDockIconPreview();
     33    VBoxDockIconPreview (VBoxConsoleWnd *aMainWnd, const QPixmap& aOverlayImage)
     34      : CocoaDockIconPreview (aMainWnd, aOverlayImage) {}
     35};
    5036
    51     void updateDockOverlay();
    52     void updateDockPreview (CGImageRef aVMImage);
    53     void updateDockPreview (VBoxFrameBuffer *aFrameBuffer);
     37#else /* QT_MAC_USE_COCOA */
    5438
    55 private:
    56     inline void initPreviewImages();
    57     inline void initOverlayData (int aBitmapByteCount);
    58     inline CGImageRef stateImage() const;
    59     void drawOverlayIcons (CGContextRef aContext);
     39#include "CarbonDockIconPreview.h"
     40class VBoxDockIconPreview: public CarbonDockIconPreview
     41{
     42public:
     43    VBoxDockIconPreview (VBoxConsoleWnd *aMainWnd, const QPixmap& aOverlayImage)
     44      : CarbonDockIconPreview (aMainWnd, aOverlayImage) {}
     45};
    6046
    61     /* Flipping is necessary cause the drawing context in Carbon is flipped by 180 degree */
    62     inline CGRect flipRect (CGRect aRect) const { return ::darwinFlipCGRect (aRect, mDockIconRect); }
    63     inline CGRect centerRect (CGRect aRect) const { return ::darwinCenterRectTo (aRect, mDockIconRect); }
    64     inline CGRect centerRectTo (CGRect aRect, const CGRect& aToRect) const { return ::darwinCenterRectTo (aRect, aToRect); }
    65 
    66     void updateDockPreviewImpl (CGContextRef aContext, CGImageRef aVMImage);
    67 
    68     /* Private member vars */
    69     VBoxConsoleWnd *mMainWnd;
    70     const CGRect mDockIconRect;
    71 
    72     CGImageRef mOverlayImage;
    73     CGImageRef mDockMonitor;
    74     CGImageRef mDockMonitorGlossy;
    75 
    76     void *mBitmapData;
    77 
    78     CGImageRef mStatePaused;
    79     CGImageRef mStateSaving;
    80     CGImageRef mStateRestoring;
    81 
    82     CGRect mUpdateRect;
    83     CGRect mMonitorRect;
    84 };
    85 #endif /* !__OBJC__ */
     47#endif /* QT_MAC_USE_COCOA */
    8648
    8749#endif /* !___VBoxDockIconPreview_h___ */
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp

    r24301 r24377  
    8282
    8383#if defined (Q_WS_MAC)
    84 # include "VBoxDockIconPreview.h"
     84# include "DockIconPreview.h"
    8585# include "DarwinKeyboard.h"
    8686# ifdef QT_MAC_USE_COCOA
     
    12831283                    viewport()->unsetCursor();
    12841284#endif
     1285
     1286#ifdef Q_WS_MAC
     1287                mDockIconPreview->setOriginalSize (re->width(), re->height());
     1288#endif /* Q_WS_MAC */
    12851289
    12861290                /* This event appears in case of guest video was changed
  • trunk/src/VBox/Frontends/VirtualBox/src/darwin/AbstractDockIconPreview.cpp

    r24376 r24377  
    2020 */
    2121
    22 #include "VBoxDockIconPreview.h"
    23 #include "VBoxUtils.h"
     22/* VBox includes */
     23#include "AbstractDockIconPreview.h"
    2424#include "VBoxConsoleWnd.h"
    2525#include "VBoxFrameBuffer.h"
    2626
    27 #include "iprt/assert.h"
     27AbstractDockIconPreview::AbstractDockIconPreview (VBoxConsoleWnd * /* aMainWnd */, const QPixmap& /* aOverlayImage */)
     28{
     29}
    2830
    29 #include <QPixmap>
     31void AbstractDockIconPreview::updateDockPreview (VBoxFrameBuffer *aFrameBuffer)
     32{
     33    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
     34    Assert (cs);
     35    /* Create the image copy of the framebuffer */
     36    CGDataProviderRef dp = CGDataProviderCreateWithData (aFrameBuffer, aFrameBuffer->address(), aFrameBuffer->bitsPerPixel() / 8 * aFrameBuffer->width() * aFrameBuffer->height(), NULL);
     37    Assert (dp);
     38    CGImageRef ir = CGImageCreate (aFrameBuffer->width(), aFrameBuffer->height(), 8, 32, aFrameBuffer->bytesPerLine(), cs,
     39                                   kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host, dp, 0, false,
     40                                   kCGRenderingIntentDefault);
     41    Assert (ir);
    3042
    31 #ifndef QT_MAC_USE_COCOA
    32 /* Import private function to capture the window content of any given window. */
    33 CG_EXTERN_C_BEGIN
    34 typedef int CGSWindowID;
    35 typedef void *CGSConnectionID;
    36 CG_EXTERN CGSWindowID GetNativeWindowFromWindowRef(WindowRef ref);
    37 CG_EXTERN CGSConnectionID CGSMainConnectionID(void);
    38 CG_EXTERN void CGContextCopyWindowCaptureContentsToRect(CGContextRef c, CGRect dstRect, CGSConnectionID connection, CGSWindowID window, int zero);
    39 CG_EXTERN_C_END
    40 #endif /* !QT_MAC_USE_COCOA */
     43    /* Update the dock preview icon */
     44    updateDockPreview (ir);
    4145
    42 VBoxDockIconPreview::VBoxDockIconPreview (VBoxConsoleWnd *aMainWnd, const QPixmap& aOverlayImage)
     46    /* Release the temp data and image */
     47    CGImageRelease (ir);
     48    CGDataProviderRelease (dp);
     49    CGColorSpaceRelease (cs);
     50}
     51
     52AbstractDockIconPreviewHelper::AbstractDockIconPreviewHelper (VBoxConsoleWnd *aMainWnd, const QPixmap& aOverlayImage)
    4353    :  mMainWnd (aMainWnd)
    4454     , mDockIconRect (CGRectMake (0, 0, 128, 128))
    4555     , mDockMonitor (NULL)
    4656     , mDockMonitorGlossy (NULL)
    47      , mBitmapData (NULL)
    4857     , mUpdateRect (CGRectMake (0, 0, 0, 0))
    4958     , mMonitorRect (CGRectMake (0, 0, 0, 0))
     
    5867    mStateRestoring = ::darwinToCGImageRef ("state_restoring_16px.png");
    5968    Assert (mStateRestoring);
    60 
    61 #ifdef QT_MAC_USE_COCOA
    62     ::darwinCreateVBoxDockIconTileView();
    63 #endif /* QT_MAC_USE_COCOA */
    6469}
    6570
    66 VBoxDockIconPreview::~VBoxDockIconPreview()
     71AbstractDockIconPreviewHelper::~AbstractDockIconPreviewHelper()
    6772{
    68 #ifdef QT_MAC_USE_COCOA
    69     ::darwinDestroyVBoxDockIconTileView();
    70 #endif /* QT_MAC_USE_COCOA */
    71 
    7273    CGImageRelease (mOverlayImage);
    7374    if (mDockMonitor)
     
    7677        CGImageRelease (mDockMonitorGlossy);
    7778
    78     if (mBitmapData)
    79         RTMemFree (mBitmapData);
    80 
    8179    CGImageRelease (mStatePaused);
    8280    CGImageRelease (mStateSaving);
     
    8482}
    8583
    86 void VBoxDockIconPreview::initPreviewImages()
     84void AbstractDockIconPreviewHelper::initPreviewImages()
    8785{
    8886    if (!mDockMonitor)
     
    108106}
    109107
    110 void VBoxDockIconPreview::initOverlayData (int aBitmapByteCount)
    111 {
    112     if (!mBitmapData)
    113         mBitmapData = RTMemAlloc (aBitmapByteCount);
    114 }
    115 
    116 CGImageRef VBoxDockIconPreview::stateImage() const
     108CGImageRef AbstractDockIconPreviewHelper::stateImage() const
    117109{
    118110    CGImageRef img;
     
    131123}
    132124
    133 void VBoxDockIconPreview::drawOverlayIcons (CGContextRef aContext)
     125void AbstractDockIconPreviewHelper::drawOverlayIcons (CGContextRef aContext)
    134126{
    135127    CGRect overlayRect = CGRectMake (0, 0, 0, 0);
     
    155147}
    156148
    157 void VBoxDockIconPreview::updateDockOverlay()
    158 {
    159     /* Remove all previously set tile images */
    160 #ifdef QT_MAC_USE_COCOA
    161     ::darwinRestoreApplicationDockTileImage();
    162 #else /* QT_MAC_USE_COCOA */
    163     ::RestoreApplicationDockTileImage();
    164 #endif /* QT_MAC_USE_COCOA */
    165 
    166     CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    167     Assert (cs);
    168 
    169     /* Four bytes per color */
    170     int bitmapBytesPerRow = mDockIconRect.size.width * 4;
    171     int bitmapByteCount = bitmapBytesPerRow * mDockIconRect.size.height;
    172 
    173     initOverlayData (bitmapByteCount);
    174     Assert (mBitmapData);
    175 
    176     CGContextRef context = CGBitmapContextCreate (mBitmapData,
    177                                                   mDockIconRect.size.width,
    178                                                   mDockIconRect.size.height,
    179                                                   8,
    180                                                   bitmapBytesPerRow,
    181                                                   cs,
    182                                                   kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
    183     /* Clear the background to be transparent */
    184     CGContextSetBlendMode (context, kCGBlendModeNormal);
    185     CGContextClearRect (context, (mDockIconRect));
    186 
    187     /* Draw the state image & the overlay image */
    188     drawOverlayIcons (context);
    189 
    190     /* Flush the content */
    191     CGContextFlush (context);
    192 
    193     /* Create a image out of the bitmap context */
    194     CGImageRef overlayImage = CGBitmapContextCreateImage (context);
    195     Assert (overlayImage);
    196 
    197     /* Update the dock overlay icon */
    198 #ifdef QT_MAC_USE_COCOA
    199     ::darwinOverlayApplicationDockTileImage (overlayImage);
    200 #else /* QT_MAC_USE_COCOA */
    201     ::OverlayApplicationDockTileImage (overlayImage);
    202 #endif /* QT_MAC_USE_COCOA */
    203 
    204     /* Release the temp image */
    205     CGImageRelease (overlayImage);
    206     CGColorSpaceRelease (cs);
    207 }
    208 
    209 void VBoxDockIconPreview::updateDockPreview (CGImageRef aVMImage)
    210 {
    211     Assert (aVMImage);
    212 
    213 #ifdef QT_MAC_USE_COCOA
    214     /* Create the context to draw on */
    215     CGContextRef context = ::darwinBeginCGContextForApplicationDockTile();
    216     updateDockPreviewImpl (context, aVMImage);
    217     /* This flush updates the dock icon */
    218     CGContextFlush (context);
    219     ::darwinEndCGContextForApplicationDockTile (context);
    220 #else /* QT_MAC_USE_COCOA */
    221     /* Create the context to draw on */
    222     CGContextRef context = BeginCGContextForApplicationDockTile ();
    223     updateDockPreviewImpl (context, aVMImage);
    224     /* This flush updates the dock icon */
    225     CGContextFlush (context);
    226     EndCGContextForApplicationDockTile (context);
    227 #endif /* QT_MAC_USE_COCOA */
    228 }
    229 
    230 void VBoxDockIconPreview::updateDockPreviewImpl (CGContextRef aContext, CGImageRef aVMImage)
    231 {
    232     Assert (aContext);
    233 
    234     /* Init all dependend images in the case it wasn't done already */
    235     initPreviewImages();
    236 
    237     CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    238     Assert (cs);
    239 
    240     /* Clear the background to be transparent */
    241     CGContextSetBlendMode (aContext, kCGBlendModeNormal);
    242     CGContextClearRect (aContext, flipRect (mDockIconRect));
    243 
    244     /* Draw the monitor as the background */
    245     CGContextDrawImage (aContext, flipRect (mMonitorRect), mDockMonitor);
    246 
    247     /* Calc the size of the dock icon image and fit it into 128x128 */
    248     int scaledWidth;
    249     int scaledHeight;
    250     float aspect = static_cast <float> (CGImageGetWidth (aVMImage)) / CGImageGetHeight (aVMImage);
    251     if (aspect > 1.0)
    252     {
    253         scaledWidth = mUpdateRect.size.width;
    254         scaledHeight = mUpdateRect.size.height / aspect;
    255     }
    256     else
    257     {
    258         scaledWidth = mUpdateRect.size.width * aspect;
    259         scaledHeight = mUpdateRect.size.height;
    260     }
    261 
    262     CGRect iconRect = centerRectTo (CGRectMake (0, 0,
    263                                                 scaledWidth, scaledHeight),
    264                                     mUpdateRect);
    265     /* Draw the VM content */
    266     CGContextDrawImage (aContext, flipRect (iconRect), aVMImage);
    267 
    268 #if 0 // ndef QT_MAC_USE_COCOA
    269     /* Process the content of any external OpenGL window. */
    270     WindowRef w = darwinToNativeWindow (mMainWnd);
    271     WindowGroupRef g = GetWindowGroup (w);
    272     WindowGroupContentOptions wgco = kWindowGroupContentsReturnWindows | kWindowGroupContentsRecurse | kWindowGroupContentsVisible;
    273     ItemCount c = CountWindowGroupContents (g, wgco);
    274     float a1 = iconRect.size.width / static_cast <float> (CGImageGetWidth (aVMImage));
    275     float a2 = iconRect.size.height / static_cast <float> (CGImageGetHeight (aVMImage));
    276     Rect tmpR;
    277     GetWindowBounds (w, kWindowContentRgn, &tmpR);
    278     HIRect mainRect = CGRectMake (tmpR.left, tmpR.top, tmpR.right-tmpR.left, tmpR.bottom-tmpR.top);
    279     /* Iterate over every window in the returned window group. */
    280     for (ItemCount i = 0; i <= c; ++i)
    281     {
    282         WindowRef wc;
    283         OSStatus status = GetIndexedWindow (g, i, wgco, &wc);
    284         /* Skip the main window */
    285         if (status == noErr &&
    286             wc != w)
    287         {
    288             WindowClass winClass;
    289             status = GetWindowClass (wc, &winClass);
    290             /* Check that the class is of type overlay window */
    291             if (status == noErr &&
    292                 winClass == kOverlayWindowClass)
    293             {
    294                 Rect tmpR1;
    295                 GetWindowBounds (wc, kWindowContentRgn, &tmpR1);
    296                 HIRect rect;
    297                 rect.size.width = (tmpR1.right-tmpR1.left) * a1;
    298                 rect.size.height = (tmpR1.bottom-tmpR1.top) * a2;
    299                 rect.origin.x = iconRect.origin.x + (tmpR1.left - mainRect.origin.x) * a1;
    300                 rect.origin.y = iconRect.origin.y + (tmpR1.top  - mainRect.origin.y) * a2;
    301                 /* This is a big, bad hack. The following functions aren't
    302                  * documented nor official supported by apple. But its the only way
    303                  * to capture the OpenGL content of a window without fiddling
    304                  * around with gPixelRead or something like that. */
    305                 CGSWindowID wid = GetNativeWindowFromWindowRef (wc);
    306                 CGContextCopyWindowCaptureContentsToRect(aContext, flipRect (rect), CGSMainConnectionID(), wid, 0);
    307             }
    308         }
    309     }
    310 #endif /* QT_MAC_USE_COCOA */
    311 
    312     /* Draw the glossy overlay */
    313     CGContextDrawImage (aContext, flipRect (mMonitorRect), mDockMonitorGlossy);
    314 
    315     /* Draw the state image & the overlay image */
    316     drawOverlayIcons (aContext);
    317 
    318     CGColorSpaceRelease (cs);
    319 }
    320 
    321 void VBoxDockIconPreview::updateDockPreview (VBoxFrameBuffer *aFrameBuffer)
    322 {
    323     CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    324     Assert (cs);
    325     /* Create the image copy of the framebuffer */
    326     CGDataProviderRef dp = CGDataProviderCreateWithData (aFrameBuffer, aFrameBuffer->address(), aFrameBuffer->bitsPerPixel() / 8 * aFrameBuffer->width() * aFrameBuffer->height(), NULL);
    327     Assert (dp);
    328     CGImageRef ir = CGImageCreate (aFrameBuffer->width(), aFrameBuffer->height(), 8, 32, aFrameBuffer->bytesPerLine(), cs,
    329                                    kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host, dp, 0, false,
    330                                    kCGRenderingIntentDefault);
    331     Assert (ir);
    332 
    333     /* Update the dock preview icon */
    334     updateDockPreview (ir);
    335 
    336     /* Release the temp data and image */
    337     CGImageRelease (ir);
    338     CGDataProviderRelease (dp);
    339     CGColorSpaceRelease (cs);
    340 }
    341 
  • trunk/src/VBox/Frontends/VirtualBox/src/darwin/CocoaDockIconPreview.mm

    r23589 r24377  
     1/* $Id$ */
    12/** @file
    23 *
     
    2122 */
    2223
    23 #import "VBoxDockIconPreview.h"
    24 
    25 #import <AppKit/NSView.h>
    26 #import <AppKit/NSDockTile.h>
    27 #import <AppKit/NSApplication.h>
    28 #import <AppKit/NSGraphicsContext.h>
    29 #import <AppKit/NSImage.h>
    30 
    31 static NSImage *gDockIconImage = NULL;
    32 
    33 /********************************************************************************
    34  *
    35  * C-Helper: This is the external interface to the Cocoa dock tile handling.
    36  *
    37  ********************************************************************************/
    38 
    39 void darwinCreateVBoxDockIconTileView (void)
    40 {
    41     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    42 
    43     if (gDockIconImage == NULL)
    44         gDockIconImage = [[NSImage imageNamed:@"NSApplicationIcon"] copy];
    45 
    46     [pool release];
    47 }
    48 
    49 void darwinDestroyVBoxDockIconTileView (void)
    50 {
    51     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    52 
    53     if (gDockIconImage != NULL)
    54     {
    55         [gDockIconImage release];
    56         gDockIconImage = NULL;
    57     }
    58 
    59     [pool release];
    60 }
    61 
    62 CGContextRef darwinBeginCGContextForApplicationDockTile (void)
    63 {
    64     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    65 
    66     [gDockIconImage lockFocus];
    67 
     24/* VBox includes */
     25#include "CocoaDockIconPreview.h"
     26#include "VBoxCocoaHelper.h"
     27
     28/* System includes */
     29#import <Cocoa/Cocoa.h>
     30
     31@interface DockTileMonitor: NSView
     32{
     33    CocoaDockIconPreviewPrivate *p;
     34
     35    NSImageView *mScreenContent;
     36    NSImageView *mMonitorGlossy;
     37}
     38- (id)initWithFrame:(NSRect)frame parent:(CocoaDockIconPreviewPrivate*)parent;
     39- (NSImageView*)screenContent;
     40- (void)resize:(NSSize)size;
     41@end
     42
     43@interface DockTileOverlay: NSView
     44{
     45    CocoaDockIconPreviewPrivate *p;
     46}
     47- (id)initWithFrame:(NSRect)frame parent:(CocoaDockIconPreviewPrivate*)parent;
     48@end
     49
     50@interface DockTile: NSView
     51{
     52    CocoaDockIconPreviewPrivate *p;
     53
     54    DockTileMonitor *mMonitor;
     55    NSImageView     *mAppIcon;
     56
     57    DockTileOverlay *mOverlay;
     58}
     59- (id)initWithParent:(CocoaDockIconPreviewPrivate*)parent;
     60- (NSView*)screenContent;
     61- (void)cleanup;
     62- (void)restoreAppIcon;
     63- (void)updateAppIcon;
     64- (void)restoreMonitor;
     65- (void)updateMonitorWithImage:(CGImageRef)image;
     66- (void)resizeMonitor:(NSSize)size;
     67@end
     68
     69/*
     70 * Helper class which allow us to access all members/methods of AbstractDockIconPreviewHelper
     71 * from any Cocoa class.
     72 */
     73class CocoaDockIconPreviewPrivate: public AbstractDockIconPreviewHelper
     74{
     75public:
     76    inline CocoaDockIconPreviewPrivate (VBoxConsoleWnd *aMainWnd, const QPixmap& aOverlayImage)
     77      :AbstractDockIconPreviewHelper (aMainWnd, aOverlayImage)
     78    {
     79        mDockTile = [[DockTile alloc] initWithParent:this];
     80    }
     81
     82    inline ~CocoaDockIconPreviewPrivate()
     83    {
     84        [mDockTile release];
     85    }
     86     
     87    DockTile *mDockTile;
     88};
     89
     90/*
     91 * Cocoa wrapper for the abstract dock icon preview class
     92 */
     93CocoaDockIconPreview::CocoaDockIconPreview (VBoxConsoleWnd *aMainWnd, const QPixmap& aOverlayImage)
     94  : AbstractDockIconPreview (aMainWnd, aOverlayImage)
     95{
     96    CocoaAutoreleasePool pool;
     97
     98    d = new CocoaDockIconPreviewPrivate (aMainWnd, aOverlayImage);
     99}
     100
     101CocoaDockIconPreview::~CocoaDockIconPreview()
     102{
     103    CocoaAutoreleasePool pool;
     104
     105    delete d;
     106}
     107
     108void CocoaDockIconPreview::updateDockOverlay()
     109{
     110    CocoaAutoreleasePool pool;
     111
     112    [d->mDockTile updateAppIcon];
     113}
     114
     115void CocoaDockIconPreview::updateDockPreview (CGImageRef aVMImage)
     116{
     117    CocoaAutoreleasePool pool;
     118
     119    [d->mDockTile updateMonitorWithImage:aVMImage];
     120}
     121
     122void CocoaDockIconPreview::updateDockPreview (VBoxFrameBuffer *aFrameBuffer)
     123{
     124    CocoaAutoreleasePool pool;
     125
     126    AbstractDockIconPreview::updateDockPreview (aFrameBuffer);
     127}
     128
     129
     130void CocoaDockIconPreview::setOriginalSize (int aWidth, int aHeight)
     131{
     132    CocoaAutoreleasePool pool;
     133
     134    [d->mDockTile resizeMonitor:NSMakeSize (aWidth, aHeight)];
     135}
     136
     137/*
     138 * Class for arranging/updating the layers for the glossy monitor preview.
     139 */
     140@implementation DockTileMonitor;
     141- (id)initWithFrame:(NSRect)frame parent:(CocoaDockIconPreviewPrivate*)parent
     142{
     143    self = [super initWithFrame:frame];
     144
     145    if (self != nil)
     146    {
     147        p = parent;
     148        /* The screen content view */
     149        mScreenContent = [[NSImageView alloc] initWithFrame:NSRectFromCGRect (p->flipRect (p->mUpdateRect))];
     150//        [mScreenContent setImageAlignment: NSImageAlignCenter];
     151        [mScreenContent setImageAlignment: NSImageAlignTop| NSImageAlignLeft];
     152        [mScreenContent setImageScaling: NSScaleToFit];
     153        [self addSubview: mScreenContent];
     154        /* The state view */
     155        mMonitorGlossy = [[NSImageView alloc] initWithFrame:NSRectFromCGRect (p->flipRect (p->mMonitorRect))];
     156        [mMonitorGlossy setImage: darwinCGImageToNSImage (p->mDockMonitorGlossy)];
     157        [self addSubview: mMonitorGlossy];
     158    }
     159
     160    return self;
     161}
     162
     163- (void)drawRect:(NSRect)aRect;
     164{
     165    NSImage *dockMonitor = darwinCGImageToNSImage (p->mDockMonitor);
     166    [dockMonitor drawInRect:NSRectFromCGRect (p->flipRect (p->mMonitorRect)) fromRect:aRect operation:NSCompositeSourceOver fraction:1.0];
     167    [dockMonitor release];
     168}
     169
     170- (NSImageView*)screenContent
     171{
     172    return mScreenContent;
     173}
     174
     175- (void)resize:(NSSize)size;
     176{
     177    /* Calculate the new size based on the aspect ratio of the original screen
     178       size */
     179    float w, h;
     180    if (size.width > size.height)
     181    {
     182        w = p->mUpdateRect.size.width;
     183        h = ((float)size.height / size.width * p->mUpdateRect.size.height);
     184    }
     185    else
     186    {
     187        w = ((float)size.width / size.height * p->mUpdateRect.size.width);
     188        h = p->mUpdateRect.size.height;
     189    }
     190    CGRect r = (p->flipRect (p->centerRectTo (CGRectMake (0, 0, (int)w, (int)h), p->mUpdateRect)));
     191    r.origin.x = (int)r.origin.x;
     192    r.origin.y = (int)r.origin.y;
     193    r.size.width = (int)r.size.width;
     194    r.size.height = (int)r.size.height;
     195//    printf("gui %f %f %f %f\n", r.origin.x, r.origin.y, r.size.width, r.size.height);
     196    /* Center within the update rect */
     197    [mScreenContent setFrame:NSRectFromCGRect (r)];
     198}
     199@end
     200
     201/*
     202 * Simple implementation for the overlay of the OS & the state icon. Is used both
     203 * in the application icon & preview mode.
     204 */
     205@implementation DockTileOverlay
     206- (id)initWithFrame:(NSRect)frame parent:(CocoaDockIconPreviewPrivate*)parent
     207{
     208    self = [super initWithFrame:frame];
     209
     210    if (self != nil)
     211        p = parent;
     212
     213    return self;
     214}
     215
     216- (void)drawRect:(NSRect)aRect;
     217{
    68218    NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
    69     CGContextRef pCGContext = [nsContext graphicsPort];
    70 
    71     [pool release];
    72     return pCGContext;
    73 }
    74 
    75 void darwinEndCGContextForApplicationDockTile (CGContextRef aContext)
    76 {
    77     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    78 
    79     [gDockIconImage unlockFocus];
    80 
    81     [NSApp setApplicationIconImage:gDockIconImage];
    82 
    83     [pool release];
    84 }
    85 
    86 void darwinOverlayApplicationDockTileImage (CGImageRef pImage)
    87 {
    88     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    89 
    90     /* Convert the CGImage to an NSImage */
    91     NSBitmapImageRep *bitmapImageRep = [[NSBitmapImageRep alloc] initWithCGImage:pImage];
    92     if (bitmapImageRep)
    93     {
    94         NSImage *badgeImage = [[NSImage alloc] initWithSize:[bitmapImageRep size]];
    95         [badgeImage addRepresentation:bitmapImageRep];
    96         [bitmapImageRep release];
    97         /* Make subsequent drawing operations on the icon */
    98         [gDockIconImage lockFocus];
    99         /* Draw the overlay bottom left */
    100         [badgeImage drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
    101         [gDockIconImage unlockFocus];
    102         [badgeImage release];
    103     }
    104     /* Set the new application icon */
    105     [NSApp setApplicationIconImage:gDockIconImage];
    106    
    107     [pool release];
    108 }
    109 
    110 void darwinRestoreApplicationDockTileImage (void)
    111 {
    112     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    113 
    114     /* Reset all */
    115     darwinDestroyVBoxDockIconTileView();
    116     darwinCreateVBoxDockIconTileView();
    117 
    118     [pool release];
    119 }
    120 
     219    CGContextRef pCGContext = (CGContextRef)[nsContext graphicsPort];
     220    p->drawOverlayIcons (pCGContext);
     221}
     222@end
     223
     224/*
     225 * VirtualBox Dock Tile implementation. Manage the switching between the icon
     226 * and preview mode & forwards all update request to the appropriate methods.
     227 */
     228@implementation DockTile
     229- (id)initWithParent:(CocoaDockIconPreviewPrivate*)parent
     230{
     231    self = [super init];
     232
     233    if (self != nil)
     234    {
     235        p = parent;
     236        /* Add self as the content view of the dock tile */
     237        NSDockTile *dock = [[NSApplication sharedApplication] dockTile];
     238        [dock setContentView: self];
     239        /* App icon is default */
     240        [self restoreAppIcon];
     241        /* The overlay */
     242        mOverlay = [[DockTileOverlay alloc] initWithFrame:NSRectFromCGRect(p->flipRect (p->mDockIconRect)) parent:p];
     243        [self addSubview: mOverlay];
     244    }
     245
     246    return self;
     247}
     248
     249- (NSView*)screenContent
     250{
     251    return [mMonitor screenContent];
     252}
     253
     254- (void)cleanup
     255{
     256    if (mAppIcon != nil)
     257    {
     258        [mAppIcon removeFromSuperview];
     259        [mAppIcon release];
     260        mAppIcon = nil;
     261    }
     262    if (mMonitor != nil)
     263    {
     264        [mMonitor removeFromSuperview];
     265        [mMonitor release];
     266        mMonitor = nil;
     267    }
     268}
     269
     270- (void)restoreAppIcon
     271{
     272    if (mAppIcon == nil)
     273    {
     274        [self cleanup];
     275        mAppIcon = [[NSImageView alloc] initWithFrame:NSRectFromCGRect (p->flipRect (p->mDockIconRect))];
     276        [mAppIcon setImage: [NSImage imageNamed:@"NSApplicationIcon"]];
     277        [self addSubview: mAppIcon positioned:NSWindowBelow relativeTo:mOverlay];
     278    }
     279}
     280
     281- (void)updateAppIcon
     282{
     283    [self restoreAppIcon];
     284    [[[NSApplication sharedApplication] dockTile] display];
     285}
     286
     287- (void)restoreMonitor
     288{
     289    if (mMonitor == nil)
     290    {
     291        p->initPreviewImages();
     292        [self cleanup];
     293        mMonitor = [[DockTileMonitor alloc] initWithFrame:NSRectFromCGRect (p->flipRect (p->mDockIconRect)) parent:p];
     294        [self addSubview: mMonitor positioned:NSWindowBelow relativeTo:mOverlay];
     295    }
     296}
     297
     298- (void)updateMonitorWithImage:(CGImageRef)image
     299{
     300    [self restoreMonitor];
     301    NSImage *nsimage = darwinCGImageToNSImage (image);
     302    [[mMonitor screenContent] setImage: nsimage];
     303    [nsimage release];
     304    [[[NSApplication sharedApplication] dockTile] display];
     305}
     306
     307- (void)resizeMonitor:(NSSize)size;
     308{
     309    [mMonitor resize:size];
     310}
     311@end
     312
  • trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m

    r22509 r24377  
    125125@end
    126126
     127@class DockOverlayView;
     128
    127129/* The custom view class. This is the main class of the cocoa OpenGL
    128130 * implementation. It manages an frame buffer object for the rendering of the
     
    145147    GLuint           m_FBOTexId;
    146148    NSSize           m_FBOTexSize;
    147     GLuint           m_FBODepthId;
    148     GLuint           m_FBOStencilId;
    149149    GLuint           m_FBODepthStencilPackedId;
     150
     151    /* The corresponding dock tile view of this OpenGL view & all helper
     152     * members. */
     153    DockOverlayView *m_DockTileView;
     154    GLuint           m_FBOThumbId;
     155    GLuint           m_FBOThumbTexId;
     156    GLfloat          m_FBOThumbScaleX;
     157    GLfloat          m_FBOThumbScaleY;
    150158
    151159    /* For clipping */
     
    157165    NSSize           m_Size;
    158166
     167    /* This is necessary for clipping on the root window */
    159168    NSPoint          m_RootShift;
    160169}
     
    167176- (void)setSize:(NSSize)size;
    168177- (NSSize)size;
     178- (void)updateViewport;
    169179- (void)reshape;
    170180
     
    182192- (void)clearVisibleRegions;
    183193- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects;
     194
     195- (NSView*)dockTileScreen;
     196- (void)reshapeDockTile;
    184197@end
    185198
     
    207220    OverlayView       *m_pOverlayView;
    208221    OverlayHelperView *m_pOverlayHelperView;
     222    NSThread          *m_Thread;
    209223}
    210224- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView;
    211225- (void)parentWindowFrameChanged:(NSNotification *)note;
    212226- (void)parentWindowChanged:(NSWindow*)pWindow;
     227@end
     228
     229@interface DockOverlayView: NSView
     230{
     231    NSBitmapImageRep *m_ThumbBitmap;
     232    NSImage          *m_ThumbImage;
     233    NSLock           *m_Lock;
     234}
     235- (void)dealloc;
     236- (void)cleanup;
     237- (void)lock;
     238- (void)unlock;
     239- (void)setFrame:(NSRect)frame;
     240- (void)drawRect:(NSRect)aRect;
     241- (NSBitmapImageRep*)thumbBitmap;
     242- (NSImage*)thumbImage;
     243@end
     244
     245@implementation DockOverlayView
     246- (id)init
     247{
     248    self = [super init];
     249
     250    if (self)
     251    {
     252        /* We need a lock cause the thumb image could be accessed from the main
     253         * thread when someone is calling display on the dock tile & from the
     254         * OpenGL thread when the thumbnail is updated. */
     255        m_Lock = [[NSLock alloc] init];
     256    }
     257
     258    return self;
     259}
     260
     261- (void)dealloc
     262{
     263    [self cleanup];
     264    [m_Lock release];
     265
     266    [super dealloc];
     267}
     268
     269- (void)cleanup
     270{
     271    if (m_ThumbImage != nil)
     272    {
     273        [m_ThumbImage release];
     274        m_ThumbImage = nil;
     275    }
     276    if (m_ThumbBitmap != nil)
     277    {
     278        [m_ThumbBitmap release];
     279        m_ThumbBitmap = nil;
     280    }
     281}
     282
     283- (void)lock
     284{
     285    [m_Lock lock];
     286}
     287
     288- (void)unlock
     289{
     290    [m_Lock unlock];
     291}
     292
     293- (void)setFrame:(NSRect)frame
     294{
     295    [super setFrame:frame];
     296
     297    [self lock];
     298    [self cleanup];
     299
     300    /* Create a buffer for our thumbnail image. Its in the size of this view. */
     301    m_ThumbBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
     302        pixelsWide:frame.size.width
     303        pixelsHigh:frame.size.height
     304        bitsPerSample:8
     305        samplesPerPixel:4
     306        hasAlpha:YES
     307        isPlanar:NO
     308        colorSpaceName:NSDeviceRGBColorSpace
     309        bytesPerRow:frame.size.width * 4
     310        bitsPerPixel:8 * 4];
     311    m_ThumbImage = [[NSImage alloc] initWithSize:[m_ThumbBitmap size]];
     312    [m_ThumbImage addRepresentation:m_ThumbBitmap];
     313    [self unlock];
     314}
     315
     316- (BOOL)isFlipped
     317{
     318    return YES;
     319}
     320
     321- (void)drawRect:(NSRect)aRect
     322{
     323    [self lock];
     324#ifdef SHOW_WINDOW_BACKGROUND
     325    [[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7] set];
     326    NSRect frame = [self frame];
     327    [NSBezierPath fillRect:NSMakeRect(0, 0, frame.size.width, frame.size.height)];
     328#endif /* SHOW_WINDOW_BACKGROUND */
     329    if (m_ThumbImage != nil)
     330        [m_ThumbImage drawAtPoint:NSMakePoint(0, 0) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
     331    [self unlock];
     332}
     333
     334- (NSBitmapImageRep*)thumbBitmap
     335{
     336    return m_ThumbBitmap;
     337}
     338
     339- (NSImage*)thumbImage
     340{
     341    return m_ThumbImage;
     342}
    213343@end
    214344
     
    308438        m_pParentView = pParentView;
    309439        m_pOverlayView = pOverlayView;
     440        m_Thread = [NSThread currentThread];
    310441
    311442        m_pOverlayHelperView = [[OverlayHelperView alloc] initWithOverlayWindow:self];
     
    332463                [m_pParentView convertPoint:NSZeroPoint toView:nil]]];
    333464
    334         /* Set the overlay view as out content view */
     465        /* Set the overlay view as our content view */
    335466        [self setContentView:m_pOverlayView];
    336467
    337         /* Add ourself as a child to the parent views window */
     468        /* Add ourself as a child to the parent views window. Note: this has to
     469         * be done last so that everything else is setup in
     470         * parentWindowChanged. */
    338471        [pParentWin addChildWindow:self ordered:NSWindowAbove];
    339 
    340         /* Ask to get notifications when our parent window frame changes. */
    341         [[NSNotificationCenter defaultCenter]
    342             addObserver:self
    343             selector:@selector(parentWindowFrameChanged:)
    344             name:NSWindowDidResizeNotification
    345             object:pParentWin];
    346472    }
    347473    return self;
     
    352478    DEBUG_MSG(("Dealloc window %X\n", (uint)self));
    353479
     480    [[NSNotificationCenter defaultCenter] removeObserver:self];
     481
    354482    [m_pOverlayHelperView removeFromSuperview];
    355 
    356483    [m_pOverlayHelperView release];
    357484
     
    361488- (void)parentWindowFrameChanged:(NSNotification*)pNote
    362489{
    363     /* Reposition this window with the help of the OverlayView */
     490    /* Reposition this window with the help of the OverlayView. Perform the
     491     * call in the OpenGL thread. */
     492//    [m_pOverlayView performSelector:@selector(reshape) onThread:m_Thread withObject:nil waitUntilDone:YES];
    364493    [m_pOverlayView reshape];
    365494}
     
    367496- (void)parentWindowChanged:(NSWindow*)pWindow
    368497{
    369     if(pWindow)
     498    [[NSNotificationCenter defaultCenter] removeObserver:self];
     499    if(pWindow != nil)
    370500    {
    371501        /* Ask to get notifications when our parent window frame changes. */
     
    379509        /* Reshape the overlay view after a short waiting time to let the main
    380510         * window resize itself properly. */
    381         [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
     511//        [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
     512//        [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(reshape) userInfo:nil repeats:NO];
     513        [m_pOverlayView reshape];
     514
    382515    }
    383516}
     
    402535    m_FBOTexId = 0;
    403536    m_FBOTexSize = NSZeroSize;
    404     m_FBODepthId = 0;
    405     m_FBOStencilId = 0;
    406537    m_FBODepthStencilPackedId = 0;
    407538    m_cClipRects = 0;
     
    490621}
    491622
     623- (void)updateViewport
     624{
     625    if (m_pSharedGLCtx)
     626    {
     627        /* Update the viewport for our OpenGL view */
     628        [m_pSharedGLCtx makeCurrentContext];
     629        [m_pSharedGLCtx update];
     630
     631        NSRect r = [self frame];
     632        /* Setup all matrices */
     633        glMatrixMode(GL_PROJECTION);
     634        glLoadIdentity();
     635        glViewport(0, 0, r.size.width, r.size.height);
     636        glOrtho(0, r.size.width, 0, r.size.height, -1, 1);
     637        glMatrixMode(GL_TEXTURE);
     638        glLoadIdentity();
     639        glTranslatef(0.0f, m_RootShift.y, 0.0f);
     640        glMatrixMode(GL_MODELVIEW);
     641        glLoadIdentity();
     642        glTranslatef(-m_RootShift.x, 0.0f, 0.0f);
     643
     644        /* Clear background to transparent */
     645        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     646
     647        glEnable(GL_TEXTURE_RECTANGLE_ARB);
     648        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
     649
     650        [m_pGLCtx makeCurrentContext];
     651    }
     652}
     653
    492654- (void)reshape
    493655{
     
    536698    /* Set the new frame. */
    537699    [[self window] setFrame:newFrame display:YES];
     700
     701    /* Inform the dock tile view as well */
     702    [self reshapeDockTile];
     703
     704    /* Make sure the context is updated according */
     705    [self updateViewport];
    538706}
    539707
     
    565733        DEBUG_MSG_1(("Create FBO %d %d\n", m_FBOId, m_FBOTexId));
    566734
    567 //    glGenRenderbuffersEXT(1, &m_FBODepthId);
    568 //    glGenRenderbuffersEXT(1, &m_FBOStencilId);
    569735        glGenRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
    570736    }
     
    612778    /* Now attach texture to the FBO as its color destination */
    613779    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId, 0);
    614 //    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
    615780
    616781    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
     
    619784    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
    620785
    621 //    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBODepthId);
    622 //    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, r.size.width, r.size.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
    623 //    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBODepthId, 0);
    624 //
    625 //    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOStencilId);
    626 //    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, r.size.width, r.size.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
    627 //    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOStencilId, 0);
    628 
    629     /* Initialize Depth Render Buffer */
    630 //    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_FBODepthId);
    631 //    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, r.size.width, r.size.height);
    632     /* and attach it to the FBO */
    633 //    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthId);
    634 //
    635 //    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_FBOStencilId);
    636 //    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, r.size.width, r.size.height);
    637 //    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBOStencilId);
    638 
    639 //    glClearColor (clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
    640 //    glClearColor (0, 0, 0, 0);
    641 //    glClear(GL_COLOR_BUFFER_BIT);
    642 
    643786    /* Make sure the FBO was created succesfully. */
    644787    if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
    645788        DEBUG_MSG(("Framebuffer Object creation or update failed!\n"));
    646        
     789
    647790    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
    648791    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
     792
     793    /* Is there a dock tile preview enabled in the GUI? If so setup a
     794     * additional thumbnail view for the dock tile. */
     795    NSView *dockScreen = [self dockTileScreen];
     796    if (dockScreen)
     797    {
     798        if (!m_FBOThumbId)
     799        {
     800            glGenFramebuffersEXT(1, &m_FBOThumbId);
     801            glGenTextures(1, &m_FBOThumbTexId);
     802        }
     803
     804        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOThumbId);
     805        /* Initialize FBO Texture */
     806        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOThumbTexId);
     807        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NICEST);
     808        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NICEST);
     809        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
     810        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
     811   
     812        /* The GPUs like the GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV combination
     813         * others are also valid, but might incur a costly software translation. */
     814        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);
     815
     816        /* Now attach texture to the FBO as its color destination */
     817        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOThumbTexId, 0);
     818
     819        /* Make sure the FBO was created succesfully. */
     820        if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
     821            DEBUG_MSG(("Framebuffer Thumb Object creation or update failed!\n"));
     822
     823        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
     824        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
     825
     826        m_DockTileView = [[DockOverlayView alloc] init];
     827        [self reshapeDockTile];
     828        [dockScreen addSubview:m_DockTileView];
     829    }
    649830
    650831    /* Initialize with one big visual region over the full size */
     
    666847        GL_SAVE_STATE;
    667848
    668         if (m_FBODepthId > 0)
    669         {
    670             glDeleteRenderbuffersEXT(1, &m_FBODepthId);
    671             m_FBODepthId = 0;
    672         }
    673         if (m_FBOStencilId > 0)
    674         {
    675             glDeleteRenderbuffersEXT(1, &m_FBOStencilId);
    676             m_FBOStencilId = 0;
    677         }
    678849        if (m_FBODepthStencilPackedId > 0)
    679850        {
     
    697868
    698869        GL_RESTORE_STATE;
     870    }
     871    if (m_DockTileView != nil)
     872    {
     873        [m_DockTileView removeFromSuperview];
     874        [m_DockTileView release];
     875        m_DockTileView = nil;
    699876    }
    700877}
     
    748925
    749926#ifdef FBO
     927    GLint tmpFB;
     928    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
     929    DEBUG_MSG_1(("Swap GetINT %d\n", tmpFB));
    750930    [m_pGLCtx flushBuffer];
    751931//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    752     if ([self lockFocusIfCanDraw])
    753     {
    754         [self renderFBOToView];
    755         [self unlockFocus];
     932        if (tmpFB == m_FBOId)
     933    {
     934        if ([self lockFocusIfCanDraw])
     935        {
     936            [self renderFBOToView];
     937            [self unlockFocus];
     938        }
    756939    }
    757940//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
     
    763946- (void)flushFBO
    764947{
     948    GLint tmpFB;
     949    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
    765950    glFlush();
    766951//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    767     if ([self lockFocusIfCanDraw])
    768     {
    769         [self renderFBOToView];
    770         [self unlockFocus];
     952    DEBUG_MSG_1 (("Flusj GetINT %d\n", tmpFB));
     953        if (tmpFB == m_FBOId)
     954    {
     955        if ([self lockFocusIfCanDraw])
     956        {
     957            [self renderFBOToView];
     958            [self unlockFocus];
     959        }
    771960    }
    772961//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
     
    775964- (void)finishFBO
    776965{
     966    GLint tmpFB;
     967    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
    777968    glFinish();
    778 //    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    779     if ([self lockFocusIfCanDraw])
    780     {
    781         [self renderFBOToView];
    782         [self unlockFocus];
     969        //    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
     970    DEBUG_MSG_1 (("Finish GetINT %d\n", tmpFB));
     971        if (tmpFB == m_FBOId)
     972    {
     973        if ([self lockFocusIfCanDraw])
     974        {
     975            [self renderFBOToView];
     976            [self unlockFocus];
     977        }
    783978    }
    784979//    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
     
    8051000        /* Set this view as the drawable for the new context */
    8061001        [m_pSharedGLCtx setView: self];
     1002        [self updateViewport];
    8071003    }
    8081004
    8091005    if (m_pSharedGLCtx)
    8101006    {
     1007        NSRect r = [self frame];
     1008
    8111009        if (m_FBOTexId > 0)
    8121010        {
    8131011            [m_pSharedGLCtx makeCurrentContext];
    814             [m_pSharedGLCtx update];
    815 
    816 //            printf ("renderFBOToView\n");
    817 //            CGLLockContext([m_pGLCtx CGLContextObj]);
    818             NSRect r = [self frame];
    8191012       
    820             GL_SAVE_STATE;
     1013            if (m_FBOThumbTexId > 0 &&
     1014                [m_DockTileView thumbBitmap] != nil)
     1015            {
     1016#if 0
     1017                /* todo: check this for optimization */
     1018                glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
     1019                glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE,
     1020                                GL_STORAGE_SHARED_APPLE);
     1021                glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
     1022                glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
     1023                             sizex, sizey, 0, GL_BGRA,
     1024                             GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr);
     1025                glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
     1026                                    0, 0, 0, 0, 0, image_width, image_height);
     1027                glFlush();
     1028                // Do other work processing here, using a double or triple buffer
     1029                glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
     1030                              GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
     1031#endif
     1032
     1033                GL_SAVE_STATE;
     1034                glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOThumbId);
     1035
     1036                /* We like to read from the primary color buffer */
     1037                glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
     1038
     1039                NSRect rr = [m_DockTileView frame];
     1040
     1041                /* Setup all matrices */
     1042                glMatrixMode(GL_PROJECTION);
     1043                glLoadIdentity();
     1044                glViewport(0, 0, rr.size.width, rr.size.height);
     1045                glOrtho(0, rr.size.width, 0, rr.size.height, -1, 1);
     1046                glScalef(m_FBOThumbScaleX, m_FBOThumbScaleY, 1.0f);
     1047                glMatrixMode(GL_TEXTURE);
     1048                glLoadIdentity();
     1049                glTranslatef(0.0f, m_RootShift.y, 0.0f);
     1050                glMatrixMode(GL_MODELVIEW);
     1051                glLoadIdentity();
     1052
     1053                /* Clear background to transparent */
     1054                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     1055                glClear(GL_COLOR_BUFFER_BIT);
     1056
     1057                glEnable(GL_TEXTURE_RECTANGLE_ARB);
     1058                glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
     1059                GLint i;
     1060                for (i = 0; i < m_cClipRects; ++i)
     1061                {
     1062                    GLint x1 = m_paClipRects[4*i];
     1063                    GLint y1 = (r.size.height - m_paClipRects[4*i+1]);
     1064                    GLint x2 = m_paClipRects[4*i+2];
     1065                    GLint y2 = (r.size.height - m_paClipRects[4*i+3]);
     1066                    glBegin(GL_QUADS);
     1067                    {
     1068                        glTexCoord2i(x1, y1); glVertex2i(x1, y1);
     1069                        glTexCoord2i(x1, y2); glVertex2i(x1, y2);
     1070                        glTexCoord2i(x2, y2); glVertex2i(x2, y2);
     1071                        glTexCoord2i(x2, y1); glVertex2i(x2, y1);
     1072                    }
     1073                    glEnd();
     1074                }
     1075                glFinish();
     1076   
     1077                /* Here the magic of reading the FBO content in our own buffer
     1078                 * happens. We have to lock this access, in the case the dock
     1079                 * is updated currently. */
     1080                [m_DockTileView lock];
     1081                glReadPixels(0, 0, rr.size.width, rr.size.height,
     1082                             GL_RGBA,
     1083                             GL_UNSIGNED_BYTE,
     1084                             [[m_DockTileView thumbBitmap] bitmapData]);
     1085                [m_DockTileView unlock];
     1086
     1087                NSDockTile *pDT = [[NSApplication sharedApplication] dockTile];
     1088
     1089                /* Send a display message to the dock tile in the main thread */
     1090                [[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
     1091
     1092                glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
     1093                GL_RESTORE_STATE;
     1094            }
     1095
     1096            /* Clear background to transparent */
     1097            glClear(GL_COLOR_BUFFER_BIT);
    8211098       
    822             /* Setup all matrices */
    823             glMatrixMode(GL_PROJECTION);
    824             glLoadIdentity();
    825             glViewport(0, 0, r.size.width, r.size.height);
    826             glOrtho(0, r.size.width, 0, r.size.height, -1, 1);
    827             glMatrixMode(GL_TEXTURE);
    828             glLoadIdentity();
    829             glTranslatef(0.0f, m_RootShift.y, 0.0f);
    830             glMatrixMode(GL_MODELVIEW);
    831             glLoadIdentity();
    832             glTranslatef(-m_RootShift.x, 0.0f, 0.0f);
    833 
    834             /* Clear background to transparent */
    835             glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    836             glClear(GL_COLOR_BUFFER_BIT);
    837 
    838             glEnable(GL_TEXTURE_RECTANGLE_ARB);
    839             glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
     1099            /* Blit the content of the FBO to the screen. todo: check for
     1100             * optimization with display lists. */
    8401101            GLint i;
    8411102            for (i = 0; i < m_cClipRects; ++i)
     
    8541115                glEnd();
    8551116            }
    856 
    8571117            [m_pSharedGLCtx flushBuffer];
    858        
    859             GL_RESTORE_STATE;
    8601118            [m_pGLCtx makeCurrentContext];
    861             [m_pGLCtx update];
    862 //            CGLUnlockContext([m_pGLCtx CGLContextObj]);
    8631119        }
    8641120    }
     
    8871143        memcpy(m_paClipRects, paRects, sizeof(GLint) * 4 * cRects);
    8881144    }
     1145}
     1146
     1147- (NSView*)dockTileScreen
     1148{
     1149    NSView *contentView = [[[NSApplication sharedApplication] dockTile] contentView];
     1150    NSView *screenContent = nil;
     1151    if ([contentView respondsToSelector:@selector(screenContent)])
     1152         screenContent = [contentView performSelector:@selector(screenContent)];
     1153    return screenContent;
     1154}
     1155
     1156- (void)reshapeDockTile
     1157{
     1158    NSRect dockFrame = [[self dockTileScreen] frame];
     1159    NSRect parentFrame = [m_pParentView frame];
     1160
     1161    m_FBOThumbScaleX = (float)dockFrame.size.width / parentFrame.size.width;
     1162    m_FBOThumbScaleY = (float)dockFrame.size.height / parentFrame.size.height;
     1163    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));
     1164//    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));
     1165//      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));
     1166//    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);
     1167    [m_DockTileView setFrame: newFrame];
    8891168}
    8901169
     
    10121291    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
    10131292
     1293    /* Hide the view early */
    10141294    [pView setHidden: YES];
    10151295
    10161296    NSWindow *win = [pView window];
    1017     [win setContentView:nil];
     1297    [[NSNotificationCenter defaultCenter] removeObserver:win];
     1298    [win setContentView: nil];
    10181299    [[win parentWindow] removeChildWindow: win];
    1019 
    1020     [win release];
    1021     [pView release];   
     1300    int b = [win retainCount];
     1301    for (; b > 1; --b)
     1302        [win release];
     1303
     1304    /* There seems to be a bug in the performSelector method which is called in
     1305     * parentWindowChanged above. The object is retained but not released. This
     1306     * results in an unbalanced reference count, which is here manually
     1307     * decremented. */
     1308    int a = [pView retainCount];
     1309    for (; a > 1; --a)
     1310        [pView release];
    10221311
    10231312    [pPool release];
     
    11081397
    11091398#ifdef FBO
     1399# if 0
    11101400    NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
    11111401    if (pCtx)
     
    11181408        }
    11191409    }
     1410# endif
    11201411#else
    11211412    glFlush();
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette