michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=8 et : michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ShadowLayerUtilsX11.h" michael@0: #include // for Drawable, XID michael@0: #include // for Display, Visual, etc michael@0: #include // for XRenderPictFormat, etc michael@0: #include // for PictFormat michael@0: #include "cairo-xlib.h" michael@0: #include // for uint32_t michael@0: #include "GLDefs.h" // for GLenum michael@0: #include "gfxPlatform.h" // for gfxPlatform michael@0: #include "gfxXlibSurface.h" // for gfxXlibSurface michael@0: #include "gfx2DGlue.h" // for Moz2D transistion helpers michael@0: #include "mozilla/X11Util.h" // for DefaultXDisplay, FinishX, etc michael@0: #include "mozilla/gfx/Point.h" // for IntSize michael@0: #include "mozilla/layers/CompositableForwarder.h" michael@0: #include "mozilla/layers/CompositorTypes.h" // for OpenMode michael@0: #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator, etc michael@0: #include "mozilla/layers/LayerManagerComposite.h" michael@0: #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc michael@0: #include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder, etc michael@0: #include "mozilla/mozalloc.h" // for operator new michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsCOMPtr.h" // for already_AddRefed michael@0: #include "nsDebug.h" // for NS_ERROR michael@0: #include "prenv.h" // for PR_GetEnv michael@0: michael@0: using namespace mozilla::gl; michael@0: michael@0: namespace mozilla { michael@0: namespace gl { michael@0: class GLContext; michael@0: class TextureImage; michael@0: } michael@0: michael@0: namespace layers { michael@0: michael@0: // Return true if we're likely compositing using X and so should use michael@0: // Xlib surfaces in shadow layers. michael@0: static bool michael@0: UsingXCompositing() michael@0: { michael@0: if (!PR_GetEnv("MOZ_LAYERS_ENABLE_XLIB_SURFACES")) { michael@0: return false; michael@0: } michael@0: return (gfxSurfaceType::Xlib == michael@0: gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType()); michael@0: } michael@0: michael@0: // LookReturn a pointer to |aFormat| that lives in the Xrender library. michael@0: // All code using render formats assumes it doesn't need to copy. michael@0: static XRenderPictFormat* michael@0: GetXRenderPictFormatFromId(Display* aDisplay, PictFormat aFormatId) michael@0: { michael@0: XRenderPictFormat tmplate; michael@0: tmplate.id = aFormatId; michael@0: return XRenderFindFormat(aDisplay, PictFormatID, &tmplate, 0); michael@0: } michael@0: michael@0: SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf) michael@0: : mId(aSurf->XDrawable()) michael@0: , mSize(aSurf->GetSize().ToIntSize()) michael@0: { michael@0: const XRenderPictFormat *pictFormat = aSurf->XRenderFormat(); michael@0: if (pictFormat) { michael@0: mFormat = pictFormat->id; michael@0: } else { michael@0: mFormat = cairo_xlib_surface_get_visual(aSurf->CairoSurface())->visualid; michael@0: } michael@0: } michael@0: michael@0: SurfaceDescriptorX11::SurfaceDescriptorX11(Drawable aDrawable, XID aFormatID, michael@0: const gfx::IntSize& aSize) michael@0: : mId(aDrawable) michael@0: , mFormat(aFormatID) michael@0: , mSize(aSize) michael@0: { } michael@0: michael@0: already_AddRefed michael@0: SurfaceDescriptorX11::OpenForeign() const michael@0: { michael@0: Display* display = DefaultXDisplay(); michael@0: Screen* screen = DefaultScreenOfDisplay(display); michael@0: michael@0: nsRefPtr surf; michael@0: XRenderPictFormat* pictFormat = GetXRenderPictFormatFromId(display, mFormat); michael@0: if (pictFormat) { michael@0: surf = new gfxXlibSurface(screen, mId, pictFormat, gfx::ThebesIntSize(mSize)); michael@0: } else { michael@0: Visual* visual; michael@0: int depth; michael@0: FindVisualAndDepth(display, mFormat, &visual, &depth); michael@0: if (!visual) michael@0: return nullptr; michael@0: michael@0: surf = new gfxXlibSurface(display, mId, visual, gfx::ThebesIntSize(mSize)); michael@0: } michael@0: return surf->CairoStatus() ? nullptr : surf.forget(); michael@0: } michael@0: michael@0: /*static*/ void michael@0: ShadowLayerForwarder::PlatformSyncBeforeUpdate() michael@0: { michael@0: if (UsingXCompositing()) { michael@0: // If we're using X surfaces, then we need to finish all pending michael@0: // operations on the back buffers before handing them to the michael@0: // parent, otherwise the surface might be used by the parent's michael@0: // Display in between two operations queued by our Display. michael@0: FinishX(DefaultXDisplay()); michael@0: } michael@0: } michael@0: michael@0: /*static*/ void michael@0: LayerManagerComposite::PlatformSyncBeforeReplyUpdate() michael@0: { michael@0: if (UsingXCompositing()) { michael@0: // If we're using X surfaces, we need to finish all pending michael@0: // operations on the *front buffers* before handing them back to michael@0: // the child, even though they will be read operations. michael@0: // Otherwise, the child might start scribbling on new back buffers michael@0: // that are still participating in requests as old front buffers. michael@0: FinishX(DefaultXDisplay()); michael@0: } michael@0: } michael@0: michael@0: /*static*/ bool michael@0: LayerManagerComposite::SupportsDirectTexturing() michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: } // namespace layers michael@0: } // namespace mozilla