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
|| !
mFrontBuffer
))
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
245
const
QPoint
scrollDelta
(
dx
,
dy
);
246
const
QMargins
margins
=
windowDecorationMargins
();
247
const
QRegion
adjustedRegion
=
region
.
translated
(
margins
.
left
(),
margins
.
top
());
248
249
const
QRegion
inPlaceRegion
=
adjustedRegion
-
mBackBuffer
->
dirtyRegion
();
250
const
QRegion
frontBufferRegion
=
adjustedRegion
-
inPlaceRegion
;
251
252
if
(!
inPlaceRegion
.
isEmpty
()) {
253
const
QRect
inPlaceBoundingRect
=
inPlaceRegion
.
boundingRect
();
254
const
QPoint
devicePixelDelta
=
scrollDelta
*
devicePixelRatio
;
255
256
qt_scrollRectInImage
(*
mBackBuffer
->
image
(),
257
QRect
(
inPlaceBoundingRect
.
topLeft
() *
devicePixelRatio
,
258
inPlaceBoundingRect
.
size
() *
devicePixelRatio
),
259
devicePixelDelta
);
260
}
261
262
if
(!
frontBufferRegion
.
isEmpty
()) {
263
QPainter
painter
(
mBackBuffer
->
image
());
264
painter
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
265
painter
.
scale
(
qreal
(1) /
devicePixelRatio
,
qreal
(1) /
devicePixelRatio
);
266
for
(
const
QRect
&
rect
:
frontBufferRegion
) {
267
QRect
sourceRect
(
rect
.
topLeft
() *
devicePixelRatio
,
268
rect
.
size
() *
devicePixelRatio
);
269
QRect
destinationRect
((
rect
.
topLeft
() +
scrollDelta
) *
devicePixelRatio
,
270
rect
.
size
() *
devicePixelRatio
);
271
painter
.
drawImage
(
destinationRect
, *
mFrontBuffer
->
image
(),
sourceRect
);
272
}
273
}
274
275
// We do not mark the source region as dirty, even though it technically has "moved".
276
// This matches the behavior of other backingstore implementations using qt_scrollRectInImage.
277
updateDirtyStates
(
adjustedRegion
.
translated
(
scrollDelta
));
278
279
return
true
;
280
}
281
282
void
QWaylandShmBackingStore
::
flush
(
QWindow
*
window
,
const
QRegion
&
region
,
const
QPoint
&
offset
)
283
{
284
// Invoked when the window is of type RasterSurface.
285
286
if
(
window
!=
this
->
window
()) {
287
auto
waylandWindow
=
static_cast
<
QWaylandWindow
*>(
window
->
handle
());
288
const
auto
scale
=
waylandWindow
->
scale
();
289
auto
newBuffer
=
new
QWaylandShmBuffer
(
290
mDisplay
,
window
->
size
() *
scale
,
mBackBuffer
->
image
()->
format
(),
291
mBackBuffer
->
image
()->
devicePixelRatio
());
292
newBuffer
->
setDeleteOnRelease
(
true
);
293
QRect
sourceRect
(
offset
*
scale
,
window
->
size
() *
scale
);
294
QPainter
painter
(
newBuffer
->
image
());
295
painter
.
drawImage
(
QPoint
(0, 0), *
mBackBuffer
->
image
(),
sourceRect
);
296
waylandWindow
->
safeCommit
(
newBuffer
,
region
);
297
return
;
298
}
299
300
if
(
mPainting
) {
301
mPendingRegion
|=
region
;
302
mPendingFlush
=
true
;
303
return
;
304
}
305
306
mPendingFlush
=
false
;
307
mPendingRegion
=
QRegion
();
308
309
if
(
windowDecoration
() &&
windowDecoration
()->
isDirty
())
310
updateDecorations
();
311
312
finalizeBackBuffer
();
313
314
mFrontBuffer
=
mBackBuffer
;
315
316
QMargins
margins
=
windowDecorationMargins
();
317
waylandWindow
()->
safeCommit
(
mFrontBuffer
,
region
.
translated
(
margins
.
left
(),
margins
.
top
()));
318
}
319
320
void
QWaylandShmBackingStore
::
resize
(
const
QSize
&
size
,
const
QRegion
&)
321
{
322
mRequestedSize
=
size
;
323
}
324
325
QWaylandShmBuffer
*
QWaylandShmBackingStore
::
getBuffer
(
const
QSize
&
size
,
bool
&
bufferWasRecreated
)
326
{
327
static
const
int
MAX_BUFFERS
= 5;
328
static
const
int
MAX_AGE
= 10 *
MAX_BUFFERS
;
329
bufferWasRecreated
=
false
;
330
331
// Prune buffers that have not been used in a while or with different size.
332
for
(
auto
i
=
mBuffers
.
size
() - 1;
i
>= 0; --
i
) {
333
QWaylandShmBuffer
*
buffer
=
mBuffers
[
i
];
334
if
(
buffer
->
age
() >
MAX_AGE
||
buffer
->
size
() !=
size
) {
335
mBuffers
.
removeAt
(
i
);
336
if
(
mBackBuffer
==
buffer
)
337
mBackBuffer
=
nullptr
;
338
if
(
mFrontBuffer
==
buffer
)
339
mFrontBuffer
=
nullptr
;
340
delete
buffer
;
341
}
342
}
343
344
QWaylandShmBuffer
*
buffer
=
nullptr
;
345
for
(
QWaylandShmBuffer
*
candidate
:
std
::
as_const
(
mBuffers
)) {
346
if
(
candidate
->
busy
())
347
continue
;
348
349
if
(!
buffer
||
candidate
->
age
() <
buffer
->
age
())
350
buffer
=
candidate
;
351
}
352
353
if
(
buffer
)
354
return
buffer
;
355
356
if
(
mBuffers
.
size
() <
MAX_BUFFERS
) {
357
QImage
::
Format
format
=
QImage
::
Format_ARGB32_Premultiplied
;
358
if
(!
waylandWindow
()->
format
().
hasAlpha
())
359
format
=
QImage
::
Format_RGB32
;
360
QWaylandShmBuffer
*
b
=
new
QWaylandShmBuffer
(
mDisplay
,
size
,
format
,
waylandWindow
()->
scale
(),
mEventQueue
);
361
bufferWasRecreated
=
true
;
362
mBuffers
.
push_front
(
b
);
363
return
b
;
364
}
365
return
nullptr
;
366
}
367
368
bool
QWaylandShmBackingStore
::
recreateBackBufferIfNeeded
()
369
{
370
wl_display_dispatch_queue_pending
(
mDisplay
->
wl_display
(),
mEventQueue
);
371
372
bool
bufferWasRecreated
=
false
;
373
QMargins
margins
=
windowDecorationMargins
();
374
qreal
scale
=
waylandWindow
()->
scale
();
375
const
QSize
sizeWithMargins
= (
mRequestedSize
+
QSize
(
margins
.
left
() +
margins
.
right
(),
margins
.
top
() +
margins
.
bottom
())) *
scale
;
376
377
// We look for a free buffer to draw into. If the buffer is not the last buffer we used,
378
// that is mBackBuffer, and the size is the same we copy the damaged content into the new
379
// buffer so that QPainter is happy to find the stuff it had drawn before. If the new
380
// buffer has a different size it needs to be redrawn completely anyway, and if the buffer
381
// is the same the stuff is there already.
382
// You can exercise the different codepaths with weston, switching between the gl and the
383
// pixman renderer. With the gl renderer release events are sent early so we can effectively
384
// run single buffered, while with the pixman renderer we have to use two.
385
QWaylandShmBuffer
*
buffer
=
getBuffer
(
sizeWithMargins
,
bufferWasRecreated
);
386
while
(!
buffer
) {
387
struct
::
wl_display
*
display
=
mDisplay
->
wl_display
();
388
if
(
wl_display_dispatch_queue
(
display
,
mEventQueue
) < 0) {
389
int
ecode
=
wl_display_get_error
(
display
);
390
if
((
ecode
==
EPIPE
||
ecode
==
ECONNRESET
))
391
qWarning
(
"The Wayland connection broke during blocking read event. Did the Wayland compositor die?"
);
392
else
393
qWarning
(
"The Wayland connection experienced a fatal error during blocking read event: %s"
,
strerror
(
ecode
));
394
_exit
(-1);
395
}
396
buffer
=
getBuffer
(
sizeWithMargins
,
bufferWasRecreated
);
397
}
398
399
qsizetype
oldSizeInBytes
=
mBackBuffer
?
mBackBuffer
->
image
()->
sizeInBytes
() : 0;
400
qsizetype
newSizeInBytes
=
buffer
->
image
()->
sizeInBytes
();
401
402
mBackBuffer
=
buffer
;
403
404
for
(
QWaylandShmBuffer
*
buffer
:
std
::
as_const
(
mBuffers
)) {
405
if
(
mBackBuffer
==
buffer
) {
406
buffer
->
setAge
(0);
407
}
else
{
408
buffer
->
setAge
(
buffer
->
age
() + 1);
409
}
410
}
411
412
if
(
windowDecoration
() &&
window
()->
isVisible
() &&
oldSizeInBytes
!=
newSizeInBytes
)
413
windowDecoration
()->
update
();
414
415
return
bufferWasRecreated
;
416
}
417
418
void
QWaylandShmBackingStore
::
finalizeBackBuffer
()
419
{
420
Q_ASSERT
(
mBackBuffer
);
421
422
const
QRegion
clipRegion
=
mBackBuffer
->
dirtyRegion
();
423
if
(
clipRegion
.
isEmpty
())
424
return
;
425
426
if
(
Q_UNLIKELY
(!
mFrontBuffer
||
mFrontBuffer
==
mBackBuffer
))
427
return
;
428
429
const
QImage
*
sourceImage
=
mFrontBuffer
->
image
();
430
QImage
*
targetImage
=
mBackBuffer
->
image
();
431
432
QPainter
painter
(
targetImage
);
433
painter
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
434
const
qreal
targetDevicePixelRatio
=
painter
.
device
()->
devicePixelRatio
();
435
const
auto
clipRects
=
clipRegion
.
rects
();
436
for
(
const
QRect
&
clipRect
:
clipRects
) {
// Iterate clip rects, because complicated clip region causes higher CPU usage
437
if
(
clipRects
.
size
() > 1)
438
painter
.
save
();
439
painter
.
setClipRect
(
clipRect
);
440
painter
.
scale
(
qreal
(1) /
targetDevicePixelRatio
,
qreal
(1) /
targetDevicePixelRatio
);
441
painter
.
drawImage
(
QRectF
(
QPointF
(),
targetImage
->
size
()), *
sourceImage
,
sourceImage
->
rect
());
442
if
(
clipRects
.
size
() > 1)
443
painter
.
restore
();
444
}
445
446
mBackBuffer
->
dirtyRegion
() =
QRegion
();
447
}
448
449
QImage
*
QWaylandShmBackingStore
::
entireSurface
()
const
450
{
451
return
mBackBuffer
->
image
();
452
}
453
454
QImage
*
QWaylandShmBackingStore
::
contentSurface
()
const
455
{
456
return
windowDecoration
() ?
mBackBuffer
->
imageInsideMargins
(
windowDecorationMargins
()) :
mBackBuffer
->
image
();
457
}
458
459
void
QWaylandShmBackingStore
::
updateDecorations
()
460
{
461
QPainter
decorationPainter
(
entireSurface
());
462
decorationPainter
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
463
QImage
sourceImage
=
windowDecoration
()->
contentImage
();
464
465
qreal
dp
=
sourceImage
.
devicePixelRatio
();
466
int
dpWidth
=
int
(
sourceImage
.
width
() /
dp
);
467
int
dpHeight
=
int
(
sourceImage
.
height
() /
dp
);
468
QTransform
sourceMatrix
;
469
sourceMatrix
.
scale
(
dp
,
dp
);
470
QRect
target
;
// needs to be in device independent pixels
471
QRegion
dirtyRegion
;
472
473
//Top
474
target
.
setX
(0);
475
target
.
setY
(0);
476
target
.
setWidth
(
dpWidth
);
477
target
.
setHeight
(
windowDecorationMargins
().
top
());
478
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
479
dirtyRegion
+=
target
;
480
481
//Left
482
target
.
setWidth
(
windowDecorationMargins
().
left
());
483
target
.
setHeight
(
dpHeight
);
484
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
485
dirtyRegion
+=
target
;
486
487
//Right
488
target
.
setX
(
dpWidth
-
windowDecorationMargins
().
right
());
489
target
.
setWidth
(
windowDecorationMargins
().
right
());
490
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
491
dirtyRegion
+=
target
;
492
493
//Bottom
494
target
.
setX
(0);
495
target
.
setY
(
dpHeight
-
windowDecorationMargins
().
bottom
());
496
target
.
setWidth
(
dpWidth
);
497
target
.
setHeight
(
windowDecorationMargins
().
bottom
());
498
decorationPainter
.
drawImage
(
target
,
sourceImage
,
sourceMatrix
.
mapRect
(
target
));
499
dirtyRegion
+=
target
;
500
501
updateDirtyStates
(
dirtyRegion
);
502
}
503
504
QWaylandAbstractDecoration
*
QWaylandShmBackingStore
::
windowDecoration
()
const
505
{
506
return
waylandWindow
()->
decoration
();
507
}
508
509
QMargins
QWaylandShmBackingStore
::
windowDecorationMargins
()
const
510
{
511
if
(
windowDecoration
())
512
return
windowDecoration
()->
margins
();
513
return
QMargins
();
514
}
515
516
QWaylandWindow
*
QWaylandShmBackingStore
::
waylandWindow
()
const
517
{
518
return
static_cast
<
QWaylandWindow
*>(
window
()->
handle
());
519
}
520
521
#
if
QT_CONFIG
(
opengl
)
522
QImage
QWaylandShmBackingStore
::
toImage
()
const
523
{
524
// Invoked from QPlatformBackingStore::composeAndFlush() that is called
525
// instead of flush() for widgets that have renderToTexture children
526
// (QOpenGLWidget, QQuickWidget).
527
528
const_cast
<
QWaylandShmBackingStore
*>(
this
)->
finalizeBackBuffer
();
529
530
return
*
contentSurface
();
531
}
532
#
endif
// opengl
533
534
}
535
536
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