52
uint32_t frgd_clr;
53
const uint8_t *palette;
54
const uint8_t *vram_end;
55
+ QemuRect scissor;
56
57
QemuRect dst;
58
int dst_stride;
92
ctx->dst_offset = s->regs.dst_offset;
93
ctx->vram_end = s->vga.vram_ptr + s->vga.vram_size;
94
95
+ ctx->scissor.width = s->regs.sc_right - s->regs.sc_left + 1;
96
+ ctx->scissor.height = s->regs.sc_bottom - s->regs.sc_top + 1;
97
+ ctx->scissor.x = s->regs.sc_left;
98
+ ctx->scissor.y = s->regs.sc_top;
99
+
100
ctx->dst.width = s->regs.dst_width;
101
ctx->dst.height = s->regs.dst_height;
102
ctx->dst.x = (ctx->left_to_right ?
131
132
static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman)
133
{
134
+ QemuRect vis_src, vis_dst;
135
+
136
if (!ctx->bpp) {
137
qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n");
138
return false;
147
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
148
return false;
149
}
150
+ qemu_rect_intersect(&ctx->dst, &ctx->scissor, &vis_dst);
151
+ if (!vis_dst.height || !vis_dst.width) {
152
+ /* Nothing is visible, completely clipped */
153
+ return false;
154
+ }
155
+ /*
156
+ * The src must be offset if clipping is applied to the dst.
157
+ * This is so that when the source is blit to a dst clipped
158
+ * on the top or left the src image is not shifted into the
159
+ * clipped region but actually clipped.
160
+ */
161
+ vis_src.x = ctx->src.x + (vis_dst.x - ctx->dst.x);
162
+ vis_src.y = ctx->src.y + (vis_dst.y - ctx->dst.y);
163
+ vis_src.width = vis_dst.width;
164
+ vis_src.height = vis_dst.height;
165
+
166
+ DPRINTF("dst: (%d,%d) %dx%d -> vis_dst: (%d,%d) %dx%d\n",
167
+ ctx->dst.x, ctx->dst.y, ctx->dst.width, ctx->dst.height,
168
+ vis_dst.x, vis_dst.y, vis_dst.width, vis_dst.height);
169
+ DPRINTF("src: (%d,%d) %dx%d -> vis_src: (%d,%d) %dx%d\n",
170
+ ctx->src.x, ctx->src.y, ctx->dst.width, ctx->dst.height,
171
+ vis_src.x, vis_src.y, vis_src.width, vis_src.height);
172
+
173
switch (ctx->rop3) {
174
case ROP3_SRCCOPY:
175
{
178
qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n");
179
return false;
180
}
150
- if (ctx->src.x > 0x3fff || ctx->src.y > 0x3fff ||
151
- ctx->src_bits >= ctx->vram_end ||
152
- ctx->src_bits + ctx->src.x + (ctx->src.y + ctx->dst.height) *
153
- ctx->src_stride >= ctx->vram_end) {
181
+ if (vis_src.x > 0x3fff || vis_src.y > 0x3fff ||
182
+ ctx->src_bits >= ctx->vram_end || ctx->src_bits + vis_src.x +
183
+ (vis_src.y + vis_dst.height) * ctx->src_stride >= ctx->vram_end) {
184
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
185
return false;
186
}
189
ctx->src_bits, ctx->dst_bits,
190
ctx->src_stride / sizeof(uint32_t),
191
ctx->dst_stride / sizeof(uint32_t),
162
- ctx->bpp, ctx->bpp, ctx->src.x, ctx->src.y, ctx->dst.x,
163
- ctx->dst.y, ctx->dst.width, ctx->dst.height);
192
+ ctx->bpp, ctx->bpp, vis_src.x, vis_src.y, vis_dst.x, vis_dst.y,
193
+ vis_dst.width, vis_dst.height);
194
#ifdef CONFIG_PIXMAN
195
int src_stride_words = ctx->src_stride / sizeof(uint32_t);
196
int dst_stride_words = ctx->dst_stride / sizeof(uint32_t);
199
fallback = !pixman_blt((uint32_t *)ctx->src_bits,
200
(uint32_t *)ctx->dst_bits, src_stride_words,
201
dst_stride_words, ctx->bpp, ctx->bpp,
172
- ctx->src.x, ctx->src.y, ctx->dst.x,
173
- ctx->dst.y, ctx->dst.width, ctx->dst.height);
202
+ vis_src.x, vis_src.y, vis_dst.x, vis_dst.y,
203
+ vis_dst.width, vis_dst.height);
204
} else if (use_pixman & BIT(1)) {
205
/* FIXME: We only really need a temporary if src and dst overlap */
176
- int llb = ctx->dst.width * (ctx->bpp / 8);
206
+ int llb = vis_dst.width * (ctx->bpp / 8);
207
int tmp_stride_words = DIV_ROUND_UP(llb, sizeof(uint32_t));
208
uint32_t *tmp = g_malloc(tmp_stride_words * sizeof(uint32_t) *
179
- ctx->dst.height);
209
+ vis_dst.height);
210
fallback = !pixman_blt((uint32_t *)ctx->src_bits, tmp,
211
src_stride_words, tmp_stride_words, ctx->bpp,
182
- ctx->bpp, ctx->src.x, ctx->src.y, 0, 0,
183
- ctx->dst.width, ctx->dst.height);
212
+ ctx->bpp, vis_src.x, vis_src.y, 0, 0,
213
+ vis_dst.width, vis_dst.height);
214
if (!fallback) {
215
fallback = !pixman_blt(tmp, (uint32_t *)ctx->dst_bits,
216
tmp_stride_words, dst_stride_words,
217
ctx->bpp, ctx->bpp, 0, 0,
188
- ctx->dst.x, ctx->dst.y,
189
- ctx->dst.width, ctx->dst.height);
218
+ vis_dst.x, vis_dst.y,
219
+ vis_dst.width, vis_dst.height);
220
}
221
g_free(tmp);
222
} else
226
}
227
if (fallback) {
228
unsigned int y, i, j, bypp = ctx->bpp / 8;
199
- for (y = 0; y < ctx->dst.height; y++) {
200
- i = ctx->dst.x * bypp;
201
- j = ctx->src.x * bypp;
229
+ for (y = 0; y < vis_dst.height; y++) {
230
+ i = vis_dst.x * bypp;
231
+ j = vis_src.x * bypp;
232
if (ctx->top_to_bottom) {
203
- i += (ctx->dst.y + y) * ctx->dst_stride;
204
- j += (ctx->src.y + y) * ctx->src_stride;
233
+ i += (vis_dst.y + y) * ctx->dst_stride;
234
+ j += (vis_src.y + y) * ctx->src_stride;
235
} else {
206
- i += (ctx->dst.y + ctx->dst.height - 1 - y)
236
+ i += (vis_dst.y + vis_dst.height - 1 - y)
237
* ctx->dst_stride;
208
- j += (ctx->src.y + ctx->dst.height - 1 - y)
238
+ j += (vis_src.y + vis_dst.height - 1 - y)
239
* ctx->src_stride;
240
}
241
memmove(&ctx->dst_bits[i], &ctx->src_bits[j],
212
- ctx->dst.width * bypp);
242
+ vis_dst.width * bypp);
243
}
244
}
245
break;
268
269
DPRINTF("pixman_fill(%p, %ld, %d, %d, %d, %d, %d, %x)\n",
270
ctx->dst_bits, ctx->dst_stride / sizeof(uint32_t), ctx->bpp,
241
- ctx->dst.x, ctx->dst.y, ctx->dst.width, ctx->dst.height,
242
- filler);
271
+ vis_dst.x, vis_dst.y, vis_dst.width, vis_dst.height, filler);
272
#ifdef CONFIG_PIXMAN
273
if (!(use_pixman & BIT(0)) ||
274
!pixman_fill((uint32_t *)ctx->dst_bits,
275
ctx->dst_stride / sizeof(uint32_t), ctx->bpp,
247
- ctx->dst.x, ctx->dst.y,
248
- ctx->dst.width, ctx->dst.height, filler))
276
+ vis_dst.x, vis_dst.y, vis_dst.width, vis_dst.height,
277
+ filler))
278
#endif
279
{
280
/* fallback when pixman failed or we don't want to call it */
281
unsigned int x, y, i, bypp = ctx->bpp / 8;
253
- for (y = 0; y < ctx->dst.height; y++) {
254
- i = ctx->dst.x * bypp + (ctx->dst.y + y) * ctx->dst_stride;
255
- for (x = 0; x < ctx->dst.width; x++, i += bypp) {
282
+ for (y = 0; y < vis_dst.height; y++) {
283
+ i = vis_dst.x * bypp + (vis_dst.y + y) * ctx->dst_stride;
284
+ for (x = 0; x < vis_dst.width; x++, i += bypp) {
285
stn_he_p(&ctx->dst_bits[i], bypp, filler);
286
}
287
}