00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2008 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: VMDDisplayList.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.33 $ $Date: 2008/03/27 19:36:49 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * Display list data structure used to hold all of the rendering commands 00019 * VMD generates and interprets in order to do its 3-D rendering. 00020 ***************************************************************************/ 00021 00022 #include "VMDDisplayList.h" 00023 #include "VMDApp.h" 00024 #include "Matrix4.h" 00025 #include "Inform.h" 00026 00027 // required word size alignment in bytes, 8 bytes is large enough for 00028 // all currently known systems. 00029 #define ALLOC_ALIGNMENT 8 00030 #define ALLOC_ALIGNMASK (ALLOC_ALIGNMENT - 1) 00031 00032 // Initial number of bytes in the display list memory block; not allocated 00033 // until the list receives its first command. 00034 00035 // Typical "empty" representations need about 64 bytes to hold their 00036 // initial material on, line thickness and resolution parameters. 00037 #define BASE_DISPLAYLIST_SIZE 64 00038 00039 // once the representation goes past being empty, it's likely going to need 00040 // a lot more space in subsequent allocations, so the next growth step is 00041 // much bigger to reduce the total number of calls without creating too much 00042 // memory fragmentation for simple representations. 00043 #define GROWN_DISPLAYLIST_SIZE 16384 00044 00045 void *VMDDisplayList::operator new(size_t n) { 00046 return vmd_alloc(n); 00047 } 00048 00049 void VMDDisplayList::operator delete(void *p, size_t) { 00050 vmd_dealloc(p); 00051 } 00052 00053 VMDDisplayList::VMDDisplayList() { 00054 materialtag = 0; 00055 serial=0; 00056 cacheskip=0; 00057 pbc = PBC_NONE; 00058 npbc = 1; 00059 00060 // Begin with no memory allocated for the pool; many display lists, 00061 // like those for DrawMolecule, DrawForce, and MoleculeGraphics, spend 00062 // their whole lives with no commands, so it's wasteful to allocate 00063 // anything for them. 00064 // 00065 // XXX In fact, DrawForce and MoleculeGraphics are creating single-element 00066 // display lists that contain nothing but DMATERIALON. This should be 00067 // fixed; better might even be to not create these Displayables at all 00068 // until/unless they are needed. 00069 listsize = 0; 00070 poolsize = 0; 00071 poolused = 0; 00072 pool = NULL; 00073 } 00074 00075 VMDDisplayList::~VMDDisplayList() { 00076 if (pool) vmd_dealloc(pool); 00077 } 00078 00079 void *VMDDisplayList::append(int code, int size) { 00080 unsigned long neededBytes = (sizeof(CommandHeader) + size + ALLOC_ALIGNMASK) & ~(ALLOC_ALIGNMASK); 00081 if (neededBytes + poolused > poolsize) { 00082 unsigned long newsize; 00083 if (!pool) { 00084 newsize = (neededBytes < BASE_DISPLAYLIST_SIZE) ? 00085 BASE_DISPLAYLIST_SIZE : neededBytes; 00086 } else { 00087 newsize = (unsigned long) (1.2f * (poolsize + neededBytes)); 00088 if (newsize < GROWN_DISPLAYLIST_SIZE) 00089 newsize = GROWN_DISPLAYLIST_SIZE; 00090 } 00091 //printf("bumping displist size from %d to %d to handle %d from cmd %d\n", poolsize, newsize, size, code); 00092 char *tmp = (char *) vmd_resize_alloc(pool, poolused, newsize); 00093 // check for failed allocations 00094 if (!tmp) { 00095 msgErr << "Failed to increase display list memory pool size, system out of memory" << sendmsg; 00096 msgErr << " Previous pool size: " << ((unsigned long) (poolsize / (1024*1024))) << "MB" << sendmsg; 00097 msgErr << " Requested pool size: " << ((unsigned long) (newsize / (1024*1024))) << "MB" << sendmsg; 00098 return NULL; 00099 } 00100 poolsize = newsize; 00101 pool = tmp; 00102 } 00103 // store header and size of header + data into pool 00104 CommandHeader *header = (CommandHeader *)(pool + poolused); 00105 poolused += neededBytes; 00106 00107 header->code = code; 00108 header->size = neededBytes; 00109 00110 // return pointer to data following header 00111 ++listsize; 00112 return header+1; 00113 } 00114 00115 void VMDDisplayList::reset_and_free(unsigned long newserial) { 00116 // if we used less than 1/4 of the total pool size, trim the pool 00117 // back to empty so that we don't hog memory. 00118 if (poolsize > BASE_DISPLAYLIST_SIZE && 00119 poolused / (float)poolsize < 0.25f) { 00120 vmd_dealloc(pool); 00121 pool = NULL; 00122 poolsize = 0; 00123 } 00124 poolused = 0; 00125 listsize = 0; 00126 serial = newserial; 00127 } 00128 00129 int VMDDisplayList::set_clip_normal(int i, const float *normal) { 00130 if (i < 0 || i >= VMD_MAX_CLIP_PLANE) return 0; 00131 float length = norm(normal); 00132 if (!length) return 0; 00133 clipplanes[i].normal[0] = normal[0]/length; 00134 clipplanes[i].normal[1] = normal[1]/length; 00135 clipplanes[i].normal[2] = normal[2]/length; 00136 return 1; 00137 } 00138 00139 int VMDDisplayList::set_clip_center(int i, const float *center) { 00140 if (i < 0 || i >= VMD_MAX_CLIP_PLANE) return 0; 00141 clipplanes[i].center[0] = center[0]; 00142 clipplanes[i].center[1] = center[1]; 00143 clipplanes[i].center[2] = center[2]; 00144 return 1; 00145 } 00146 00147 int VMDDisplayList::set_clip_color(int i, const float *color) { 00148 if (i < 0 || i >= VMD_MAX_CLIP_PLANE) return 0; 00149 clipplanes[i].color[0] = color[0]; 00150 clipplanes[i].color[1] = color[1]; 00151 clipplanes[i].color[2] = color[2]; 00152 return 1; 00153 } 00154 00155 int VMDDisplayList::set_clip_status(int i, int mode) { 00156 if (i < 0 || i >= VMD_MAX_CLIP_PLANE) return 0; 00157 clipplanes[i].mode = mode; 00158 return 1; 00159 } 00160 00161
1.2.14 written by Dimitri van Heesch,
© 1997-2002