From ac83e70ce590503930da49fb303d12ec1019a56b Mon Sep 17 00:00:00 2001 From: Rudolf Cornelissen Date: Mon, 3 May 2004 16:17:24 +0000 Subject: [PATCH] added move_overlay() for virtualscreens git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7375 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/accelerants/nvidia/Cursor.c | 5 +- .../accelerants/nvidia/InitAccelerant.c | 5 +- .../accelerants/nvidia/engine/nv_bes.c | 343 +++++++++++++++++- .../accelerants/nvidia/engine/nv_general.c | 4 +- .../accelerants/nvidia/engine/nv_proto.h | 1 + 5 files changed, 349 insertions(+), 9 deletions(-) diff --git a/src/add-ons/accelerants/nvidia/Cursor.c b/src/add-ons/accelerants/nvidia/Cursor.c index 90a8b4fff3..6ec7033655 100644 --- a/src/add-ons/accelerants/nvidia/Cursor.c +++ b/src/add-ons/accelerants/nvidia/Cursor.c @@ -4,7 +4,7 @@ Other authors: Mark Watson, - Rudolf Cornelissen 4/2003-4/2004 + Rudolf Cornelissen 4/2003-5/2004 */ #define MODULE_BIT 0x20000000 @@ -96,8 +96,7 @@ void MOVE_CURSOR(uint16 x, uint16 y) if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start)) { MOVE_DISPLAY(hds,vds); - //fixme: implement: - //move_overlay(hds,vds); + nv_bes_move_overlay(); } /* put cursor in correct physical position, so stay onscreen (rel. to CRTC) */ diff --git a/src/add-ons/accelerants/nvidia/InitAccelerant.c b/src/add-ons/accelerants/nvidia/InitAccelerant.c index be3f399c04..23310c6962 100644 --- a/src/add-ons/accelerants/nvidia/InitAccelerant.c +++ b/src/add-ons/accelerants/nvidia/InitAccelerant.c @@ -4,7 +4,7 @@ Other authors: Mark Watson, - Rudolf Cornelissen 10/2002-4/2004. + Rudolf Cornelissen 10/2002-5/2004. */ #define MODULE_BIT 0x00800000 @@ -171,6 +171,9 @@ status_t INIT_ACCELERANT(int the_fd) { /* make sure overlay unit is 'marked' as being free */ si->overlay.myToken = NULL; + /* note that overlay is not in use (for nv_bes_move_overlay()) */ + si->overlay.active = false; + /* bail out if something failed */ if (result != B_OK) goto error1; diff --git a/src/add-ons/accelerants/nvidia/engine/nv_bes.c b/src/add-ons/accelerants/nvidia/engine/nv_bes.c index 06b9e0eb95..7ffe5f4c9a 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_bes.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_bes.c @@ -1,12 +1,334 @@ /* Nvidia TNT and GeForce Back End Scaler functions */ -/* Written by Rudolf Cornelissen 05/2002-4/2004 */ +/* Written by Rudolf Cornelissen 05/2002-5/2004 */ #define MODULE_BIT 0x00000200 #include "nv_std.h" -//fixme: implement: (used for virtual screens!) -//void move_overlay(uint16 hdisp_start, uint16 vdisp_start); +/* move the overlay output window in virtualscreens */ +/* Note: + * si->dm.h_display_start and si->dm.v_display_start determine where the new + * output window is located! */ +void nv_bes_move_overlay() +{ + /* calculated BES register values */ + uint32 hcoordv, vcoordv, hsrcstv, a1orgv, v1srcstv; + /* misc used variables */ + uint16 temp1, temp2; + /* visible screen window in virtual workspaces */ + uint16 crtc_hstart, crtc_vstart, crtc_hend, crtc_vend; + + /* abort if overlay is not active */ + if (!si->overlay.active) return; + + /* the BES does not respect virtual_workspaces, but adheres to CRTC + * constraints only */ + crtc_hstart = si->dm.h_display_start; + /* make dualhead stretch and switch mode work while we're at it.. */ + if (si->overlay.crtc) + { + crtc_hstart += si->dm.timing.h_display; + } + + /* horizontal end is the first position beyond the displayed range on the CRTC */ + crtc_hend = crtc_hstart + si->dm.timing.h_display; + crtc_vstart = si->dm.v_display_start; + /* vertical end is the first position beyond the displayed range on the CRTC */ + crtc_vend = crtc_vstart + si->dm.timing.v_display; + + + /**************************************** + *** setup all edges of output window *** + ****************************************/ + + /* setup left and right edges of output window */ + hcoordv = 0; + /* left edge coordinate of output window, must be inside desktop */ + /* clipping on the left side */ + if (si->overlay.ow.h_start < crtc_hstart) + { + temp1 = 0; + } + else + { + /* clipping on the right side */ + if (si->overlay.ow.h_start >= (crtc_hend - 1)) + { + /* width < 2 is not allowed */ + temp1 = (crtc_hend - crtc_hstart - 2) & 0x7ff; + } + else + /* no clipping here */ + { + temp1 = (si->overlay.ow.h_start - crtc_hstart) & 0x7ff; + } + } + hcoordv |= temp1 << 16; + /* right edge coordinate of output window, must be inside desktop */ + /* width < 2 is not allowed */ + if (si->overlay.ow.width < 2) + { + temp2 = (temp1 + 1) & 0x7ff; + } + else + { + /* clipping on the right side */ + if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) > (crtc_hend - 1)) + { + temp2 = (crtc_hend - crtc_hstart - 1) & 0x7ff; + } + else + { + /* clipping on the left side */ + if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) < (crtc_hstart + 1)) + { + /* width < 2 is not allowed */ + temp2 = 1; + } + else + /* no clipping here */ + { + temp2 = ((uint16)(si->overlay.ow.h_start + si->overlay.ow.width - crtc_hstart - 1)) & 0x7ff; + } + } + } + hcoordv |= temp2 << 0; + LOG(4,("Overlay: CRTC left-edge output %d, right-edge output %d\n",temp1, temp2)); + + /* setup top and bottom edges of output window */ + vcoordv = 0; + /* top edge coordinate of output window, must be inside desktop */ + /* clipping on the top side */ + if (si->overlay.ow.v_start < crtc_vstart) + { + temp1 = 0; + } + else + { + /* clipping on the bottom side */ + if (si->overlay.ow.v_start >= (crtc_vend - 1)) + { + /* height < 2 is not allowed */ + temp1 = (crtc_vend - crtc_vstart - 2) & 0x7ff; + } + else + /* no clipping here */ + { + temp1 = (si->overlay.ow.v_start - crtc_vstart) & 0x7ff; + } + } + vcoordv |= temp1 << 16; + /* bottom edge coordinate of output window, must be inside desktop */ + /* height < 2 is not allowed */ + if (si->overlay.ow.height < 2) + { + temp2 = (temp1 + 1) & 0x7ff; + } + else + { + /* clipping on the bottom side */ + if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) > (crtc_vend - 1)) + { + temp2 = (crtc_vend - crtc_vstart - 1) & 0x7ff; + } + else + { + /* clipping on the top side */ + if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) < (crtc_vstart + 1)) + { + /* height < 2 is not allowed */ + temp2 = 1; + } + else + /* no clipping here */ + { + temp2 = ((uint16)(si->overlay.ow.v_start + si->overlay.ow.height - crtc_vstart - 1)) & 0x7ff; + } + } + } + vcoordv |= temp2 << 0; + LOG(4,("Overlay: CRTC top-edge output %d, bottom-edge output %d\n",temp1, temp2)); + + + /********************************* + *** setup horizontal clipping *** + *********************************/ + + /* Setup horizontal source start: first (sub)pixel contributing to output picture */ + /* Note: + * The method is to calculate, based on 1:1 scaling, based on the output window. + * After this is done, include the scaling factor so you get a value based on the input bitmap. + * Then add the left starting position of the bitmap's view (zoom function) to get the final value needed. + * Note: The input bitmaps slopspace is automatically excluded from the calculations this way! */ + /* Note also: + * Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */ + hsrcstv = 0; + /* check for destination horizontal clipping at left side */ + if (si->overlay.ow.h_start < crtc_hstart) + { + /* check if entire destination picture is clipping left: + * (2 pixels will be clamped onscreen at least) */ + if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) < (crtc_hstart + 1)) + { + /* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */ + hsrcstv += (si->overlay.ow.width - 2); + } + else + { + /* increase 'first contributing pixel' with actual number of dest. clipping pixels */ + hsrcstv += (crtc_hstart - si->overlay.ow.h_start); + } + LOG(4,("Overlay: clipping left...\n")); + + /* The calculated value is based on scaling = 1x. So we now compensate for scaling. + * Note that this also already takes care of aligning the value to the BES register! */ + hsrcstv *= si->overlay.h_ifactor; + } + /* take zoom into account */ + hsrcstv += ((uint32)si->overlay.my_ov.h_start) << 16; + /* AND below required by hardware */ + hsrcstv &= 0x03fffffc; + LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", hsrcstv / (float)65536)); + + + /******************************* + *** setup vertical clipping *** + *******************************/ + + /* calculate inputbitmap origin adress */ + a1orgv = (uint32)((vuint32 *)si->overlay.ob.buffer); + a1orgv -= (uint32)((vuint32 *)si->framebuffer); + + /* Setup vertical source start: first (sub)pixel contributing to output picture. */ + /* Note: + * The method is to calculate, based on 1:1 scaling, based on the output window. + * 'After' this is done, include the scaling factor so you get a value based on the input bitmap. + * Then add the top starting position of the bitmap's view (zoom function) to get the final value needed. */ + /* Note also: + * Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */ + + v1srcstv = 0; + /* check for destination vertical clipping at top side */ + if (si->overlay.ow.v_start < crtc_vstart) + { + /* check if entire destination picture is clipping at top: + * (2 pixels will be clamped onscreen at least) */ + if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) < (crtc_vstart + 1)) + { + /* increase 'number of clipping pixels' with 'fixed value': + * 'total height - 2' of dest. picture in pixels * inverse scaling factor */ + v1srcstv = (si->overlay.ow.height - 2) * si->overlay.v_ifactor; + /* on pre-NV10 we need to do clipping in the source + * bitmap because no seperate clipping registers exist... */ + if (si->ps.card_arch < NV10A) + a1orgv += ((v1srcstv >> 16) * si->overlay.ob.bytes_per_row); + } + else + { + /* increase 'first contributing pixel' with: + * number of destination picture clipping pixels * inverse scaling factor */ + v1srcstv = (crtc_vstart - si->overlay.ow.v_start) * si->overlay.v_ifactor; + /* on pre-NV10 we need to do clipping in the source + * bitmap because no seperate clipping registers exist... */ + if (si->ps.card_arch < NV10A) + a1orgv += ((v1srcstv >> 16) * si->overlay.ob.bytes_per_row); + } + LOG(4,("Overlay: clipping at top...\n")); + } + /* take zoom into account */ + v1srcstv += (((uint32)si->overlay.my_ov.v_start) << 16); + if (si->ps.card_arch < NV10A) + { + a1orgv += (si->overlay.my_ov.v_start * si->overlay.ob.bytes_per_row); + LOG(4,("Overlay: 'contributing part of buffer' origin is (cardRAM offset) $%08x\n", a1orgv)); + } + LOG(4,("Overlay: first vert. (sub)pixel of input bitmap contributing %f\n", v1srcstv / (float)65536)); + + /* AND below is probably required by hardware. */ + /* Buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */ + a1orgv &= 0xfffffff0; + LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",a1orgv)); + + + /************************************* + *** sync to BES (Back End Scaler) *** + *************************************/ + + /* Done in card hardware: + * double buffered registers + trigger if programming complete feature. */ + + + /************************************** + *** actually program the registers *** + **************************************/ + + if (si->ps.card_arch < NV10A) + { + /* unknown, but needed (otherwise high-res distortions and only half the frames */ + BESW(NV04_OE_STATE, 0x00000000); + /* select buffer 0 as active (b16) */ + BESW(NV04_SU_STATE, 0x00000000); + /* unknown (no effect?) */ + BESW(NV04_RM_STATE, 0x00000000); + /* setup clipped(!) buffer startadress in RAM */ + /* RIVA128 - TNT bes doesn't have clipping registers, so no subpixelprecise clipping + * either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */ + /* (program both buffers to prevent sync distortions) */ + /* first include 'pixel precise' left clipping... (top clipping was already included) */ + a1orgv += ((hsrcstv >> 16) * 2); + /* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */ + BESW(NV04_0BUFADR, (a1orgv & ~0x03)); + BESW(NV04_1BUFADR, (a1orgv & ~0x03)); + + /* setup buffer source pitch including slopspace (in bytes). + * Note: + * source pitch granularity = 16 pixels on the RIVA128 - TNT (so pre-NV10) bes */ + /* (program both buffers to prevent sync distortions) */ +// BESW(NV04_0SRCPTCH, (ob->width * 2)); +// BESW(NV04_1SRCPTCH, (ob->width * 2)); + /* setup output window position */ + BESW(NV04_DSTREF, ((vcoordv & 0xffff0000) | ((hcoordv & 0xffff0000) >> 16))); + /* setup output window size */ + BESW(NV04_DSTSIZE, ( + (((vcoordv & 0x0000ffff) - ((vcoordv & 0xffff0000) >> 16) + 1) << 16) | + ((hcoordv & 0x0000ffff) - ((hcoordv & 0xffff0000) >> 16) + 1) + )); + + /* enable BES (b0), enable colorkeying (b4), format yuy2 (b8: 0 = ccir) */ +// BESW(NV04_GENCTRL, 0x00000111); + /* select buffer 1 as active (b16) */ + BESW(NV04_SU_STATE, 0x00010000); + } + else + { + /* >= NV10A */ + + /* setup buffer origin: GeForce uses subpixel precise clipping on left and top! (12.4 values) */ + BESW(NV10_0SRCREF, ((v1srcstv << 4) & 0xffff0000) | ((hsrcstv >> 12) & 0x0000ffff)); + /* setup buffersize */ + //fixme if needed: width must be even officially... +// BESW(NV10_0SRCSIZE, ((ob->height << 16) | ob->width)); + /* setup source pitch including slopspace (in bytes), + * b16: select YUY2 (0 = YV12), b20: use colorkey, b24: no iturbt_709 (do iturbt_601) */ + /* Note: + * source pitch granularity = 32 pixels on GeForce cards!! */ +// BESW(NV10_0SRCPTCH, (((ob->width * 2) & 0x0000ffff) | (1 << 16) | (1 << 20) | (0 << 24))); + /* setup output window position */ + BESW(NV10_0DSTREF, ((vcoordv & 0xffff0000) | ((hcoordv & 0xffff0000) >> 16))); + /* setup output window size */ + BESW(NV10_0DSTSIZE, ( + (((vcoordv & 0x0000ffff) - ((vcoordv & 0xffff0000) >> 16) + 1) << 16) | + ((hcoordv & 0x0000ffff) - ((hcoordv & 0xffff0000) >> 16) + 1) + )); + /* setup (unclipped!) buffer startadress in RAM */ +// BESW(NV10_0BUFADR, a1orgv); + /* enable BES (b0 = 0) */ +// BESW(NV10_GENCTRL, 0x00000000); + /* We only use buffer buffer 0: select it. (0x01 = buffer 0, 0x10 = buffer 1) */ + /* This also triggers activation of programmed values (double buffered registers feature) */ + BESW(NV10_BUFSEL, 0x00000001); + } +} status_t nv_bes_to_crtc(bool crtc) { @@ -128,6 +450,11 @@ status_t nv_configure_bes LOG(6,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n", my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height)); + /* save for nv_bes_move_overlay() */ + si->overlay.ow = *ow; + si->overlay.ob = *ob; + si->overlay.my_ov = my_ov; + /* the BES does not respect virtual_workspaces, but adheres to CRTC * constraints only */ crtc_hstart = si->dm.h_display_start; @@ -302,6 +629,8 @@ status_t nv_configure_bes /* correct factor to prevent most-right visible 'line' from distorting */ ifactor -= (1 << 2); hiscalv = ifactor; + /* save for nv_bes_move_overlay() */ + si->overlay.h_ifactor = ifactor; LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor)); /* check scaling factor (and modify if needed) to be within scaling limits */ @@ -431,6 +760,8 @@ status_t nv_configure_bes /* preserve ifactor for source positioning calculations later on */ viscalv = ifactor; + /* save for nv_bes_move_overlay() */ + si->overlay.v_ifactor = ifactor; /* check scaling factor (and modify if needed) to be within scaling limits */ /* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */ @@ -709,6 +1040,9 @@ status_t nv_configure_bes } } + /* note that overlay is in use (for nv_bes_move_overlay()) */ + si->overlay.active = true; + return B_OK; } @@ -725,5 +1059,8 @@ status_t nv_release_bes() BESW(NV10_GENCTRL, 0x00000001); } + /* note that overlay is not in use (for nv_bes_move_overlay()) */ + si->overlay.active = false; + return B_OK; } diff --git a/src/add-ons/accelerants/nvidia/engine/nv_general.c b/src/add-ons/accelerants/nvidia/engine/nv_general.c index 22ba2ef890..69720f9190 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_general.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_general.c @@ -1,7 +1,7 @@ /* Authors: Mark Watson 12/1999, Apsed, - Rudolf Cornelissen 10/2002-4/2004 + Rudolf Cornelissen 10/2002-5/2004 */ #define MODULE_BIT 0x00008000 @@ -80,7 +80,7 @@ status_t nv_general_powerup() { status_t status; - LOG(1,("POWERUP: nVidia (open)BeOS Accelerant 0.10-17 running.\n")); + LOG(1,("POWERUP: nVidia (open)BeOS Accelerant 0.10-18 running.\n")); /* preset no laptop */ si->ps.laptop = false; diff --git a/src/add-ons/accelerants/nvidia/engine/nv_proto.h b/src/add-ons/accelerants/nvidia/engine/nv_proto.h index 8d6780d1a3..9bac930c04 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_proto.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_proto.h @@ -111,6 +111,7 @@ status_t nv_acc_wait_idle(void); /*backend scaler functions*/ status_t check_overlay_capability(uint32 feature); +void nv_bes_move_overlay(void); status_t nv_bes_to_crtc(bool crtc); status_t nv_bes_init(void); status_t nv_configure_bes