@@ -53,6 +53,10 @@ void ati_2d_blt(ATIVGAState *s)
53
53
s -> vga .vbe_start_addr , surface_data (ds ), surface_stride (ds ),
54
54
surface_bits_per_pixel (ds ),
55
55
(s -> regs .dp_mix & GMC_ROP3_MASK ) >> 16 );
56
+ int dst_x = (s -> regs .dp_cntl & DST_X_LEFT_TO_RIGHT ?
57
+ s -> regs .dst_x : s -> regs .dst_x + 1 - s -> regs .dst_width );
58
+ int dst_y = (s -> regs .dp_cntl & DST_Y_TOP_TO_BOTTOM ?
59
+ s -> regs .dst_y : s -> regs .dst_y + 1 - s -> regs .dst_height );
56
60
int bpp = ati_bpp_from_datatype (s );
57
61
int dst_stride = DEFAULT_CNTL ? s -> regs .dst_pitch : s -> regs .default_pitch ;
58
62
uint8_t * dst_bits = s -> vga .vram_ptr + (DEFAULT_CNTL ?
@@ -63,20 +67,25 @@ void ati_2d_blt(ATIVGAState *s)
63
67
dst_stride *= bpp ;
64
68
}
65
69
uint8_t * end = s -> vga .vram_ptr + s -> vga .vram_size ;
66
- if (dst_bits >= end ||
67
- dst_bits + s -> regs .dst_x + (s -> regs .dst_y + s -> regs .dst_height ) *
70
+ if (dst_bits >= end || dst_bits + dst_x + (dst_y + s -> regs .dst_height ) *
68
71
dst_stride >= end ) {
69
72
qemu_log_mask (LOG_UNIMP , "blt outside vram not implemented\n" );
70
73
return ;
71
74
}
72
- DPRINTF ("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d\n" ,
75
+ DPRINTF ("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c \n" ,
73
76
s -> regs .src_offset , s -> regs .dst_offset , s -> regs .default_offset ,
74
77
s -> regs .src_pitch , s -> regs .dst_pitch , s -> regs .default_pitch ,
75
78
s -> regs .src_x , s -> regs .src_y , s -> regs .dst_x , s -> regs .dst_y ,
76
- s -> regs .dst_width , s -> regs .dst_height );
79
+ s -> regs .dst_width , s -> regs .dst_height ,
80
+ (s -> regs .dp_cntl & DST_X_LEFT_TO_RIGHT ? '>' : '<' ),
81
+ (s -> regs .dp_cntl & DST_Y_TOP_TO_BOTTOM ? 'v' : '^' ));
77
82
switch (s -> regs .dp_mix & GMC_ROP3_MASK ) {
78
83
case ROP3_SRCCOPY :
79
84
{
85
+ int src_x = (s -> regs .dp_cntl & DST_X_LEFT_TO_RIGHT ?
86
+ s -> regs .src_x : s -> regs .src_x + 1 - s -> regs .dst_width );
87
+ int src_y = (s -> regs .dp_cntl & DST_Y_TOP_TO_BOTTOM ?
88
+ s -> regs .src_y : s -> regs .src_y + 1 - s -> regs .dst_height );
80
89
int src_stride = DEFAULT_CNTL ?
81
90
s -> regs .src_pitch : s -> regs .default_pitch ;
82
91
uint8_t * src_bits = s -> vga .vram_ptr + (DEFAULT_CNTL ?
@@ -86,9 +95,8 @@ void ati_2d_blt(ATIVGAState *s)
86
95
src_bits += s -> regs .crtc_offset & 0x07ffffff ;
87
96
src_stride *= bpp ;
88
97
}
89
- if (src_bits >= end ||
90
- src_bits + s -> regs .src_x + (s -> regs .src_y + s -> regs .dst_height ) *
91
- src_stride >= end ) {
98
+ if (src_bits >= end || src_bits + src_x +
99
+ (src_y + s -> regs .dst_height ) * src_stride >= end ) {
92
100
qemu_log_mask (LOG_UNIMP , "blt outside vram not implemented\n" );
93
101
return ;
94
102
}
@@ -97,19 +105,36 @@ void ati_2d_blt(ATIVGAState *s)
97
105
dst_stride /= sizeof (uint32_t );
98
106
DPRINTF ("pixman_blt(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)\n" ,
99
107
src_bits , dst_bits , src_stride , dst_stride , bpp , bpp ,
100
- s -> regs . src_x , s -> regs . src_y , s -> regs . dst_x , s -> regs . dst_y ,
108
+ src_x , src_y , dst_x , dst_y ,
101
109
s -> regs .dst_width , s -> regs .dst_height );
102
- pixman_blt ((uint32_t * )src_bits , (uint32_t * )dst_bits ,
103
- src_stride , dst_stride , bpp , bpp ,
104
- s -> regs .src_x , s -> regs .src_y ,
105
- s -> regs .dst_x , s -> regs .dst_y ,
106
- s -> regs .dst_width , s -> regs .dst_height );
110
+ if (s -> regs .dp_cntl & DST_X_LEFT_TO_RIGHT &&
111
+ s -> regs .dp_cntl & DST_Y_TOP_TO_BOTTOM ) {
112
+ pixman_blt ((uint32_t * )src_bits , (uint32_t * )dst_bits ,
113
+ src_stride , dst_stride , bpp , bpp ,
114
+ src_x , src_y , dst_x , dst_y ,
115
+ s -> regs .dst_width , s -> regs .dst_height );
116
+ } else {
117
+ /* FIXME: We only really need a temporary if src and dst overlap */
118
+ int llb = s -> regs .dst_width * (bpp / 8 );
119
+ int tmp_stride = DIV_ROUND_UP (llb , sizeof (uint32_t ));
120
+ uint32_t * tmp = g_malloc (tmp_stride * sizeof (uint32_t ) *
121
+ s -> regs .dst_height );
122
+ pixman_blt ((uint32_t * )src_bits , tmp ,
123
+ src_stride , tmp_stride , bpp , bpp ,
124
+ src_x , src_y , 0 , 0 ,
125
+ s -> regs .dst_width , s -> regs .dst_height );
126
+ pixman_blt (tmp , (uint32_t * )dst_bits ,
127
+ tmp_stride , dst_stride , bpp , bpp ,
128
+ 0 , 0 , dst_x , dst_y ,
129
+ s -> regs .dst_width , s -> regs .dst_height );
130
+ g_free (tmp );
131
+ }
107
132
if (dst_bits >= s -> vga .vram_ptr + s -> vga .vbe_start_addr &&
108
133
dst_bits < s -> vga .vram_ptr + s -> vga .vbe_start_addr +
109
134
s -> vga .vbe_regs [VBE_DISPI_INDEX_YRES ] * s -> vga .vbe_line_offset ) {
110
135
memory_region_set_dirty (& s -> vga .vram , s -> vga .vbe_start_addr +
111
136
s -> regs .dst_offset +
112
- s -> regs . dst_y * surface_stride (ds ),
137
+ dst_y * surface_stride (ds ),
113
138
s -> regs .dst_height * surface_stride (ds ));
114
139
}
115
140
s -> regs .dst_x += s -> regs .dst_width ;
@@ -151,7 +176,7 @@ void ati_2d_blt(ATIVGAState *s)
151
176
s -> vga .vbe_regs [VBE_DISPI_INDEX_YRES ] * s -> vga .vbe_line_offset ) {
152
177
memory_region_set_dirty (& s -> vga .vram , s -> vga .vbe_start_addr +
153
178
s -> regs .dst_offset +
154
- s -> regs . dst_y * surface_stride (ds ),
179
+ dst_y * surface_stride (ds ),
155
180
s -> regs .dst_height * surface_stride (ds ));
156
181
}
157
182
s -> regs .dst_y += s -> regs .dst_height ;
0 commit comments