Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandshmbackingstore.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
#
include
"qwaylandshmbackingstore_p.h"
4
#
include
"qwaylandwindow_p.h"
5
#
include
"qwaylandsubsurface_p.h"
6
#
include
"qwaylanddisplay_p.h"
7
#
include
"qwaylandscreen_p.h"
8
#
include
"qwaylandabstractdecoration_p.h"
9
10
#
include
<
QtCore
/
qdebug
.
h
>
11
#
include
<
QtCore
/
qstandardpaths
.
h
>
12
#
include
<
QtCore
/
qtemporaryfile
.
h
>
13
#
include
<
QtGui
/
QPainter
>
14
#
include
<
QtGui
/
QTransform
>
15
#
include
<
QMutexLocker
>
16
17
#
include
<
QtWaylandClient
/
private
/
wayland
-
wayland
-
client
-
protocol
.
h
>
18
19
#
include
<
memory
>
20
21
#
include
<
fcntl
.
h
>
22
#
include
<
unistd
.
h
>
23
#
include
<
sys
/
mman
.
h
>
24
25
#
ifdef
Q_OS_LINUX
26
#
include
<
sys
/
syscall
.
h
>
27
// from linux/memfd.h:
28
#
ifndef
MFD_CLOEXEC
29
#
define
MFD_CLOEXEC
0x0001U
30
#
endif
31
#
ifndef
MFD_ALLOW_SEALING
32
#
define
MFD_ALLOW_SEALING
0x0002U
33
#
endif
34
// from bits/fcntl-linux.h
35
#
ifndef
F_ADD_SEALS
36
#
define
F_ADD_SEALS
1033
37
#
endif
38
#
ifndef
F_SEAL_SEAL
39
#
define
F_SEAL_SEAL
0x0001
40
#
endif
41
#
ifndef
F_SEAL_SHRINK
42
#
define
F_SEAL_SHRINK
0x0002
43
#
endif
44
#
endif
45
46
QT_BEGIN_NAMESPACE
47
48
extern
void
qt_scrollRectInImage
(QImage &,
const
QRect &,
const
QPoint &);
49
50
namespace
QtWaylandClient
{
51
52
QWaylandShmBuffer
::
QWaylandShmBuffer
(
QWaylandDisplay
*
display
,
53
const
QSize
&
size
,
QImage
::
Format
format
,
qreal
scale
,
wl_event_queue
*
customEventQueue
)
54
:
mDirtyRegion
(
QRect
(
QPoint
(0, 0),
size
/
scale
))
55
{
56
int
stride
=
size
.
width
() * 4;
57
int
alloc
=
stride
*
size
.
height
();
58
int
fd
= -1;
59
60
#
ifdef
SYS_memfd_create
61
fd
=
syscall
(
SYS_memfd_create
,
"wayland-shm"
,
MFD_CLOEXEC
|
MFD_ALLOW_SEALING
);
62
if
(
fd
>= 0)
63
fcntl
(
fd
,
F_ADD_SEALS
,
F_SEAL_SHRINK
|
F_SEAL_SEAL
);
64
#
endif
65
66
std
::
unique_ptr
<
QFile
>
filePointer
;
67
bool
opened
;
68
69
if
(
fd
== -1) {
70
auto
tmpFile
=
71
std
::
make_unique
<
QTemporaryFile
>(
QStandardPaths
::
writableLocation
(
QStandardPaths
::
RuntimeLocation
) +
72
QLatin1String
(
"/wayland-shm-XXXXXX"
));
73
opened
=
tmpFile
->
open
();
74
filePointer
=
std
::
move
(
tmpFile
);
75
}
else
{
76
auto
file
=
std
::
make_unique
<
QFile
>();
77
opened
=
file
->
open
(
fd
,
QIODevice
::
ReadWrite
|
QIODevice
::
Unbuffered
,
QFile
::
AutoCloseHandle
);
78
filePointer
=
std
::
move
(
file
);
79
}
80
// NOTE beginPaint assumes a new buffer be all zeroes, which QFile::resize does.
81
if
(!
opened
|| !
filePointer
->
resize
(
alloc
)) {
82
qWarning
(
"QWaylandShmBuffer: failed: %s"
,
qUtf8Printable
(
filePointer
->
errorString
()));
83
return
;
84
}
85
fd
=
filePointer
->
handle
();
86
87
// map ourselves: QFile::map() will unmap when the object is destroyed,
88
// but we want this mapping to persist (unmapping in destructor)
89
uchar
*
data
= (
uchar
*)
90
mmap
(
nullptr
,
alloc
, PROT_READ | PROT_WRITE, MAP_SHARED,
fd
, 0);
91
if
(
data
== (
uchar
*)
MAP_FAILED
) {
92
qErrnoWarning
(
"QWaylandShmBuffer: mmap failed"
);
93
return
;
94
}
95
96
QWaylandShm
*
shm
=
display
->
shm
();
97
wl_shm_format
wl_format
=
shm
->
formatFrom
(
format
);
98
mImage
=
QImage
(
data
,
size
.
width
(),
size
.
height
(),
stride
,
format
);
99
mImage
.
setDevicePixelRatio
(
scale
);
100
101
mShmPool
=
wl_shm_create_pool
(
shm
->
object
(),
fd
,
alloc
);
102
init
(
wl_shm_pool_create_buffer
(
mShmPool
,0,
size
.
width
(),
size
.
height
(),
103
stride
,
wl_format
));
104
if
(
customEventQueue
)
105
wl_proxy_set_queue
(
reinterpret_cast
<
struct
wl_proxy
*>(
buffer
()),
customEventQueue
);
106
}
107
108
QWaylandShmBuffer
::~
QWaylandShmBuffer
(
void
)
109
{
110
delete
mMarginsImage
;
111
if
(
mImage
.
constBits
())
112
munmap
((
void
*)
mImage
.
constBits
(),
mImage
.
sizeInBytes
());
113
if
(
mShmPool
)
114
wl_shm_pool_destroy
(
mShmPool
);
115
}
116
117
QImage
*
QWaylandShmBuffer
::
imageInsideMargins
(
const
QMargins
&
marginsIn
)
118
{
119
QMargins
margins
=
marginsIn
*
mImage
.
devicePixelRatio
();
120
121
if
(!
margins
.
isNull
() &&
margins
!=
mMargins
) {
122
if
(
mMarginsImage
) {
123
delete
mMarginsImage
;
124
}
125
uchar
*
bits
=
const_cast
<
uchar
*>(
mImage
.
constBits
());
126
uchar
*
b_s_data
=
bits
+
margins
.
top
() *
mImage
.
bytesPerLine
() +
margins
.
left
() * 4;
127
int
b_s_width
=
mImage
.
size
().
width
() -
margins
.
left
() -
margins
.
right
();
128
int
b_s_height
=
mImage
.
size
().
height
() -
margins
.
top
() -
margins
.
bottom
();
129
mMarginsImage
=
new
QImage
(
b_s_data
,
b_s_width
,
b_s_height
,
mImage
.
bytesPerLine
(),
mImage
.
format
());
130
mMarginsImage
->
setDevicePixelRatio
(
mImage
.
devicePixelRatio
());
131
}
132
if
(
margins
.
isNull
()) {
133
delete
mMarginsImage
;
134
mMarginsImage
=
nullptr
;
135
}
136
137
mMargins
=
margins
;
138
if
(!
mMarginsImage
)
139
return
&
mImage
;
140
141
return
mMarginsImage
;
142
143
}
144
145
QWaylandShmBackingStore
::
QWaylandShmBackingStore
(
QWindow
*
window
,
QWaylandDisplay
*
display
)
146
:
QPlatformBackingStore
(
window
)
147
,
mDisplay
(
display
)
148
{
149
mEventQueue
=
wl_display_create_queue
(
mDisplay
->
wl_display
());
150
QObject
::
connect
(
mDisplay
, &
QWaylandDisplay
::
connected
,
window
, [
this
]() {
151
auto
oldEventQueue
=
mEventQueue
;
152
mEventQueue
=
wl_display_create_queue
(
mDisplay
->
wl_display
());
153
auto
copy
=
mBuffers
;
154
// clear available buffers so we create new ones
155
// actual deletion is deferred till after resize call so we can copy
156
// contents from the back buffer
157
mBuffers
.
clear
();
158
mFrontBuffer
=
nullptr
;
159
// recreateBackBufferIfNeeded always resets mBackBuffer
160
if
(
mRequestedSize
.
isValid
() &&
waylandWindow
())
161
recreateBackBufferIfNeeded
();
162
else
163
mBackBuffer
=
nullptr
;
164
qDeleteAll
(
copy
);
165
wl_event_queue_destroy
(
oldEventQueue
);
166
});
167
}
168
169
QWaylandShmBackingStore
::~
QWaylandShmBackingStore
()
170
{
171
if
(
QWaylandWindow
*
w
=
waylandWindow
())
172
w
->
setBackingStore
(
nullptr
);
173
174
// if (mFrontBuffer == waylandWindow()->attached())
175
// waylandWindow()->attach(0);
176
177
qDeleteAll
(
mBuffers
);
178
wl_event_queue_destroy
(
mEventQueue
);
179
}
180
181
QPaintDevice
*
QWaylandShmBackingStore
::
paintDevice
()
182
{
183
return
contentSurface
();
184
}
185
186
void
QWaylandShmBackingStore
::
updateDirtyStates
(
const
QRegion
&
region
)
187
{
188
// Update dirty state of buffers based on what was painted. The back buffer will be
189
// less dirty, since we painted to it, while other buffers will become more dirty.
190
// This allows us to minimize copies between front and back buffers on swap in the
191
// cases where the painted region overlaps with the previous frame (front buffer).
192
for
(
QWaylandShmBuffer
*
b
:
std
::
as_const
(
mBuffers
)) {
193
if
(
b
!=
mBackBuffer
)
194
b
->
dirtyRegion
() +=
region
;
195
else
196
b
->
dirtyRegion
() -=
region
;
197
}
198
}
199
200
void
QWaylandShmBackingStore
::
beginPaint
(
const
QRegion
&
region
)
201
{
202
mPainting
=
true
;
203
waylandWindow
()->
setBackingStore
(
this
);
204
205
const
QMargins
margins
=
windowDecorationMargins
();
206
const
QRegion
regionTranslated
=
region
.
translated
(
margins
.
left
(),
margins
.
top
());
207
const
bool
bufferWasRecreated
=
recreateBackBufferIfNeeded
();
208
updateDirtyStates
(
regionTranslated
);
209
210
// Although undocumented, QBackingStore::beginPaint expects the painted region
211
// to be cleared before use if the window has a surface format with an alpha.
212
// Fresh QWaylandShmBuffer are already cleared, so we don't need to clear those.
213
if
(!
bufferWasRecreated
&&
window
()->
format
().
hasAlpha
()) {
214
QPainter
p
(
paintDevice
());
215
p
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
216
const
QColor
blank
=
Qt
::
transparent
;
217
for
(
const
QRect
&
rect
:
region
)
218
p
.
fillRect
(
rect
,
blank
);
219
}
220
}
221
222
void
QWaylandShmBackingStore
::
endPaint
()
223
{
224
mPainting
=
false
;
225
if
(
mPendingFlush
)
226
flush
(
window
(),
mPendingRegion
,
QPoint
());
227
}
228
229
// Inspired by QCALayerBackingStore.
230
bool
QWaylandShmBackingStore
::
scroll
(
const
QRegion
&
region
,
int
dx
,
int
dy
)
231
{
232
if
(
Q_UNLIKELY
(!
mBackBuffer
))
233
return
false
;
234
235
const
qreal
devicePixelRatio
=
waylandWindow
()->
scale
();
236
237
// On Wayland, the window can have a device pixel ratio different from
238
// the window/screen, therefore we cannot rely on QHighDpi here, cf. QBackingStore::scroll.
239
// With fractional scaling we cannot easily scroll the existing pixels.
240
if
(!
qFuzzyIsNull
(
devicePixelRatio
-
static_cast
<
int
>(
devicePixelRatio
)))
241
return
false
;
242
243
recreateBackBufferIfNeeded
();
244
if
(!
mFrontBuffer
)
245
return
false
;
246
247
const
QPoint
scrollDelta
(
dx
,
dy
);
248
const
QMargins
margins
=
windowDecorationMargins
();
249
const
QRegion
adjustedRegion
=
region
.
translated
(
margins
.
left
(),
margins
.
top
());
250
251
const
QRegion
inPlaceRegion
=
adjustedRegion
-
mBackBuffer
->
dirtyRegion
();
252
const
QRegion
frontBufferRegion
=
adjustedRegion
-
inPlaceRegion
;
253
254
if
(!
inPlaceRegion
.
isEmpty
()) {
255
const
QRect
inPlaceBoundingRect
=
inPlaceRegion
.
boundingRect
();
256
const
QPoint
devicePixelDelta
=
scrollDelta
*
devicePixelRatio
;
257
258
qt_scrollRectInImage
(*
mBackBuffer
->
image
(),
259
QRect
(
inPlaceBoundingRect
.
topLeft
() *
devicePixelRatio
,
260
inPlaceBoundingRect
.
size
() *
devicePixelRatio
),
261
devicePixelDelta
);
262
}
263
264
if
(!
frontBufferRegion
.
isEmpty
()) {
265
QPainter
painter
(
mBackBuffer
->
image
());
266
painter
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
267
painter
.
scale
(
qreal
(1) /
devicePixelRatio
,
qreal
(1) /
devicePixelRatio
);
268
for
(
const
QRect
&
rect
:
frontBufferRegion
) {
269
QRect
sourceRect
(
rect
.
topLeft
() *
devicePixelRatio
,
270
rect
.
size
() *
devicePixelRatio
);
271
QRect
destinationRect
((
rect
.
topLeft
() +
scrollDelta
) *
devicePixelRatio
,
272
rect
.
size
() *
devicePixelRatio
);
273
painter
.
drawImage
(
destinationRect
, *
mFrontBuffer
->
image
(),
sourceRect
);
274
}
275
}
276
277
// We do not mark the source region as dirty, even though it technically has "moved".
278
// This matches the behavior of other backingstore implementations using qt_scrollRectInImage.
279
updateDirtyStates
(
adjustedRegion
.
translated
(
scrollDelta
));
280
281
return
true
;
282
}
283
284
void
QWaylandShmBackingStore
::
flush
(
QWindow
*
window
,
const
QRegion
&
region
,
const
QPoint
&
offset
)
285
{
286
// Invoked when the window is of type RasterSurface.
287
288
if
(
window
!=
this
->
window
()) {
289
auto
waylandWindow
=
static_cast
<
QWaylandWindow
*>(
window
->
handle
());
290
const
auto
scale
=
waylandWindow
->
scale
();
291
auto
newBuffer
=
new
QWaylandShmBuffer
(
292
mDisplay
,
window
->
size
() *
scale
,
mBackBuffer
->
image
()->
format
(),
293
mBackBuffer
->
image
()->
devicePixelRatio
());
294
newBuffer
->
setDeleteOnRelease
(
true
);
295
QRect
sourceRect
(
offset
*
scale
,
window
->
size
() *
scale
);
296
QPainter
painter
(
newBuffer
->
image
());
297
painter
.
drawImage
(
QPoint
(0, 0), *
mBackBuffer
->
image
(),
sourceRect
);
298
waylandWindow
->
safeCommit
(
newBuffer
,
region
);
299
return
;
300
}
301
302
if
(
mPainting
) {
303
mPendingRegion
|=
region
;
304
mPendingFlush
=
true
;
305
return
;
306
}
307
308
mPendingFlush
=
false
;
309
mPendingRegion
=
QRegion
();
310
311
if
(
windowDecoration
() &&
windowDecoration
()->
isDirty
())
312
updateDecorations
();
313
314
finalizeBackBuffer
();
315
316
mFrontBuffer
=
mBackBuffer
;
317
318
QMargins
margins
=
windowDecorationMargins
();
319
waylandWindow
()->
safeCommit
(
mFrontBuffer
,
region
.
translated
(
margins
.
left
(),
margins
.
top
()));
320
}
321
322
void
QWaylandShmBackingStore
::
resize
(
const
QSize
&
size
,
const
QRegion
&)
323
{
324
mRequestedSize
=
size
;
325
}
326
327
QWaylandShmBuffer
*
QWaylandShmBackingStore
::
getBuffer
(
const
QSize
&
size
,
bool
&
bufferWasRecreated
)
328
{
329
static
const
int
MAX_BUFFERS
= 5;
330
static
const
int
MAX_AGE
= 10 *
MAX_BUFFERS
;
331
bufferWasRecreated
=
false
;
332
333
// Prune buffers that have not been used in a while or with different size.
334
for
(
auto
i
=
mBuffers
.
size
() - 1;
i
>= 0; --
i
) {
335
QWaylandShmBuffer
*
buffer
=
mBuffers
[
i
];
336
if
(
buffer
->
age
() >
MAX_AGE
||
buffer
->
size
() !=
size
) {
337
mBuffers
.
removeAt
(
i
);
338
if
(
mBackBuffer
==
buffer
)
339
mBackBuffer
=
nullptr
;
340
if
(
mFrontBuffer
==
buffer
)
341
mFrontBuffer
=
nullptr
;
342
delete
buffer
;
343
}
344
}
345
346
QWaylandShmBuffer
*
buffer
=
nullptr
;
347
for
(
QWaylandShmBuffer
*
candidate
:
std
::
as_const
(
mBuffers
)) {
348
if
(
candidate
->
busy
())
349
continue
;
350
351
if
(!
buffer
||
candidate
->
age
() <
buffer
->
age
())
352
buffer
=
candidate
;
353
}
354
355
if
(
buffer
)
356
return
buffer
;
357
358
if
(
mBuffers
.
size
() <
MAX_BUFFERS
) {
359
QImage
::
Format
format
=
QImage
::
Format_ARGB32_Premultiplied
;
360
if
(!
waylandWindow
()->
format
().
hasAlpha
())
361
format
=
QImage
::
Format_RGB32
;
362
QWaylandShmBuffer
*
b
=
new
QWaylandShmBuffer
(
mDisplay
,
size
,
format
,
waylandWindow
()->
scale
(),
mEventQueue
);
363
bufferWasRecreated
=
true
;
364
mBuffers
.
push_front
(
b
);
365
return
b
;
366
}
367
return
nullptr
;
368
}
369
370
bool
QWaylandShmBackingStore
::
recreateBackBufferIfNeeded
()
371
{
372
wl_display_dispatch_queue_pending
(
mDisplay
->
wl_display
(),
mEventQueue
);
373
374
bool
bufferWasRecreated
=
false
;
375
QMargins
margins
=
windowDecorationMargins
();
376
qreal
scale
=
waylandWindow
()->
scale
();
377
const
QSize
sizeWithMargins
= (
mRequestedSize
+
QSize
(
margins
.
left
() +
margins
.
right
(),
margins
.
top
() +
margins
.
bottom
())) *
scale
;
378
379
// We look for a free buffer to draw into. If the buffer is not the last buffer we used,
380
// that is mBackBuffer, and the size is the same we copy the damaged content into the new
381
// buffer so that QPainter is happy to find the stuff it had drawn before. If the new
382
// buffer has a different size it needs to be redrawn completely anyway, and if the buffer
383
// is the same the stuff is there already.
384
// You can exercise the different codepaths with weston, switching between the gl and the
385
// pixman renderer. With the gl renderer release events are sent early so we can effectively
386
// run single buffered, while with the pixman renderer we have to use two.
387
QWaylandShmBuffer
*
buffer
=
getBuffer
(
sizeWithMargins
,
bufferWasRecreated
);
388
while
(!
buffer
) {
389
struct
::
wl_display
*
display
=
mDisplay
->
wl_display
();
390
if
(
wl_display_dispatch_queue
(
display
,
mEventQueue
) < 0) {
391
int
ecode
=
wl_display_get_error
(
display
);
392
if
((
ecode
==
EPIPE
||
ecode
==
ECONNRESET
))
393
qWarning
(
"The Wayland connection broke during blocking read event. Did the Wayland compositor die?"
);
394
else
395
qWarning
(
"The Wayland connection experienced a fatal error during blocking read event: %s"
,
strerror
(
ecode
));
396
_exit
(-1);
397
}
398
buffer
=
getBuffer
(
sizeWithMargins
,
bufferWasRecreated
);
399
}
400
401
qsizetype
oldSizeInBytes
=
mBackBuffer
?
mBackBuffer
->
image
()->
sizeInBytes
() : 0;
402
qsizetype
newSizeInBytes
=
buffer
->
image
()->
sizeInBytes
();
403
404
mBackBuffer
=
buffer
;
405
406
for
(
QWaylandShmBuffer
*
buffer
:
std
::
as_const
(
mBuffers
)) {
407
if
(
mBackBuffer
==
buffer
) {
408
buffer
->
setAge
(0);
409
}
else
{
410
buffer
->
setAge
(
buffer
->
age
() + 1);
411
}
412
}
413
414
if
(
windowDecoration
() &&
window
()->
isVisible
() &&
oldSizeInBytes
!=
newSizeInBytes
)
415
windowDecoration
()->
update
();
416
417
return
bufferWasRecreated
;
418
}
419
420
void
QWaylandShmBackingStore
::
finalizeBackBuffer
()
421
{
422
Q_ASSERT
(
mBackBuffer
);
423
424
const
QRegion
clipRegion
=
mBackBuffer
->
dirtyRegion
();
425
if
(
clipRegion
.
isEmpty
())
426
return
;
427
428
if
(
Q_UNLIKELY
(!
mFrontBuffer
||
mFrontBuffer
==
mBackBuffer
))
429
return
;
430
431
const
QImage
*
sourceImage
=
mFrontBuffer
->
image
();
432
QImage
*
targetImage
=
mBackBuffer
->
image
();
433
434
QPainter
painter
(
targetImage
);
435
painter
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
436
const
qreal
targetDevicePixelRatio
=
painter
.
device
()->
devicePixelRatio
();
437
const
auto
clipRects
=
clipRegion
.
rects
();
438
for
(
const
QRect
&
clipRect
:
clipRects
) {
// Iterate clip rects, because complicated clip region causes higher CPU usage
439
if
(
clipRects
.
size
() > 1)
440
painter
.
save
();
441
painter
.
setClipRect
(
clipRect
);
442
painter
.
scale
(
qreal
(1) /
targetDevicePixelRatio
,
qreal
(1) /
targetDevicePixelRatio
);
443
painter
.
drawImage
(
QRectF
(
QPointF
(),
targetImage
->
size
()), *
sourceImage
,
sourceImage
->
rect
());
444
if
(
clipRects
.
size
() > 1)
445
painter
.
restore
();
446
}
447
448
mBackBuffer
->
dirtyRegion
() =
QRegion
();
449
}
450
451
QImage
*
QWaylandShmBackingStore
::
entireSurface
()
const
452
{
453
return
mBackBuffer
->
image
();
454
}
455
456
QImage
*
QWaylandShmBackingStore
::
contentSurface
()
const
457
{
458
return
windowDecoration
() ?
mBackBuffer
->
imageInsideMargins
(
windowDecorationMargins
()) :
mBackBuffer
->
image
();
459
}
460
461
void
QWaylandShmBackingStore
::
updateDecorations
()
462
{
463
QPainter
decorationPainter
(
entireSurface
());
464
decorationPainter
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
465
QImage
sourceImage
=
windowDecoration
()->
contentImage
();
466
467
qreal
dp
=
sourceImage
.
devicePixelRatio
();
468
int
dpWidth
=
int
(
sourceImage
.
width
() /
dp
);
469
int
dpHeight
=
int
(
sourceImage
.
height
() /
dp
);
470
QTransform
sourceMatrix
;
471
sourceMatrix
.
scale
(
dp
,
dp
);
472
QRect
target
;
// needs to be in device independent pixels
473
QRegion
dirtyRegion
;
474
475
//Top
476
target
.
setX
(0);
477
target
.
setY
(0);
478
target
.
setWidth
(
dpWidth
);
479
target
.
setHeight
(
windowDecorationMargins
().
top
());
480
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
481
dirtyRegion
+=
target
;
482
483
//Left
484
target
.
setWidth
(
windowDecorationMargins
().
left
());
485
target
.
setHeight
(
dpHeight
);
486
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
487
dirtyRegion
+=
target
;
488
489
//Right
490
target
.
setX
(
dpWidth
-
windowDecorationMargins
().
right
());
491
target
.
setWidth
(
windowDecorationMargins
().
right
());
492
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
493
dirtyRegion
+=
target
;
494
495
//Bottom
496
target
.
setX
(0);
497
target
.
setY
(
dpHeight
-
windowDecorationMargins
().
bottom
());
498
target
.
setWidth
(
dpWidth
);
499
target
.
setHeight
(
windowDecorationMargins
().
bottom
());
500
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
501
dirtyRegion
+=
target
;
502
503
updateDirtyStates
(
dirtyRegion
);
504
}
505
506
QWaylandAbstractDecoration
*
QWaylandShmBackingStore
::
windowDecoration
()
const
507
{
508
return
waylandWindow
()->
decoration
();
509
}
510
511
QMargins
QWaylandShmBackingStore
::
windowDecorationMargins
()
const
512
{
513
if
(
windowDecoration
())
514
return
windowDecoration
()->
margins
();
515
return
QMargins
();
516
}
517
518
QWaylandWindow
*
QWaylandShmBackingStore
::
waylandWindow
()
const
519
{
520
return
static_cast
<
QWaylandWindow
*>(
window
()->
handle
());
521
}
522
523
#
if
QT_CONFIG
(
opengl
)
524
QImage
QWaylandShmBackingStore
::
toImage
()
const
525
{
526
// Invoked from QPlatformBackingStore::composeAndFlush() that is called
527
// instead of flush() for widgets that have renderToTexture children
528
// (QOpenGLWidget, QQuickWidget).
529
530
const_cast
<
QWaylandShmBackingStore
*>(
this
)->
finalizeBackBuffer
();
531
532
return
*
contentSurface
();
533
}
534
#
endif
// opengl
535
536
}
537
538
QT_END_NAMESPACE
QtWaylandClient
Definition
qwaylandclientextension.h:15
MAP_FAILED
#define MAP_FAILED
Definition
qresource.cpp:1159
qt_scrollRectInImage
QT_BEGIN_NAMESPACE void qt_scrollRectInImage(QImage &, const QRect &, const QPoint &)
Definition
qbackingstore.cpp:300
qtbase
src
plugins
platforms
wayland
qwaylandshmbackingstore.cpp
Generated on
for Qt by
1.14.0