void _disown_child( QSP_ARG_DECL Data_Obj *dp ) { Node *np; if( OBJ_PARENT(dp) == NULL ) return; np=remData(OBJ_CHILDREN( OBJ_PARENT(dp) ),dp); assert( np != NULL ); rls_node(np); if( eltcount(OBJ_CHILDREN( OBJ_PARENT(dp) )) == 0 ){ rls_list(OBJ_CHILDREN( OBJ_PARENT(dp) )); /* free list */ OBJ_CHILDREN( OBJ_PARENT(dp) ) = NULL; } }
static COMMAND_FUNC( do_relocate ) { Data_Obj *dp; long x,y,t; const char *obj_name; dp=pick_obj("subimage"); x=(long) how_many("x offset"); y=(long) how_many("y offset"); t=(long) how_many("t offset"); if( dp==NULL ) return; obj_name = OBJ_NAME(dp); INSIST_NONNEGATIVE(x,"x offset","relocate"); INSIST_NONNEGATIVE(y,"y offset","relocate"); INSIST_NONNEGATIVE(t,"t offset","relocate"); if( OBJ_PARENT(dp) == NULL ){ sprintf(ERROR_STRING, "relocate: object \"%s\" is not a subimage", OBJ_NAME(dp)); warn(ERROR_STRING); return; } relocate(dp,(index_t)x,(index_t)y,(index_t)t); }
static cl_mem _find_parent_buf(QSP_ARG_DECL Data_Obj *dp, int *offset_p ) { int offset=0; while( ! OWNS_DATA(dp) ){ //fprintf(stderr,"%s does not own its data...\n",OBJ_NAME(dp)); offset += OBJ_OFFSET(dp); // Do we need to multiply? //fprintf(stderr,"offset = %d\n",offset); dp = OBJ_PARENT(dp); } //fprintf(stderr,"returning offset = %d\n",offset); *offset_p = offset; //fprintf(stderr,"returning %s data ptr at 0x%lx\n",OBJ_NAME(dp),(u_long)OBJ_DATA_PTR(dp)); return OBJ_DATA_PTR(dp); }
static void vl2_update_offset(QSP_ARG_DECL Data_Obj *dp ) { // We don't need to SET_OBJ_OFFSET, because the child offset // is relative to the parent... // OBJ_OFFSET is in bytes, not pixels? //fprintf(stderr,"vl2_update_offset: obj = %s, obj_offset = 0x%x, prec_size = %d\n", //OBJ_NAME(dp),OBJ_OFFSET(dp),PREC_SIZE(OBJ_PREC_PTR(dp))); // change the base pointer... // we originally scaled the offset by PREC_SIZE, but it appears // the offset is kept in bytes. SET_OBJ_DATA_PTR(dp, ((char *)OBJ_DATA_PTR(OBJ_PARENT(dp)))+OBJ_OFFSET(dp) /* *PREC_SIZE(OBJ_PREC_PTR(dp))*/ ); }
static double _get_dobj_posn(QSP_ARG_DECL Item *ip, int index ) { double d=(-1); Data_Obj *dp; index_t pix_offset; int i; index_t offsets[N_DIMENSIONS]; Data_Obj *parent; dp = (Data_Obj *)ip; // should this be an assertion? if( dp == NULL ) return 0.0; parent = OBJ_PARENT(dp); if( parent == NULL ) return 0.0; // The position is relative to the parent // // The position offsets are not stored when we create // a subimage, they are used to create a data ptr offset. // We use this offset together with the parent's shape // to convert back to coordinates... pix_offset = OBJ_OFFSET( dp ); for(i=N_DIMENSIONS-1;i>=0;i--){ // MACH_INC is 0 when the corresponding dimension is 1 if( OBJ_MACH_INC(parent,i) == 0 ){ offsets[i] = 0; } else { offsets[i] = pix_offset / OBJ_MACH_INC(parent,i); pix_offset -= offsets[i] * OBJ_MACH_INC(parent,i); } } assert( index >= 0 && index <= 1 ); d = offsets[index+1]; return(d); }
static void _ocl_offset_data(QSP_ARG_DECL Data_Obj *dp, index_t offset) { #ifndef USE_OPENCL_SUBREGION /* The original code used subBuffers, but overlapping subregions * don't work... * So instead we use a common memory buffer, but keep track * of the starting offset (in elements). This offset has * to be passed to the kernels. */ //fprintf(stderr,"ocl_offset_data: obj %s, offset = %d\n",OBJ_NAME(dp),offset); //fprintf(stderr,"\tparent obj %s, parent offset = %d\n",OBJ_NAME(OBJ_PARENT(dp)), //OBJ_OFFSET(OBJ_PARENT(dp))); if( IS_COMPLEX(dp) ){ assert( (offset & 1) == 0 ); offset /= 2; //fprintf(stderr,"Adjusted offset (%d) for complex object %s\n",offset,OBJ_NAME(dp)); } else if( IS_QUAT(dp) ){ assert( (offset & 3) == 0 ); offset /= 4; } SET_OBJ_DATA_PTR(dp,OBJ_DATA_PTR(OBJ_PARENT(dp))); SET_OBJ_OFFSET( dp, OBJ_OFFSET(OBJ_PARENT(dp)) + offset ); #else // USE_OPENCL_SUBREGION cl_mem buf; cl_mem parent_buf; cl_buffer_region reg; cl_int status; int extra_offset; parent_buf = find_parent_buf(OBJ_PARENT(dp),&extra_offset); assert( parent_buf != NULL ); reg.origin = (offset+extra_offset) * ELEMENT_SIZE(dp); // No - the region has to be big enough for all of the elements. // The safest thing is to include everything from the start // of the subregion to the end of the parent. Note that this // cannot handle negative increments!? // reg.size = OBJ_N_MACH_ELTS(dp) * ELEMENT_SIZE(dp); // p p p p p p p // p p c c c p p // p p p p p p p // p p c c c p p reg.size = OBJ_SEQ_INC(dp)*(OBJ_SEQS(dp)-1) + OBJ_FRM_INC(dp)*(OBJ_FRAMES(dp)-1) + OBJ_ROW_INC(dp)*(OBJ_ROWS(dp)-1) + OBJ_PXL_INC(dp)*(OBJ_COLS(dp)-1) + OBJ_COMP_INC(dp)*(OBJ_COMPS(dp)-1) + 1; reg.size *= ELEMENT_SIZE(dp); //fprintf(stderr,"requesting subregion of %ld bytes at offset %ld\n", //reg.size,reg.origin); buf = clCreateSubBuffer ( parent_buf, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®, &status); if( status != CL_SUCCESS ){ report_ocl_error(status, "clCreateSubBuffer"); SET_OBJ_DATA_PTR(dp,OBJ_DATA_PTR(OBJ_PARENT(dp))); } else { SET_OBJ_DATA_PTR(dp,buf); } // BUG - Because this object doesn't "own" the data, the sub-buffer // won't be released when the object is destroyed, a possible memory // leak... // We need to add a special case, or make data releasing a // platform-specific function... #endif // USE_OPENCL_SUBREGION }
void _delvec(QSP_ARG_DECL Data_Obj *dp) { assert(dp!=NULL); assert(OBJ_NAME(dp)!=NULL); #ifdef ZOMBIE_SUPPORT // This should go back in eventually! if( OBJ_FLAGS(dp) & DT_STATIC && OWNS_DATA(dp) ){ sprintf(ERROR_STRING,"delvec: static object %s will be made a zombie",OBJ_NAME(dp)); advise(ERROR_STRING); make_zombie(dp); return; } if( OBJ_REFCOUNT(dp) > 0 ){ /* This zombie business was introduced at a time * when a displayed image had to be kept around * to refresh its window... with the current * X windows implementation of viewers that is * no longer the case, so this may be unecessary... * * But another case arises when we have a static * object in the expression language, that gets * deleted outside of the expression language. * This shouldn't be done, but we don't want to * be able to crash the program either... */ sprintf(ERROR_STRING,"delvec: object %s (refcount = %d) will be made a zombie",OBJ_NAME(dp),dp->dt_refcount); advise(ERROR_STRING); make_zombie(dp); return; } #endif /* ZOMBIE_SUPPORT */ // If the object has been exported, we need to delete // the associated identifier... // // BUT if it was exported, then it may be referenced!? // So it should be static... // // If we have references, and are therefore keeping the // object as a zombie, then we don't want to delete the // identifier, and we probably don't want to change the // object's name... if( IS_EXPORTED(dp) ){ Identifier *idp; idp = id_of(OBJ_NAME(dp)); assert( idp != NULL ); delete_id((Item *)idp); } if( OBJ_CHILDREN( dp ) != NULL ){ delete_subobjects(dp); } if( OBJ_PARENT(dp) != NULL ){ disown_child(dp); } if( IS_TEMP(dp) ){ if( OBJ_DECLFILE(dp) != NULL ){ sprintf(ERROR_STRING,"delvec %s: temp object has declfile %s!?\n", OBJ_NAME(dp),OBJ_DECLFILE(dp)); advise(ERROR_STRING); } release_tmp_obj(dp); /* * Most likely called when parent is deleted. * Temp objects are not hashed, and are not dynamically * allocated. * * Simply mark as free by clearing name field. */ return; } // We might clean this up by making the release // function a platform member... if( OWNS_DATA(dp) ){ if( ! UNKNOWN_SHAPE(OBJ_SHAPE(dp)) ){ release_data(dp); } } // In the first OpenCL implementation, we used subbuffers, which had // to be released here even for subimages. But now we handle subobjects // ourselves, managing offsets, so non-data-owners don't need to release. rls_shape( OBJ_SHAPE(dp) ); // We don't need to do this if we have garbage collection? /* The name might be null if we had an error creating the object... */ if( OBJ_DECLFILE(dp) != NULL ){ rls_str( OBJ_DECLFILE(dp) ); } #ifdef ZOMBIE_SUPPORT /* BUG context code assumes that this is really deleted... */ // not sure I understand the above comment? if( IS_ZOMBIE(dp) ){ // The object is a zombie that is no longer referenced... /* NOTE: we used to release the struct here with givbuf, * but in the current implementation of the item package, * objects aren't allocated with getbuf! */ // The object has already been removed from the dictionary, // so we don't need to call del_item... /* put this back on the free list... */ recycle_item(dobj_itp,dp); } else { del_item(dobj_itp, dp ); } #else /* ! ZOMBIE_SUPPORT */ DELETE_OBJ_ITEM(dp); // del_dobj - item function #endif /* ! ZOMBIE_SUPPORT */ // used to release the name here // and set to null, but that is done in del_item }