/* * * * Version PureC / Gcc */ #define PCGEMLIB 1 /* mettre 1 si les utilisateurs de Pure C * utilise les librairies GEM Pure C */ /* Fichiers headers */ #include /* Forget this and sprintf will badly format numbers */ #include #if PCGEMLIB #include #include #else #include #include #endif #include #include #include #include #include "..\..\ldg.h" #include "..\..\vapi.h" #include "..\..\ldv.h" #include "..\..\mt_aes.h" /* Prototypages */ LDV_INFOS * cdecl GetLDVCapabilities(VAPI *vapi) ; LDV_STATUS cdecl PreRun(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) ; LDV_STATUS cdecl Run(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) ; LDV_STATUS cdecl Preview(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) ; void OnClose(void) ; /* Variables globales */ PROC Proc[] = { "GetLDVCapabilities", "LDV Capabilities", (void *)GetLDVCapabilities, "PreRun", "Run Initiliaze", (void *)PreRun, "Run", "LDV Feature", (void *)Run, "Preview", "Preview", (void *)Preview, } ; char Info[] = "LDV"; LDGLIB Ldg[] = { 0x0100, /* LDV version */ 4, /* Number of functions in the lib */ Proc, /* Pointers to LDV functions */ Info, /* Library Information */ 0x0, /* Lib flags, mandatory */ OnClose, /* Closing, free VDIHandle */ }; #define BP_CAPS (LDVF_ATARIFORMAT | LDVF_SUPPORTPREVIEW | LDVF_SUPPORTPROG | LDVF_REALTIMEPARAMS | LDVF_SUPPORTCANCEL | LDVF_NOSELECTION) #define TC_CAPS (LDVF_SPECFORMAT | LDVF_SUPPORTPREVIEW | LDVF_SUPPORTPROG | LDVF_REALTIMEPARAMS | LDVF_SUPPORTCANCEL | LDVF_NOSELECTION) LDV_INFOS LdvInfos = { (short) sizeof(LDV_INFOS), /* Size of this structure */ TLDV_MODIFYIMG, /* LDV Type */ "Jean Lusetti", /* Authors */ { { 1, 1, BP_CAPS }, /* 1 bit-plane capabilities */ { 2, 2, BP_CAPS }, /* 2 bit-plane capabilities */ { 4, 4, BP_CAPS }, /* 4 bit-plane capabilities */ { 8, 8, BP_CAPS }, /* 8 bit-plane capabilities */ { 16, 16, TC_CAPS }, /* 16 bit-plane capabilities */ { 32, 32, TC_CAPS }, /* 32 bit-plane capabilities */ { 0, 0, 0UL } /* End of capabilities list */ }, } ; VAPI *Vapi = NULL ; #define ITRIGO_ARRAY_NBITS 14 #define ITRIGO_ARRAY_SIZE (1 << ITRIGO_ARRAY_NBITS) #define ITRIGO_ANGLE_MAX (ITRIGO_ARRAY_SIZE-1) #define QUARTER (ITRIGO_ARRAY_SIZE/4) #define ANGLE_ADD (M_PI/2.0/(double)QUARTER) ; long* pre_cosin = NULL ; /* Array of pre-computed cosinus/sinus values */ long* pre_loffset = NULL ; /* To hold pre-computation of line offsets */ int lo_w=0, lo_h=0, lo_nplanes=0 ; /* Current parameters for line offset */ unsigned long VapiLogLevel = LL_DISABLED ; unsigned long ProcMask = 0L ; short UseSym = -1 ; /* By default use symmetry to save CPU calculations */ /* On Aranym, this is usually slower, so there is a */ /* Setting in bhole.ini to force no symetry usage */ /* Macro to access pre-computed cosinus/sinus array */ /* Sinus is right after cosinus value */ #define COS(i) (pre_cosin[(i)<<1]) #define SIN(i) (pre_cosin[1 + ( (i)<<1 )]) /* Back Hole computation parameters are not passed to speed up calculations, */ /* They are global to the module */ /* Black Hole symmetry rotation */ typedef struct _RECT { short x ; short y ; short w ; short h ; } RECT, *PRECT ; typedef struct _BH_SPROPERTIES { short estdpc ; /* Estimated duration in % (100 being the one without using symmetry) */ short nrect ; short nsym ; RECT rect[9] ; } BH_SPROPERTIES, *PBH_SPROPERTIES ; extern long bh_xd, bh_yd, bh_rd2, bh_xs, bh_ys, bh_ref ; extern long bh_xc, bh_yc ; extern short bh_out_w, bh_out_h, bh_in_w, bh_in_h ; extern short bh_out_x, bh_out_y ; short bh_pc, bh_nrect ; /* This is the routine address that will operate on a line basis */ static void (*BHLRoutine)(short use_sym, void* in, void* out) ; /* Specific 68030 and FPU routines */ /* In BHOLE.S */ extern void BHL32_68030(short use_sym, void* in, void* out) ; extern void BHL16_68030(short use_sym, void* in, void* out) ; extern void BHLInd_68030(short use_sym, void* in, void* out) ; extern void BHL32_F68030(short use_sym, void* in, void* out) ; extern void BHL16_F68030(short use_sym, void* in, void* out) ; extern void BHLInd_F68030(short use_sym, void* in, void* out) ; extern void lcosin_fpu(long i, long* pcs) ; /* GET/SET pixel macros for True Color 16 and 32bit */ #define SET_TCPIXEL(p,x,y,val) (p[pre_loffset[y]+x]=val) #define GET_TCPIXEL(p,x,y) (p[pre_loffset[y]+x]) /* Rotation by 90° macro */ #define R90(x,y) { long _x=x; x=-y; y=_x; } /* Macro to initialize calculations for a line */ #define BH_INIT_LINE\ bh_xd = bh_out_x-bh_xc ;\ bh_rd2 = (bh_xd*bh_xd + bh_yd*bh_yd) ;\ /* This is the routine that computes the resulting pixel (bh_xs,bh_ys) in source image */ /* From the pixel (bh_xd, bh_yd) in destination image */ /* (bh_xc,bh_yc) is the center pixel of the back hole */ /* This routine also returns if the resulting pixel is in the source image */ int rBH_68000(void) { int not_in_range = 1 ; long alpha ; bh_rd2 += ( bh_xd << 1 ) + 1 ; alpha = bh_ref / (1+bh_rd2) ; alpha &= ITRIGO_ANGLE_MAX ; bh_xs = bh_xd * COS(alpha) - bh_yd * SIN(alpha) ; bh_xs >>= 16 ; if ( (bh_xs >= -bh_xc) && (bh_xs < -bh_xc+bh_in_w) ) { bh_ys = bh_xd * SIN(alpha) + bh_yd * COS(alpha) ; bh_ys >>= 16 ; if ( (bh_ys >= -bh_yc) && (bh_ys < -bh_yc+bh_in_h) ) not_in_range = 0 ; } return not_in_range ; } /* For 68000/bit-planes organization: */ /* This routine returns the value of the pixel index in the source image */ /* Assuming (bh_xs,bh_ys) is within the source image */ #pragma warn -par void BHLInd_68000(short use_sym, void* in, void* out) { unsigned char* in_ptr = (unsigned char*) in ; unsigned char* out_ptr = (unsigned char*) out ; short x ; for ( x = bh_out_x; x < bh_out_w; x++, bh_xd++ ) { if ( rBH_68000() == 0 ) out_ptr[x] = in_ptr[pre_loffset[bh_ys+bh_yc] + bh_xs+bh_xc] ; else out_ptr[x] = 0 ; } } #pragma warn +par /* For 68000/16bit TrueColor organization: */ /* This routine returns the value of the pixel index in the source image */ /* Assuming (bh_xs,bh_ys) is within the source image */ void BHL16_68000(short use_sym, void* in, void* out) { unsigned int* in_ptr = (unsigned int*) in ; unsigned int* out_ptr = (unsigned int*) out ; short x ; if (use_sym) { unsigned long save_bh_xd, save_bh_yd ; short n ; for ( x = bh_out_x; x <= bh_out_x+bh_out_w/2; x++, bh_xd++ ) { /* Save bh_xd and bh_yd as they will change */ save_bh_xd = bh_xd ; save_bh_yd = bh_yd ; if ( rBH_68000() == 0 ) /* Compute 1st pixel with Black Hole formula */ SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ; else SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFF) ; /* Deduce 2nd, 3rd and 4th pixel */ for (n=0; n < 3; n++) { R90(bh_xd, bh_yd) ; R90(bh_xs, bh_ys) ; if ( (bh_xd>=-bh_xc) && (bh_xd < -bh_xc+bh_in_w) && (bh_yd >= -bh_yc) && (bh_yd < -bh_yc+bh_in_h)) { if ( (bh_xs>=-bh_xc) && (bh_xs < -bh_xc+bh_in_w) && (bh_ys >= -bh_yc) && (bh_ys < -bh_yc+bh_in_h)) SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ; else SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFF) ; } } /* Restore bh_xd and bh_yd */ bh_xd = save_bh_xd ; bh_yd = save_bh_yd ; } } else { for ( x = bh_out_x; x < bh_out_x+bh_out_w; x++, bh_xd++ ) { if ( rBH_68000() == 0 ) out_ptr[x] = in_ptr[pre_loffset[bh_ys+bh_yc] + bh_xs+bh_xc] ; else out_ptr[x] = 0xFFFF ; } } } /* For 68000/32bit TrueColor organization: */ /* This routine returns the value of the pixel index in the source image */ /* Assuming (bh_xs,bh_ys) is within the source image */ void BHL32_68000(short use_sym, void* in, void* out) { unsigned long* in_ptr = (unsigned long*) in ; unsigned long* out_ptr = (unsigned long*) out ; short x ; if (use_sym) { unsigned long save_bh_xd, save_bh_yd ; short n ; for ( x = bh_out_x; x <= bh_out_x+bh_out_w/2; x++, bh_xd++ ) { /* Save bh_xd and bh_yd as they will change */ save_bh_xd = bh_xd ; save_bh_yd = bh_yd ; if ( rBH_68000() == 0 ) /* Compute 1st pixel with Black Hole formula */ SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ; else SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFFFFFFL) ; /* Deduce 2nd, 3rd and 4th pixel */ for (n=0; n < 3; n++) { R90(bh_xd, bh_yd) ; R90(bh_xs, bh_ys) ; if ( (bh_xd>=-bh_xc) && (bh_xd < -bh_xc+bh_in_w) && (bh_yd >= -bh_yc) && (bh_yd < -bh_yc+bh_in_h)) { if ( (bh_xs>=-bh_xc) && (bh_xs < -bh_xc+bh_in_w) && (bh_ys >= -bh_yc) && (bh_ys < -bh_yc+bh_in_h)) SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ; else SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFFFFFFL) ; } } /* Restore bh_xd and bh_yd */ bh_xd = save_bh_xd ; bh_yd = save_bh_yd ; } } else { for ( x = bh_out_x; x < bh_out_x+bh_out_w; x++, bh_xd++ ) { if ( rBH_68000() == 0 ) out_ptr[x] = in_ptr[pre_loffset[bh_ys+bh_yc] + bh_xs+bh_xc] ; else out_ptr[x] = 0xFFFFFFFFL ; } } } void lcosin(long i, long* pcs) { double angle = i*ANGLE_ADD ; pcs[0] = (long) (65536.0 * cos(angle)) ; pcs[1] = (long) (65536.0 * sin(angle)) ; } int InitTrigo(int fpu) { void (*rlcosin)(long i, long* pcs) ; long cs[2] ; long q, i; clock_t t0 ; /* if ( pre_cosin[0] == 65536L ) return 0 ; Used to detect init done before dynamic allocation design */ if ( pre_cosin ) return 0 ; pre_cosin = (long*) calloc( ITRIGO_ARRAY_SIZE, 2*sizeof(long) ) ; if ( pre_cosin == NULL ) return -1 ; t0 = clock() ; if (fpu) rlcosin = lcosin_fpu ; else rlcosin = lcosin ; for ( i = 0; i < QUARTER; i++ ) { rlcosin( i, cs ) ; COS(i) = cs[0] ; SIN(i) = cs[1] ; q = QUARTER ; /* Set [PI/2;PI] */ COS(q+i) = -SIN(i) ; SIN(q+i) = COS(i) ; q += QUARTER ; /* Set [PI;3*PI/2] */ COS(q+i) = -COS(i) ; SIN(q+i) = -SIN(i) ; q += QUARTER ; /* Set [3*PI/2; 2*PI] */ COS(q+i) = COS(i) ; SIN(q+i) = -SIN(i) ; } if (Vapi && Vapi->LoDoLog) Vapi->LoDoLog(LL_INFO, "IniTrigo%s done in %ldms", fpu ? "(FPU)":"", 1000L * (clock()-t0)/CLK_TCK) ; return 0 ; } /* Called when LDV is loaded, take this opportunity to get some */ /* Info about system: VAPI version and CPU/FPU availability */ LDV_INFOS * cdecl GetLDVCapabilities(VAPI *vapi) { Vapi = vapi ; VapiLogLevel = LL_DISABLED ; if ( Vapi && (Vapi->Header.Version >= 0x0104) && Vapi->LoDoLog && Vapi->LoGetLogLevel ) { VapiLogLevel = Vapi->LoGetLogLevel() ; if (Vapi->CoGetProcessors) ProcMask = Vapi->CoGetProcessors() ; if (ProcMask & CO_HAS_030) Vapi->LoDoLog(LL_INFO, "%s", "68030 processor available") ; if (ProcMask & CO_HAS_FPU) Vapi->LoDoLog(LL_INFO, "%s", "Floating Point unit available") ; } return( &LdvInfos ) ; } /* Free allocated RunTime stuff */ void OnClose(void) { if ( pre_cosin ) free( pre_cosin ) ; pre_cosin = NULL ; if ( pre_loffset ) free( pre_loffset ) ; pre_loffset = NULL ; } /* Pre-compute line offsets from source to speed-up computations */ int compute_loffset(MFDB* in, long** ppre_lo, int* plo_w, int* plo_h, int* plo_nplanes) { /* Sanity checks */ if ( (ppre_lo == NULL) || (plo_w == NULL) || (plo_h == NULL) || (plo_nplanes == NULL) ) return -2 ; if ( *ppre_lo && (*plo_w == in->fd_w) && (*plo_h == in->fd_h) && (*plo_nplanes == in->fd_nplanes) ) { /* Current line offsets are still valid */ return 0 ; } else { /* Need to compute line offsets */ *plo_w = *plo_h = *plo_nplanes = 0 ; if (*ppre_lo) free(*ppre_lo) ; *ppre_lo = (long*) malloc(sizeof(long) * (long)in->fd_h) ; if (*ppre_lo) { long* pt_off ; long add = (long) ALIGN16( in->fd_w ) ; long offset = 0L ; int y ; pt_off = *ppre_lo ; for ( y = 0; y < in->fd_h; y++ ) { *pt_off++ = offset ; offset += add ; } *plo_w = in->fd_w ; *plo_h = in->fd_h ; *plo_nplanes = in->fd_nplanes ; return 0 ; } } return -1 ; } #pragma warn -par /* Just say that output image has same width/length than source */ LDV_STATUS cdecl PreRun(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) { out->Raster.fd_w = in->Raster.fd_w ; out->Raster.fd_h = in->Raster.fd_h ; return( ELDV_NOERROR ) ; } #pragma warn +par /* Update progression window 1 time on 16 */ char check_prog(short y, short ymax) { char cancel = 0 ; if ( ( y & 0x0F ) == 0 ) { int pc = (short) ( ( 100L * (long)y ) / (long)ymax ) ; cancel = Vapi->PrSetProgEx( bh_pc+pc/bh_nrect ) ; } return cancel ; } /* Initialize global variables for calculation */ void init_computation(short xc, short yc, long angle, MFDB* in, RECT* rect) { long maxrd2 ; bh_xd = -xc ; bh_yd = -yc ; maxrd2 = bh_xd*bh_xd + bh_yd*bh_yd ; if ( (ProcMask & (CO_HAS_030|CO_HAS_FPU)) == (CO_HAS_030|CO_HAS_FPU) ) maxrd2 = (long) sqrt(maxrd2) ; bh_ref = (angle * maxrd2) ; bh_xc = xc ; bh_yc = yc ; bh_in_w = in->fd_w ; bh_in_h = in->fd_h ; bh_out_x = rect->x ; bh_out_y = rect->y ; bh_out_w = rect->w ; bh_out_h = rect->h ; bh_yd = bh_out_y-bh_yc ; } /* 68000 routine for bit-plane images */ LDV_STATUS bpRun(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym) { MFDB dst_line ; LDV_STATUS status = ELDV_NOERROR ; size_t size_indexes, size_dst_line ; short y ; long wout, sizelout ; unsigned char *index_in, *index_out, *out_ptr ; char cancel = 0 ; /* We will convert the whole image in indexes */ /* Allocate memory to convert then to bitplanes */ /* A line to destination tion */ size_indexes = (long) ALIGN16( in->fd_w ) ; size_indexes *= (long) in->fd_h ; size_dst_line = (long) ALIGN16( out->fd_w ) ; index_in = (unsigned char *) malloc( size_indexes ) ; if ( index_in == NULL ) return ELDV_NOTENOUGHMEMORY ; index_out = (unsigned char *) malloc(size_dst_line) ; if ( index_out == NULL ) { free(index_in) ; return ELDV_NOTENOUGHMEMORY ; } /* Convert all source to indexes */ Vapi->RaRaster2Ind( in->fd_addr, size_indexes, (long)in->fd_nplanes, index_in ) ; memcpy( &dst_line, out, sizeof(MFDB) ) ; dst_line.fd_wdwidth = out->fd_w / 16 ; if ( out->fd_w % 16 ) dst_line.fd_wdwidth++ ; dst_line.fd_h = 1 ; wout = (long) ALIGN16( out->fd_w ) ; out_ptr = out->fd_addr ; sizelout = Vapi->RaGetImgSize( (long) dst_line.fd_w, (long) dst_line.fd_h, (long) out->fd_nplanes ) ; init_computation(xc, yc, angle, in, rect) ; for ( y = 0; !cancel && (y < out->fd_h); y++, bh_yd++, out_ptr += sizelout ) { BH_INIT_LINE ; BHLRoutine(use_sym, index_in, index_out) ; dst_line.fd_addr = out_ptr ; Vapi->RaInd2RasterInit( &dst_line, wout ) ; Vapi->RaInd2Raster( index_out, wout ) ; cancel = check_prog(y, out->fd_h) ; } free(index_in) ; free(index_out) ; if ( cancel ) status = ELDV_CANCELLED ; return( status ) ; } /* 68000 routine for 16bit True Color images */ LDV_STATUS Run16(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym) { LDV_STATUS status = ELDV_NOERROR ; unsigned int *in_ptr, *out_ptr ; unsigned long sizelout = 0 ; short y, hy ; char cancel = 0 ; in_ptr = (unsigned int*) in->fd_addr ; out_ptr = (unsigned int*) out->fd_addr ; init_computation(xc, yc, angle, in, rect) ; hy = bh_out_y+bh_out_h/2 ; if (!use_sym) { sizelout = (long) ALIGN16( out->fd_w ) ; out_ptr += sizelout*(long)rect->y ; hy = bh_out_y+bh_out_h ; } for ( y = bh_out_y; !cancel && (y < hy); y++, bh_yd++, out_ptr += sizelout ) { BH_INIT_LINE ; BHLRoutine(use_sym, in_ptr, out_ptr) ; cancel = check_prog(y, hy-bh_out_y) ; } if ( cancel ) status = ELDV_CANCELLED ; return( status ) ; } /* 68000 routine for 32bit True Color images */ LDV_STATUS Run32(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym) { LDV_STATUS status = ELDV_NOERROR ; unsigned long *in_ptr, *out_ptr ; unsigned long sizelout = 0 ; short y, hy ; char cancel = 0 ; in_ptr = (unsigned long*) in->fd_addr ; out_ptr = (unsigned long*) out->fd_addr ; init_computation(xc, yc, angle, in, rect) ; hy = bh_out_y+bh_out_h/2 ; if (!use_sym) { sizelout = (long) ALIGN16( out->fd_w ) ; out_ptr += sizelout*(long)rect->y ; hy = bh_out_y+bh_out_h ; } for ( y = bh_out_y; !cancel && (y < hy); y++, bh_yd++, out_ptr += sizelout ) { BH_INIT_LINE ; BHLRoutine(use_sym, in_ptr, out_ptr) ; cancel = check_prog(y, hy-bh_out_y) ; } if ( cancel ) status = ELDV_CANCELLED ; return( status ) ; } int MayAddRect(RECT* subRect, BH_SPROPERTIES* sgProps) { int add = (subRect->w && subRect->h) ; if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"MayAddRect (%d,%d,%d,%d)", subRect->x, subRect->y, subRect->w, subRect->h); if ( add ) /* Sub Rectangle not empty */ memcpy( &sgProps->rect[sgProps->nrect++], subRect, sizeof(RECT) ) ; return( add ) ; } /* Estimation of the expected gain by using rotation symmetry */ void SymmetrySplit(MFDB* img, short xc, short yc, BH_SPROPERTIES* sgProps) { long npts_insym, npts_total, npts_to_compute ; short sw = 0 ; if ( UseSym && ( (img->fd_nplanes == 16) || (img->fd_nplanes == 32) ) ) { /* Bitplane organization would have make things too complicated */ /* By the way, who is using bitplanes nowadays ? */ sw = xc ; if ( img->fd_w-xc < sw ) sw = img->fd_w-xc ; if ( yc < sw ) sw = yc ; if ( img->fd_h-yc < sw ) sw = img->fd_h-yc ; if ( img->fd_h-yc < sw ) sw = img->fd_h-yc ; /* Let's build the rectangle arrays to define the image */ /* First rectangle (square actually) is the one to use for symmetry */ /* On this one only 25% of pixels will be computed with Black Hole formula */ sgProps->nrect = 1 ; sgProps->nsym = 0 ; sgProps->rect[0].x = xc-sw ; sgProps->rect[0].y = yc-sw ; sgProps->rect[0].w = 2*sw ; sgProps->rect[0].h = 2*sw ; } npts_total = (long)img->fd_w*(long)img->fd_h ; npts_insym = 4L*(long)sw*(long)sw ; npts_to_compute = npts_total-((3L*npts_insym)/4L) ; sgProps->estdpc = (100L*npts_to_compute)/npts_total ; if ( sgProps->estdpc > 70 ) { /* Not worth make things complicated for that gain */ sgProps->nrect = 1 ; sgProps->nsym = -1 ; sgProps->rect[0].x = 0 ; sgProps->rect[0].y = 0 ; sgProps->rect[0].w = img->fd_w ; sgProps->rect[0].h = img->fd_h ; } else { /* Let's build the remaining rectangles */ RECT* sRect = &sgProps->rect[0] ; /* Symmetry Rectangle */ RECT subRect ; /* |----------------------------------------| | R1 | R2 | R3 | |----------------------------------------| | ****** | | R4 ****** R5 | | ****** | | ****** | |----------------------------------------| | R6 | R7 | R8 | |----------------------------------------| */ /* R1 */ subRect.x = 0 ; subRect.y = 0 ; subRect.w = sRect->x ; subRect.h = sRect->y ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R1(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); /* R2 */ subRect.x = sRect->x ; subRect.y = 0 ; subRect.w = sRect->w ; subRect.h = sRect->y ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R2(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); /* R3 */ subRect.x = sRect->x+sRect->w ; subRect.y = 0 ; subRect.w = img->fd_w-sRect->x-sRect->w ; subRect.h = sRect->y ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R3(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); /* R4 */ subRect.x = 0 ; subRect.y = sRect->y ; subRect.w = sRect->x ; subRect.h = sRect->h ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R4(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); /* R5 */ subRect.x = sRect->x+sRect->w ; subRect.y = sRect->y ; subRect.w = img->fd_w-sRect->x-sRect->w ; subRect.h = sRect->h ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R5(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); /* R6 */ subRect.x = 0 ; subRect.y = sRect->y+sRect->h ; subRect.w = sRect->x ; subRect.h = img->fd_h-sRect->y-sRect->h ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R6(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); /* R7 */ subRect.x = sRect->x ; subRect.y = sRect->y+sRect->h ; subRect.w = sRect->w ; subRect.h = img->fd_h-sRect->y-sRect->h ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R7(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); /* R8 */ subRect.x = sRect->x+sRect->w ; subRect.y = sRect->y+sRect->h ; subRect.w = img->fd_w-sRect->x-sRect->w ; subRect.h = img->fd_h-sRect->y-sRect->h ; if (MayAddRect( &subRect, sgProps )) if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG,"Adding R8(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h); } } short GetSymetryUsageFromIni(void) { short use_sym = 1 ; /* Unless INI file say no, assume symetry usage */ long found = 0 ; char *path_ldv, *language ; char val_key[64] ; path_ldv = Vapi->CoGetLDVPath() ; language = Vapi->CoGetCurrentLanguage() ; if ( path_ldv && language && Vapi->InGetKeyFromFile ) { char filename[256] ; sprintf( filename, "%s\\%s\\BHOLE.INI", path_ldv, language ) ; if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_INFO,"Looking into %s to see symetry usage...", filename) ; found = Vapi->InGetKeyFromFile( filename, "Private", "UseSym", val_key ) ; if ( !found ) { sprintf( filename, "%s\\BHOLE.INI", path_ldv ) ; if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_INFO,"Looking into non language specific %s to see symetry usage...", filename) ; found = Vapi->InGetKeyFromFile( filename, "Private", "UseSym", val_key ) ; } } else if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_WARNING,"Can't access LDV (%s) or language path (%s)!", path_ldv, language) ; if ( found ) use_sym = atoi( val_key ) ; if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_INFO,"Symetry usage: %d (found=%ld)", use_sym, found) ; return use_sym ; } /* LDV Run routine */ LDV_STATUS cdecl Run(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) { BH_SPROPERTIES sgProps ; LDV_STATUS (*RunRoutine)(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym) ; LDV_STATUS status = ELDV_NOERROR ; long angle, np=0 ; short xc, yc, n ; if ( Vapi->Header.Version < 0x102 ) return ELDV_BADVAPIVERSION ; if ( InitTrigo((ProcMask & CO_HAS_FPU) == CO_HAS_FPU) != 0 ) return ELDV_NOTENOUGHMEMORY ; if ( compute_loffset(&in->Raster, &pre_loffset, &lo_w, &lo_h, &lo_nplanes) ) return ELDV_NOTENOUGHMEMORY ; if ( UseSym == -1 ) UseSym = GetSymetryUsageFromIni() ; if ( in->Raster.fd_nplanes <= 8 ) { BHLRoutine = BHLInd_68000 ; RunRoutine = bpRun ; } else if ( in->Raster.fd_nplanes == 16 ) { BHLRoutine = BHL16_68000 ; RunRoutine = Run16 ; } else if ( in->Raster.fd_nplanes == 32 ) { BHLRoutine = BHL32_68000 ; RunRoutine = Run32 ; } else return ELDV_IMGFORMATMISMATCH ; if (ProcMask & CO_HAS_030) { if (ProcMask & CO_HAS_FPU) { /* Note that FPU requires also a 68030 here */ /* To avoid having another set of macros in bhole.s */ /* And convert even 68000 routines to ASM */ /* FPU won't speed-up computations; it will just */ /* Make the angle proportional to the distance to */ /* Black Hole Center instead of its square */ Vapi->PrOptimize(0x05) ; if ( in->Raster.fd_nplanes <= 8 ) BHLRoutine = BHLInd_F68030 ; else if ( in->Raster.fd_nplanes == 16 ) BHLRoutine = BHL16_F68030 ; else if ( in->Raster.fd_nplanes == 32 ) BHLRoutine = BHL32_F68030 ; } else { /* CPU 030 'only', note that it is about 2 times faster than 68000 */ /* Routine mostly because of 32x32x-->32 MULS.L instruction */ Vapi->PrOptimize(0x01) ; if ( in->Raster.fd_nplanes <= 8 ) BHLRoutine = BHLInd_68030 ; else if ( in->Raster.fd_nplanes == 16 ) BHLRoutine = BHL16_68030 ; else if ( in->Raster.fd_nplanes == 32 ) BHLRoutine = BHL32_68030 ; } } angle = (long) params->Param[0].s ; xc = ((long)params->Param[1].s * (long)in->Raster.fd_w)/100L ; yc = ((long)params->Param[2].s * (long)in->Raster.fd_h)/100L ; SymmetrySplit(&in->Raster, xc, yc, &sgProps) ; if (Vapi->LoDoLog) { Vapi->LoDoLog(LL_DEBUG, "100 being the time without using symmetry, using symmetry would be %d", sgProps.estdpc) ; Vapi->LoDoLog(LL_DEBUG, "Image source : (0,0,+%d,+%d); %ld pixels", in->Raster.fd_w, in->Raster.fd_h, (long)in->Raster.fd_w * (long)in->Raster.fd_h) ; Vapi->LoDoLog(LL_DEBUG, "Symmetry zone : (%d,%d,+%d,+%d), index:%d", sgProps.rect[0].x, sgProps.rect[0].y, sgProps.rect[0].w, sgProps.rect[0].h, sgProps.nsym) ; } bh_nrect = sgProps.nrect ; for ( n=0; (status != ELDV_CANCELLED) && (n < sgProps.nrect); n++) { long npix ; bh_pc = (100*n)/sgProps.nrect ; /* For progression indicator as we may have multiple loops */ npix = (long)sgProps.rect[n].w * (long)sgProps.rect[n].h ; np += npix ; if ( VapiLogLevel >= LL_PERF) { size_t t0, tms ; t0 = clock() ; status = RunRoutine( &in->Raster, angle, xc, yc, &out->Raster, &sgProps.rect[n], (sgProps.nsym == n) ) ; tms = (1000L * (clock() - t0) ) / CLK_TCK ; if (tms == 0 ) tms = 1 ; if (Vapi->LoDoLog) Vapi->LoDoLog(LL_PERF, "Run zone %d: (%d,%d,+%d,+%d), use_sym=%d, %ld pixels, done in %ldms, %ld Kpixels/s", n, sgProps.rect[n].x, sgProps.rect[n].y, sgProps.rect[n].w, sgProps.rect[n].h, (sgProps.nsym == n), (long)sgProps.rect[n].w * (long)sgProps.rect[n].h, tms, npix/tms) ; } else status = RunRoutine( &in->Raster, angle, xc, yc, &out->Raster, &sgProps.rect[n], (sgProps.nsym == n) ) ; } if (Vapi->LoDoLog) Vapi->LoDoLog(LL_DEBUG, "%ld pixels computed or deduced", np) ; return( status ) ; } LDV_STATUS cdecl Preview(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) { return( Run( in, params, out ) ) ; } int main(void) { ldg_init( Ldg ) ; return( 0 ) ; }