Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/gfx/layers/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 23 kB image not shown  

Quelle  NativeLayerWayland.cpp   Sprache: C

 
/* 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 "mozilla/layers/NativeLayerWayland.h"

#include <dlfcn.h>
#include <utility>
#include <algorithm>

#include "gfxUtils.h"
#include "nsGtkUtils.h"
#include "GLContextProvider.h"
#include "GLBlitHelper.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/layers/SurfacePoolWayland.h"
#include "mozilla/StaticPrefs_widget.h"
#include "mozilla/webrender/RenderThread.h"

namespace mozilla::layers {

using gfx::BackendType;
using gfx::DrawTarget;
using gfx::IntPoint;
using gfx::IntRect;
using gfx::IntRegion;
using gfx::IntSize;
using gfx::Matrix4x4;
using gfx::Point;
using gfx::Rect;
using gfx::SamplingFilter;
using gfx::Size;

static const struct wl_callback_listener sFrameListenerNativeLayerWayland = {
    NativeLayerWayland::FrameCallbackHandler};

CallbackMultiplexHelper::CallbackMultiplexHelper(CallbackFunc aCallbackFunc,
                                                 void* aCallbackData)
    : mCallbackFunc(aCallbackFunc), mCallbackData(aCallbackData) {}

void CallbackMultiplexHelper::Callback(uint32_t aTime) {
  if (!mActive) {
    return;
  }
  mActive = false;

  // This is likely the first of a batch of frame callbacks being processed and
  // may trigger the setup of a successive one. In order to avoid complexity,
  // defer calling the callback function until we had a chance to process
  // all pending frame callbacks.

  AddRef();
  nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod<uint32_t>(
      "layers::CallbackMultiplexHelper::RunCallback"this,
      &CallbackMultiplexHelper::RunCallback, aTime);
  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThreadQueue(
      runnable.forget(), EventQueuePriority::Vsync));
}

void CallbackMultiplexHelper::RunCallback(uint32_t aTime) {
  mCallbackFunc(mCallbackData, aTime);
  Release();
}

/* static */
already_AddRefed<NativeLayerRootWayland>
NativeLayerRootWayland::CreateForMozContainer(MozContainer* aContainer) {
  RefPtr<NativeLayerRootWayland> layerRoot =
      new NativeLayerRootWayland(aContainer);
  return layerRoot.forget();
}

NativeLayerRootWayland::NativeLayerRootWayland(MozContainer* aContainer)
    : mMutex("NativeLayerRootWayland"), mContainer(aContainer) {
  g_object_ref(mContainer);
}

NativeLayerRootWayland::~NativeLayerRootWayland() {
  GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(mContainer));
  if (gdkWindow) {
    GdkFrameClock* frameClock = gdk_window_get_frame_clock(gdkWindow);
    g_signal_handlers_disconnect_by_data(frameClock, this);
  }
  g_object_unref(mContainer);
}

already_AddRefed<NativeLayer> NativeLayerRootWayland::CreateLayer(
    const IntSize& aSize, bool aIsOpaque,
    SurfacePoolHandle* aSurfacePoolHandle) {
  RefPtr<NativeLayer> layer = new NativeLayerWayland(
      aSize, aIsOpaque, aSurfacePoolHandle->AsSurfacePoolHandleWayland());
  return layer.forget();
}

already_AddRefed<NativeLayer>
NativeLayerRootWayland::CreateLayerForExternalTexture(bool aIsOpaque) {
  RefPtr<NativeLayer> layer = new NativeLayerWayland(aIsOpaque);
  return layer.forget();
}

void NativeLayerRootWayland::AppendLayer(NativeLayer* aLayer) {
  MOZ_RELEASE_ASSERT(false);
  MutexAutoLock lock(mMutex);

  RefPtr<NativeLayerWayland> layerWayland = aLayer->AsNativeLayerWayland();
  MOZ_RELEASE_ASSERT(layerWayland);

  mSublayers.AppendElement(layerWayland);
}

void NativeLayerRootWayland::RemoveLayer(NativeLayer* aLayer) {
  MOZ_RELEASE_ASSERT(false);
  MutexAutoLock lock(mMutex);

  RefPtr<NativeLayerWayland> layerWayland = aLayer->AsNativeLayerWayland();
  MOZ_RELEASE_ASSERT(layerWayland);

  mSublayers.RemoveElement(layerWayland);
}

void NativeLayerRootWayland::SetLayers(
    const nsTArray<RefPtr<NativeLayer>>& aLayers) {
  MutexAutoLock lock(mMutex);

  nsTArray<RefPtr<NativeLayerWayland>> newSublayers(aLayers.Length());
  for (const RefPtr<NativeLayer>& sublayer : aLayers) {
    RefPtr<NativeLayerWayland> layer = sublayer->AsNativeLayerWayland();
    newSublayers.AppendElement(layer);
  }

  if (newSublayers != mSublayers) {
    for (const RefPtr<NativeLayerWayland>& layer : mSublayers) {
      if (!newSublayers.Contains(layer)) {
        mOldSublayers.AppendElement(layer);
      }
    }
    mSublayers = std::move(newSublayers);
    mNewLayers = true;
  }
}

bool NativeLayerRootWayland::CommitToScreen() {
  MutexAutoLock lock(mMutex);
  return CommitToScreen(lock);
}

bool NativeLayerRootWayland::CommitToScreen(const MutexAutoLock& aProofOfLock) {
  mFrameInProcess = false;

#if 0
  MozContainerSurfaceLock lock(mContainer);
  struct wl_surface* containerSurface = lock.GetSurface();
  if (!containerSurface) {
    if (!mCallbackRequested) {
      RefPtr<NativeLayerRootWayland> self(this);
      moz_container_wayland_add_initial_draw_callback_locked(
          mContainer, [self]() -> void {
            MutexAutoLock lock(self->mMutex);
            if (!self->mFrameInProcess) {
              self->CommitToScreen(lock);
            }
            self->mCallbackRequested = false;
          });
      mCallbackRequested = true;
    }
    return true;
  }

  wl_surface* previousSurface = nullptr;
  for (RefPtr<NativeLayerWayland>& layer : mSublayers) {
    layer->EnsureParentSurface(containerSurface);

    if (mNewLayers) {
      wl_subsurface_place_above(layer->mWlSubsurface, previousSurface
                                                          ? previousSurface
                                                          : containerSurface);
      previousSurface = layer->mWlSurface;
    }

    MOZ_RELEASE_ASSERT(layer->mTransform.Is2D());
    auto transform2D = layer->mTransform.As2D();

    Rect surfaceRectClipped =
        Rect(0, 0, (float)layer->mSize.width, (float)layer->mSize.height);
    surfaceRectClipped =
        surfaceRectClipped.Intersect(Rect(layer->mDisplayRect));

    transform2D.PostTranslate((float)layer->mPosition.x,
                              (float)layer->mPosition.y);
    surfaceRectClipped = transform2D.TransformBounds(surfaceRectClipped);

    if (layer->mClipRect) {
      surfaceRectClipped =
          surfaceRectClipped.Intersect(Rect(layer->mClipRect.value()));
    }

    if (roundf(surfaceRectClipped.width) > 0 &&
        roundf(surfaceRectClipped.height) > 0) {
      layer->SetBufferTransformFlipped(transform2D._11 < 0.0,
                                       transform2D._22 < 0.0);

      double bufferScale = moz_container_wayland_get_scale(mContainer);
      layer->SetSubsurfacePosition(floor(surfaceRectClipped.x / bufferScale),
                                   floor(surfaceRectClipped.y / bufferScale));
      layer->SetViewportDestinationSize(
          ceil(surfaceRectClipped.width / bufferScale),
          ceil(surfaceRectClipped.height / bufferScale));

      auto transform2DInversed = transform2D.Inverse();
      Rect bufferClip = transform2DInversed.TransformBounds(surfaceRectClipped);
      layer->SetViewportSourceRect(bufferClip);

      layer->Commit();
    } else {
      layer->Unmap();
    }
  }

  if (mNewLayers) {
    for (RefPtr<NativeLayerWayland>& layer : mOldSublayers) {
      layer->Unmap();
    }
    mOldSublayers.Clear();

    nsCOMPtr<nsIRunnable> updateLayersRunnable = NewRunnableMethod<>(
        "layers::NativeLayerRootWayland::UpdateLayersOnMainThread"this,
        &NativeLayerRootWayland::UpdateLayersOnMainThread);
    MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThreadQueue(
        updateLayersRunnable.forget(), EventQueuePriority::Normal));
    mNewLayers = false;
  }

  if (containerSurface != mWlSurface) {
    if (!mShmBuffer) {
      mShmBuffer = widget::WaylandBufferSHM::Create(LayoutDeviceIntSize(1, 1));
      mShmBuffer->Clear();
    }
    mShmBuffer->AttachAndCommit(containerSurface);
    mWlSurface = containerSurface;
  } else {
    wl_surface_commit(containerSurface);
  }
#endif
  wl_display_flush(widget::WaylandDisplayGet()->GetDisplay());
  return true;
}

void NativeLayerRootWayland::RequestFrameCallback(CallbackFunc aCallbackFunc,
                                                  void* aCallbackData) {
  MutexAutoLock lock(mMutex);

  mCallbackMultiplexHelper =
      new CallbackMultiplexHelper(aCallbackFunc, aCallbackData);

  for (const RefPtr<NativeLayerWayland>& layer : mSublayersOnMainThread) {
    layer->RequestFrameCallback(mCallbackMultiplexHelper);
  }
#if 0
  MozContainerSurfaceLock lockContainer(mContainer);
  struct wl_surface* wlSurface = lockContainer.GetSurface();
  if (wlSurface) {
    wl_surface_commit(wlSurface);
    wl_display_flush(widget::WaylandDisplayGet()->GetDisplay());
  }
#endif
}

#if 0
static void sAfterFrameClockAfterPaint(
    GdkFrameClock* aClock, NativeLayerRootWayland* aNativeLayerRoot) {
  aNativeLayerRoot->AfterFrameClockAfterPaint();
}
#endif

void NativeLayerRootWayland::AfterFrameClockAfterPaint() {
  MutexAutoLock lock(mMutex);
#if 0
  MozContainerSurfaceLock lockContainer(mContainer);
  struct wl_surface* containerSurface = lockContainer.GetSurface();
  for (const RefPtr<NativeLayerWayland>& layer : mSublayersOnMainThread) {
    wl_surface_commit(layer->mWlSurface);
  }
  if (containerSurface) {
    wl_surface_commit(containerSurface);
  }
#endif
}

void NativeLayerRootWayland::UpdateLayersOnMainThread() {
#if 0
  AssertIsOnMainThread();
  MutexAutoLock lock(mMutex);

  static auto sGdkWaylandWindowAddCallbackSurface =
      (void (*)(GdkWindow*, struct wl_surface*))dlsym(
          RTLD_DEFAULT, "gdk_wayland_window_add_frame_callback_surface");
  static auto sGdkWaylandWindowRemoveCallbackSurface =
      (void (*)(GdkWindow*, struct wl_surface*))dlsym(
          RTLD_DEFAULT, "gdk_wayland_window_remove_frame_callback_surface");

  MozContainerSurfaceLock lockContainer(mContainer);
  struct wl_surface* containerSurface = lockContainer.GetSurface();
  GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(mContainer));

  mSublayersOnMainThread.RemoveElementsBy([&](const auto& layer) {
    if (!mSublayers.Contains(layer)) {
      if (layer->IsOpaque() &&
          StaticPrefs::widget_wayland_opaque_region_enabled_AtStartup() &&
          sGdkWaylandWindowAddCallbackSurface && gdkWindow) {
        sGdkWaylandWindowRemoveCallbackSurface(gdkWindow, layer->mWlSurface);

        wl_compositor* compositor =
            widget::WaylandDisplayGet()->GetCompositor();
        wl_region* region = wl_compositor_create_region(compositor);
        wl_surface_set_opaque_region(layer->mWlSurface, region);
        wl_region_destroy(region);
        wl_surface_commit(layer->mWlSurface);
      }
      return true;
    }
    return false;
  });

  for (const RefPtr<NativeLayerWayland>& layer : mSublayers) {
    if (!mSublayersOnMainThread.Contains(layer)) {
      if (layer->IsOpaque() &&
          StaticPrefs::widget_wayland_opaque_region_enabled_AtStartup() &&
          sGdkWaylandWindowRemoveCallbackSurface && gdkWindow) {
        sGdkWaylandWindowAddCallbackSurface(gdkWindow, layer->mWlSurface);

        wl_compositor* compositor =
            widget::WaylandDisplayGet()->GetCompositor();
        wl_region* region = wl_compositor_create_region(compositor);
        wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
        wl_surface_set_opaque_region(layer->mWlSurface, region);
        wl_region_destroy(region);
        wl_surface_commit(layer->mWlSurface);
      }
      if (mCallbackMultiplexHelper && mCallbackMultiplexHelper->IsActive()) {
        layer->RequestFrameCallback(mCallbackMultiplexHelper);
      }
      mSublayersOnMainThread.AppendElement(layer);
    }
  }

  if (containerSurface) {
    wl_surface_commit(containerSurface);
  }

  if (!mGdkAfterPaintId && gdkWindow) {
    GdkFrameClock* frameClock = gdk_window_get_frame_clock(gdkWindow);
    mGdkAfterPaintId =
        g_signal_connect_after(frameClock, "after-paint",
                               G_CALLBACK(sAfterFrameClockAfterPaint), this);
  }
#endif
}

NativeLayerWayland::NativeLayerWayland(
    const IntSize& aSize, bool aIsOpaque,
    SurfacePoolHandleWayland* aSurfacePoolHandle)
    : mMutex("NativeLayerWayland"),
      mSurfacePoolHandle(aSurfacePoolHandle),
      mSize(aSize),
      mIsOpaque(aIsOpaque) {
  MOZ_RELEASE_ASSERT(mSurfacePoolHandle,
                     "Need a non-null surface pool handle.");

  widget::nsWaylandDisplay* waylandDisplay = widget::WaylandDisplayGet();
  wl_compositor* compositor = waylandDisplay->GetCompositor();
  mWlSurface = wl_compositor_create_surface(compositor);

  wl_region* region = wl_compositor_create_region(compositor);
  wl_surface_set_input_region(mWlSurface, region);
  wl_region_destroy(region);

  wp_viewporter* viewporter = waylandDisplay->GetViewporter();
  mViewport = wp_viewporter_get_viewport(viewporter, mWlSurface);
}

NativeLayerWayland::NativeLayerWayland(bool aIsOpaque)
    : mMutex("NativeLayerWayland"),
      mSurfacePoolHandle(nullptr),
      mIsOpaque(aIsOpaque) {
  MOZ_RELEASE_ASSERT(false);  // external image
}

NativeLayerWayland::~NativeLayerWayland() {
  MutexAutoLock lock(mMutex);

  if (mInProgressBuffer) {
    mSurfacePoolHandle->ReturnBufferToPool(mInProgressBuffer);
    mInProgressBuffer = nullptr;
  }
  if (mFrontBuffer) {
    mSurfacePoolHandle->ReturnBufferToPool(mFrontBuffer);
    mFrontBuffer = nullptr;
  }
  MozClearPointer(mCallback, wl_callback_destroy);
  MozClearPointer(mViewport, wp_viewport_destroy);
  MozClearPointer(mWlSubsurface, wl_subsurface_destroy);
  MozClearPointer(mWlSurface, wl_surface_destroy);
}

void NativeLayerWayland::AttachExternalImage(
    wr::RenderTextureHost* aExternalImage) {
  MOZ_RELEASE_ASSERT(false);
}

void NativeLayerWayland::SetSurfaceIsFlipped(bool aIsFlipped) {
  MutexAutoLock lock(mMutex);

  if (aIsFlipped != mSurfaceIsFlipped) {
    mSurfaceIsFlipped = aIsFlipped;
  }
}

bool NativeLayerWayland::SurfaceIsFlipped() {
  MutexAutoLock lock(mMutex);

  return mSurfaceIsFlipped;
}

IntSize NativeLayerWayland::GetSize() {
  MutexAutoLock lock(mMutex);
  return mSize;
}

void NativeLayerWayland::SetPosition(const IntPoint& aPosition) {
  MutexAutoLock lock(mMutex);

  if (aPosition != mPosition) {
    mPosition = aPosition;
  }
}

IntPoint NativeLayerWayland::GetPosition() {
  MutexAutoLock lock(mMutex);
  return mPosition;
}

void NativeLayerWayland::SetTransform(const Matrix4x4& aTransform) {
  MutexAutoLock lock(mMutex);
  MOZ_ASSERT(aTransform.IsRectilinear());

  if (aTransform != mTransform) {
    mTransform = aTransform;
  }
}

void NativeLayerWayland::SetSamplingFilter(SamplingFilter aSamplingFilter) {
  MutexAutoLock lock(mMutex);

  if (aSamplingFilter != mSamplingFilter) {
    mSamplingFilter = aSamplingFilter;
  }
}

Matrix4x4 NativeLayerWayland::GetTransform() {
  MutexAutoLock lock(mMutex);
  return mTransform;
}

IntRect NativeLayerWayland::GetRect() {
  MutexAutoLock lock(mMutex);
  return IntRect(mPosition, mSize);
}

bool NativeLayerWayland::IsOpaque() {
  MutexAutoLock lock(mMutex);
  return mIsOpaque;
}

void NativeLayerWayland::SetClipRect(const Maybe<IntRect>& aClipRect) {
  MutexAutoLock lock(mMutex);

  if (aClipRect != mClipRect) {
    mClipRect = aClipRect;
  }
}

Maybe<IntRect> NativeLayerWayland::ClipRect() {
  MutexAutoLock lock(mMutex);
  return mClipRect;
}

IntRect NativeLayerWayland::CurrentSurfaceDisplayRect() {
  MutexAutoLock lock(mMutex);
  return mDisplayRect;
}

RefPtr<DrawTarget> NativeLayerWayland::NextSurfaceAsDrawTarget(
    const IntRect& aDisplayRect, const IntRegion& aUpdateRegion,
    BackendType aBackendType) {
  MutexAutoLock lock(mMutex);

  mDisplayRect = IntRect(aDisplayRect);
  mDirtyRegion = IntRegion(aUpdateRegion);

  MOZ_ASSERT(!mInProgressBuffer);
  if (mFrontBuffer && !mFrontBuffer->IsAttached()) {
    // the Wayland compositor released the buffer early, we can reuse it
    mInProgressBuffer = std::move(mFrontBuffer);
  } else {
    mInProgressBuffer = mSurfacePoolHandle->ObtainBufferFromPool(mSize);
    if (mFrontBuffer) {
      HandlePartialUpdate(lock);
      mSurfacePoolHandle->ReturnBufferToPool(mFrontBuffer);
    }
  }
  mFrontBuffer = nullptr;

  if (!mInProgressBuffer) {
    gfxCriticalError() << "Failed to obtain buffer";
    wr::RenderThread::Get()->HandleWebRenderError(
        wr::WebRenderError::NEW_SURFACE);
    return nullptr;
  }

  return mInProgressBuffer->Lock();
}

Maybe<GLuint> NativeLayerWayland::NextSurfaceAsFramebuffer(
    const IntRect& aDisplayRect, const IntRegion& aUpdateRegion,
    bool aNeedsDepth) {
  MutexAutoLock lock(mMutex);

  mDisplayRect = IntRect(aDisplayRect);
  mDirtyRegion = IntRegion(aUpdateRegion);

  MOZ_ASSERT(!mInProgressBuffer);
  if (mFrontBuffer && !mFrontBuffer->IsAttached()) {
    // the Wayland compositor released the buffer early, we can reuse it
    mInProgressBuffer = std::move(mFrontBuffer);
    mFrontBuffer = nullptr;
  } else {
    mInProgressBuffer = mSurfacePoolHandle->ObtainBufferFromPool(mSize);
  }

  if (!mInProgressBuffer) {
    gfxCriticalError() << "Failed to obtain buffer";
    wr::RenderThread::Get()->HandleWebRenderError(
        wr::WebRenderError::NEW_SURFACE);
    return Nothing();
  }

  // get the framebuffer before handling partial damage so we don't accidently
  // create one without depth buffer
  Maybe<GLuint> fbo = mSurfacePoolHandle->GetFramebufferForBuffer(
      mInProgressBuffer, aNeedsDepth);
  MOZ_RELEASE_ASSERT(fbo, "GetFramebufferForBuffer failed.");

  if (mFrontBuffer) {
    HandlePartialUpdate(lock);
    mSurfacePoolHandle->ReturnBufferToPool(mFrontBuffer);
    mFrontBuffer = nullptr;
  }

  return fbo;
}

void NativeLayerWayland::HandlePartialUpdate(
    const MutexAutoLock& aProofOfLock) {
  IntRegion copyRegion = IntRegion(mDisplayRect);
  copyRegion.SubOut(mDirtyRegion);

  if (!copyRegion.IsEmpty()) {
    if (mSurfacePoolHandle->gl()) {
      mSurfacePoolHandle->gl()->MakeCurrent();
      for (auto iter = copyRegion.RectIter(); !iter.Done(); iter.Next()) {
        gfx::IntRect r = iter.Get();
        Maybe<GLuint> sourceFB =
            mSurfacePoolHandle->GetFramebufferForBuffer(mFrontBuffer, false);
        Maybe<GLuint> destFB = mSurfacePoolHandle->GetFramebufferForBuffer(
            mInProgressBuffer, false);
        MOZ_RELEASE_ASSERT(sourceFB && destFB);
        mSurfacePoolHandle->gl()->BlitHelper()->BlitFramebufferToFramebuffer(
            sourceFB.value(), destFB.value(), r, r, LOCAL_GL_NEAREST);
      }
    } else {
      RefPtr<gfx::DataSourceSurface> dataSourceSurface =
          gfx::CreateDataSourceSurfaceFromData(
              mSize, mFrontBuffer->GetSurfaceFormat(),
              (const uint8_t*)mFrontBuffer->GetImageData(),
              mSize.width * BytesPerPixel(mFrontBuffer->GetSurfaceFormat()));
      RefPtr<DrawTarget> dt = mInProgressBuffer->Lock();

      for (auto iter = copyRegion.RectIter(); !iter.Done(); iter.Next()) {
        IntRect r = iter.Get();
        dt->CopySurface(dataSourceSurface, r, IntPoint(r.x, r.y));
      }
    }
  }
}

void NativeLayerWayland::NotifySurfaceReady() {
  MOZ_ASSERT(!mFrontBuffer);
  MOZ_ASSERT(mInProgressBuffer);
  mFrontBuffer = mInProgressBuffer;
  mInProgressBuffer = nullptr;
}

void NativeLayerWayland::DiscardBackbuffers() {}

void NativeLayerWayland::Commit() {
#if 0
  MutexAutoLock lock(mMutex);

  if (mDirtyRegion.IsEmpty() && mHasBufferAttached) {
    wl_surface_commit(mWlSurface);
    return;
  }

  for (auto iter = mDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
    IntRect r = iter.Get();
    wl_surface_damage_buffer(mWlSurface, r.x, r.y, r.width, r.height);
  }

  MOZ_ASSERT(mFrontBuffer);
  mFrontBuffer->AttachAndCommit(mWlSurface);
  mHasBufferAttached = true;
  mDirtyRegion.SetEmpty();
#endif
}

void NativeLayerWayland::Unmap() {
  MutexAutoLock lock(mMutex);

  if (!mHasBufferAttached) {
    return;
  }

  wl_surface_attach(mWlSurface, nullptr, 0, 0);
  wl_surface_commit(mWlSurface);
  mHasBufferAttached = false;
}

void NativeLayerWayland::EnsureParentSurface(wl_surface* aParentSurface) {
  MutexAutoLock lock(mMutex);

  if (aParentSurface != mParentWlSurface) {
    MozClearPointer(mWlSubsurface, wl_subsurface_destroy);
    mSubsurfacePosition = IntPoint(0, 0);

    if (aParentSurface) {
      wl_subcompositor* subcompositor =
          widget::WaylandDisplayGet()->GetSubcompositor();
      mWlSubsurface = wl_subcompositor_get_subsurface(subcompositor, mWlSurface,
                                                      aParentSurface);
    }
    mParentWlSurface = aParentSurface;
  }
}

void NativeLayerWayland::SetBufferTransformFlipped(bool aFlippedX,
                                                   bool aFlippedY) {
  MutexAutoLock lock(mMutex);

  if (aFlippedX == mBufferTransformFlippedX &&
      aFlippedY == mBufferTransformFlippedY) {
    return;
  }

  mBufferTransformFlippedX = aFlippedX;
  mBufferTransformFlippedY = aFlippedY;

  if (mBufferTransformFlippedY) {
    if (mBufferTransformFlippedX) {
      wl_surface_set_buffer_transform(mWlSurface, WL_OUTPUT_TRANSFORM_180);
    } else {
      wl_surface_set_buffer_transform(mWlSurface,
                                      WL_OUTPUT_TRANSFORM_FLIPPED_180);
    }
  } else {
    if (mBufferTransformFlippedX) {
      wl_surface_set_buffer_transform(mWlSurface, WL_OUTPUT_TRANSFORM_FLIPPED);
    } else {
      wl_surface_set_buffer_transform(mWlSurface, WL_OUTPUT_TRANSFORM_NORMAL);
    }
  }
}

void NativeLayerWayland::SetSubsurfacePosition(int aX, int aY) {
  MutexAutoLock lock(mMutex);

  if ((aX == mSubsurfacePosition.x && aY == mSubsurfacePosition.y) ||
      !mWlSubsurface) {
    return;
  }

  mSubsurfacePosition.x = aX;
  mSubsurfacePosition.y = aY;
  wl_subsurface_set_position(mWlSubsurface, mSubsurfacePosition.x,
                             mSubsurfacePosition.y);
}

void NativeLayerWayland::SetViewportSourceRect(const Rect aSourceRect) {
  MutexAutoLock lock(mMutex);

  Rect bufferRect = Rect(0, 0, mSize.width, mSize.height);
  Rect sourceRect = aSourceRect.Intersect(bufferRect);

  if (mViewportSourceRect == sourceRect) {
    return;
  }

  mViewportSourceRect = sourceRect;
  wp_viewport_set_source(mViewport, wl_fixed_from_double(mViewportSourceRect.x),
                         wl_fixed_from_double(mViewportSourceRect.y),
                         wl_fixed_from_double(mViewportSourceRect.width),
                         wl_fixed_from_double(mViewportSourceRect.height));
}

void NativeLayerWayland::SetViewportDestinationSize(int aWidth, int aHeight) {
  MutexAutoLock lock(mMutex);

  if (aWidth == mViewportDestinationSize.width &&
      aHeight == mViewportDestinationSize.height) {
    return;
  }

  mViewportDestinationSize.width = aWidth;
  mViewportDestinationSize.height = aHeight;
  wp_viewport_set_destination(mViewport, mViewportDestinationSize.width,
                              mViewportDestinationSize.height);
}

void NativeLayerWayland::RequestFrameCallback(
    const RefPtr<CallbackMultiplexHelper>& aMultiplexHelper) {
  MutexAutoLock lock(mMutex);
  MOZ_ASSERT(aMultiplexHelper->IsActive());

  // Avoid piling up old helpers if this surface does not receive callbacks
  // for a longer time
  mCallbackMultiplexHelpers.RemoveElementsBy(
      [&](const auto& object) { return !object->IsActive(); });

  mCallbackMultiplexHelpers.AppendElement(aMultiplexHelper);
  if (!mCallback) {
    mCallback = wl_surface_frame(mWlSurface);
    wl_callback_add_listener(mCallback, &sFrameListenerNativeLayerWayland,
                             this);
    wl_surface_commit(mWlSurface);
  }
}

void NativeLayerWayland::FrameCallbackHandler(wl_callback* aCallback,
                                              uint32_t aTime) {
  MutexAutoLock lock(mMutex);

  MOZ_RELEASE_ASSERT(aCallback == mCallback);
  MozClearPointer(mCallback, wl_callback_destroy);

  for (const RefPtr<CallbackMultiplexHelper>& callbackMultiplexHelper :
       mCallbackMultiplexHelpers) {
    callbackMultiplexHelper->Callback(aTime);
  }
  mCallbackMultiplexHelpers.Clear();
}

/* static */
void NativeLayerWayland::FrameCallbackHandler(void* aData,
                                              wl_callback* aCallback,
                                              uint32_t aTime) {
  auto surface = reinterpret_cast<NativeLayerWayland*>(aData);
  surface->FrameCallbackHandler(aCallback, aTime);
}

}  // namespace mozilla::layers

91%


¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.