DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (e67641c2e4cc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- */
/* 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