Banshee/Voodoo3: Some work on the YUV format support.
- Added YUV planar space write support. - Added YUV format support for screen-to-screen stretching BitBlt function. TODO: YUV format overlay still has issues.
This commit is contained in:
parent
c41a2ae00d
commit
b100d354e7
@ -76,6 +76,7 @@ Detailed change log :
|
||||
- Banshee/Voodoo3: Added 16 bpp to 32 bpp pixel format conversion for screen-to-screen bitblt operation
|
||||
- Banshee: added host-to-screen stretching BitBlt support
|
||||
- Banshee/Voodoo3: Added support for combined desktop / overlay mode
|
||||
- Banshee/Voodoo3: Added YUV planar space write support
|
||||
- USB
|
||||
- Now includes the USB Debugger support for the xHCI and UHCI controllers
|
||||
- Sound
|
||||
|
@ -59,7 +59,7 @@
|
||||
// 3dfx Voodoo Banshee / Voodoo3 emulation (partly based on a patch for DOSBox)
|
||||
|
||||
// TODO:
|
||||
// - 2D host-to-screen stretching support
|
||||
// - 2D host-to-screen pattern stretching support
|
||||
// - 2D screen-to-screen pattern stretching support
|
||||
// - 2D chromaKey support
|
||||
// - 2D reversible line drawing
|
||||
@ -1449,7 +1449,7 @@ void bx_banshee_c::mem_write(bx_phy_address addr, unsigned len, void *data)
|
||||
} else if (offset < 0xc00000) {
|
||||
BX_DEBUG(("reserved write to offset 0x%08x", offset));
|
||||
} else if (offset < 0x1000000) {
|
||||
BX_ERROR(("TODO: YUV planar space write to offset 0x%08x", offset));
|
||||
yuv_planar_write(offset, value);
|
||||
} else {
|
||||
Bit8u temp = v->fbi.lfb_stride;
|
||||
v->fbi.lfb_stride = 11;
|
||||
@ -1652,6 +1652,46 @@ void bx_banshee_c::agp_reg_write(Bit8u reg, Bit32u value)
|
||||
v->banshee.agp[reg] = value;
|
||||
}
|
||||
|
||||
void bx_banshee_c::yuv_planar_write(Bit32u offset, Bit32u value)
|
||||
{
|
||||
Bit8u plane = (Bit8u)((offset >> 20) & 3);
|
||||
Bit16u stride = v->banshee.agp[yuvStride] & 0x3fff;
|
||||
Bit16u x = (Bit16u)((offset & 0xfffff) % 1024);
|
||||
Bit16u y = (Bit16u)((offset & 0xfffff) / 1024);
|
||||
Bit32u fbaddr = v->banshee.agp[yuvBaseAddress];
|
||||
int i;
|
||||
|
||||
switch (plane) {
|
||||
case 0:
|
||||
fbaddr += (y * stride + (x << 1));
|
||||
v->fbi.ram[fbaddr & v->fbi.mask] = value & 0xff;
|
||||
v->fbi.ram[(fbaddr + 2) & v->fbi.mask] = (value >> 8) & 0xff;
|
||||
v->fbi.ram[(fbaddr + 4) & v->fbi.mask] = (value >> 16) & 0xff;
|
||||
v->fbi.ram[(fbaddr + 6) & v->fbi.mask] = (value >> 24) & 0xff;
|
||||
break;
|
||||
case 1:
|
||||
fbaddr += ((y << 1) * stride + (x << 2));
|
||||
for (i = 0; i < 2; i++) {
|
||||
v->fbi.ram[(fbaddr + 1) & v->fbi.mask] = value & 0xff;
|
||||
v->fbi.ram[(fbaddr + 5) & v->fbi.mask] = (value >> 8) & 0xff;
|
||||
v->fbi.ram[(fbaddr + 9) & v->fbi.mask] = (value >> 16) & 0xff;
|
||||
v->fbi.ram[(fbaddr + 13) & v->fbi.mask] = (value >> 24) & 0xff;
|
||||
fbaddr += stride;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
fbaddr += ((y << 1) * stride + (x << 2));
|
||||
for (i = 0; i < 2; i++) {
|
||||
v->fbi.ram[(fbaddr + 3) & v->fbi.mask] = value & 0xff;
|
||||
v->fbi.ram[(fbaddr + 7) & v->fbi.mask] = (value >> 8) & 0xff;
|
||||
v->fbi.ram[(fbaddr + 11) & v->fbi.mask] = (value >> 16) & 0xff;
|
||||
v->fbi.ram[(fbaddr + 15) & v->fbi.mask] = (value >> 24) & 0xff;
|
||||
fbaddr += stride;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define BLT v->banshee.blt
|
||||
|
||||
Bit32u bx_banshee_c::blt_reg_read(Bit8u reg)
|
||||
@ -2295,6 +2335,53 @@ Bit8u bx_banshee_c::blt_colorkey_check(Bit8u *ptr, Bit8u pxsize, bool dst)
|
||||
return pass;
|
||||
}
|
||||
|
||||
Bit32u bx_banshee_c::blt_yuv_conversion(Bit8u *ptr, Bit16u xc, Bit16u yc,
|
||||
Bit16u pitch, Bit8u fmt, Bit8u pxsize)
|
||||
{
|
||||
Bit32u value = 0;
|
||||
unsigned r, g, b;
|
||||
Bit8u *src_ptr, data[4], px, Y[2];
|
||||
Bit8s U, V;
|
||||
|
||||
px = xc & 1;
|
||||
xc &= ~1;
|
||||
src_ptr = ptr + (xc << 1) + (yc * pitch);
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
data[i] = *(src_ptr + i);
|
||||
}
|
||||
if (fmt == 8) {
|
||||
Y[0] = data[0];
|
||||
U = data[1] - 0x80;
|
||||
Y[1] = data[2];
|
||||
V = data[3] - 0x80;
|
||||
} else {
|
||||
U = data[0] - 0x80;
|
||||
Y[0] = data[1];
|
||||
V = data[2] - 0x80;
|
||||
Y[1] = data[3];
|
||||
}
|
||||
r = (unsigned)(Y[px] + (double)V / 0.877);
|
||||
if (r > 255) r = 255;
|
||||
g = (unsigned)(Y[px] - (double)U * 0.39393 - (double)V * 0.58081);
|
||||
if (g > 255) g = 255;
|
||||
b = (unsigned)(Y[px] + (double)U / 0.493);
|
||||
if (b > 255) b = 255;
|
||||
if (pxsize == 2) {
|
||||
#ifdef BX_LITTLE_ENDIAN
|
||||
value = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
||||
#else
|
||||
value = ((b >> 3) << 27) | ((g >> 2) << 21) | ((r >> 3) << 16);
|
||||
#endif
|
||||
} else if ((pxsize == 3) || (pxsize == 4)) {
|
||||
#ifdef BX_LITTLE_ENDIAN
|
||||
value = (r << 16) | (g << 8) | b;
|
||||
#else
|
||||
value = (b << 24) | (g << 16) | (r << 8);
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void bx_banshee_c::blt_rectangle_fill()
|
||||
{
|
||||
Bit32u dpitch = BLT.dst_pitch;
|
||||
@ -2653,7 +2740,9 @@ void bx_banshee_c::blt_screen_to_screen_pattern()
|
||||
void bx_banshee_c::blt_screen_to_screen_stretch()
|
||||
{
|
||||
Bit8u *dst_ptr, *dst_ptr1, *src_ptr, *src_ptr1;
|
||||
Bit8u spxsize = (BLT.src_fmt > 1) ? (BLT.src_fmt - 1) : 1;
|
||||
Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
|
||||
bool yuv_src = ((BLT.src_fmt & 0x0e) == 8);
|
||||
int spitch = BLT.src_pitch;
|
||||
int dpitch = BLT.dst_pitch;
|
||||
Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
|
||||
@ -2661,6 +2750,7 @@ void bx_banshee_c::blt_screen_to_screen_stretch()
|
||||
int nrows, stepy;
|
||||
int dx, dy, x2, x3, y2, y3, w0, h0, w1, h1;
|
||||
double fx, fy;
|
||||
Bit32u src_val;
|
||||
|
||||
w0 = BLT.src_w;
|
||||
h0 = BLT.src_h;
|
||||
@ -2668,13 +2758,17 @@ void bx_banshee_c::blt_screen_to_screen_stretch()
|
||||
h1 = BLT.dst_h;
|
||||
BX_DEBUG(("Screen to screen stretch blt: : %d x %d -> %d x %d ROP0 %02X",
|
||||
w0, h0, w1, h1, BLT.rop[0]));
|
||||
if (BLT.dst_fmt != BLT.src_fmt) {
|
||||
if ((BLT.dst_fmt != BLT.src_fmt) && !yuv_src) {
|
||||
BX_ERROR(("Pixel format conversion not supported yet"));
|
||||
}
|
||||
BX_LOCK(render_mutex);
|
||||
dy = BLT.dst_y;
|
||||
if (yuv_src) {
|
||||
// YUYV / UYVY
|
||||
spxsize = 2;
|
||||
}
|
||||
dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + BLT.dst_x * dpxsize];
|
||||
src_ptr = &v->fbi.ram[BLT.src_base + BLT.src_y * spitch + BLT.src_x * dpxsize];
|
||||
src_ptr = &v->fbi.ram[BLT.src_base + BLT.src_y * spitch + BLT.src_x * spxsize];
|
||||
if (BLT.y_dir) {
|
||||
spitch *= -1;
|
||||
dpitch *= -1;
|
||||
@ -2693,7 +2787,12 @@ void bx_banshee_c::blt_screen_to_screen_stretch()
|
||||
if (blt_clip_check(dx, dy)) {
|
||||
x3 = (int)((double)x2 / fx + 0.49f);
|
||||
y3 = (int)((double)y2 / fy + 0.49f);
|
||||
src_ptr1 = src_ptr + (y3 * spitch + x3 * dpxsize);
|
||||
if (yuv_src) {
|
||||
src_val = blt_yuv_conversion(src_ptr, x3, y3, spitch, BLT.src_fmt, dpxsize);
|
||||
src_ptr1 = (Bit8u*)&src_val;
|
||||
} else {
|
||||
src_ptr1 = src_ptr + (y3 * spitch + x3 * spxsize);
|
||||
}
|
||||
if (colorkey_en & 1) {
|
||||
rop = blt_colorkey_check(src_ptr1, dpxsize, 0);
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ public:
|
||||
|
||||
virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len);
|
||||
|
||||
void yuv_planar_write(Bit32u offset, Bit32u value);
|
||||
Bit32u blt_reg_read(Bit8u reg);
|
||||
#if BX_DEBUGGER
|
||||
virtual void debug_dump(int argc, char **argv);
|
||||
@ -167,6 +168,7 @@ private:
|
||||
bool blt_apply_clipwindow(int *x0, int *y0, int *x1, int *y1, int *w, int *h);
|
||||
bool blt_clip_check(int x, int y);
|
||||
Bit8u blt_colorkey_check(Bit8u *ptr, Bit8u pxsize, bool dst);
|
||||
Bit32u blt_yuv_conversion(Bit8u *ptr, Bit16u xc, Bit16u yc, Bit16u pitch, Bit8u fmt, Bit8u pxsize);
|
||||
|
||||
void blt_rectangle_fill(void);
|
||||
void blt_pattern_fill_mono(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user