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>
20 using namespace mozilla::gfx
;
22 // gfxImageSurface pixel format configuration.
23 #define SHAPED_IMAGE_SURFACE_BPP 4
25 # define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 0
27 # define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 3
30 WindowSurfaceX11Image::WindowSurfaceX11Image(Display
* aDisplay
, Window aWindow
,
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()) {
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()) {
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());
97 gfx::IntRect bounds
= aInvalidRegion
.GetBounds().ToUnknownRect();
98 if (bounds
.IsEmpty()) {
102 uint32_t numRects
= aInvalidRegion
.GetNumRects();
104 dt
->CopySurface(surf
, bounds
, bounds
.TopLeft());
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
));
121 } // namespace widget
122 } // namespace mozilla