Example #1
0
File: str.c Project: kanzure/brlcad
char *
bu_strdupm(register const char *cp, const char *label)
{
    char *base;
    size_t len;

    if (UNLIKELY(!cp && label)) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fprintf(stderr, "WARNING: [%s] NULL copy buffer\n", label);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
    if (!label) {
	label = "bu_strdup";
    }

    len = strlen(cp)+1;
    base = (char *)bu_malloc(len, label);

    if (UNLIKELY(bu_debug&BU_DEBUG_MEM_LOG)) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fprintf(stderr, "%p strdup%llu \"%s\"\n", (void *)base, (unsigned long long)len, cp);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    memcpy(base, cp, len);
    return base;
}
Example #2
0
void
db_sync(struct db_i *dbip)
{
    RT_CK_DBI(dbip);

    bu_semaphore_acquire(BU_SEM_SYSCALL);

    /* make sure we have something to do */
    if (!dbip->dbi_fp) {
	bu_semaphore_release(BU_SEM_SYSCALL);
	return;
    }

    /* flush the file */
    (void)fflush(dbip->dbi_fp);

#if defined(HAVE_FSYNC) && !defined(STRICT_FLAGS)
    /* make sure it's written out */
    (void)fsync(fileno(dbip->dbi_fp));
#else
#  if defined(HAVE_SYNC) && !defined(STRICT_FLAGS)
    /* try the whole filesystem if sans fsync() */
    sync();
#  endif
#endif

    bu_semaphore_release(BU_SEM_SYSCALL);
}
HIDDEN void
parallel_interface_arg(struct thread_data *user_thread_data)
{
    /* keep track of our parallel ID number */
    thread_set_cpu(user_thread_data->cpu_id);

    if (user_thread_data->affinity) {
	int ret;
	/* lock us onto a core corresponding to our parallel ID number */
	ret = parallel_set_affinity(user_thread_data->cpu_id);
	if (ret) {
	    bu_log("WARNING: encountered unexpected problem setting CPU affinity\n");
	}
    }

    bu_semaphore_acquire(BU_SEM_THREAD);
    user_thread_data->parent->started++;
    bu_semaphore_release(BU_SEM_THREAD);

    (*(user_thread_data->user_func))(user_thread_data->cpu_id, user_thread_data->user_arg);

    bu_semaphore_acquire(BU_SEM_THREAD);
    user_thread_data->parent->finished++;
    bu_semaphore_release(BU_SEM_THREAD);

    parallel_mapping(PARALLEL_PUT, user_thread_data->cpu_id, 0);

}
Example #4
0
HIDDEN void
parallel_interface_arg(struct thread_data *user_thread_data)
{
    /* keep track of our parallel ID number */
    thread_set_cpu(user_thread_data->cpu_id);

    if (user_thread_data->affinity) {
	int ret;
	/* lock us onto a core corresponding to our parallel ID number */
	ret = parallel_set_affinity(user_thread_data->cpu_id);
	if (ret) {
	    bu_log("WARNING: encountered unexpected problem setting CPU affinity\n");
	}
    }

    if (!user_thread_data->counted) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	parallel_nthreads_started++;
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    (*(user_thread_data->user_func))(user_thread_data->cpu_id, user_thread_data->user_arg);

    if (!user_thread_data->counted) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	parallel_nthreads_finished++;
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
}
Example #5
0
void
paintCellFb(struct application *ap, unsigned char *pixpaint, unsigned char *pixexpendable)
{
    int gx, gy;
    int gyfin, gxfin;
    int gxorg, gyorg;
    int x, y;
    int cnt;
#if DEBUG_CELLFB
    brst_log("paintCellFb: expendable {%d, %d, %d}\n",
	     pixexpendable[RED],
	     pixexpendable[GRN],
	     pixexpendable[BLU]);
#endif
    gridToFb(ap->a_x, ap->a_y, &gx, &gy);
    gxorg = gx+1;
    gyorg = gy+1;
    gxfin = zoom == 1 ? gx+zoom+1 : gx+zoom;
    gyfin = zoom == 1 ? gy+zoom+1 : gy+zoom;
    cnt = gxfin - gxorg;
    for (y = gyorg; y < gyfin; y++) {
	if (zoom != 1 && (y - gy) % zoom == 0)
	    continue;
	bu_semaphore_acquire(RT_SEM_STATS);
	(void) fb_read(fbiop, gxorg, y, (unsigned char *)pixbuf, cnt);
	bu_semaphore_release(RT_SEM_STATS);
	for (x = gxorg; x < gxfin; x++) {
	    if (SAMERGB(&pixbuf[x-gxorg][0], pixexpendable)
		) {
#if DEBUG_CELLFB
		brst_log("Clobbering:<%d, %d>{%d, %d, %d}\n",
			 x, y,
			 pixbuf[x-gxorg][RED],
			 pixbuf[x-gxorg][GRN],
			 pixbuf[x-gxorg][BLU]);
#endif
		COPYRGB(&pixbuf[x-gxorg][0], pixpaint);
	    }
#if DEBUG_CELLFB
	    else
		brst_log("Preserving:<%d, %d>{%d, %d, %d}\n",
			 x, y,
			 pixbuf[x-gxorg][RED],
			 pixbuf[x-gxorg][GRN],
			 pixbuf[x-gxorg][BLU]);
#endif
	}
	bu_semaphore_acquire(RT_SEM_STATS);
	(void) fb_write(fbiop, gxorg, y, (unsigned char *)pixbuf, cnt);
	bu_semaphore_release(RT_SEM_STATS);
#if DEBUG_CELLFB
	brst_log("paintCellFb: fb_write(%d, %d)\n", x, y);
#endif
    }
    return;
}
Example #6
0
void
bu_free_mapped_files(int verbose)
{
    struct bu_mapped_file *mp, *next;

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	bu_log("bu_free_mapped_files(verbose=%d)\n", verbose);

    bu_semaphore_acquire(BU_SEM_MAPPEDFILE);

    next = BU_LIST_FIRST(bu_mapped_file, &bu_mapped_file_list);
    while (BU_LIST_NOT_HEAD(next, &bu_mapped_file_list)) {
	BU_CK_MAPPED_FILE(next);
	mp = next;
	next = BU_LIST_NEXT(bu_mapped_file, &mp->l);

	if (mp->uses > 0)  continue;

	/* Found one that needs to have storage released */
	if (UNLIKELY(verbose || (bu_debug&BU_DEBUG_MAPPED_FILE)))
	    bu_pr_mapped_file("freeing", mp);

	BU_LIST_DEQUEUE(&mp->l);

	/* If application pointed mp->apbuf at mp->buf, break that
	 * association so we don't double-free the buffer.
	 */
	if (mp->apbuf == mp->buf)  mp->apbuf = (void *)NULL;

#ifdef HAVE_SYS_MMAN_H
	if (mp->is_mapped) {
	    int ret;
	    bu_semaphore_acquire(BU_SEM_SYSCALL);
	    ret = munmap(mp->buf, (size_t)mp->buflen);
	    bu_semaphore_release(BU_SEM_SYSCALL);

	    if (UNLIKELY(ret < 0))
		perror("munmap");

	    /* XXX How to get this chunk of address space back to malloc()? */
	} else
#endif
	{
	    bu_free(mp->buf, "bu_mapped_file.buf[]");
	}
	mp->buf = (void *)NULL;		/* sanity */
	bu_free((void *)mp->name, "bu_mapped_file.name");

	if (mp->appl)
	    bu_free((void *)mp->appl, "bu_mapped_file.appl");

	bu_free((void *)mp, "struct bu_mapped_file");
    }
    bu_semaphore_release(BU_SEM_MAPPEDFILE);
}
Example #7
0
File: str.c Project: kanzure/brlcad
size_t
bu_strlcatm(char *dst, const char *src, size_t size, const char *label)
{
    size_t srcsize;
    size_t dstsize;

    if (!dst && label) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fprintf(stderr, "WARNING: NULL destination string, size %lu [%s]\n", (unsigned long)size, label);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
    if (UNLIKELY(!dst || !src || size <= 0)) {
	return 0;
    }
    if (!label) {
	label = "bu_strlcat";
    }

    dstsize = strlen(dst);
    srcsize = strlen(src);

    if (UNLIKELY(dstsize == size - 1)) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fprintf(stderr, "WARNING: [%s] concatenation string is already full at %lu chars\n", label, (unsigned long)size-1);
	bu_semaphore_release(BU_SEM_SYSCALL);
    } else if (UNLIKELY(dstsize > size - 1)) {
	/* probably missing null-termination or is not an initialized buffer */
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fprintf(stderr, "WARNING: [%s] concatenation string is already full, exceeds size (%lu > %lu)\n", label, (unsigned long)dstsize, (unsigned long)size-1);
	bu_semaphore_release(BU_SEM_SYSCALL);
    } else if (UNLIKELY(srcsize > size - dstsize - 1)) {
	if (UNLIKELY(bu_debug)) {
	    bu_semaphore_acquire(BU_SEM_SYSCALL);
	    fprintf(stderr, "WARNING: [%s] string truncation, exceeding %lu char max concatenating %lu chars (started with %lu)\n", label, (unsigned long)size-1, (unsigned long)srcsize, (unsigned long)dstsize);
	    bu_semaphore_release(BU_SEM_SYSCALL);
	}
    }

#ifdef HAVE_STRLCAT
    /* don't return to ensure consistent null-termination behavior in following */
    (void)strlcat(dst, src, size);
#else
    (void)strncat(dst, src, size - dstsize - 1);
#endif

    /* be sure to null-terminate, contrary to strncat behavior */
    if (dstsize + srcsize < size - 1) {
	dst[dstsize + srcsize] = '\0';
    } else {
	dst[size-1] = '\0'; /* sanity */
    }

    return strlen(dst);
}
Example #8
0
void
bn_noise_init(void)
{
    int i, j, k, temp;
    int rndtabi = BN_RAND_TABSIZE - 1;

    bu_semaphore_acquire( BU_SEM_BN_NOISE );

    if (ht.hashTableValid) {
	bu_semaphore_release( BU_SEM_BN_NOISE );
	return;
    }

    BN_RANDSEED(rndtabi, (BN_RAND_TABSIZE-1) );
    ht.hashTableMagic1 = (long *) bu_malloc(
	2*sizeof(long) + 4096*sizeof(short int),
	"noise hashTable");
    ht.hashTable = (short *)&ht.hashTableMagic1[1];
    ht.hashTableMagic2 = (long *)&ht.hashTable[4096];

    *ht.hashTableMagic1 = MAGIC_TAB1;
    *ht.hashTableMagic2 = MAGIC_TAB2;

    ht.magic_end = MAGIC_STRHT2;
    ht.magic = MAGIC_STRHT1;

    for (i = 0; i < 4096; i++)
	ht.hashTable[i] = i;

    /* scramble the hash table */
    for (i = 4095; i > 0; i--) {
	j = (int)(BN_RANDOM(rndtabi) * 4096.0);

	temp = ht.hashTable[i];
	ht.hashTable[i] = ht.hashTable[j];
	ht.hashTable[j] = temp;
    }

    BN_RANDSEED(k, 13);

    for (i = 0; i < MAXSIZE; i++)
	RTable[i] = BN_RANDOM(k) * 2.0 - 1.0;


    ht.hashTableValid = 1;

    bu_semaphore_release( BU_SEM_BN_NOISE );


    CK_HT();
}
Example #9
0
/**
 * b u _ v l s _ r e a d
 *
 * Read the remainder of a UNIX file onto the end of a vls.
 *
 * Returns -
 *	nread	number of characters read
 *	0	if EOF encountered immediately
 *	-1	read error
 */
int
bu_vls_read( struct bu_vls *vp, int fd )
{
    size_t todo;
    int	got;
    int	ret = 0;

    BU_CK_VLS(vp);

    for (;;)  {
	bu_vls_extend( vp, _VLS_ALLOC_READ );
	todo = (size_t)vp->vls_max - vp->vls_len - vp->vls_offset - 1;
	
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	got = read(fd, vp->vls_str+vp->vls_offset+vp->vls_len, todo );
	bu_semaphore_release(BU_SEM_SYSCALL);
	
	if ( got < 0 )  {
	    /* Read error, abandon the read */
	    return -1;
	}
	if (got == 0)
	    break;

	vp->vls_len += got;
	ret += got;
    }

    /* force null termination */
    vp->vls_str[vp->vls_len+vp->vls_offset] = '\0';

    return ret;
}
Example #10
0
static union tree *
bev_facetize_region_end(struct db_tree_state *UNUSED(tsp), const struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
{
    struct bu_list vhead;
    struct ged *gedp = (struct ged *)client_data;

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK) {
	char *sofar = db_path_to_string(pathp);

	bu_vls_printf(gedp->ged_result_str, "bev_facetize_region_end() path='%s'\n", sofar);
	bu_free((genptr_t)sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP) return curtree;

    bu_semaphore_acquire(RT_SEM_MODEL);
    if (bev_facetize_tree) {
	union tree *tr;
	BU_ALLOC(tr, union tree);
	RT_TREE_INIT(tr);
	tr->tr_op = OP_UNION;
	tr->tr_b.tb_regionp = REGION_NULL;
	tr->tr_b.tb_left = bev_facetize_tree;
	tr->tr_b.tb_right = curtree;
	bev_facetize_tree = tr;
    } else {
	bev_facetize_tree = curtree;
    }
    bu_semaphore_release(RT_SEM_MODEL);

    /* Tree has been saved, and will be freed later */
    return TREE_NULL;
}
Example #11
0
/*
 *			R A Y M I S S
 *
 *  Called via a_miss linkage from rt_shootray() when ray misses.
 */
int
raymiss(register struct application *ap)
{
    bu_semaphore_acquire( RT_SEM_RESULTS );
    scanbuf[ap->a_x] = 255;
    bu_semaphore_release( RT_SEM_RESULTS );
    return(0);
}
Example #12
0
/*
 *			R A Y H I T
 *
 *  Called via a_hit linkage from rt_shootray() when ray hits.
 */
int
rayhit(register struct application *ap, struct partition *PartHeadp, struct seg *segp)
{
    bu_semaphore_acquire( RT_SEM_RESULTS );
    scanbuf[ap->a_x] = 1;
    bu_semaphore_release( RT_SEM_RESULTS );
    return(1);	/* report hit to main routine */
}
Example #13
0
File: str.c Project: kanzure/brlcad
size_t
bu_strlcpym(char *dst, const char *src, size_t size, const char *label)
{
    size_t srcsize;


    if (UNLIKELY(!dst && label)) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fprintf(stderr, "WARNING: NULL destination string, size %lu [%s]\n", (unsigned long)size, label);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
    if (UNLIKELY(!dst || !src || size <= 0)) {
	return 0;
    }
    if (!label) {
	label = "bu_strlcpy";
    }

    srcsize = strlen(src);

    if (UNLIKELY(bu_debug)) {
	if (srcsize > size - 1) {
	    bu_semaphore_acquire(BU_SEM_SYSCALL);
	    fprintf(stderr, "WARNING: [%s] string truncation, exceeding %lu char max copying %lu chars\n", label, (unsigned long)size-1, (unsigned long)srcsize);
	    bu_semaphore_release(BU_SEM_SYSCALL);
	}
    }

#ifdef HAVE_STRLCPY
    /* don't return to ensure consistent null-termination behavior in following */
    (void)strlcpy(dst, src, size);
#else
    (void)strncpy(dst, src, size - 1);
#endif

    /* be sure to always null-terminate, contrary to strncpy behavior */
    if (srcsize < size - 1) {
	dst[srcsize] = '\0';
    } else {
	dst[size-1] = '\0'; /* sanity */
    }

    return strlen(dst);
}
Example #14
0
/*
 *			V I E W _ E O L
 *
 *  Called by worker() at the end of each line.  Depricated.
 *  Any end-of-line processing should be done in view_pixel().
 */
void
view_eol(register struct application *ap)
{
    bu_semaphore_acquire( BU_SEM_SYSCALL );
    if ( outfp != NULL )
	fwrite( scanbuf, 1, width, outfp );
#if 0
    else if ( fbp != FBIO_NULL )
	fb_write( fbp, 0, ap->a_y, scanbuf, width );
#endif
    bu_semaphore_release( BU_SEM_SYSCALL );
}
Example #15
0
/**
 * grab the next row of rays to be evaluated
 */
int
get_next_row(struct fitness_state *fstate)
{
    int r;
    bu_semaphore_acquire(SEM_WORK);
    if (fstate->row < fstate->res[Y])
	r = ++fstate->row; /* get a row to work on */
    else
	r = 0; /* signal end of work */
    bu_semaphore_release(SEM_WORK);

    return r;
}
Example #16
0
struct region_pair *
add_unique_pair(struct region_pair *list, /* list to add into */
		struct region *r1,        /* first region involved */
		struct region *r2,        /* second region involved */
		double dist,              /* distance/thickness metric value */
		point_t pt)               /* location where this takes place */
{
    struct region_pair *rp, *rpair;

    /* look for it in our list */
    bu_semaphore_acquire(GED_SEM_LIST);
    for (BU_LIST_FOR (rp, region_pair, &list->l)) {

	if ((r1 == rp->r.r1 && r2 == rp->r2) || (r1 == rp->r2 && r2 == rp->r.r1)) {
	    /* we already have an entry for this region pair, we
	     * increase the counter, check the depth and update
	     * thickness maximum and entry point if need be and
	     * return.
	     */
	    rp->count++;

	    if (dist > rp->max_dist) {
		rp->max_dist = dist;
		VMOVE(rp->coord, pt);
	    }
	    rpair = rp;
	    goto found;
	}
    }
    /* didn't find it in the list.  Add it */
    BU_ALLOC(rpair, struct region_pair);
    rpair->r.r1 = r1;
    rpair->r2 = r2;
    rpair->count = 1;
    rpair->max_dist = dist;
    VMOVE(rpair->coord, pt);
    list->max_dist ++; /* really a count */

    /* insert in the list at the "nice" place */
    for (BU_LIST_FOR (rp, region_pair, &list->l)) {
	if (bu_strcmp(rp->r.r1->reg_name, r1->reg_name) <= 0)
	    break;
    }
    BU_LIST_INSERT(&rp->l, &rpair->l);
 found:
    bu_semaphore_release(GED_SEM_LIST);
    return rpair;
}
Example #17
0
void
bu_close_mapped_file(struct bu_mapped_file *mp)
{
    BU_CK_MAPPED_FILE(mp);

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	bu_pr_mapped_file("close:uses--", mp);

    if (UNLIKELY(!mp)) {
	bu_log("bu_close_mapped_file() called with null pointer\n");
	return;
    }

    bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
    --mp->uses;
    bu_semaphore_release(BU_SEM_MAPPEDFILE);
}
void
plotPartition(struct hit *ihitp, struct hit *ohitp)
{
    if (plotfp == NULL)
	return;
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    pl_3line(plotfp,
	     (int) ihitp->hit_point[X],
	     (int) ihitp->hit_point[Y],
	     (int) ihitp->hit_point[Z],
	     (int) ohitp->hit_point[X],
	     (int) ohitp->hit_point[Y],
	     (int) ohitp->hit_point[Z]
	);
    bu_semaphore_release(BU_SEM_SYSCALL);
    return;
}
void
plotRayPoint(struct xray *rayp)
{
    int endpoint[3];
    if (plotfp == NULL)
	return;
    VJOIN1(endpoint, rayp->r_pt, cellsz, rayp->r_dir);

    bu_semaphore_acquire(BU_SEM_SYSCALL);
    pl_color(plotfp, R_BURST, G_BURST, B_BURST);

    /* draw point */
    pl_3point(plotfp, (int) endpoint[X], (int) endpoint[Y], (int) endpoint[Z]);

    bu_semaphore_release(BU_SEM_SYSCALL);
    return;
}
/* this function provides book-keeping so that we give out unique
 * thread identifiers and for tracking a thread's parent context.
 */
static struct parallel_info *
parallel_mapping(parallel_action_t action, int id, size_t max)
{
    /* container for keeping track of recursive invocation data, limits, current values */
    static struct parallel_info mapping[MAX_PSW] = {{0,0,0,0,0}};
    int got_cpu;

    switch (action) {
	case PARALLEL_GET:
	    if (id < 0) {
		bu_semaphore_acquire(BU_SEM_THREAD);
		for (got_cpu = 1; got_cpu < MAX_PSW; got_cpu++) {
		    if (mapping[got_cpu].id == 0) {
			mapping[got_cpu].id = got_cpu;
			break;
		    }
		}
		bu_semaphore_release(BU_SEM_THREAD);

		if (got_cpu >= MAX_PSW)
		    bu_bomb("Compile-time parallelism limit reached.  Unable to track more threading.\n");

		mapping[got_cpu].started = mapping[got_cpu].finished = 0;
		mapping[got_cpu].parent = bu_parallel_id();

	    } else {
		got_cpu = id;
		if (mapping[got_cpu].id != got_cpu) {
		    /* presumably id == 0 */
		    mapping[got_cpu].id = got_cpu;
		}
	    }

	    if (mapping[got_cpu].lim == 0 && max > 0)
		mapping[got_cpu].lim = max;

	    return &mapping[got_cpu];

	case PARALLEL_PUT:
	    mapping[id].started = mapping[id].finished = mapping[id].lim = mapping[id].parent = 0;
	    mapping[id].id = 0; /* separate to avoid race */
    }

    return NULL;
}
Example #21
0
/**
 * b u _ v l s _ w r i t e
 *
 * Write the VLS to the provided file descriptor.
 */
void
bu_vls_write( int fd, const struct bu_vls *vp )
{
    int status;

    BU_CK_VLS(vp);

    if ( vp->vls_len <= 0 )
	return;

    bu_semaphore_acquire(BU_SEM_SYSCALL);
    status = write( fd, vp->vls_str + vp->vls_offset, (size_t)vp->vls_len );
    bu_semaphore_release(BU_SEM_SYSCALL);
    
    if ( status != vp->vls_len ) {
	perror("write");
	bu_bomb("bu_vls_write() write error\n");
    }
}
Example #22
0
/**
 * b u _ v l s _ f w r i t e
 *
 * Write the VLS to the provided file pointer.
 */
void
bu_vls_fwrite(FILE *fp, const struct bu_vls *vp)
{
    int status;

    BU_CK_VLS(vp);

    if ( vp->vls_len <= 0 )
	return;

    bu_semaphore_acquire(BU_SEM_SYSCALL);
    status = fwrite( vp->vls_str + vp->vls_offset, (size_t)vp->vls_len, 1, fp );
    bu_semaphore_release(BU_SEM_SYSCALL);

    if ( status != 1 ) {
	perror("fwrite");
	bu_bomb("bu_vls_fwrite() write error\n");
    }
}
Example #23
0
void
paintSpallFb(struct application *ap)
{
    unsigned char pixel[3];
    int x, y;
    int err;
    fastf_t celldist;
#if DEBUG_SPALLFB
    brst_log("paintSpallFb: a_x=%d a_y=%d a_cumlen=%g cellsz=%g zoom=%d\n",
	     ap->a_x, ap->a_y, ap->a_cumlen, cellsz, zoom);
#endif
    pixel[RED] = ap->a_color[RED] * 255;
    pixel[GRN] = ap->a_color[GRN] * 255;
    pixel[BLU] = ap->a_color[BLU] * 255;
    gridToFb(ap->a_x, ap->a_y, &x, &y);
    CenterCell(x);	/* center of cell */
    CenterCell(y);
    celldist = ap->a_cumlen/cellsz * zoom;
    x = roundToInt(x + VDOT(ap->a_ray.r_dir, gridhor) * celldist);
    y = roundToInt(y + VDOT(ap->a_ray.r_dir, gridver) * celldist);
    bu_semaphore_acquire(RT_SEM_STATS);
    err = fb_write(fbiop, x, y, pixel, 1);
    bu_semaphore_release(RT_SEM_STATS);
#if DEBUG_SPALLFB
    brst_log("paintSpallFb:gridhor=<%g, %g, %g> gridver=<%g, %g, %g>\n",
	     gridhor[X], gridhor[Y], gridhor[Z],
	     gridver[X], gridver[Y], gridver[Z]);
    brst_log("paintSpallFb:fb_write(x=%d, y=%d, pixel={%d, %d, %d})\n",
	     x, y,
	     (int) pixel[RED],
	     (int) pixel[GRN],
	     (int) pixel[BLU]
	);
#endif
    if (err == -1)
	brst_log("Write failed to pixel <%d, %d> from cell <%d, %d>.\n",
		 x, y, ap->a_x, ap->a_y);
    return;
}
void
prnt_Scroll(const char *fmt, ...)
{
    va_list ap;
    /* We use the same lock as malloc.  Sys-call or mem lock, really */
    bu_semaphore_acquire(BU_SEM_SYSCALL);		/* lock */
    va_start(ap, fmt);
    if (tty) {
	/* Only move cursor and scroll if newline is output.	*/
	static int newline = 1;
	if (CS != NULL) {
	    SetScrlReg(TOP_SCROLL_WIN, PROMPT_LINE - 1);
	    if (newline) {
		SCROLL_PR_MOVE();
		(void) ClrEOL();
	    }
	    (void)vfprintf(stdout, fmt, ap);
	    (void) ResetScrlReg();
	} else if (DL != NULL) {
	    if (newline) {
		SCROLL_DL_MOVE();
		(void) DeleteLn();
		SCROLL_PR_MOVE();
		(void) ClrEOL();
	    }
	    (void)vfprintf(stdout, fmt, ap);
	} else
	    (void)vfprintf(stdout, fmt, ap);

	/* End of line detected by existence of a newline. */
	newline = fmt[strlen(fmt)-1] == '\n';
	hmredraw();
    } else
	(void)vfprintf(stderr, fmt, ap);
    va_end(ap);
    bu_semaphore_release(BU_SEM_SYSCALL);		/* unlock */
    return;
}
Example #25
0
/*
 *  Log an error.
 *  This version buffers a full line, to save network traffic.
 */
void
bu_log(const char *fmt, ...)
{
    va_list vap;
    char buf[512];		/* a generous output line.  Must be AUTO, else non-PARALLEL. */

    if (print_on == 0)  return;
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    va_start(vap, fmt);
    (void)vsprintf(buf, fmt, vap);
    va_end(vap);

    if (pcsrv == PKC_NULL || pcsrv == PKC_ERROR)  {
	fprintf(stderr, "%s", buf);
	goto out;
    }
    if (debug) fprintf(stderr, "%s", buf);
    if (pkg_send(MSG_PRINT, buf, strlen(buf)+1, pcsrv) < 0)  {
	fprintf(stderr, "pkg_send MSG_PRINT failed\n");
	bu_exit(12, NULL);
    }
 out:
    bu_semaphore_release(BU_SEM_SYSCALL);
}
Example #26
0
struct fbm_spec		*
find_spec_wgt(double h, double l, double o)
{
    struct fbm_spec	*ep;
    int i;


    for (ep = etbl, i=0; i < etbl_next; i++, ep++) {
	if (ep->magic != MAGIC_fbm_spec_wgt)
	    bu_bomb("find_spec_wgt");
	if (ep->lacunarity == l && ep->h_val == h && ep->octaves >= o)
	    return ep;
    }

    /* we didn't find the table we wanted so we've got to semaphore on
     * the list to wait our turn to add what we want to the table.
     */

    bu_semaphore_acquire( BU_SEM_BN_NOISE );

    /* We search the list one more time in case the last process to
     * hold the semaphore just created the table we were about to add
     */
    for (ep = etbl, i=0; i < etbl_next; i++, ep++) {
	if (ep->magic != MAGIC_fbm_spec_wgt)
	    bu_bomb("find_spec_wgt");
	if (ep->lacunarity == l && ep->h_val == h && ep->octaves >= o)
	    break;
    }

    if (i >= etbl_next) ep = build_spec_tbl(h, l, o);

    bu_semaphore_release( BU_SEM_BN_NOISE );

    return (ep);
}
Example #27
0
/*
 *			R A Y H I T
 *
 *  Rayhit() is called by rt_shootray() when the ray hits one or more objects.
 *  A per-shotline header record is written, followed by information about
 *  each object hit.
 *
 *  Note that the GIFT-3 format uses a different convention for the "zero"
 *  distance along the ray.  RT has zero at the ray origin (emanation plain),
 *  while GIFT has zero at the screen plain translated so that it contains
 *  the model origin.  This difference is compensated for by adding the
 *  'dcorrection' distance correction factor.
 *
 *  Also note that the GIFT-3 format requires information about the start
 *  point of the ray in two formats.  First, the h, v coordinates of the
 *  grid cell CENTERS (in screen space coordinates) are needed.
 *  Second, the ACTUAL h, v coordinates fired from are needed.
 *
 *  An optional rtg3.pl UnixPlot file is written, permitting a
 *  color vector display of ray-model intersections.
 */
int
rayhit(struct application *ap, register struct partition *PartHeadp, struct seg *segp)
{
    register struct partition *pp = PartHeadp->pt_forw;
    int 			comp_count;	/* component count */
    fastf_t			dfirst, dlast;	/* ray distances */
    static fastf_t		dcorrection = 0; /* RT to GIFT dist corr */
    int			card_count;	/* # comp. on this card */
    const char		*fmt;		/* printf() format string */
    struct bu_vls		str;
    char			buf[128];	/* temp. sprintf() buffer */
    point_t			hv;		/* GIFT h, v coords, in inches */
    point_t			hvcen;
    int			prev_id=-1;
    point_t			first_hit;
    int			first;

    if ( pp == PartHeadp )
	return(0);		/* nothing was actually hit?? */

    if ( ap->a_rt_i->rti_save_overlaps )
	rt_rebuild_overlaps( PartHeadp, ap, 1 );

    part_compact(ap, PartHeadp, TOL);

    /* count components in partitions */
    comp_count = 0;
    for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw )  {
	if ( pp->pt_regionp->reg_regionid > 0 ) {
	    prev_id = pp->pt_regionp->reg_regionid;
	    comp_count++;
	} else if ( prev_id <= 0 ) {
	    /* normally air would be output along with a solid partition, but this will require a '111' partition */
	    prev_id = pp->pt_regionp->reg_regionid;
	    comp_count++;
	} else
	    prev_id = pp->pt_regionp->reg_regionid;
    }
    pp = PartHeadp->pt_back;
    if ( pp!=PartHeadp && pp->pt_regionp->reg_regionid <= 0 )
	comp_count++;  /* a trailing '111' ident */
    if ( comp_count == 0 )
	return( 0 );

    /* Set up variable length string, to buffer this shotline in.
     * Note that there is one component per card, and that each card
     * (line) is 80 characters long.  Hence the parameters given to
     * rt-vls-extend().
     */

    bu_vls_init( &str );
    bu_vls_extend( &str, 80 * (comp_count+1) );

    /*
     *  Find the H, V coordinates of the grid cell center.
     *  RT uses the lower left corner of each cell.
     */
    {
	point_t		center;
	fastf_t		dx;
	fastf_t		dy;

	dx = ap->a_x + 0.5;
	dy = ap->a_y + 0.5;
	VJOIN2( center, viewbase_model, dx, dx_model, dy, dy_model );
	MAT4X3PNT( hvcen, model2hv, center );
    }

    /*
     *  Find exact h, v coordinates of actual ray start by
     *  projecting start point into GIFT h, v coordinates.
     */
    MAT4X3PNT( hv, model2hv, ap->a_ray.r_pt );

    /*
     *  In RT, rays are launched from the plane of the screen,
     *  and ray distances are relative to the start point.
     *  In GIFT-3 output files, ray distances are relative to
     *  the (H, V) plane translated so that it contains the origin.
     *  A distance correction is required to convert between the two.
     *  Since this really should be computed only once, not every time,
     *  the trip_count flag was added.
     */
    {

	static int  trip_count;
	vect_t	tmp;
	vect_t	viewZdir;

	if ( trip_count == 0) {

	    VSET( tmp, 0, 0, -1 );		/* viewing direction */
	    MAT4X3VEC( viewZdir, view2model, tmp );
	    VUNITIZE( viewZdir );
	    /* dcorrection will typically be negative */
	    dcorrection = VDOT( ap->a_ray.r_pt, viewZdir );
	    trip_count = 1;
	}
    }

    /* This code is for diagnostics.
     * bu_log("dcorrection=%g\n", dcorrection);
     */

    /* dfirst and dlast have been made negative to account for GIFT looking
     * in the opposite direction of RT.
     */

    dfirst = -(PartHeadp->pt_forw->pt_inhit->hit_dist + dcorrection);
    dlast = -(PartHeadp->pt_back->pt_outhit->hit_dist + dcorrection);
#if 0
    /* This code is to note any occurances of negative distances. */
    if ( PartHeadp->pt_forw->pt_inhit->hit_dist < 0)  {
	bu_log("ERROR: dfirst=%g at partition x%x\n", dfirst, PartHeadp->pt_forw );
	bu_log("\tdcorrection = %f\n", dcorrection );
	bu_log("\tray start point is ( %f %f %f ) in direction ( %f %f %f )\n", V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ) );
	VJOIN1( PartHeadp->pt_forw->pt_inhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_inhit->hit_dist, ap->a_ray.r_dir );
	VJOIN1( PartHeadp->pt_back->pt_outhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_outhit->hit_dist, ap->a_ray.r_dir );
	rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
    }
    /* End of bug trap. */
#endif
    /*
     *  Output the ray header.  The GIFT statements that
     *  would have generated this are:
     *  410	write(1, 411) hcen, vcen, h, v, ncomp, dfirst, dlast, a, e
     *  411	format(2f7.1, 2f9.3, i3, 2f8.2,' A', f6.1,' E', f6.1)
     */

#define	SHOT_FMT	"%7.1f%7.1f%9.3f%9.3f%3d%8.2f%8.2f A%6.1f E%6.1f"

    if ( rt_perspective > 0 )  {
	bn_ae_vec( &azimuth, &elevation, ap->a_ray.r_dir );
    }

    bu_vls_printf( &str, SHOT_FMT,
		   hvcen[0], hvcen[1],
		   hv[0], hv[1],
		   comp_count,
		   dfirst * MM2IN, dlast * MM2IN,
		   azimuth, elevation );

    /*
     *  As an aid to debugging, take advantage of the fact that
     *  there are more than 80 columns on UNIX "cards", and
     *  add debugging information to the end of the line to
     *  allow this shotline to be reproduced offline.
     *   -b gives the shotline x, y coordinates when re-running RTG3,
     *   -p and -d are used with RTSHOT
     *  The easy way to activate this is with the harmless -!1 option
     *  when running RTG3.
     */
    if ( R_DEBUG || bu_debug || RT_G_DEBUG )  {
	bu_vls_printf( &str, "   -b%d,%d -p %26.20e %26.20e %26.20e -d %26.20e %26.20e %26.20e\n",
		       ap->a_x, ap->a_y,
		       V3ARGS(ap->a_ray.r_pt),
		       V3ARGS(ap->a_ray.r_dir) );
    } else {
	bu_vls_putc( &str, '\n' );
    }

    /* loop here to deal with individual components */
    card_count = 0;
    prev_id = -1;
    first = 1;
    for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw )  {
	/*
	 *  The GIFT statements that would have produced
	 *  this output are:
	 *	do 632 i=icomp, iend
	 *	if (clos(icomp).gt.999.99.or.slos(i).gt.999.9) goto 635
	 * 632	continue
	 * 	write(1, 633)(item(i), clos(i), cangi(i), cango(i),
	 * &			kspac(i), slos(i), i=icomp, iend)
	 * 633	format(1x, 3(i4, f6.2, 2f5.1, i1, f5.1))
	 *	goto 670
	 * 635	write(1, 636)(item(i), clos(i), cangi(i), cango(i),
	 * &			kspac(i), slos(i), i=icomp, iend)
	 * 636	format(1x, 3(i4, f6.1, 2f5.1, i1, f5.0))
	 */
	fastf_t	comp_thickness;	/* component line of sight thickness */
	fastf_t	in_obliq;	/* in obliquity angle */
	fastf_t	out_obliq;	/* out obliquity angle */
	int	region_id;	/* solid region's id */
	int	air_id;		/* air id */
	fastf_t	dot_prod;	/* dot product of normal and ray dir */
	fastf_t	air_thickness;	/* air line of sight thickness */
	vect_t	normal;		/* surface normal */
	register struct partition	*nextpp = pp->pt_forw;

	region_id = pp->pt_regionp->reg_regionid;

	if ( region_id <= 0 && prev_id > 0 )
	{
	    /* air region output with previous partition */
	    prev_id = region_id;
	    continue;
	}
	comp_thickness = pp->pt_outhit->hit_dist -
	    pp->pt_inhit->hit_dist;

	/* The below code is meant to catch components with zero or
	 * negative thicknesses.  This is not supposed to be possible,
	 * but the condition has been seen.
	 */
#if 0
	if ( comp_thickness <= 0 )  {
	    VJOIN1( pp->pt_inhit->hit_point, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	    VJOIN1( pp->pt_outhit->hit_point, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir );
	    bu_log("ERROR: comp_thickness=%g for region id = %d at h=%g, v=%g (x=%d, y=%d), partition at x%x\n",
		   comp_thickness, region_id, hv[0], hv[1], ap->a_x, ap->a_y, pp );
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	    bu_log("Send this output to the BRL-CAD Developers ([email protected])\n");
	    if ( ! (RT_G_DEBUG & DEBUG_ARB8)) {
		rt_g.debug |= DEBUG_ARB8;
		rt_shootray(ap);
		rt_g.debug &= ~DEBUG_ARB8;
	    }
	}
#endif

	if ( nextpp == PartHeadp )  {
	    if ( region_id <= 0 ) {
		/* last partition is air, need a 111 'phantom armor' before AND after */
		bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before and after air region %s\n",
			pp->pt_regionp->reg_name );
		region_id = 111;
		air_id = pp->pt_regionp->reg_aircode;
		air_thickness = comp_thickness;
		comp_thickness = 0.0;
	    } else {
		/* Last partition, no air follows, use code 9 */
		air_id = 9;
		air_thickness = 0.0;
	    }
	} else if ( region_id <= 0 ) {
	    /* air region, need a 111 'phantom armor' */
	    bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before air region %s\n",
		    pp->pt_regionp->reg_name );
	    prev_id = region_id;
	    region_id = 111;
	    air_id = pp->pt_regionp->reg_aircode;
	    air_thickness = comp_thickness;
	    comp_thickness = 0.0;
	} else if ( nextpp->pt_regionp->reg_regionid <= 0 &&
		    nextpp->pt_regionp->reg_aircode != 0 )  {
	    /* Next partition is air region */
	    air_id = nextpp->pt_regionp->reg_aircode;
	    air_thickness = nextpp->pt_outhit->hit_dist -
		nextpp->pt_inhit->hit_dist;
	    prev_id = air_id;
	} else {
	    /* 2 solid regions, maybe with gap */
	    air_id = 0;
	    air_thickness = nextpp->pt_inhit->hit_dist -
		pp->pt_outhit->hit_dist;
	    if ( air_thickness < 0.0 )
		air_thickness = 0.0;
	    if ( !NEAR_ZERO( air_thickness, 0.1 ) )  {
		air_id = 1;	/* air gap */
		if ( R_DEBUG & RDEBUG_HITS )
		    bu_log("air gap added\n");
	    } else {
		air_thickness = 0.0;
	    }
	    prev_id = region_id;
	}

	/*
	 *  Compute the obliquity angles in degrees, ie,
	 *  the "declension" angle down off the normal vector.
	 *  RT normals always point outwards;
	 *  the "inhit" normal points opposite the ray direction,
	 *  the "outhit" normal points along the ray direction.
	 *  Hence the one sign change.
	 *  XXX this should probably be done with atan2()
	 */

	if ( first ) {
	    first = 0;
	    VJOIN1( first_hit, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	}
    out:
	RT_HIT_NORMAL( normal, pp->pt_inhit, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip );
	dot_prod = VDOT( ap->a_ray.r_dir, normal );
	if ( dot_prod > 1.0 )
	    dot_prod = 1.0;
	if ( dot_prod < -1.0 )
	    dot_prod = (-1.0);

	in_obliq = acos( -dot_prod ) *
	    bn_radtodeg;
	RT_HIT_NORMAL( normal, pp->pt_outhit, pp->pt_outseg->seg_stp, &(ap->a_ray), pp->pt_outflip );
	dot_prod = VDOT( ap->a_ray.r_dir, normal );
	if ( dot_prod > 1.0 )
	    dot_prod = 1.0;
	if ( dot_prod < -1.0 )
	    dot_prod = (-1.0);

	out_obliq = acos( dot_prod ) *
	    bn_radtodeg;

	/* Check for exit obliquties greater than 90 degrees. */
#if 0
	if ( in_obliq > 90 || in_obliq < 0 )  {
	    bu_log("ERROR: in_obliquity=%g\n", in_obliq);
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	}
	if ( out_obliq > 90 || out_obliq < 0 )  {
	    bu_log("ERROR: out_obliquity=%g\n", out_obliq);
	    VPRINT(" r_dir", ap->a_ray.r_dir);
	    VPRINT("normal", normal);
	    bu_log("dot=%g, acos(dot)=%g\n",
		   VDOT( ap->a_ray.r_dir, normal ),
		   acos( VDOT( ap->a_ray.r_dir, normal ) ) );
	    /* Print the defective one */
	    rt_pr_pt( ap->a_rt_i, pp );
	    /* Print the whole ray's partition list */
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	}
#endif

	if ( in_obliq > 90.0 )
	    in_obliq = 90.0;
	if ( in_obliq < 0.0 )
	    in_obliq = 0.0;
	if ( out_obliq > 90.0 )
	    out_obliq = 90.0;
	if ( out_obliq < 0.0 )
	    out_obliq = 0.0;

	/*
	 *  Handle 3-components per card output format, with
	 *  a leading space in front of the first component.
	 */
	if ( card_count == 0 )  {
	    bu_vls_strcat( &str, " " );
	}
	comp_thickness *= MM2IN;
	/* Check thickness fields for format overflow */
	if ( comp_thickness > 999.99 || air_thickness*MM2IN > 999.9 )
	    fmt = "%4d%6.1f%5.1f%5.1f%1d%5.0f";
	else
	    fmt = "%4d%6.2f%5.1f%5.1f%1d%5.1f";
#ifdef SPRINTF_NOT_PARALLEL
	bu_semaphore_acquire( BU_SEM_SYSCALL );
#endif
	snprintf(buf, 128, fmt,
		 region_id,
		 comp_thickness,
		 in_obliq, out_obliq,
		 air_id, air_thickness*MM2IN );
#ifdef SPRINTF_NOT_PARALLEL
	bu_semaphore_release( BU_SEM_SYSCALL );
#endif
	bu_vls_strcat( &str, buf );
	card_count++;
	if ( card_count >= 3 )  {
	    bu_vls_strcat( &str, "\n" );
	    card_count = 0;
	}

	/* A color rtg3.pl UnixPlot file of output commands
	 * is generated.  This is processed by plot(1)
	 * plotting filters such as pl-fb or pl-sgi.
	 * Portions of a ray passing through air within the
	 * model are represented in blue, while portions
	 * passing through a solid are assigned green.
	 * This will always be done single CPU,
	 * to prevent output garbling.  (See view_init).
	 */
	if (R_DEBUG & RDEBUG_RAYPLOT) {
	    vect_t     inpt;
	    vect_t     outpt;
	    VJOIN1(inpt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist,
		   ap->a_ray.r_dir);
	    VJOIN1(outpt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist,
		   ap->a_ray.r_dir);
	    pl_color(plotfp, 0, 255, 0);	/* green */
	    pdv_3line(plotfp, inpt, outpt);

	    if (air_thickness > 0) {
		vect_t     air_end;
		VJOIN1(air_end, ap->a_ray.r_pt,
		       pp->pt_outhit->hit_dist + air_thickness,
		       ap->a_ray.r_dir);
		pl_color(plotfp, 0, 0, 255);	/* blue */
		pdv_3cont(plotfp, air_end);
	    }
	}
	if ( nextpp == PartHeadp && air_id != 9 ) {
	    /* need to output a 111 'phantom armor' at end of shotline */
	    air_id = 9;
	    air_thickness = 0.0;
	    region_id = 111;
	    comp_thickness = 0.0;
	    goto out;
	}
    }

    /* If partway through building the line, add a newline */
    if ( card_count > 0 )  {
	/*
	 *  Note that GIFT zero-fills the unused component slots,
	 *  but neither COVART II nor COVART III require it,
	 *  so just end the line here.
	 */
	bu_vls_strcat( &str, "\n" );
    }

    /* Single-thread through file output.
     * COVART will accept non-sequential ray data provided the
     * ray header and its associated data are not separated.  CAVEAT:
     * COVART will not accept headers out of sequence.
     */
    bu_semaphore_acquire( BU_SEM_SYSCALL );

    fputs( bu_vls_addr( &str ), outfp );

    if ( shot_fp )
    {
	fprintf( shot_fp, "%.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %ld %.5f %.5f %.5f\n",
		 azimuth, elevation, V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ),
		 line_num, V3ARGS( first_hit) );

	line_num +=  1 + (comp_count / 3 );
	if ( comp_count % 3 )
	    line_num++;
    }

    /* End of single-thread region */
    bu_semaphore_release( BU_SEM_SYSCALL );

    /* Release vls storage */
    bu_vls_free( &str );

    return(0);
}
Example #28
0
void
render_camera_render_thread(int UNUSED(cpu), void *ptr)
{
    render_camera_thread_data_t *td;
    int d, n, res_ind, scanline, v_scanline;
    vect_t pixel, accum, v1, v2;
    struct tie_ray_s ray;
    fastf_t view_inv;

    VSETALL(v1, 0);

    td = (render_camera_thread_data_t *)ptr;
    view_inv = 1.0 / td->camera->view_num;

    td->camera->render.tie = td->tie;

    res_ind = 0;
/* row, vertical */
/*
  for (i = td->tile->orig_y; i < td->tile->orig_y + td->tile->size_y; i++) {
*/
    while (1) {
	/* Determine if this scanline should be computed by this thread */
	bu_semaphore_acquire(TIE_SEM_WORKER);
	if (*td->scanline == td->tile->size_y) {
	    bu_semaphore_release(TIE_SEM_WORKER);
	    return;
	} else {
	    scanline = *td->scanline;
	    (*td->scanline)++;
	}
	bu_semaphore_release(TIE_SEM_WORKER);

	v_scanline = scanline + td->tile->orig_y;
	if (td->tile->format == RENDER_CAMERA_BIT_DEPTH_24) {
	    res_ind = 3*scanline*td->tile->size_x;
	} else if (td->tile->format == RENDER_CAMERA_BIT_DEPTH_128) {
	    res_ind = 4*scanline*td->tile->size_x;
	}


	/* optimization if there is no depth of field being applied */
	if (td->camera->view_num == 1) {
	    VSCALE(v1, td->camera->view_list[0].step_y, v_scanline);
	    VADD2(v1, v1, td->camera->view_list[0].top_l);
	}


	/* scanline, horizontal, each pixel */
	for (n = td->tile->orig_x; n < td->tile->orig_x + td->tile->size_x; n++) {
	    /* depth of view samples */
	    if (td->camera->view_num > 1) {
		VSET(accum, 0, 0, 0);

		for (d = 0; d < td->camera->view_num; d++) {
		    VSCALE(ray.dir, td->camera->view_list[d].step_y, v_scanline);
		    VADD2(ray.dir, ray.dir, td->camera->view_list[d].top_l);
		    VSCALE(v1, td->camera->view_list[d].step_x, n);
		    VADD2(ray.dir, ray.dir, v1);

		    VSET(pixel, (tfloat)RENDER_CAMERA_BGR, (tfloat)RENDER_CAMERA_BGG, (tfloat)RENDER_CAMERA_BGB);

		    VMOVE(ray.pos, td->camera->view_list[d].pos);
		    ray.depth = 0;
		    VUNITIZE(ray.dir);

		    /* Compute pixel value using this ray */
		    td->camera->render.work(&td->camera->render, td->tie, &ray, &pixel);

		    VADD2(accum, accum, pixel);
		}

		/* Find Mean value of all views */
		VSCALE(pixel, accum, view_inv);
	    } else {
		if (td->camera->type == RENDER_CAMERA_PERSPECTIVE) {
		    VSCALE(v2, td->camera->view_list[0].step_x, n);
		    VADD2(ray.dir, v1, v2);

		    VSET(pixel, (tfloat)RENDER_CAMERA_BGR, (tfloat)RENDER_CAMERA_BGG, (tfloat)RENDER_CAMERA_BGB);

		    VMOVE(ray.pos, td->camera->view_list[0].pos);
		    ray.depth = 0;
		    VUNITIZE(ray.dir);

		    /* Compute pixel value using this ray */
		    td->camera->render.work(&td->camera->render, td->tie, &ray, &pixel);
		} else {
		    VMOVE(ray.pos, td->camera->view_list[0].pos);
		    VMOVE(ray.dir, td->camera->view_list[0].top_l);

		    VSCALE(v1, td->camera->view_list[0].step_x, n);
		    VSCALE(v2, td->camera->view_list[0].step_y, v_scanline);
		    VADD2(ray.pos, ray.pos, v1);
		    VADD2(ray.pos, ray.pos, v2);

		    VSET(pixel, (tfloat)RENDER_CAMERA_BGR, (tfloat)RENDER_CAMERA_BGG, (tfloat)RENDER_CAMERA_BGB);
		    ray.depth = 0;

		    /* Compute pixel value using this ray */
		    td->camera->render.work(&td->camera->render, td->tie, &ray, &pixel);
		}
	    }


	    if (td->tile->format == RENDER_CAMERA_BIT_DEPTH_24) {
		if (pixel[0] > 1) pixel[0] = 1;
		if (pixel[1] > 1) pixel[1] = 1;
		if (pixel[2] > 1) pixel[2] = 1;
		((char *)(td->res_buf))[res_ind+0] = (unsigned char)(255 * pixel[0]);
		((char *)(td->res_buf))[res_ind+1] = (unsigned char)(255 * pixel[1]);
		((char *)(td->res_buf))[res_ind+2] = (unsigned char)(255 * pixel[2]);
		res_ind += 3;
	    } else if (td->tile->format == RENDER_CAMERA_BIT_DEPTH_128) {
		tfloat alpha;

		alpha = 1.0;

		((tfloat *)(td->res_buf))[res_ind + 0] = pixel[0];
		((tfloat *)(td->res_buf))[res_ind + 1] = pixel[1];
		((tfloat *)(td->res_buf))[res_ind + 2] = pixel[2];
		((tfloat *)(td->res_buf))[res_ind + 3] = alpha;

		res_ind += 4;
	    }
/*          printf("Pixel: [%d, %d, %d]\n", rgb[0], rgb[1], rgb[2]); */

	}
    }
}
Example #29
0
/**
 * action performed at the end of each scanline
 */
void
view_eol(struct application *ap)
{
    int cpu = ap->a_resource->re_cpu;
    int i;

    if (overlay) {
	/*
	 * Overlay mode. Check if the pixel is an edge.  If so, write
	 * it to the framebuffer.
	 */
	for (i = 0; i < per_processor_chunk; ++i) {
	    if (writeable[cpu][i]) {
		/*
		 * Write this pixel
		 */
		bu_semaphore_acquire(BU_SEM_SYSCALL);
		fb_write(fbp, i, ap->a_y, &scanline[cpu][i*3], 1);
		bu_semaphore_release(BU_SEM_SYSCALL);
	    }
	}
	return;
    } else if (blend) {
	/*
	 * Blend mode.
	 *
	 * Read a line from the existing framebuffer, convert to HSV,
	 * manipulate, and put the results in the scanline as RGB.
	 */
	int replace_down = 0; /* flag that specifies if the pixel in the
			       * scanline below must be replaced.
			       */
	RGBpixel rgb;
	fastf_t hsv[3];

	bu_semaphore_acquire(BU_SEM_SYSCALL);
	if (fb_read(fbp, 0, ap->a_y, blendline[cpu], per_processor_chunk) < 0)
	    bu_exit(EXIT_FAILURE, "rtedge: error reading from framebuffer.\n");
	bu_semaphore_release(BU_SEM_SYSCALL);

	for (i = 0; i < per_processor_chunk; ++i) {
	    /*
	     * Is this pixel an edge?
	     */
	    if (writeable[cpu][i]) {

		/*
		 * The pixel is an edge, retrieve the appropriate
		 * pixel from the line buffer and convert it to HSV.
		 */
		rgb[RED] = blendline[cpu][i*3+RED];
		rgb[GRN] = blendline[cpu][i*3+GRN];
		rgb[BLU] = blendline[cpu][i*3+BLU];

		/*
		 * Is the pixel in the blendline array the background
		 * color? If so, look left and down to determine which
		 * pixel is the "source" of the edge. Unless, of
		 * course, we are on the bottom scanline or the
		 * leftmost column (x=y=0)
		 */
		if (i != 0 && ap->a_y != 0 && !diffpixel(rgb, fb_bg_color)) {
		    RGBpixel left;
		    RGBpixel down;

		    left[RED] = blendline[cpu][(i-1)*3+RED];
		    left[GRN] = blendline[cpu][(i-1)*3+GRN];
		    left[BLU] = blendline[cpu][(i-1)*3+BLU];

		    bu_semaphore_acquire(BU_SEM_SYSCALL);
		    fb_read(fbp, i, ap->a_y - 1, down, 1);
		    bu_semaphore_release(BU_SEM_SYSCALL);

		    if (diffpixel(left, fb_bg_color)) {
			/*
			 * Use this one.
			 */
			rgb[RED] = left[RED];
			rgb[GRN] = left[GRN];
			rgb[BLU] = left[BLU];
		    } else if (diffpixel(down, fb_bg_color)) {
			/*
			 * Use the pixel from the scanline below
			 */
			replace_down = 1;

			rgb[RED] = down[RED];
			rgb[GRN] = down[GRN];
			rgb[BLU] = down[BLU];
		    }
		}
		/*
		 * Convert to HSV
		 */
		bu_rgb_to_hsv(rgb, hsv);

		/*
		 * Now perform the manipulations.
		 */
		hsv[VAL] *= 3.0;
		hsv[SAT] /= 3.0;

		if (hsv[VAL] > 1.0) {
		    fastf_t d = hsv[VAL] - 1.0;

		    hsv[VAL] = 1.0;
		    hsv[SAT] -= d;
		    hsv[SAT] = hsv[SAT] >= 0.0 ? hsv[SAT] : 0.0;
		}

		/*
		 * Convert back to RGB.
		 */
		bu_hsv_to_rgb(hsv, rgb);

		if (replace_down) {
		    /*
		     * Write this pixel immediately, do not put it
		     * into the blendline since it corresponds to the
		     * wrong scanline.
		     */
		    bu_semaphore_acquire(BU_SEM_SYSCALL);
		    fb_write(fbp, i, ap->a_y, rgb, 1);
		    bu_semaphore_release(BU_SEM_SYSCALL);

		    replace_down = 0;
		} else {
		    /*
		     * Put this pixel back into the blendline array.
		     * We'll push it to the buffer when the entire
		     * scanline has been processed.
		     */
		    blendline[cpu][i*3+RED] = rgb[RED];
		    blendline[cpu][i*3+GRN] = rgb[GRN];
		    blendline[cpu][i*3+BLU] = rgb[BLU];
		}
	    } /* end "if this pixel is an edge" */
	} /* end pixel loop */

	/*
	 * Write the blendline to the framebuffer.
	 */
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fb_write(fbp, 0, ap->a_y, blendline[cpu], per_processor_chunk);
	bu_semaphore_release(BU_SEM_SYSCALL);
	return;
    } /* end blend */

    if (fbp != FBIO_NULL) {
	/*
	 * Simple whole scanline write to a framebuffer.
	 */
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fb_write(fbp, 0, ap->a_y, scanline[cpu], per_processor_chunk);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
    if (outputfile != NULL) {
	/*
	 * Write to a file.
	 */
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	/* TODO : Add double type data to maintain resolution */
	icv_writeline(bif, ap->a_y, scanline[cpu],  ICV_DATA_UCHAR);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }
    if (fbp == FBIO_NULL && outputfile == NULL)
	bu_log("rtedge: strange, no end of line actions taken.\n");

    return;

}
Example #30
0
/**
 * compare a ray that hit to source
 */
int
compare_hit(register struct application *ap, struct partition *partHeadp, struct seg *UNUSED(segs))
{
    register struct partition *pp=NULL;
    register struct part *mp=NULL;
    struct fitness_state *fstate = (struct fitness_state *) ap->a_uptr;
    fastf_t xp, yp, lastpt=0.0;
    int status = 0;

    if (partHeadp == NULL && fstate->ray[ap->a_user] == NULL) {
	bu_semaphore_acquire(SEM_SAME);
	fstate->same += fstate->a_len;
	bu_semaphore_release(SEM_SAME);
	return 0;
    }


    /* move from head */
    if (partHeadp!=NULL)
	pp = partHeadp->pt_forw;
    if (fstate->ray[ap->a_user] !=NULL)
	mp = BU_LIST_FORW(part, &fstate->ray[ap->a_user]->l);

    /* if both rays missed, count this as the same.
     * no need to evaluate further*/

    bu_semaphore_acquire(SEM_SAME);
    bu_semaphore_acquire(SEM_DIFF);

    while (pp != partHeadp && mp != fstate->ray[ap->a_user]) {
	if (status & STATUS_PP)	xp = pp->pt_outhit->hit_dist;
	else			xp = pp->pt_inhit->hit_dist;
	if (status & STATUS_MP)	yp = mp->outhit_dist;
	else			yp = mp->inhit_dist;
	if (xp < 0) xp = 0;
	if (yp < 0) yp = 0;

	if (status==STATUS_EMPTY) {
	    if (NEAR_EQUAL(xp, yp, 1.0e-5)) {
		fstate->same += xp;
		status = (STATUS_PP | STATUS_MP);
		lastpt = xp;
	    } else if (xp < yp) {
		fstate->same+= xp;

		lastpt = xp;
		status = STATUS_PP;
	    } else if (yp < xp) {
		fstate->same+= yp;
		lastpt = yp;
		status = STATUS_MP;
	    }
	} else if (status == (STATUS_MP | STATUS_PP)) {
	    if (NEAR_EQUAL(xp, yp, 1.0e-5)) {
		fstate->same += xp - lastpt;
		status = STATUS_EMPTY;
		pp = pp->pt_forw;
		mp = BU_LIST_FORW(part, &mp->l);
		lastpt = xp;
	    } else if (xp < yp) {
		fstate->same += xp - lastpt;
		lastpt = xp;
		status = STATUS_MP;
		pp=pp->pt_forw;
	    } else if (yp < xp) {
		fstate->same += yp - lastpt;
		lastpt = yp;
		status = STATUS_PP;
		mp = BU_LIST_FORW(part, &mp->l);
	    }

	}

	else if (status == STATUS_PP) {
	    if (NEAR_EQUAL(xp, yp, 1.0e-5)) {
		fstate->diff += xp - lastpt;
		status = STATUS_MP;
		lastpt = yp;
		pp = pp->pt_forw;
	    } else if (xp > yp) {
		fstate->diff += yp - lastpt;
		lastpt = yp;
		status = STATUS_PP | STATUS_MP;
	    } else if (xp < yp) {
		fstate->diff += xp - lastpt;
		status = STATUS_EMPTY;
		pp = pp ->pt_forw;
		lastpt = xp;
	    }
	}
	else if (status == STATUS_MP) {
	    if (NEAR_EQUAL(xp, yp, 1.0e-5)) {
		fstate->diff += yp - lastpt;
		status = STATUS_PP;
		lastpt = xp;
		mp = BU_LIST_FORW(part, &mp->l);
	    } else if (xp < yp) {
		fstate->diff += xp - lastpt;
		lastpt = xp;
		status = STATUS_PP | STATUS_MP;
	    } else if (xp > yp) {
		fstate->diff += yp - lastpt;
		status = STATUS_EMPTY;
		mp = BU_LIST_FORW(part, &mp->l);
		lastpt = yp;
	    }
	}
    }

    /* we could be halfway through evaluating a partition
     * finish evaluating it before proceeding */
    if (status == STATUS_PP) {
	if (pp->pt_outhit->hit_dist > fstate->a_len) {
	    /* trim ray */
	    fstate->diff += fstate->a_len - lastpt;
	    lastpt = fstate->a_len;
	} else {
	    fstate->diff+= pp->pt_outhit->hit_dist - lastpt;
	    lastpt = pp->pt_outhit->hit_dist;
	}
	pp = pp->pt_forw;
    } else if (status == STATUS_MP) {
	fstate->diff += mp->outhit_dist - lastpt;
	lastpt = mp->outhit_dist;
	mp = BU_LIST_FORW(part, &mp->l);
    }

    /* if there are a different # of partitions in source and individual */
    while (mp != fstate->ray[ap->a_user]) {
	fstate->diff += mp->outhit_dist - mp->inhit_dist;
	lastpt = mp->outhit_dist;
	mp = BU_LIST_FORW(part, &mp->l);
    }
    while (pp != partHeadp && pp->pt_inhit->hit_dist < fstate->a_len) {
	if (pp->pt_outhit->hit_dist > fstate->a_len) {
	    /* trim bounding box */
	    fstate->diff += fstate->a_len - pp->pt_inhit->hit_dist;
	    lastpt = fstate->a_len;
	} else {
	    fstate->diff += pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist;
	    lastpt = pp->pt_outhit->hit_dist;
	}
	pp = pp->pt_forw;
    }

    /* include trailing empty space as similar */
    fstate->same += fstate->a_len - lastpt;

    bu_semaphore_release(SEM_SAME);
    bu_semaphore_release(SEM_DIFF);

    return 1;
}