Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / widget / gtk / WindowSurfaceX11Image.cpp
blobc32fe50e1bcf9210b11f77db362287b8fc8982d9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WindowSurfaceX11Image.h"
9 #include "mozilla/gfx/2D.h"
10 #include "mozilla/gfx/Tools.h"
11 #include "mozilla/gfx/gfxVars.h"
12 #include "gfxPlatform.h"
13 #include "gfx2DGlue.h"
15 #include <X11/extensions/shape.h>
17 namespace mozilla {
18 namespace widget {
20 using namespace mozilla::gfx;
22 // gfxImageSurface pixel format configuration.
23 #define SHAPED_IMAGE_SURFACE_BPP 4
24 #ifdef IS_BIG_ENDIAN
25 # define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 0
26 #else
27 # define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 3
28 #endif
30 WindowSurfaceX11Image::WindowSurfaceX11Image(Display* aDisplay, Window aWindow,
31 Visual* aVisual,
32 unsigned int aDepth)
33 : WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth) {}
35 WindowSurfaceX11Image::~WindowSurfaceX11Image() {}
37 already_AddRefed<gfx::DrawTarget> WindowSurfaceX11Image::Lock(
38 const LayoutDeviceIntRegion& aRegion) {
39 gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
40 gfx::IntSize size(bounds.XMost(), bounds.YMost());
42 if (!mWindowSurface || mWindowSurface->CairoStatus() ||
43 !(size <= mWindowSurface->GetSize())) {
44 mWindowSurface = new gfxXlibSurface(mDisplay, mWindow, mVisual, size);
46 if (mWindowSurface->CairoStatus()) {
47 return nullptr;
50 if (!mImageSurface || mImageSurface->CairoStatus() ||
51 !(size <= mImageSurface->GetSize())) {
52 gfxImageFormat format = SurfaceFormatToImageFormat(mFormat);
53 if (format == gfx::SurfaceFormat::UNKNOWN) {
54 format = mDepth == 32 ? gfx::SurfaceFormat::A8R8G8B8_UINT32
55 : gfx::SurfaceFormat::X8R8G8B8_UINT32;
58 mImageSurface = new gfxImageSurface(size, format);
59 if (mImageSurface->CairoStatus()) {
60 return nullptr;
64 gfxImageFormat format = mImageSurface->Format();
65 // Cairo prefers compositing to BGRX instead of BGRA where possible.
66 // Cairo/pixman lacks some fast paths for compositing BGRX onto BGRA, so
67 // just report it as BGRX directly in that case.
68 // Otherwise, for Skia, report it as BGRA to the compositor. The alpha
69 // channel will be discarded when we put the image.
70 if (format == gfx::SurfaceFormat::X8R8G8B8_UINT32) {
71 gfx::BackendType backend = gfxVars::ContentBackend();
72 if (!gfx::Factory::DoesBackendSupportDataDrawtarget(backend)) {
73 backend = gfx::BackendType::SKIA;
75 if (backend != gfx::BackendType::CAIRO) {
76 format = gfx::SurfaceFormat::A8R8G8B8_UINT32;
80 return gfxPlatform::CreateDrawTargetForData(
81 mImageSurface->Data(), mImageSurface->GetSize(), mImageSurface->Stride(),
82 ImageFormatToSurfaceFormat(format));
85 void WindowSurfaceX11Image::Commit(
86 const LayoutDeviceIntRegion& aInvalidRegion) {
87 RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateDrawTargetForCairoSurface(
88 mWindowSurface->CairoSurface(), mWindowSurface->GetSize());
89 RefPtr<gfx::SourceSurface> surf =
90 gfx::Factory::CreateSourceSurfaceForCairoSurface(
91 mImageSurface->CairoSurface(), mImageSurface->GetSize(),
92 mImageSurface->Format());
93 if (!dt || !surf) {
94 return;
97 gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect();
98 if (bounds.IsEmpty()) {
99 return;
102 uint32_t numRects = aInvalidRegion.GetNumRects();
103 if (numRects == 1) {
104 dt->CopySurface(surf, bounds, bounds.TopLeft());
105 } else {
106 AutoTArray<IntRect, 32> rects;
107 rects.SetCapacity(numRects);
108 for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
109 rects.AppendElement(iter.Get().ToUnknownRect());
111 dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length());
113 dt->DrawSurface(surf, gfx::Rect(bounds), gfx::Rect(bounds),
114 DrawSurfaceOptions(),
115 DrawOptions(1.0f, CompositionOp::OP_SOURCE));
117 dt->PopClip();
121 } // namespace widget
122 } // namespace mozilla