Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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/. */
6 :
7 : #include "WindowSurfaceX11Image.h"
8 :
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"
14 :
15 : namespace mozilla {
16 : namespace widget {
17 :
18 0 : WindowSurfaceX11Image::WindowSurfaceX11Image(Display* aDisplay,
19 : Window aWindow,
20 : Visual* aVisual,
21 0 : unsigned int aDepth)
22 0 : : WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth)
23 : {
24 0 : }
25 :
26 0 : WindowSurfaceX11Image::~WindowSurfaceX11Image()
27 : {
28 0 : }
29 :
30 : already_AddRefed<gfx::DrawTarget>
31 0 : WindowSurfaceX11Image::Lock(const LayoutDeviceIntRegion& aRegion)
32 : {
33 0 : gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
34 0 : gfx::IntSize size(bounds.XMost(), bounds.YMost());
35 :
36 0 : if (!mWindowSurface || mWindowSurface->CairoStatus() ||
37 0 : !(size <= mWindowSurface->GetSize())) {
38 0 : mWindowSurface = new gfxXlibSurface(mDisplay, mWindow, mVisual, size);
39 : }
40 0 : if (mWindowSurface->CairoStatus()) {
41 0 : return nullptr;
42 : }
43 :
44 0 : if (!mImageSurface || mImageSurface->CairoStatus() ||
45 0 : !(size <= mImageSurface->GetSize())) {
46 0 : gfxImageFormat format = SurfaceFormatToImageFormat(mFormat);
47 0 : if (format == gfx::SurfaceFormat::UNKNOWN) {
48 0 : format = mDepth == 32 ?
49 : gfx::SurfaceFormat::A8R8G8B8_UINT32 :
50 : gfx::SurfaceFormat::X8R8G8B8_UINT32;
51 : }
52 :
53 0 : mImageSurface = new gfxImageSurface(size, format);
54 0 : if (mImageSurface->CairoStatus()) {
55 0 : return nullptr;
56 : }
57 : }
58 :
59 0 : gfxImageFormat format = mImageSurface->Format();
60 : // Cairo prefers compositing to BGRX instead of BGRA where possible.
61 0 : if (format == gfx::SurfaceFormat::X8R8G8B8_UINT32) {
62 0 : gfx::BackendType backend = gfxVars::ContentBackend();
63 0 : if (!gfx::Factory::DoesBackendSupportDataDrawtarget(backend)) {
64 : #ifdef USE_SKIA
65 0 : backend = gfx::BackendType::SKIA;
66 : #else
67 : backend = gfx::BackendType::CAIRO;
68 : #endif
69 : }
70 0 : if (backend != gfx::BackendType::CAIRO) {
71 0 : format = gfx::SurfaceFormat::A8R8G8B8_UINT32;
72 : }
73 : }
74 :
75 : return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(),
76 0 : mImageSurface->GetSize(),
77 : mImageSurface->Stride(),
78 0 : ImageFormatToSurfaceFormat(format));
79 : }
80 :
81 : void
82 0 : WindowSurfaceX11Image::Commit(const LayoutDeviceIntRegion& aInvalidRegion)
83 : {
84 : RefPtr<gfx::DrawTarget> dt =
85 0 : gfx::Factory::CreateDrawTargetForCairoSurface(mWindowSurface->CairoSurface(),
86 0 : mWindowSurface->GetSize());
87 : RefPtr<gfx::SourceSurface> surf =
88 0 : gfx::Factory::CreateSourceSurfaceForCairoSurface(mImageSurface->CairoSurface(),
89 0 : mImageSurface->GetSize(),
90 0 : mImageSurface->Format());
91 0 : if (!dt || !surf) {
92 0 : return;
93 : }
94 :
95 0 : gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect();
96 0 : gfx::Rect rect(0, 0, bounds.XMost(), bounds.YMost());
97 0 : if (rect.IsEmpty()) {
98 0 : return;
99 : }
100 :
101 0 : uint32_t numRects = aInvalidRegion.GetNumRects();
102 0 : if (numRects != 1) {
103 0 : AutoTArray<IntRect, 32> rects;
104 0 : rects.SetCapacity(numRects);
105 0 : for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
106 0 : rects.AppendElement(iter.Get().ToUnknownRect());
107 : }
108 0 : dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length());
109 : }
110 :
111 0 : dt->DrawSurface(surf, rect, rect);
112 :
113 0 : if (numRects != 1) {
114 0 : dt->PopClip();
115 : }
116 : }
117 :
118 : } // namespace widget
119 : } // namespace mozilla
|