summaryrefslogtreecommitdiffstats
path: root/gfx/gl/SharedSurfaceGLX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl/SharedSurfaceGLX.cpp')
-rw-r--r--gfx/gl/SharedSurfaceGLX.cpp144
1 files changed, 144 insertions, 0 deletions
diff --git a/gfx/gl/SharedSurfaceGLX.cpp b/gfx/gl/SharedSurfaceGLX.cpp
new file mode 100644
index 000000000..69bee24ba
--- /dev/null
+++ b/gfx/gl/SharedSurfaceGLX.cpp
@@ -0,0 +1,144 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceGLX.h"
+#include "gfxXlibSurface.h"
+#include "GLXLibrary.h"
+#include "GLContextProvider.h"
+#include "GLContextGLX.h"
+#include "GLScreenBuffer.h"
+#include "mozilla/gfx/SourceSurfaceCairo.h"
+#include "mozilla/layers/LayersSurfaces.h"
+#include "mozilla/layers/ShadowLayerUtilsX11.h"
+#include "mozilla/layers/ISurfaceAllocator.h"
+#include "mozilla/layers/TextureForwarder.h"
+#include "mozilla/X11Util.h"
+
+namespace mozilla {
+namespace gl {
+
+/* static */
+UniquePtr<SharedSurface_GLXDrawable>
+SharedSurface_GLXDrawable::Create(GLContext* prodGL,
+ const SurfaceCaps& caps,
+ const gfx::IntSize& size,
+ bool deallocateClient,
+ bool inSameProcess)
+{
+ UniquePtr<SharedSurface_GLXDrawable> ret;
+ Display* display = DefaultXDisplay();
+ Screen* screen = XDefaultScreenOfDisplay(display);
+ Visual* visual = gfxXlibSurface::FindVisual(screen, gfx::SurfaceFormat::A8R8G8B8_UINT32);
+
+ RefPtr<gfxXlibSurface> surf = gfxXlibSurface::Create(screen, visual, size);
+ if (!deallocateClient)
+ surf->ReleasePixmap();
+
+ ret.reset(new SharedSurface_GLXDrawable(prodGL, size, inSameProcess, surf));
+ return Move(ret);
+}
+
+
+SharedSurface_GLXDrawable::SharedSurface_GLXDrawable(GLContext* gl,
+ const gfx::IntSize& size,
+ bool inSameProcess,
+ const RefPtr<gfxXlibSurface>& xlibSurface)
+ : SharedSurface(SharedSurfaceType::GLXDrawable,
+ AttachmentType::Screen,
+ gl,
+ size,
+ true,
+ true)
+ , mXlibSurface(xlibSurface)
+ , mInSameProcess(inSameProcess)
+{}
+
+void
+SharedSurface_GLXDrawable::ProducerReleaseImpl()
+{
+ mGL->MakeCurrent();
+ mGL->fFlush();
+}
+
+void
+SharedSurface_GLXDrawable::LockProdImpl()
+{
+ mGL->Screen()->SetReadBuffer(LOCAL_GL_FRONT);
+ GLContextGLX::Cast(mGL)->OverrideDrawable(mXlibSurface->GetGLXPixmap());
+}
+
+void
+SharedSurface_GLXDrawable::UnlockProdImpl()
+{
+ GLContextGLX::Cast(mGL)->RestoreDrawable();
+}
+
+bool
+SharedSurface_GLXDrawable::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
+{
+ if (!mXlibSurface)
+ return false;
+
+ *out_descriptor = layers::SurfaceDescriptorX11(mXlibSurface, mInSameProcess);
+ return true;
+}
+
+bool
+SharedSurface_GLXDrawable::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
+{
+ MOZ_ASSERT(out_surface);
+ RefPtr<gfx::DataSourceSurface> dataSurf =
+ new gfx::DataSourceSurfaceCairo(mXlibSurface->CairoSurface());
+
+ gfx::DataSourceSurface::ScopedMap mapSrc(dataSurf, gfx::DataSourceSurface::READ);
+ if (!mapSrc.IsMapped()) {
+ return false;
+ }
+
+ gfx::DataSourceSurface::ScopedMap mapDest(out_surface, gfx::DataSourceSurface::WRITE);
+ if (!mapDest.IsMapped()) {
+ return false;
+ }
+
+ if (mapDest.GetStride() == mapSrc.GetStride()) {
+ memcpy(mapDest.GetData(),
+ mapSrc.GetData(),
+ out_surface->GetSize().height * mapDest.GetStride());
+ } else {
+ for (int32_t i = 0; i < dataSurf->GetSize().height; i++) {
+ memcpy(mapDest.GetData() + i * mapDest.GetStride(),
+ mapSrc.GetData() + i * mapSrc.GetStride(),
+ std::min(mapSrc.GetStride(), mapDest.GetStride()));
+ }
+ }
+
+ return true;
+}
+
+/* static */
+UniquePtr<SurfaceFactory_GLXDrawable>
+SurfaceFactory_GLXDrawable::Create(GLContext* prodGL,
+ const SurfaceCaps& caps,
+ const RefPtr<layers::LayersIPCChannel>& allocator,
+ const layers::TextureFlags& flags)
+{
+ MOZ_ASSERT(caps.alpha, "GLX surfaces require an alpha channel!");
+
+ typedef SurfaceFactory_GLXDrawable ptrT;
+ UniquePtr<ptrT> ret(new ptrT(prodGL, caps, allocator,
+ flags & ~layers::TextureFlags::ORIGIN_BOTTOM_LEFT));
+ return Move(ret);
+}
+
+UniquePtr<SharedSurface>
+SurfaceFactory_GLXDrawable::CreateShared(const gfx::IntSize& size)
+{
+ bool deallocateClient = !!(mFlags & layers::TextureFlags::DEALLOCATE_CLIENT);
+ return SharedSurface_GLXDrawable::Create(mGL, mCaps, size, deallocateClient,
+ mAllocator->IsSameProcess());
+}
+
+} // namespace gl
+} // namespace mozilla