]> git.proxmox.com Git - mirror_qemu.git/blame - hw/display/ati_2d.c
Clean up includes
[mirror_qemu.git] / hw / display / ati_2d.c
CommitLineData
862b4a29
BZ
1/*
2 * QEMU ATI SVGA emulation
3 * 2D engine functions
4 *
5 * Copyright (c) 2019 BALATON Zoltan
6 *
7 * This work is licensed under the GNU GPL license version 2 or later.
8 */
9
bbfff196 10#include "qemu/osdep.h"
862b4a29
BZ
11#include "ati_int.h"
12#include "ati_regs.h"
13#include "qemu/log.h"
14#include "ui/pixel_ops.h"
15
16/*
17 * NOTE:
18 * This is 2D _acceleration_ and supposed to be fast. Therefore, don't try to
19 * reinvent the wheel (unlikely to get better with a naive implementation than
20 * existing libraries) and avoid (poorly) reimplementing gfx primitives.
21 * That is unnecessary and would become a performance problem. Instead, try to
22 * map to and reuse existing optimised facilities (e.g. pixman) wherever
23 * possible.
24 */
25
26static int ati_bpp_from_datatype(ATIVGAState *s)
27{
28 switch (s->regs.dp_datatype & 0xf) {
29 case 2:
30 return 8;
31 case 3:
32 case 4:
33 return 16;
34 case 5:
35 return 24;
36 case 6:
37 return 32;
38 default:
39 qemu_log_mask(LOG_UNIMP, "Unknown dst datatype %d\n",
40 s->regs.dp_datatype & 0xf);
41 return 0;
42 }
43}
44
45void ati_2d_blt(ATIVGAState *s)
46{
47 /* FIXME it is probably more complex than this and may need to be */
48 /* rewritten but for now as a start just to get some output: */
49 DisplaySurface *ds = qemu_console_surface(s->vga.con);
50 DPRINTF("%p %u ds: %p %d %d rop: %x\n", s->vga.vram_ptr,
51 s->vga.vbe_start_addr, surface_data(ds), surface_stride(ds),
52 surface_bits_per_pixel(ds),
53 (s->regs.dp_mix & GMC_ROP3_MASK) >> 16);
54 DPRINTF("%d %d, %d %d, (%d,%d) -> (%d,%d) %dx%d\n", s->regs.src_offset,
55 s->regs.dst_offset, s->regs.src_pitch, s->regs.dst_pitch,
56 s->regs.src_x, s->regs.src_y, s->regs.dst_x, s->regs.dst_y,
57 s->regs.dst_width, s->regs.dst_height);
58 switch (s->regs.dp_mix & GMC_ROP3_MASK) {
59 case ROP3_SRCCOPY:
60 {
61 uint8_t *src_bits, *dst_bits, *end;
62 int src_stride, dst_stride, bpp = ati_bpp_from_datatype(s);
63 src_bits = s->vga.vram_ptr + s->regs.src_offset;
64 dst_bits = s->vga.vram_ptr + s->regs.dst_offset;
65 src_stride = s->regs.src_pitch;
66 dst_stride = s->regs.dst_pitch;
67
68 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
69 src_bits += s->regs.crtc_offset & 0x07ffffff;
70 dst_bits += s->regs.crtc_offset & 0x07ffffff;
71 src_stride *= bpp;
72 dst_stride *= bpp;
73 }
74 src_stride /= sizeof(uint32_t);
75 dst_stride /= sizeof(uint32_t);
76
77 DPRINTF("pixman_blt(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)\n",
78 src_bits, dst_bits, src_stride, dst_stride, bpp, bpp,
79 s->regs.src_x, s->regs.src_y, s->regs.dst_x, s->regs.dst_y,
80 s->regs.dst_width, s->regs.dst_height);
81 end = s->vga.vram_ptr + s->vga.vram_size;
82 if (src_bits >= end || dst_bits >= end ||
349ebdd7
BZ
83 src_bits + s->regs.src_x + (s->regs.src_y + s->regs.dst_height) *
84 src_stride * sizeof(uint32_t) >= end ||
85 dst_bits + s->regs.dst_x + (s->regs.dst_y + s->regs.dst_height) *
86 dst_stride * sizeof(uint32_t) >= end) {
862b4a29
BZ
87 qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
88 return;
89 }
90 pixman_blt((uint32_t *)src_bits, (uint32_t *)dst_bits,
91 src_stride, dst_stride, bpp, bpp,
92 s->regs.src_x, s->regs.src_y,
93 s->regs.dst_x, s->regs.dst_y,
94 s->regs.dst_width, s->regs.dst_height);
95 if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr &&
96 dst_bits < s->vga.vram_ptr + s->vga.vbe_start_addr +
97 s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] * s->vga.vbe_line_offset) {
98 memory_region_set_dirty(&s->vga.vram, s->vga.vbe_start_addr +
99 s->regs.dst_offset +
100 s->regs.dst_y * surface_stride(ds),
101 s->regs.dst_height * surface_stride(ds));
102 }
103 s->regs.dst_x += s->regs.dst_width;
104 s->regs.dst_y += s->regs.dst_height;
105 break;
106 }
107 case ROP3_PATCOPY:
108 case ROP3_BLACKNESS:
109 case ROP3_WHITENESS:
110 {
111 uint8_t *dst_bits, *end;
112 int dst_stride, bpp = ati_bpp_from_datatype(s);
113 uint32_t filler = 0;
114 dst_bits = s->vga.vram_ptr + s->regs.dst_offset;
115 dst_stride = s->regs.dst_pitch;
116
117 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
118 dst_bits += s->regs.crtc_offset & 0x07ffffff;
119 dst_stride *= bpp;
120 }
121 dst_stride /= sizeof(uint32_t);
122
123 switch (s->regs.dp_mix & GMC_ROP3_MASK) {
124 case ROP3_PATCOPY:
125 filler = bswap32(s->regs.dp_brush_frgd_clr);
126 break;
127 case ROP3_BLACKNESS:
128 filler = rgb_to_pixel32(s->vga.palette[0], s->vga.palette[1],
129 s->vga.palette[2]) << 8 | 0xff;
130 break;
131 case ROP3_WHITENESS:
132 filler = rgb_to_pixel32(s->vga.palette[3], s->vga.palette[4],
133 s->vga.palette[5]) << 8 | 0xff;
134 break;
135 }
136
137 DPRINTF("pixman_fill(%p, %d, %d, %d, %d, %d, %d, %x)\n",
138 dst_bits, dst_stride, bpp,
139 s->regs.dst_x, s->regs.dst_y,
140 s->regs.dst_width, s->regs.dst_height,
141 filler);
142 end = s->vga.vram_ptr + s->vga.vram_size;
143 if (dst_bits >= end ||
349ebdd7
BZ
144 dst_bits + s->regs.dst_x + (s->regs.dst_y + s->regs.dst_height) *
145 dst_stride * sizeof(uint32_t) >= end) {
862b4a29
BZ
146 qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
147 return;
148 }
149 pixman_fill((uint32_t *)dst_bits, dst_stride, bpp,
150 s->regs.dst_x, s->regs.dst_y,
151 s->regs.dst_width, s->regs.dst_height,
152 filler);
153 if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr &&
154 dst_bits < s->vga.vram_ptr + s->vga.vbe_start_addr +
155 s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] * s->vga.vbe_line_offset) {
156 memory_region_set_dirty(&s->vga.vram, s->vga.vbe_start_addr +
157 s->regs.dst_offset +
158 s->regs.dst_y * surface_stride(ds),
159 s->regs.dst_height * surface_stride(ds));
160 }
161 s->regs.dst_y += s->regs.dst_height;
162 break;
163 }
164 default:
165 qemu_log_mask(LOG_UNIMP, "Unimplemented ati_2d blt op %x\n",
166 (s->regs.dp_mix & GMC_ROP3_MASK) >> 16);
167 }
168}