VBoxFBQuartz2D.cpp revision 1c94c0a63ba68be1a7b2c640e70d7a06464e4fca
/* $Id$ */
/** @file
* Qt GUI (aka VirtualBox) - Quartz2D framebuffer implementation.
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#if defined (VBOX_GUI_USE_QUARTZ2D)
/* VBox includes */
#include "VBoxFrameBuffer.h"
#include "VBoxConsoleView.h"
#include "VBoxProblemReporter.h"
#include "VBoxGlobal.h"
/* Needed for checking against seamless mode */
#include "VBoxConsoleWnd.h"
#include "VBoxIChatTheaterWrapper.h"
/* Qt includes */
#include <qapplication.h>
#include <qmainwindow.h>
#include <qstatusbar.h>
/** @class VBoxQuartz2DFrameBuffer
*
* The VBoxQuartz2dFrameBuffer class is a class that implements the IFrameBuffer
* interface and uses Apples Quartz2D to store and render VM display data.
*/
{
Log (("Quartz2D: Creating\n"));
}
{
Log (("Quartz2D: Deleting\n"));
clean();
}
/** @note This method is called on EMT from under this object's lock */
{
/* Log (("Quartz2D: NotifyUpdate %d,%d %dx%d\n", aX, aY, aW, aH));*/
/* the update has been finished, return TRUE */
return S_OK;
}
{
if (!rects)
return E_POINTER;
/** @todo r=bird: Is this thread safe? If I remember the code flow correctly, the
* GUI thread could be happily jogging along paintEvent now on another cpu core.
* This function is called on the EMT (emulation thread). Which means, blocking
* execution waiting for a lock is out of the question. A quick solution using
* ASMAtomic(Cmp)XchgPtr and a struct { cAllocated; cRects; aRects[1]; }
* *mRegion, *mUnusedRegion; should suffice (and permit you to reuse allocations). */
{
}
if (!rgnRcts)
{
if (!rgnRcts)
return E_OUTOFMEMORY;
}
// printf ("Region rects follow...\n");
{
/* QRect are inclusive */
/* The rect should intersect with the vm screen. */
++ rects;
/* Make sure only valid rects are distributed */
/* todo: Test if the other framebuffer implementation have the same
else
continue;
// printf ("Region rect[%d - %d]: %d %d %d %d\n", rgnRcts->used, aCount, rect.x(), rect.y(), rect.height(), rect.width());
}
// printf ("..................................\n");
if ( pvOld
return S_OK;
}
{
/* Some general hints at the beginning:
* The console is not a real sub window of the main window. There is
* one real mac window only. This means all the drawing on the context has
* to pay attention to the statusbar, the scrollbars, the shifting spacers
* and any frame borders.
* Secondly the origin of the coordinate system is differently defined in
*
* For debugging /Developer/Applications/Performance Tools/Quartz Debug.app
* is a nice tool to see which parts of the screen are updated. */
/* Calculate the view rect to draw in */
QRect Q2DViewRect = mapYOrigin (QRect (p.x(), p.y(), mView->width(), mView->height()), pMain->height());
/* We have to pay special attention to the scrollbars */
/* Create the context to draw on */
/* We handle the seamless mode as a special case. */
{
/* Here we paint the windows without any wallpaper.
* So the background would be set transparently. */
/* Create a subimage of the current view.
* Currently this subimage is the whole screen. */
CGImageRef subImage = CGImageCreateWithImageInRect (mImage, CGRectMake (mView->contentsX(), mView->contentsY(), mView->visibleWidth(), mView->visibleHeight()));
/* Clear the background (Make the rect fully transparent) */
CGContextClearRect (ctx, CGRectMake (winRect.left, winRect.top, winRect.right - winRect.left, winRect.bottom - winRect.top));
/* Grab the current visible region. */
if (rgnRcts)
{
{
/* Save state for display fliping */
/* Flip the y-coord */
/* Add the clipping rects all at once. They are defined in
* SetVisibleRegion. */
/* Restore the context state. Note that the
* current path isn't destroyed. */
/* Now convert the path to a clipping path. */
CGContextClip (ctx);
}
/* Put back the visible region, free if we cannot (2+ SetVisibleRegion calls). */
}
/* In any case clip the drawing to the view window */
/* At this point draw the real vm image */
}
else
{
/* Here we paint if we didn't care about any masks */
/* Create a subimage of the current view in the size
* of the bounding box of the current paint event */
QRect is = QRect (ir.x() + mView->contentsX(), ir.y() + mView->contentsY(), ir.width(), ir.height());
/* Ok, for more performance we set a clipping path of the
* regions given by this paint event. */
if (a.size() > 0)
{
/* Save state for display fliping */
/* Flip the y-coord */
/* Add all region rects to the current context as path components */
for (unsigned int i = 0; i < a.size(); ++i)
/* Now convert the path to a clipping path. */
CGContextClip (ctx);
}
/* In any case clip the drawing to the view window */
/* Draw the sub image to the right position */
}
}
/* Save for later shadow stuff ... */
// CGContextSetShadow (myContext, myShadowOffset, 10);
// CGContextBeginTransparencyLayer (myContext, NULL);
// CGContextSetShadow (myContext, CGSizeMake (10, 5), 1);
// CGContextClipToRect (myContext, rect);
// QRect ir = pe->rect();
// CGContextClipToRect (myContext, CGRectMake (ir.y(), ir.x(), ir.width(), ir.height()));
// CGContextEndTransparencyLayer (myContext);
{
#if 0
printf ("fmt=%lu, vram=%X, bpp=%lu, bpl=%lu, width=%lu, height=%lu\n",
#endif
/* Clean out old stuff */
clean();
bool remind = false;
/* We need a color space in any case */
/* Check if we support the pixel format/colordepth and can use the guest VRAM directly.
* Mac OS X supports 16 bit also but not in the 565 mode. So we could use
* 32 bit only. */
{
// printf ("VRAM\n");
/* Create the image copy of the framebuffer */
CGDataProviderRef dp = CGDataProviderCreateWithData (NULL, re->VRAM(), re->bitsPerPixel() / 8 * mWdt * mHgt, NULL);
}
else
{
remind = true;
// printf ("No VRAM\n");
/* Create the memory we need for our image copy
* Read somewhere that an alignment of 16 is
* best for optimal performance. So why not. */
// int bitmapBytesPerRow = RT_ALIGN (mWdt * 4, 16);
}
#ifdef VBOX_WITH_ICHAT_THEATER
#endif
// if (remind)
// {
// class RemindEvent : public VBoxAsyncEvent
// {
// ulong mRealBPP;
// public:
// RemindEvent (ulong aRealBPP)
// : mRealBPP (aRealBPP) {}
// void handle()
// {
// vboxProblem().remindAboutWrongColorDepth (mRealBPP, 32);
// }
// };
// (new RemindEvent (re->bitsPerPixel()))->post();
// }
}
void VBoxQuartz2DFrameBuffer::clean()
{
if (mImage)
{
}
if (mBitmapData)
{
mBitmapData = NULL;
}
if (mRegion)
{
}
if (mRegionUnused)
{
RTMemFree ((void *) mRegionUnused);
}
}
#endif /* defined (VBOX_GUI_USE_QUARTZ2D) */