void xfer_dobj_flag(Data_Obj *dpto, Data_Obj *dpfr, uint32_t flagbit) { if( OBJ_FLAGS(dpfr) & flagbit ){ SET_OBJ_FLAG_BITS(dpto, flagbit); } else { CLEAR_OBJ_FLAG_BITS(dpto, flagbit); } }
static void _update_pf_viewer(QSP_ARG_DECL Platform_Viewer *pvp, Data_Obj *dp) { #ifdef HAVE_OPENGL int t; //cudaError_t e; // unmap buffer before using w/ GL if( BUF_IS_MAPPED(dp) ){ if( (*PF_UNMAPBUF_FN(PFDEV_PLATFORM(OBJ_PFDEV(dp)))) (QSP_ARG dp) < 0 ) { warn("update_pf_viewer: buffer unmap error!?"); } CLEAR_OBJ_FLAG_BITS(dp, DT_BUF_MAPPED); // propagate change to children and parents propagate_flag(dp,DT_BUF_MAPPED); } glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, OBJ_TEX_ID(dp)); // is glBindBuffer REALLY part of libGLEW??? //#ifdef HAVE_LIBGLEW glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OBJ_BUF_ID(dp)); //#endif // HAVE_LIBGLEW t=gl_pixel_type(dp); glTexSubImage2D(GL_TEXTURE_2D, 0, // target, level 0, 0, // x0, y0 OBJ_COLS(dp), OBJ_ROWS(dp), // dx, dy t, GL_UNSIGNED_BYTE, // type OFFSET(0)); // offset into PIXEL_UNPACK_BUFFER //#ifdef HAVE_LIBGLEW glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); //#endif // HAVE_LIBGLEW glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex2f(-1.0, -1.0); glTexCoord2f(0, 0); glVertex2f(-1.0, 1.0); glTexCoord2f(1, 0); glVertex2f(1.0, 1.0); glTexCoord2f(1, 1); glVertex2f(1.0, -1.0); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); if( (*PF_MAPBUF_FN(PFDEV_PLATFORM(OBJ_PFDEV(dp))))(QSP_ARG dp) < 0 ){ warn("update_pf_viewer: Error mapping buffer!?"); } SET_OBJ_FLAG_BITS(dp, DT_BUF_MAPPED); // propagate change to children and parents propagate_flag(dp,DT_BUF_MAPPED); #else // ! HAVE_OPENGL NO_OGL_MSG #endif // ! HAVE_OPENGL }
int enlarge(QSP_ARG_DECL Data_Obj *big_dp,Data_Obj *lil_dp) /* reduce into lil_dp */ { if( change_size(QSP_ARG big_dp,lil_dp) < 0 ) return(-1); SET_OBJ_FLAG_BITS(big_dp, DT_ASSIGNED); return(0); }
static COMMAND_FUNC( do_protect ) { Data_Obj *dp; dp=pick_obj(""); if( dp == NULL ) return; if( IS_STATIC(dp) ){ sprintf(ERROR_STRING,"do_protect: Object %s is already static!?",OBJ_NAME(dp)); warn(ERROR_STRING); return; } SET_OBJ_FLAG_BITS(dp,DT_STATIC); }
static void cuda_display_finish(QSP_ARG_DECL Data_Obj *dp) { cudaError_t e; // re-map so we can use again with CUDA // BUG? Is it safe to do this before the call to swap_buffers??? //cutilSafeCall(cudaGLMapBufferObject( &OBJ_DATA_PTR(dp), OBJ_BUF_ID(dp) )); e = cudaGLMapBufferObject( &OBJ_DATA_PTR(dp), OBJ_BUF_ID(dp) ); if( e != cudaSuccess ){ WARN("Error mapping buffer object!?"); // should we return now, with possibly other cleanup??? } SET_OBJ_FLAG_BITS(dp, DT_BUF_MAPPED); // propagate change to children and parents propagate_flag(dp,DT_BUF_MAPPED); }
static void _make_zombie(QSP_ARG_DECL Data_Obj *dp) { static int n_zombie=1; char zname[LLEN]; /* this function removes it from the hash table and * active item list, doesn't add the structure to the * item free list. This is why we release the node * and later free the object... * * I think the idea here is that there might be a dangling reference * to an image - for instance, if we display an image, then delete it, * and then later want to refresh the window... */ zombie_item(dobj_itp,(Item *)dp); sprintf(zname,"Z.%s.%d",OBJ_NAME(dp),n_zombie++); fprintf(stderr,"make_zombie, changing object %s to %s\n",OBJ_NAME(dp),zname); rls_str( (char *) OBJ_NAME(dp) ); /* unsave old name, make_zombie */ SET_OBJ_NAME(dp,savestr(zname)); SET_OBJ_FLAG_BITS(dp,DT_ZOMBIE); } // make_zombie
// This is the normal display path static void update_pf_viewer(QSP_ARG_DECL Platform_Viewer *pvp, Data_Obj *dp) { #ifdef HAVE_OPENGL int t; //cudaError_t e; // unmap buffer before using w/ GL if( BUF_IS_MAPPED(dp) ){ if( (*PF_UNMAPBUF_FN(PFDEV_PLATFORM(OBJ_PFDEV(dp)))) (QSP_ARG dp) < 0 ) { WARN("update_pf_viewer: buffer unmap error!?"); } #ifdef FOOBAR e = cudaGLUnmapBufferObject( OBJ_BUF_ID(dp) ); if( e != cudaSuccess ){ describe_cuda_driver_error2("update_pf_viewer", "cudaGLUnmapBufferObject",e); NERROR1("failed to unmap buffer object"); } #endif // FOOBAR CLEAR_OBJ_FLAG_BITS(dp, DT_BUF_MAPPED); // propagate change to children and parents propagate_flag(dp,DT_BUF_MAPPED); } // //bind_texture(OBJ_DATA_PTR(dp)); glClear(GL_COLOR_BUFFER_BIT); /* sprintf(ERROR_STRING,"update_pf_viewer: tex_id = %d, buf_id = %d", OBJ_TEX_ID(dp),OBJ_BUF_ID(dp)); advise(ERROR_STRING); */ glBindTexture(GL_TEXTURE_2D, OBJ_TEX_ID(dp)); // is glBindBuffer REALLY part of libGLEW??? //#ifdef HAVE_LIBGLEW glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OBJ_BUF_ID(dp)); //#endif // HAVE_LIBGLEW #ifdef FOOBAR switch(OBJ_COMPS(dp)){ /* what used to be here??? */ } #endif /* FOOBAR */ t=gl_pixel_type(dp); glTexSubImage2D(GL_TEXTURE_2D, 0, // target, level 0, 0, // x0, y0 OBJ_COLS(dp), OBJ_ROWS(dp), // dx, dy t, GL_UNSIGNED_BYTE, // type OFFSET(0)); // offset into PIXEL_UNPACK_BUFFER //#ifdef HAVE_LIBGLEW glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); //#endif // HAVE_LIBGLEW glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex2f(-1.0, -1.0); glTexCoord2f(0, 0); glVertex2f(-1.0, 1.0); glTexCoord2f(1, 0); glVertex2f(1.0, 1.0); glTexCoord2f(1, 1); glVertex2f(1.0, -1.0); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); #ifdef FOOBAR e = cudaGLMapBufferObject( &OBJ_DATA_PTR(dp), OBJ_BUF_ID(dp) ); if( e != cudaSuccess ){ WARN("Error mapping buffer object!?"); // should we return now, with possibly other cleanup??? } #endif // FOOBAR if( (*PF_MAPBUF_FN(PFDEV_PLATFORM(OBJ_PFDEV(dp))))(QSP_ARG dp) < 0 ){ WARN("update_pf_viewer: Error mapping buffer!?"); } SET_OBJ_FLAG_BITS(dp, DT_BUF_MAPPED); // propagate change to children and parents propagate_flag(dp,DT_BUF_MAPPED); #else // ! HAVE_OPENGL NO_OGL_MSG #endif // ! HAVE_OPENGL }
static COMMAND_FUNC( do_new_gl_buffer ) { const char *s; Data_Obj *dp; Platform_Device *pdp; Compute_Platform *cdp; dimension_t d,w,h; #ifdef HAVE_OPENGL Dimension_Set ds; int t; #endif // HAVE_OPENGL s = NAMEOF("name for GL buffer object"); cdp = pick_platform("platform"); if( cdp != NULL ) push_pfdev_context(QSP_ARG PF_CONTEXT(cdp) ); pdp = pick_pfdev("device"); if( cdp != NULL ) pop_pfdev_context(SINGLE_QSP_ARG); w = (int)HOW_MANY("width"); h = (int)HOW_MANY("height"); d = (int)HOW_MANY("depth"); /* what should the depth be??? default to 1 for now... */ if( pdp == NULL ) return; /* Make sure this name isn't already in use... */ dp = dobj_of(s); if( dp != NULL ){ sprintf(ERROR_STRING,"Data object name '%s' is already in use, can't use for GL buffer object.",s); warn(ERROR_STRING); return; } #ifdef HAVE_OPENGL // BUG need to be able to set the cuda device. // Note, however, that we don't need GL buffers on the Tesla... //set_data_area(cuda_data_area[0][0]); set_data_area( PFDEV_AREA(pdp,PFDEV_GLOBAL_AREA_INDEX) ); ds.ds_dimension[0]=d; ds.ds_dimension[1]=w; ds.ds_dimension[2]=h; ds.ds_dimension[3]=1; ds.ds_dimension[4]=1; dp = _make_dp(QSP_ARG s,&ds,PREC_FOR_CODE(PREC_UBY)); if( dp == NULL ){ sprintf(ERROR_STRING, "Error creating data_obj header for %s",s); error1(ERROR_STRING); } SET_OBJ_FLAG_BITS(dp, DT_NO_DATA); /* can't free this data */ SET_OBJ_FLAG_BITS(dp, DT_GL_BUF); /* indicate obj is a GL buffer */ SET_OBJ_DATA_PTR(dp, NULL); //fprintf(stderr,"do_new_gl_buffer: allocating gl_info for %s\n",OBJ_NAME(dp)); SET_OBJ_GL_INFO(dp, (GL_Info *) getbuf( sizeof(GL_Info) ) ); //fprintf(stderr,"do_new_gl_buffer: DONE allocating gl_info for %s\n",OBJ_NAME(dp)); glew_check(SINGLE_QSP_ARG); /* without this, we get a segmentation * violation on glGenBuffers??? */ // We need an extra field in which to store the GL identifier... // AND another extra field in which to store the associated texid. // Why is this ifdef here? These don't seem to depend // on libglew??? // Answer: We need libglew to bring in openGL extensions like glBindBuffer... //advise("calling glGenBuffers"); //fprintf(stderr,"OBJ_GL_INFO(%s) = 0x%lx\n",OBJ_NAME(dp),(long)OBJ_GL_INFO(dp)); //fprintf(stderr,"OBJ_BUF_ID_P(%s) = 0x%lx\n",OBJ_NAME(dp),(long)OBJ_BUF_ID_P(dp)); // BUG glGenBuffers seems to require v1.5??? glGenBuffers(1, OBJ_BUF_ID_P(dp) ); // first arg is # buffers to generate? //sprintf(ERROR_STRING,"glGenBuffers gave us buf_id = %d",OBJ_BUF_ID(dp)); //advise(ERROR_STRING); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OBJ_BUF_ID(dp) ); // glBufferData will allocate the memory for the buffer, // but won't copy unless the pointer is non-null // How do we get the gpu memory space address? // That must be with map glBufferData(GL_PIXEL_UNPACK_BUFFER, OBJ_COMPS(dp) * OBJ_COLS(dp) * OBJ_ROWS(dp), NULL, GL_STREAM_DRAW); /* buffer arg set to 0 unbinds any previously bound buffers... * and restores client memory usage. */ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); //#endif // HAVE_LIBGLEW glGenTextures(1, OBJ_TEX_ID_P(dp) ); // makes a texture name fprintf(stderr,"new_gl_buffer: new texture name is 0x%x\n",OBJ_TEX_ID(dp)); glBindTexture(GL_TEXTURE_2D, OBJ_TEX_ID(dp) ); t = gl_pixel_type(dp); glTexImage2D( GL_TEXTURE_2D, 0, // level-of-detail - is this the same as miplevel??? OBJ_COMPS(dp), // internal format, can also be symbolic constant such as // GL_RGBA etc OBJ_COLS(dp), // width - must be 2^n+2 (border) for some n??? OBJ_ROWS(dp), // height - must be 2^m+2 (border) for some m??? 0, // border - must be 0 or 1 t, // format of pixel data GL_UNSIGNED_BYTE, // type of pixel data NULL // pixel data - null pointer means // allocate but do not copy? // - offset into PIXEL_UNPACK_BUFFER?? ); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Why was this here? It would seem to un-bind the target??? glBindTexture(GL_TEXTURE_2D, 0); //glFinish(); // necessary or not? //advise("calling platform-specific buffer registration function"); if( (*PF_REGBUF_FN(PFDEV_PLATFORM(pdp)))( QSP_ARG dp ) < 0 ){ WARN("do_new_gl_buffer: Error in platform-specific buffer registration!?"); // BUG? - should clean up here! } // Leave the buffer mapped by default //cutilSafeCall(cudaGLMapBufferObject( &OBJ_DATA_PTR(dp), OBJ_BUF_ID(dp) )); //advise("calling platform-specific buffer mapping function"); if( (*PF_MAPBUF_FN(PFDEV_PLATFORM(pdp)))( QSP_ARG dp ) < 0 ){ WARN("do_new_gl_buffer: Error in platform-specific buffer mapping!?"); // BUG? - should clean up here! } SET_OBJ_FLAG_BITS(dp, DT_BUF_MAPPED); // propagate change to children and parents propagate_flag(dp,DT_BUF_MAPPED); #else // ! HAVE_OPENGL NO_OGL_MSG #endif // ! HAVE_OPENGL } /* end do_new_gl_buffer */
static int change_size(QSP_ARG_DECL Data_Obj *dst_dp,Data_Obj *src_dp ) { Dimension_Set ef, *enlargement_factor=&ef; Dimension_Set rf, *reduction_factor=&rf; Vec_Obj_Args oa1, *oap=&oa1; Dimension_Set size_ds, n_ds; Dimension_Set *size_dsp=(&size_ds), *n_dsp=(&n_ds); Data_Obj *src_ss_dp, *dst_ss_dp; dimension_t i,j,k,l,m; index_t offsets[N_DIMENSIONS]={0,0,0,0,0}; incr_t dst_incrs[N_DIMENSIONS], src_incrs[N_DIMENSIONS]; index_t dst_indices[N_DIMENSIONS]={0,0,0,0,0}, src_indices[N_DIMENSIONS]={0,0,0,0,0}; /* For simplicity, we don't allow size changes to be combined with conversions */ if( !dp_same_prec(QSP_ARG dst_dp,src_dp,"change_size") ) return(-1); for(i=0;i<N_DIMENSIONS;i++){ if( OBJ_TYPE_DIM(dst_dp,i) > OBJ_TYPE_DIM(src_dp,i) ){ /* enlargement - subsample the destination */ SET_DIMENSION(enlargement_factor,i, floor( OBJ_TYPE_DIM(dst_dp,i) / OBJ_TYPE_DIM(src_dp,i) ) ); SET_DIMENSION(reduction_factor,i, 0); SET_DIMENSION(size_dsp,i, OBJ_TYPE_DIM(src_dp,i) ); SET_DIMENSION(n_dsp,i, DIMENSION(enlargement_factor,i) ); dst_incrs[i] = DIMENSION(n_dsp,i); src_incrs[i] = 1; } else { /* reduction - subsample the source */ SET_DIMENSION(reduction_factor,i, ceil( OBJ_TYPE_DIM(src_dp,i) / OBJ_TYPE_DIM(dst_dp,i) ) ); SET_DIMENSION(enlargement_factor,i, 0 ); SET_DIMENSION(size_dsp,i, floor( OBJ_TYPE_DIM(src_dp,i) / DIMENSION(reduction_factor,i) ) ); /* We don't need to do this multiple times, just pick one and do it */ /*SET_DIMENSION(n_dsp,i, DIMENSION(reduction_factor,i) ); */ SET_DIMENSION(n_dsp,i, 1); src_incrs[i] = DIMENSION(reduction_factor,i); dst_incrs[i] = 1; } } /* make the subsamples. * the column increment is expressed in columns, etc. */ dst_ss_dp=make_subsamp(QSP_ARG "chngsize_dst_obj",dst_dp,size_dsp,offsets,dst_incrs); src_ss_dp=make_subsamp(QSP_ARG "chngsize_src_obj",src_dp,size_dsp,offsets,src_incrs); clear_obj_args(oap); SET_OA_DEST(oap,dst_ss_dp); SET_OA_SRC_OBJ(oap,0, src_ss_dp); SET_OA_ARGSTYPE(oap, REAL_ARGS); SET_OA_PFDEV(oap,OBJ_PFDEV(dst_dp)); for(i=0;i<DIMENSION(n_dsp,4);i++){ /* foreach sequence to copy */ if( dst_incrs[4] > 1 ) dst_indices[4]=i; else src_indices[4]=i; for(j=0;j<DIMENSION(n_dsp,3);j++){ /* foreach frame to copy */ if( dst_incrs[3] > 1 ) dst_indices[3]=j; else src_indices[3]=j; for(k=0;k<DIMENSION(n_dsp,2);k++){ /* foreach row */ if( dst_incrs[2] > 1 ) dst_indices[2]=k; else src_indices[2]=k; for(l=0;l<DIMENSION(n_dsp,1);l++){ /* foreach col */ if( dst_incrs[1] > 1 ) dst_indices[1]=l; else src_indices[1]=l; for(m=0;m<DIMENSION(n_dsp,0);m++){ /* foreach comp */ if( dst_incrs[0] > 1 ) dst_indices[0]=m; else src_indices[0]=m; /* relocate the appropriate subsample */ SET_OBJ_DATA_PTR(dst_ss_dp, multiply_indexed_data(dst_dp,dst_indices) ); SET_OBJ_DATA_PTR(src_ss_dp, multiply_indexed_data(src_dp,src_indices) ); // This doesn't check for cuda obj... //vmov(oap); perf_vfunc(QSP_ARG FVMOV, oap ); } } } } } delvec(QSP_ARG dst_ss_dp); delvec(QSP_ARG src_ss_dp); SET_OBJ_FLAG_BITS(dst_dp, DT_ASSIGNED); return(0); }
static Data_Obj *insure_ram_obj(QSP_ARG_DECL Data_Obj *dp) { Data_Obj *tmp_dp; char *tname; Data_Area *save_ap; Data_Obj *c_dp=NULL; if( OBJ_IS_RAM(dp) ) return dp; // This object lives on a different platform. // We create a copy in RAM, and download the data // using the platform download function. save_ap = curr_ap; curr_ap = ram_area_p; tname = getbuf( strlen(OBJ_NAME(dp)) + strlen(DNAME_PREFIX) + 1 ); sprintf(tname,"%s%s",DNAME_PREFIX,OBJ_NAME(dp)); tmp_dp = dup_obj(QSP_ARG dp, tname); givbuf(tname); if( tmp_dp == NO_OBJ ){ // This can happen if the object is subscripted, // as the bracket characters are illegal in names return NO_OBJ; } curr_ap = save_ap; // We can't download if the source data is not contiguous... // // We have a problem with bit precision, because the bits can // be non-contiguous when the long words are - any time the number of columns // is not evenly divided by the bits-per-word if( (! IS_CONTIGUOUS(dp)) && ! HAS_CONTIGUOUS_DATA(dp) ){ Vec_Obj_Args oa1, *oap=&oa1; advise("object is not contiguous, and does not have contiguous data..."); longlist(QSP_ARG dp); save_ap = curr_ap; curr_ap = OBJ_AREA( dp ); tname = getbuf( strlen(OBJ_NAME(dp)) + strlen(CNAME_PREFIX) + 1 ); sprintf(tname,"%s%s",CNAME_PREFIX,OBJ_NAME(dp)); c_dp = dup_obj(QSP_ARG dp, tname ); givbuf(tname); curr_ap = save_ap; // Now do the move... setvarg2(oap,c_dp,dp); if( IS_BITMAP(dp) ){ SET_OA_SBM(oap,dp); SET_OA_SRC1(oap,NO_OBJ); } if( IS_REAL(dp) ) /* BUG case for QUAT too? */ OA_ARGSTYPE(oap) = REAL_ARGS; else if( IS_COMPLEX(dp) ) /* BUG case for QUAT too? */ OA_ARGSTYPE(oap) = COMPLEX_ARGS; else if( IS_QUAT(dp) ) /* BUG case for QUAT too? */ OA_ARGSTYPE(oap) = QUATERNION_ARGS; else //ERROR1("CAUTIOUS: insure_ram_obj: bad argset type!?"); assert( AERROR("insure_ram_obj: bad argset type!?") ); //fprintf(stderr,"insure_ram_obj: moving remote data to a contiguous object\n"); call_vfunc( QSP_ARG FIND_VEC_FUNC(FVMOV), oap ); //fprintf(stderr,"insure_ram_obj: DONE moving remote data to a contiguous object\n"); dp = c_dp; } gen_obj_dnload(QSP_ARG tmp_dp, dp); if( c_dp != NO_OBJ ) delvec(QSP_ARG c_dp); // BUG - when to delete? // We try using the VOLATILE flag. This will work as long as // the input object is not VOLATILE!? SET_OBJ_FLAG_BITS(tmp_dp, DT_VOLATILE ) ; return tmp_dp; }