finally adding move_overlay() function: still needs to be incorporated (to be continued).
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9976 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,12 +1,401 @@
|
|||||||
/* NeoMagic Back End Scaler functions */
|
/* NeoMagic Back End Scaler functions */
|
||||||
/* Written by Rudolf Cornelissen 05/2002-08/2004 */
|
/* Written by Rudolf Cornelissen 05/2002-11/2004 */
|
||||||
|
|
||||||
#define MODULE_BIT 0x00000200
|
#define MODULE_BIT 0x00000200
|
||||||
|
|
||||||
#include "nm_std.h"
|
#include "nm_std.h"
|
||||||
|
|
||||||
//fixme: implement: (used for virtual screens!)
|
//fixme: implementation of move_overlay() function in progress...
|
||||||
//void move_overlay(uint16 hdisp_start, uint16 vdisp_start);
|
//fixme: probably best to add routine:status_t nm_bes_init(void);
|
||||||
|
typedef struct move_overlay_info move_overlay_info;
|
||||||
|
|
||||||
|
struct move_overlay_info
|
||||||
|
{
|
||||||
|
uint32 hcoordv; /* left and right edges of video output window */
|
||||||
|
uint32 vcoordv; /* top and bottom edges of video output window */
|
||||||
|
uint32 hsrcstv; /* horizontal source start in source buffer (clipping) */
|
||||||
|
uint32 hsrcendv; /* horizontal source end in source buffer (clipping) */
|
||||||
|
uint32 a1orgv; /* vertical source clipping via startadress of source buffer */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void nm_bes_calc_move_overlay(move_overlay_info *moi);
|
||||||
|
static void nm_bes_program_move_overlay(move_overlay_info moi);
|
||||||
|
|
||||||
|
/* 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 nm_bes_move_overlay()
|
||||||
|
{
|
||||||
|
move_overlay_info moi;
|
||||||
|
|
||||||
|
/* abort if overlay is not active */
|
||||||
|
if (!si->overlay.active) return;
|
||||||
|
|
||||||
|
nm_bes_calc_move_overlay(&moi);
|
||||||
|
nm_bes_program_move_overlay(moi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nm_bes_calc_move_overlay(move_overlay_info *moi)
|
||||||
|
{
|
||||||
|
/* misc used variables */
|
||||||
|
uint16 temp1, temp2;
|
||||||
|
/* visible screen window in virtual workspaces */
|
||||||
|
uint16 crtc_hstart, crtc_vstart, crtc_hend, crtc_vend;
|
||||||
|
|
||||||
|
/* the BES does not respect virtual_workspaces, but adheres to CRTC
|
||||||
|
* constraints only */
|
||||||
|
crtc_hstart = si->dm.h_display_start;
|
||||||
|
/* 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 */
|
||||||
|
moi->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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* no clipping here */
|
||||||
|
{
|
||||||
|
temp1 = (si->overlay.ow.h_start - crtc_hstart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moi->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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moi->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 */
|
||||||
|
moi->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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* no clipping here */
|
||||||
|
{
|
||||||
|
temp1 = (si->overlay.ow.v_start - crtc_vstart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moi->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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moi->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.! */
|
||||||
|
moi->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) */
|
||||||
|
moi->hsrcstv += (si->overlay.ow.width - 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* increase 'first contributing pixel' with actual number of dest. clipping pixels */
|
||||||
|
moi->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! */
|
||||||
|
moi->hsrcstv *= (si->overlay.h_ifactor << 4);
|
||||||
|
}
|
||||||
|
/* take zoom into account */
|
||||||
|
moi->hsrcstv += ((uint32)si->overlay.my_ov.h_start) << 16;
|
||||||
|
LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", moi->hsrcstv / (float)65536));
|
||||||
|
|
||||||
|
/* Setup horizontal source end: last (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 right ending 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 end pos.! */
|
||||||
|
|
||||||
|
moi->hsrcendv = 0;
|
||||||
|
/* check for destination horizontal clipping at right side */
|
||||||
|
if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) > (crtc_hend - 1))
|
||||||
|
{
|
||||||
|
/* check if entire destination picture is clipping right:
|
||||||
|
* (2 pixels will be clamped onscreen at least) */
|
||||||
|
if (si->overlay.ow.h_start > (crtc_hend - 2))
|
||||||
|
{
|
||||||
|
/* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */
|
||||||
|
moi->hsrcendv += (si->overlay.ow.width - 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* increase 'number of clipping pixels' with actual number of dest. clipping pixels */
|
||||||
|
moi->hsrcendv += ((si->overlay.ow.h_start + si->overlay.ow.width - 1) - (crtc_hend - 1));
|
||||||
|
}
|
||||||
|
LOG(4,("Overlay: clipping right...\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! */
|
||||||
|
moi->hsrcendv *= (si->overlay.h_ifactor << 4);
|
||||||
|
/* now subtract this value from the last used pixel in (zoomed) inputbuffer, aligned to BES */
|
||||||
|
moi->hsrcendv = (((uint32)((si->overlay.my_ov.h_start + si->overlay.my_ov.width) - 1)) << 16) - moi->hsrcendv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* set last contributing pixel to last used pixel in (zoomed) inputbuffer, aligned to BES */
|
||||||
|
moi->hsrcendv = (((uint32)((si->overlay.my_ov.h_start + si->overlay.my_ov.width) - 1)) << 16);
|
||||||
|
}
|
||||||
|
/* AND below required by hardware */
|
||||||
|
moi->hsrcendv &= 0x03ffffff;
|
||||||
|
LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", moi->hsrcendv / (float)65536));
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
*** setup vertical clipping ***
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
/* calculate inputbitmap origin adress */
|
||||||
|
moi->a1orgv = (uint32)((vuint32 *)si->overlay.ob.buffer);
|
||||||
|
moi->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.! */
|
||||||
|
|
||||||
|
/* 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 source buffer origin with 'fixed value':
|
||||||
|
* (integer part of ('total height - 2' of dest. picture in pixels * inverse scaling factor)) *
|
||||||
|
* bytes per row source picture */
|
||||||
|
moi->a1orgv +=
|
||||||
|
((((si->overlay.ow.height - 2) * (si->overlay.v_ifactor << 4)) >> 16) *
|
||||||
|
si->overlay.ob.bytes_per_row);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* increase source buffer origin with:
|
||||||
|
* (integer part of (number of destination picture clipping pixels * inverse scaling factor)) *
|
||||||
|
* bytes per row source picture */
|
||||||
|
moi->a1orgv +=
|
||||||
|
((((crtc_vstart - si->overlay.ow.v_start) * (si->overlay.v_ifactor << 4)) >> 16) *
|
||||||
|
si->overlay.ob.bytes_per_row);
|
||||||
|
}
|
||||||
|
LOG(4,("Overlay: clipping at top...\n"));
|
||||||
|
}
|
||||||
|
/* take zoom into account */
|
||||||
|
moi->a1orgv += (si->overlay.my_ov.v_start * si->overlay.ob.bytes_per_row);
|
||||||
|
/* now include 'pixel precise' left clipping...
|
||||||
|
* (subpixel precision is not supported by NeoMagic cards) */
|
||||||
|
moi->a1orgv += ((moi->hsrcstv >> 16) * 2);
|
||||||
|
/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */
|
||||||
|
moi->a1orgv &= ~0x03;
|
||||||
|
LOG(4,("Overlay: 'contributing part of buffer' origin is (cardRAM offset) $%08x\n", moi->a1orgv));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nm_bes_program_move_overlay(move_overlay_info moi)
|
||||||
|
{
|
||||||
|
/*************************************
|
||||||
|
*** sync to BES (Back End Scaler) ***
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
/* Make sure reprogramming the BES completes before the next retrace occurs,
|
||||||
|
* to prevent register-update glitches (double buffer feature). */
|
||||||
|
|
||||||
|
//fixme if needed...
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
*** actually program the registers ***
|
||||||
|
**************************************/
|
||||||
|
if (si->ps.card_type >= NM2097)
|
||||||
|
{
|
||||||
|
/* PCI card */
|
||||||
|
LOG(4,("Overlay: accelerant is programming BES\n"));
|
||||||
|
/* unlock card overlay sequencer registers (b5 = 1) */
|
||||||
|
PCIGRPHW(GENLOCK, (PCIGRPHR(GENLOCK) | 0x20));
|
||||||
|
/* destination rectangle #1 (output window position and size) */
|
||||||
|
PCIGRPHW(HD1COORD1L, ((moi.hcoordv >> 16) & 0xff));
|
||||||
|
PCIGRPHW(HD1COORD2L, (moi.hcoordv & 0xff));
|
||||||
|
PCIGRPHW(HD1COORD21H, (((moi.hcoordv >> 4) & 0xf0) | ((moi.hcoordv >> 24) & 0x0f)));
|
||||||
|
PCIGRPHW(VD1COORD1L, ((moi.vcoordv >> 16) & 0xff));
|
||||||
|
PCIGRPHW(VD1COORD2L, (moi.vcoordv & 0xff));
|
||||||
|
PCIGRPHW(VD1COORD21H, (((moi.vcoordv >> 4) & 0xf0) | ((moi.vcoordv >> 24) & 0x0f)));
|
||||||
|
/* inputbuffer #1 origin */
|
||||||
|
/* (we don't program buffer #2 as it's unused.) */
|
||||||
|
if (si->ps.card_type < NM2200)
|
||||||
|
{
|
||||||
|
moi.a1orgv >>= 1;
|
||||||
|
/* horizontal source end does not use subpixelprecision: granularity is 8 pixels */
|
||||||
|
/* notes:
|
||||||
|
* - correctly programming horizontal source end minimizes used bandwidth;
|
||||||
|
* - adding 9 below is in fact:
|
||||||
|
* - adding 1 to round-up to the nearest whole source-end value
|
||||||
|
(making SURE we NEVER are a (tiny) bit too low);
|
||||||
|
- adding 1 to convert 'last used position' to 'number of used pixels';
|
||||||
|
- adding 7 to round-up to the nearest higher (or equal) valid register
|
||||||
|
value (needed because of it's 8-pixel granularity). */
|
||||||
|
PCIGRPHW(0xbc, ((((moi.hsrcendv >> 16) + 9) >> 3) - 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* horizontal source end does not use subpixelprecision: granularity is 16 pixels */
|
||||||
|
/* notes:
|
||||||
|
* - programming this register just a tiny bit too low messes up vertical
|
||||||
|
* scaling badly (also distortion stripes and flickering are reported)!
|
||||||
|
* - not programming this register correctly will mess-up the picture when
|
||||||
|
* it's partly clipping on the right side of the screen...
|
||||||
|
* - make absolutely sure the engine can fetch the last pixel needed from
|
||||||
|
* the sourcebitmap even if only to generate a tiny subpixel from it!
|
||||||
|
* (see remarks for < NM2200 cards regarding programming this register) */
|
||||||
|
PCIGRPHW(0xbc, ((((moi.hsrcendv >> 16) + 17) >> 4) - 1));
|
||||||
|
}
|
||||||
|
PCIGRPHW(BUF1ORGL, (moi.a1orgv & 0xff));
|
||||||
|
PCIGRPHW(BUF1ORGM, ((moi.a1orgv >> 8) & 0xff));
|
||||||
|
PCIGRPHW(BUF1ORGH, ((moi.a1orgv >> 16) & 0xff));
|
||||||
|
/* ??? */
|
||||||
|
PCIGRPHW(0xbd, 0x02);
|
||||||
|
PCIGRPHW(0xbe, 0x00);
|
||||||
|
/* b2 = 0: don't use horizontal mirroring (NM2160) */
|
||||||
|
/* other bits do ??? */
|
||||||
|
PCIGRPHW(0xbf, 0x02);
|
||||||
|
/* ??? */
|
||||||
|
PCISEQW(0x1c, 0xfb);
|
||||||
|
PCISEQW(0x1d, 0x00);
|
||||||
|
PCISEQW(0x1e, 0xe2);
|
||||||
|
PCISEQW(0x1f, 0x02);
|
||||||
|
/* b1 = 0: disable alternating hardware buffers (NM2160) */
|
||||||
|
/* other bits do ??? */
|
||||||
|
PCISEQW(0x09, 0x11);
|
||||||
|
/* we don't use PCMCIA Zoomed Video port capturing, set 1:1 scale just in case */
|
||||||
|
/* (b6-4 = Y downscale = 100%, b2-0 = X downscale = 100%;
|
||||||
|
* downscaling selectable in 12.5% steps on increasing setting by 1) */
|
||||||
|
PCISEQW(ZVCAP_DSCAL, 0x00);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* bes setup data */
|
||||||
|
nm_bes_data bi;
|
||||||
|
|
||||||
|
/* ISA card. Speed required, so:
|
||||||
|
* program entire sequence in kerneldriver in one context switch! */
|
||||||
|
LOG(4,("Overlay: kerneldriver programs BES\n"));
|
||||||
|
|
||||||
|
/* setup BES info struct... */
|
||||||
|
// bi.moi = moi;
|
||||||
|
bi.card_type = si->ps.card_type;
|
||||||
|
// bi.pgm_all = false; //maybe better to setup a seperate kerneldriver function..
|
||||||
|
/* ... and call kerneldriver to program the BES */
|
||||||
|
bi.magic = NM_PRIVATE_DATA_MAGIC;
|
||||||
|
ioctl(fd, NM_PGM_BES, &bi, sizeof(bi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
status_t nm_configure_bes
|
status_t nm_configure_bes
|
||||||
(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
|
(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ status_t nm_acc_wait_idle(void);
|
|||||||
|
|
||||||
/*backend scaler functions*/
|
/*backend scaler functions*/
|
||||||
status_t check_overlay_capability(uint32 feature);
|
status_t check_overlay_capability(uint32 feature);
|
||||||
|
void nm_bes_move_overlay(void);
|
||||||
status_t nm_configure_bes
|
status_t nm_configure_bes
|
||||||
(const overlay_buffer *ob, const overlay_window *ow,const overlay_view *ov, int offset);
|
(const overlay_buffer *ob, const overlay_window *ow,const overlay_view *ov, int offset);
|
||||||
status_t nm_release_bes(void);
|
status_t nm_release_bes(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user