Bug 570625, part 8: Share Xlib surfaces across processes on X11 platforms. r=karl

This commit is contained in:
Chris Jones 2010-09-14 00:23:08 -05:00
parent fe90c2afa2
commit 61979f9825
2 changed files with 116 additions and 1 deletions

View File

@ -38,7 +38,10 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/layers/ShadowLayerUtilsX11.h"
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
#include "gfxPlatform.h"
#include "gfxXlibSurface.h"
#include "mozilla/X11Util.h"
@ -56,6 +59,51 @@ GetXRenderPictFormatFromId(Display* aDisplay, PictFormat aFormatId)
return XRenderFindFormat(aDisplay, PictFormatID, &tmplate, 0);
}
// FIXME/bug 594921: stopgap until we have better cairo_xlib_surface
// APIs for working with Xlib surfaces across processes
static already_AddRefed<gfxXlibSurface>
CreateSimilar(gfxXlibSurface* aReference,
gfxASurface::gfxContentType aType, const gfxIntSize& aSize)
{
Display* display = aReference->XDisplay();
XRenderPictFormat* xrenderFormat = nsnull;
// Try to re-use aReference's render format if it's compatible
if (aReference->GetContentType() == aType) {
xrenderFormat = aReference->XRenderFormat();
} else {
// Couldn't use aReference's directly. Use a standard format then.
gfxASurface::gfxImageFormat format;
switch (aType) {
case gfxASurface::CONTENT_COLOR:
// FIXME/bug 593175: investigate 16bpp
format = gfxASurface::ImageFormatRGB24; break;
case gfxASurface::CONTENT_ALPHA:
format = gfxASurface::ImageFormatA8; break;
case gfxASurface::CONTENT_COLOR_ALPHA:
format = gfxASurface::ImageFormatARGB32; break;
default:
NS_NOTREACHED("unknown gfxContentType");
}
xrenderFormat = gfxXlibSurface::FindRenderFormat(display, format);
}
NS_ABORT_IF_FALSE(xrenderFormat, "should have a render format by now");
return gfxXlibSurface::Create(aReference->XScreen(), xrenderFormat,
aSize, aReference->XDrawable());
}
static PRBool
TakeAndDestroyXlibSurface(SurfaceDescriptor* aSurface)
{
nsRefPtr<gfxXlibSurface> surf =
aSurface->get_SurfaceDescriptorX11().OpenForeign();
surf->TakePixmap();
*aSurface = SurfaceDescriptor();
// the Pixmap is destroyed when |surf| goes out of scope
return PR_TRUE;
}
SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf)
: mId(aSurf->XDrawable())
, mSize(aSurf->GetSize())
@ -74,5 +122,71 @@ SurfaceDescriptorX11::OpenForeign() const
return surf->CairoStatus() ? nsnull : surf.forget();
}
PRBool
ShadowLayerForwarder::PlatformAllocDoubleBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent,
SurfaceDescriptor* aFrontBuffer,
SurfaceDescriptor* aBackBuffer)
{
gfxASurface* reference = gfxPlatform::GetPlatform()->ScreenReferenceSurface();
NS_ABORT_IF_FALSE(reference->GetType() == gfxASurface::SurfaceTypeXlib,
"can't alloc an Xlib surface on non-X11");
gfxXlibSurface* xlibRef = static_cast<gfxXlibSurface*>(reference);
nsRefPtr<gfxXlibSurface> front = CreateSimilar(xlibRef, aContent, aSize);
nsRefPtr<gfxXlibSurface> back = CreateSimilar(xlibRef, aContent, aSize);
if (!front || !back) {
NS_ERROR("creating Xlib front/back surfaces failed!");
return PR_FALSE;
}
// Release Pixmap ownership to the layers model
front->ReleasePixmap();
back->ReleasePixmap();
*aFrontBuffer = SurfaceDescriptorX11(front);
*aBackBuffer = SurfaceDescriptorX11(back);
return PR_TRUE;
}
/*static*/ already_AddRefed<gfxASurface>
ShadowLayerForwarder::PlatformOpenDescriptor(const SurfaceDescriptor& aSurface)
{
if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface.type()) {
return nsnull;
}
return aSurface.get_SurfaceDescriptorX11().OpenForeign();
}
PRBool
ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
{
if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface->type()) {
return PR_FALSE;
}
return TakeAndDestroyXlibSurface(aSurface);
}
/*static*/ void
ShadowLayerForwarder::PlatformSyncBeforeUpdate()
{
XSync(DefaultXDisplay(), False);
}
/*static*/ void
ShadowLayerManager::PlatformSyncBeforeReplyUpdate()
{
XSync(DefaultXDisplay(), False);
}
PRBool
ShadowLayerManager::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
{
if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface->type()) {
return PR_FALSE;
}
return TakeAndDestroyXlibSurface(aSurface);
}
} // namespace layers
} // namespace mozilla

View File

@ -47,6 +47,7 @@
#include "IPC/IPCMessageUtils.h"
#define MOZ_HAVE_SURFACEDESCRIPTORX11
#define MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
class gfxXlibSurface;