From 57edb25a2720046aca75f14bb1d6c537011bceaa Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 24 Mar 2025 01:13:04 +0000 Subject: [PATCH] GDI acceleration type A + chroma test --- .../86box/nv/classes/vid_nv3_classes.h | 60 +++++++++++++++---- src/include/86box/nv/render/vid_nv3_render.h | 4 +- src/include/86box/nv/vid_nv3.h | 14 +++-- .../nv/nv3/classes/nv3_class_007_rectangle.c | 6 +- .../classes/nv3_class_00c_win95_gdi_text.c | 36 ++++++++++- .../nv/nv3/classes/nv3_class_011_image.c | 6 +- src/video/nv/nv3/render/nv3_render_core.c | 24 +++++++- src/video/nv/nv3/subsystems/nv3_pbus.c | 7 +++ src/video/nv/nv3/subsystems/nv3_pfb.c | 8 +++ src/video/nv/nv3/subsystems/nv3_pgraph.c | 8 +++ 10 files changed, 146 insertions(+), 27 deletions(-) diff --git a/src/include/86box/nv/classes/vid_nv3_classes.h b/src/include/86box/nv/classes/vid_nv3_classes.h index 076502f63..309a1c5aa 100644 --- a/src/include/86box/nv/classes/vid_nv3_classes.h +++ b/src/include/86box/nv/classes/vid_nv3_classes.h @@ -132,9 +132,54 @@ typedef enum nv3_pgraph_class_e #define NV3_IMAGE_IN_MEMORY_TOP_LEFT_OFFSET 0x030C #define NV3_IMAGE_IN_MEMORY_TOP_LEFT_OFFSET_END 22 -#define NV3_W95TXT_COLORA 0x03FC // It's the colour of the text. This is used to submit a dummy object so the notifier can be used to sync in Win2000 DDraw6 drivers. -#define NV3_W95TXT_COLORA_RECT_START 0x0400 -#define NV3_W95TXT_COLORA_RECT_END 0x05FF +/* GDI */ + +/* Type A: Unclipped Rectangle */ +#define NV3_W95TXT_A_COLOR 0x03FC // It's the colour of the text. This is used to submit a dummy object so the notifier can be used to sync in Win2000 DDraw6 drivers. +#define NV3_W95TXT_A_RECT_START 0x0400 +#define NV3_W95TXT_A_RECT_SIZE 64 // Number of rects +#define NV3_W95TXT_A_RECT_END 0x05FF + +/* Type B: Clipped Rectangle */ +#define NV3_W95TXT_B_CLIP_TOPLEFT 0x07F4 +#define NV3_W95TXT_B_CLIP_BOTTOMRIGHT 0x07F8 +#define NV3_W95TXT_B_CLIP_CLIPRECT_START 0x0800 +#define NV3_W95TXT_B_CLIP_CLIPRECT_SIZE 128 // Number of rects +#define NV3_W95TXT_B_CLIP_CLIPRECT_END 0x09FF + +/* Type C: Unscaled Single-Colour Text (filled in from mono bitmap) */ +#define NV3_W95TXT_C_CLIP_TOPLEFT 0x0BEC +#define NV3_W95TXT_C_CLIP_BOTTOMRIGHT 0x0BF0 +#define NV3_W95TXT_C_CLIP_COLOR 0x0BF4 +#define NV3_W95TXT_C_CLIP_SIZE 0x0BF8 +#define NV3_W95TXT_C_CLIP_POSITION 0x0BFC /* TOP LEFT */ +#define NV3_W95TXT_C_CLIP_CLIPRECT_START 0x0C00 +#define NV3_W95TXT_C_CLIP_CLIPRECT_SIZE 64 // Number of rects +#define NV3_W95TXT_C_CLIP_CLIPRECT_END 0x0DFF + +/* Type D: Scaled Single-Colour Text (filled in from mono bitmap) */ +#define NV3_W95TXT_D_CLIP_TOPLEFT 0x0FE8 +#define NV3_W95TXT_D_CLIP_BOTTOMRIGHT 0x0FEC +#define NV3_W95TXT_D_CLIP_COLOR 0x0FF0 +#define NV3_W95TXT_D_CLIP_SIZE_IN 0x0FF4 +#define NV3_W95TXT_D_CLIP_SIZE_OUT 0x0FF8 +#define NV3_W95TXT_D_CLIP_POSITION 0x0FFC /* TOP LEFT */ +#define NV3_W95TXT_D_CLIP_CLIPRECT_START 0x1000 +#define NV3_W95TXT_D_CLIP_CLIPRECT_SIZE 128 // Number of rects +#define NV3_W95TXT_D_CLIP_CLIPRECT_END 0x11FF + +/* Type E: Scaled Pattern-type Bitmap Text (filled) */ +#define NV3_W95TXT_E_CLIP_TOPLEFT 0x13E4 +#define NV3_W95TXT_E_CLIP_BOTTOMRIGHT 0x13E8 +#define NV3_W95TXT_E_CLIP_COLOR_0 0x13EC +#define NV3_W95TXT_E_CLIP_COLOR_1 0x13F0 +#define NV3_W95TXT_E_CLIP_SIZE_IN 0x13F4 +#define NV3_W95TXT_E_CLIP_SIZE_OUT 0x13F8 +#define NV3_W95TXT_E_CLIP_POSITION 0x13FC /* TOP LEFT */ +#define NV3_W95TXT_E_CLIP_CLIPRECT_START 0x1400 +#define NV3_W95TXT_E_CLIP_CLIPRECT_SIZE 128 // Number of rects +#define NV3_W95TXT_E_CLIP_CLIPRECT_END 0x15FF + /* Class context switch method */ typedef struct nv3_class_ctx_switch_method_s @@ -523,12 +568,6 @@ typedef struct nv3_object_class_00B uint8_t reserved4[0x19FB]; } nv3_triangle_t; -typedef struct nv3_object_class_00C_nclip_s -{ - nv3_position_16_t position; - nv3_size_16_t size; -} nv3_object_class_00C_nclip_t; - /* Object Class 0x0C (real hardware) 0x0C (drivers) @@ -544,7 +583,8 @@ typedef struct nv3_object_class_00C uint32_t set_notify; // Set notifier uint8_t reserved2[0x2F4]; uint32_t color_a; // Color for Clip A - nv3_object_class_00C_nclip_t rect_nclip[64]; + nv3_position_16_t rect_a_position[64]; + nv3_size_16_t rect_a_size[64]; uint8_t reserved3[0x1F0]; nv3_clip_16_t clip_b; uint32_t color_b; // Color for Clip B diff --git a/src/include/86box/nv/render/vid_nv3_render.h b/src/include/86box/nv/render/vid_nv3_render.h index e1cb0f65f..5f6d39ae2 100644 --- a/src/include/86box/nv/render/vid_nv3_render.h +++ b/src/include/86box/nv/render/vid_nv3_render.h @@ -27,8 +27,6 @@ uint32_t nv3_render_to_chroma(nv3_color_expanded_t expanded); nv3_color_expanded_t nv3_render_expand_color(nv3_grobj_t grobj, uint32_t color); // Convert a colour to full RGB10 format from the current working format. uint32_t nv3_render_downconvert_color(nv3_grobj_t grobj, nv3_color_expanded_t color); // Convert a colour from the current working format to RGB10 format. - - /* Pattern */ uint32_t nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool use_color1); @@ -36,7 +34,7 @@ uint32_t nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t color, nv3_grobj_t grobj); /* Chroma */ -void nv3_render_chroma_test(nv3_grobj_t grobj); +bool nv3_render_chroma_test(nv3_grobj_t grobj, uint32_t color); /* Blit */ void nv3_render_blit_screen2screen(nv3_grobj_t grobj); \ No newline at end of file diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index aa59f7e69..d4ceb5cf4 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -202,6 +202,7 @@ extern const device_config_t nv3_config[]; #define NV3_CIO_START 0x3b0 // Legacy SVGA Emulation Subsystem #define NV3_CIO_END 0x3df #define NV3_PBUS_START 0x1000 // Bus Control Subsystem +#define NV3_PBUS_DEBUG_0 0x1084 // Bus Control Debug #define NV3_PBUS_INTR 0x1100 // Bus Control - Interrupt Status #define NV3_PBUS_INTR_EN 0x1140 // Bus Control - Interrupt Enable @@ -375,6 +376,7 @@ extern const device_config_t nv3_config[]; #define NV3_PFB_BOOT_RAM_EXTENSION_8MB 0x1 #define NV3_PFB_DELAY 0x100044 +#define NV3_PFB_DEBUG_0 0x100080 // Debug register for pfb #define NV3_PFB_GREEN_0 0x1000C0 #define NV3_PFB_CONFIG_0 0x100200 // Framebuffer interface config register 0 @@ -569,10 +571,10 @@ extern const device_config_t nv3_config[]; #define NV3_PGRAPH_SRC_CANVAS_MAX 0x400554 // Maximum Source Canvas for Blit, Y=30:16, X=10:0 #define NV3_PGRAPH_DST_CANVAS_MIN 0x400558 // Minimum Destination Canvas for Blit, Y=30:16, X=10:0 #define NV3_PGRAPH_DST_CANVAS_MAX 0x40055C // Maximum Destination Canvas for Blit, Y=30:16, X=10:0 -#define NV3_PGRAPH_PATTERN_COLOR_0_RGB 0x400600 -#define NV3_PGRAPH_PATTERN_COLOR_0_ALPHA 0x400604 -#define NV3_PGRAPH_PATTERN_COLOR_1_RGB 0x400608 -#define NV3_PGRAPH_PATTERN_COLOR_1_ALPHA 0x40060C // pattern color +#define NV3_PGRAPH_PATTERN_COLOR_0_RGB 0x400600 +#define NV3_PGRAPH_PATTERN_COLOR_0_ALPHA 0x400604 +#define NV3_PGRAPH_PATTERN_COLOR_1_RGB 0x400608 +#define NV3_PGRAPH_PATTERN_COLOR_1_ALPHA 0x40060C // pattern color #define NV3_PGRAPH_PATTERN_BITMAP_HIGH 0x400610 // pattern bitmap [31:0] #define NV3_PGRAPH_PATTERN_BITMAP_LOW 0x400614 // pattern bitmap [63:32] #define NV3_PGRAPH_PATTERN_SHAPE 0x400618 @@ -581,6 +583,7 @@ extern const device_config_t nv3_config[]; #define NV3_PGRAPH_CHROMA_KEY 0x40062C #define NV3_PGRAPH_BETA 0x400640 // Beta factor (30:23 fractional, 22:0 before fraction) #define NV3_PGRAPH_DMA 0x400680 +#define NV3_PGRAPH_INSTANCE 0x400688 // Current instance (?) // Current notification object for pgraph #define NV3_PGRAPH_NOTIFY 0x400684 // Notifier for PGRAPH @@ -905,6 +908,7 @@ typedef struct nv3_straps_s typedef struct nv3_pfb_s { uint32_t boot; + uint32_t debug_0; // debug stuff uint32_t config_0; // Framebuffer width, etc. uint32_t config_1; uint32_t green; @@ -960,6 +964,7 @@ typedef struct nv3_pbus_rma_s // Bus Configuration typedef struct nv3_pbus_s { + uint32_t debug_0; uint32_t interrupt_status; // Interrupt status uint32_t interrupt_enable; // Interrupt enable nv3_pbus_rma_t rma; @@ -1207,6 +1212,7 @@ typedef struct nv3_pgraph_s nv3_pgraph_status_t status; // Current status of the 3D engine. uint32_t trapped_address; uint32_t trapped_data; + uint32_t instance; // no idea what this is but possibly an object context uint32_t trapped_instance; /* This area is used for holding universal representations of the U* registers, which are actually mapped into MMIO */ diff --git a/src/video/nv/nv3/classes/nv3_class_007_rectangle.c b/src/video/nv/nv3/classes/nv3_class_007_rectangle.c index 8f304fdac..fcf31132f 100644 --- a/src/video/nv/nv3/classes/nv3_class_007_rectangle.c +++ b/src/video/nv/nv3/classes/nv3_class_007_rectangle.c @@ -39,14 +39,13 @@ void nv3_class_007_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ /* Check for any rectangle point or size method. */ if (method_id >= NV3_RECTANGLE_START && method_id <= NV3_RECTANGLE_END) { - uint32_t index = (method_id - NV3_RECTANGLE_START) / 8; + uint32_t index = (method_id - NV3_RECTANGLE_START) >> 3; // If the size is submitted, render it. if (method_id & 0x04) { nv3->pgraph.rectangle.size[index].w = param & 0xFFFF; - nv3->pgraph.rectangle.size[index].h = (param >> 16) & 0xFFFF; - + nv3->pgraph.rectangle.size[index].h = (param >> 16) & 0xFFFF; nv_log("Rect%d Size=%d,%d Color=0x%08x\n", index, nv3->pgraph.rectangle.size[index].w, nv3->pgraph.rectangle.size[index].h, nv3->pgraph.rectangle.color); @@ -57,7 +56,6 @@ void nv3_class_007_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ nv3->pgraph.rectangle.position[index].x = param & 0xFFFF; nv3->pgraph.rectangle.position[index].y = (param >> 16) & 0xFFFF; - nv_log("Rect%d Position=%d,%d\n", index, nv3->pgraph.rectangle.position[index].x, nv3->pgraph.rectangle.position[index].y); } diff --git a/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c b/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c index 2b14ec2ff..9fbc92006 100644 --- a/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c +++ b/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c @@ -32,9 +32,43 @@ void nv3_class_00c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ { switch (method_id) { + /* Type A: Unclipped Rectangle */ + + /* NOTE: This method is used by the GDI driver as part of the notification engine. */ + case NV3_W95TXT_A_COLOR: + nv3->pgraph.win95_gdi_text.color_a = param; + break; default: + /* These are the same things as rectangles */ + if (method_id >= NV3_W95TXT_A_RECT_START && method_id <= NV3_W95TXT_A_RECT_END) + { + uint32_t index = (method_id - NV3_RECTANGLE_START) >> 3; + + // If the size is submitted, render it. + if (method_id & 0x04) + { + nv3->pgraph.win95_gdi_text.rect_a_size[index].w = param & 0xFFFF; + nv3->pgraph.win95_gdi_text.rect_a_size[index].h = (param >> 16) & 0xFFFF; + + nv_log("Rect GDI-A%d Size=%d,%d Color=0x%08x\n", index, nv3->pgraph.win95_gdi_text.rect_a_size[index].w, + nv3->pgraph.win95_gdi_text.rect_a_size[index].h, nv3->pgraph.win95_gdi_text.color_a); + + nv3_render_rect(nv3->pgraph.win95_gdi_text.rect_a_position[index], + nv3->pgraph.win95_gdi_text.rect_a_size[index], nv3->pgraph.win95_gdi_text.color_a, grobj); + } + else // position + { + nv3->pgraph.win95_gdi_text.rect_a_position[index].x = param & 0xFFFF; + nv3->pgraph.win95_gdi_text.rect_a_position[index].y = (param >> 16) & 0xFFFF; + + nv_log("Rect GDI-A%d Position=%d,%d\n", index, + nv3->pgraph.win95_gdi_text.rect_a_position[index].x, nv3->pgraph.win95_gdi_text.rect_a_position[index].y); + } + return; + } + nv_log("%s: Invalid or Unimplemented method 0x%04x", nv3_class_names[context.class_id & 0x1F], method_id); nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_SOFTWARE_METHOD_PENDING); - return; + break; } } \ No newline at end of file diff --git a/src/video/nv/nv3/classes/nv3_class_011_image.c b/src/video/nv/nv3/classes/nv3_class_011_image.c index dc865243e..8dee40a21 100644 --- a/src/video/nv/nv3/classes/nv3_class_011_image.c +++ b/src/video/nv/nv3/classes/nv3_class_011_image.c @@ -76,7 +76,7 @@ void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ /* the reverse order is due to the endianness */ switch (nv3->nvbase.svga.bpp) { - // 4pixels packed into one + // 4pixels packed into one param case 8: //pixel3 @@ -101,7 +101,7 @@ void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ nv3_class_011_check_line_bounds(); break; - //2pixels packed into 1 + //2pixels packed into one param case 16: pixel1 = (param) & 0xFFFF; nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel1, grobj); @@ -114,7 +114,7 @@ void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ nv3_class_011_check_line_bounds(); break; - // just one + // just one pixel in 32bpp case 32: pixel0 = param; nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj); diff --git a/src/video/nv/nv3/render/nv3_render_core.c b/src/video/nv/nv3/render/nv3_render_core.c index c7ffd5f44..7ef08e665 100644 --- a/src/video/nv/nv3/render/nv3_render_core.c +++ b/src/video/nv/nv3/render/nv3_render_core.c @@ -155,10 +155,28 @@ uint32_t nv3_render_downconvert_color(nv3_grobj_t grobj, nv3_color_expanded_t co return packed_color; } -/* Runs the chroma key test */ -void nv3_render_chroma_test(nv3_grobj_t grobj) +/* Runs the chroma key/color key test */ +bool nv3_render_chroma_test(nv3_grobj_t grobj, uint32_t color) { + bool chroma_enabled = ((grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_CHROMA_KEY) & 0x01); + if (!chroma_enabled) + return true; + + bool alpha = ((nv3->pgraph.chroma_key >> 31) & 0x01); + + if (!alpha) + return true; + + /* this is dumb but i'm lazy, if it kills perf, fix it later - we need to do some format shuffling */ + nv3_grobj_t grobj_fake = {0}; + grobj_fake.grobj_0 = 0x02; /* we don't care about any other bits */ + + nv3_color_expanded_t chroma_expanded = nv3_render_expand_color(grobj_fake, nv3->pgraph.chroma_key); + + uint32_t chroma_downconverted = nv3_render_downconvert_color(grobj, chroma_expanded); + + return !(chroma_downconverted == color); } /* Convert expanded colour format to chroma key format */ @@ -295,6 +313,8 @@ void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grob } /* TODO: Chroma Key, Pattern, Plane Mask...*/ + if (!nv3_render_chroma_test(grobj, color)) + return; uint32_t pixel_addr_vram = nv3_render_get_vram_address(position, grobj); diff --git a/src/video/nv/nv3/subsystems/nv3_pbus.c b/src/video/nv/nv3/subsystems/nv3_pbus.c index ca631edfc..46d829fb2 100644 --- a/src/video/nv/nv3/subsystems/nv3_pbus.c +++ b/src/video/nv/nv3/subsystems/nv3_pbus.c @@ -33,6 +33,7 @@ // Putting this in pbus because imo it makes the most sense (related to memory access/memory interface) nv_register_t pbus_registers[] = { + { NV3_PBUS_DEBUG_0, "PBUS - Debug Register", NULL, NULL}, { NV3_PBUS_INTR, "PBUS - Interrupt Status", NULL, NULL}, { NV3_PBUS_INTR_EN, "PBUS - Interrupt Enable", NULL, NULL,}, { NV_REG_LIST_END, NULL, NULL, NULL}, // sentinel value @@ -65,6 +66,9 @@ uint32_t nv3_pbus_read(uint32_t address) { switch (reg->address) { + case NV3_PBUS_DEBUG_0: + ret = nv3->pbus.debug_0; + break; case NV3_PBUS_INTR: ret = nv3->pbus.interrupt_status; break; @@ -108,6 +112,9 @@ void nv3_pbus_write(uint32_t address, uint32_t value) { switch (reg->address) { + case NV3_PBUS_DEBUG_0: + nv3->pbus.debug_0 = value; + break; // Interrupt registers // Interrupt state: // Bit 0 - PCI Bus Error diff --git a/src/video/nv/nv3/subsystems/nv3_pfb.c b/src/video/nv/nv3/subsystems/nv3_pfb.c index 160cbff08..644d4090d 100644 --- a/src/video/nv/nv3/subsystems/nv3_pfb.c +++ b/src/video/nv/nv3/subsystems/nv3_pfb.c @@ -35,6 +35,7 @@ void nv3_pfb_config0_write(uint32_t val); nv_register_t pfb_registers[] = { { NV3_PFB_BOOT, "PFB Boot Config", NULL, NULL}, { NV3_PFB_DELAY, "PFB Delay", NULL, NULL}, + { NV3_PFB_DEBUG_0, "PFB Debug", NULL, NULL }, { NV3_PFB_GREEN_0, "PFB Green / Power Saving", NULL, NULL,}, { NV3_PFB_CONFIG_0, "PFB Framebuffer Config 0", nv3_pfb_config0_read, nv3_pfb_config0_write }, { NV3_PFB_CONFIG_1, "PFB Framebuffer Config 1", NULL, NULL }, @@ -85,6 +86,9 @@ uint32_t nv3_pfb_read(uint32_t address) case NV3_PFB_BOOT: ret = nv3->pfb.boot; break; + case NV3_PFB_DEBUG_0: + ret = nv3->pfb.debug_0; + break; // Config 0 has a read/write function case NV3_PFB_CONFIG_1: ret = nv3->pfb.config_1; @@ -136,6 +140,10 @@ void nv3_pfb_write(uint32_t address, uint32_t value) { switch (reg->address) { + // Boot is read only + case NV3_PFB_DEBUG_0: + nv3->pfb.debug_0 = value; + break; // Config 0 has a read/write function case NV3_PFB_CONFIG_1: // Config Register 1 nv3->pfb.config_1 = value; diff --git a/src/video/nv/nv3/subsystems/nv3_pgraph.c b/src/video/nv/nv3/subsystems/nv3_pgraph.c index 251ec7a5f..ece125b0f 100644 --- a/src/video/nv/nv3/subsystems/nv3_pgraph.c +++ b/src/video/nv/nv3/subsystems/nv3_pgraph.c @@ -240,6 +240,7 @@ uint32_t nv3_pgraph_read(uint32_t address) case NV3_PGRAPH_CLIP_MISC: ret = *(uint32_t*)&nv3->pgraph.clip_misc_settings; break; + // Overall Status case NV3_PGRAPH_STATUS: ret = *(uint32_t*)&nv3->pgraph.status; @@ -251,6 +252,9 @@ uint32_t nv3_pgraph_read(uint32_t address) case NV3_PGRAPH_TRAPPED_DATA: ret = nv3->pgraph.trapped_data; break; + case NV3_PGRAPH_INSTANCE: + ret = nv3->pgraph.instance; + break; case NV3_PGRAPH_TRAPPED_INSTANCE: ret = nv3->pgraph.trapped_instance; break; @@ -454,9 +458,13 @@ void nv3_pgraph_write(uint32_t address, uint32_t value) case NV3_PGRAPH_TRAPPED_DATA: nv3->pgraph.trapped_data = value; break; + case NV3_PGRAPH_INSTANCE: + nv3->pgraph.instance = value; + break; case NV3_PGRAPH_TRAPPED_INSTANCE: nv3->pgraph.trapped_instance = value; break; + } } }