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
use super::SwRenderer;
use super::blit_fast::{blit_1to1_fast, blit_2to2_fast, blit_dda};
use crate::render::texture::Texture;
use crate::types::{Point, Rect};
impl SwRenderer<'_> {
pub(super) fn blit_inner(
&mut self,
src: &Texture,
src_rect: &Rect,
dst: Point,
dst_size: Point,
clip: &Rect,
opa: u8,
) {
let phys_dst = self.viewport.point_to_physical(dst);
let phys_dst_size = self.viewport.point_to_physical(dst_size);
let phys_clip = self.viewport.rect_to_physical(*clip);
let (sx0, sy0, sw, sh) = src_rect.to_px();
// Negative clip x flowing through to the byte-offset math
// (`dx0 as usize * 4`) wraps; clamp to target bounds first.
let target_w = self.target.width as i32;
let target_h = self.target.height as i32;
let (raw_x0, raw_y0, raw_x1, raw_y1) = phys_clip.pixel_bounds();
let clip_x0 = raw_x0.max(0);
let clip_y0 = raw_y0.max(0);
let clip_x1 = raw_x1.min(target_w);
let clip_y1 = raw_y1.min(target_h);
let dx0 = phys_dst.x.to_int();
let dy0 = phys_dst.y.to_int();
let dw = phys_dst_size.x.to_int();
let dh = phys_dst_size.y.to_int();
if dw <= 0 || dh <= 0 || sw == 0 || sh == 0 {
return;
}
if opa == 0 {
return;
}
// opa < 255 → bypass per-format fast paths and go through the
// per-pixel DDA so the alpha gets folded into each blend; the
// fast paths' memcpy-ish row copies have no per-pixel hook.
if opa < 255 {
blit_dda(
&mut self.target,
src,
sx0,
sy0,
sw,
sh,
dx0,
dy0,
dw,
dh,
clip_x0,
clip_y0,
clip_x1,
clip_y1,
opa,
);
return;
}
let sw_i = sw as i32;
let sh_i = sh as i32;
// 1× → format-specialized 1to1 fast path; 2× → 2to2; arbitrary → DDA.
#[allow(clippy::if_same_then_else)]
if dw == sw_i && dh == sh_i {
blit_1to1_fast(
&mut self.target,
src,
sx0,
sy0,
sw,
sh,
dx0,
dy0,
clip_x0,
clip_y0,
clip_x1,
clip_y1,
);
} else if dw == sw_i * 2 && dh == sh_i * 2 {
blit_2to2_fast(
&mut self.target,
src,
sx0,
sy0,
sw,
sh,
dx0,
dy0,
clip_x0,
clip_y0,
clip_x1,
clip_y1,
);
} else {
blit_dda(
&mut self.target,
src,
sx0,
sy0,
sw,
sh,
dx0,
dy0,
dw,
dh,
clip_x0,
clip_y0,
clip_x1,
clip_y1,
255,
);
}
}
}