1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#include "SurfaceState.hpp"
#include "helpers/Format.hpp"
#include "protocols/types/Buffer.hpp"
#include "render/Renderer.hpp"
#include "render/Texture.hpp"
Vector2D SSurfaceState::sourceSize() {
if UNLIKELY (!texture)
return {};
if UNLIKELY (viewport.hasSource)
return viewport.source.size();
Vector2D trc = transform % 2 == 1 ? Vector2D{bufferSize.y, bufferSize.x} : bufferSize;
return trc / scale;
}
CRegion SSurfaceState::accumulateBufferDamage() {
if (damage.empty())
return bufferDamage;
CRegion surfaceDamage = damage;
if (viewport.hasDestination) {
Vector2D scale = sourceSize() / viewport.destination;
surfaceDamage.scale(scale);
}
if (viewport.hasSource)
surfaceDamage.translate(viewport.source.pos());
Vector2D trc = transform % 2 == 1 ? Vector2D{bufferSize.y, bufferSize.x} : bufferSize;
bufferDamage = surfaceDamage.scale(scale).transform(Math::wlTransformToHyprutils(Math::invertTransform(transform)), trc.x, trc.y).add(bufferDamage);
damage.clear();
return bufferDamage;
}
void SSurfaceState::updateSynchronousTexture(SP<Render::ITexture> lastTexture) {
auto [dataPtr, fmt, size] = buffer->beginDataPtr(0);
if (dataPtr) {
auto drmFmt = NFormatUtils::shmToDRM(fmt);
auto stride = bufferSize.y ? size / bufferSize.y : 0;
if (lastTexture && lastTexture->m_isSynchronous && lastTexture->m_size == bufferSize) {
texture = lastTexture;
texture->update(drmFmt, dataPtr, stride, accumulateBufferDamage());
} else
texture = g_pHyprRenderer->createTexture(drmFmt, dataPtr, stride, bufferSize);
}
buffer->endDataPtr();
}
void SSurfaceState::reset() {
updated.all = false;
// After commit, there is no pending buffer until the next attach.
buffer = {};
// applies only to the buffer that is attached to the surface
acquire = {};
// wl_surface.commit assigns pending ... and clears pending damage.
damage.clear();
bufferDamage.clear();
callbacks.clear();
lockMask = LOCK_REASON_NONE;
barrierSet = false;
surfaceLocked = false;
fifoScheduled = false;
pendingTimeout.reset();
timer.reset(); // CEventLoopManager::nudgeTimers should handle it eventually
}
void SSurfaceState::updateFrom(SSurfaceState& ref) {
updated = ref.updated;
if (ref.updated.bits.buffer) {
buffer = ref.buffer;
texture = ref.texture;
size = ref.size;
bufferSize = ref.bufferSize;
}
if (ref.updated.bits.damage) {
damage = ref.damage;
bufferDamage = ref.bufferDamage;
} else {
// damage is always relative to the current commit
damage.clear();
bufferDamage.clear();
}
if (ref.updated.bits.input)
input = ref.input;
if (ref.updated.bits.opaque)
opaque = ref.opaque;
if (ref.updated.bits.offset)
offset = ref.offset;
if (ref.updated.bits.scale)
scale = ref.scale;
if (ref.updated.bits.transform)
transform = ref.transform;
if (ref.updated.bits.viewport)
viewport = ref.viewport;
if (ref.updated.bits.acquire)
acquire = ref.acquire;
if (ref.updated.bits.acked)
ackedSize = ref.ackedSize;
if (ref.updated.bits.frame) {
callbacks.insert(callbacks.end(), std::make_move_iterator(ref.callbacks.begin()), std::make_move_iterator(ref.callbacks.end()));
ref.callbacks.clear();
}
if (ref.barrierSet)
barrierSet = ref.barrierSet;
}
|