Blender  V2.59
RAS_ListRasterizer.cpp
Go to the documentation of this file.
00001 
00004 //
00005 #include <iostream>
00006 
00007 #include "RAS_ListRasterizer.h"
00008 
00009 #ifdef WIN32
00010 #include <windows.h>
00011 #endif // WIN32
00012 
00013 #include "GL/glew.h"
00014 
00015 #include "RAS_MaterialBucket.h"
00016 #include "RAS_TexVert.h"
00017 #include "MT_assert.h"
00018 
00019 //#if defined(DEBUG)
00020 //#ifdef WIN32
00021 //#define spit(x) std::cout << x << std::endl;
00022 //#endif //WIN32
00023 //#else
00024 #define spit(x)
00025 //#endif
00026 
00027 RAS_ListSlot::RAS_ListSlot(RAS_ListRasterizer* rasty)
00028 :       KX_ListSlot(),
00029         m_list(0),
00030         m_flag(LIST_MODIFY|LIST_CREATE),
00031         m_matnr(0),
00032         m_rasty(rasty)
00033 {
00034 }
00035 
00036 int RAS_ListSlot::Release()
00037 {
00038         if (--m_refcount > 0)
00039                 return m_refcount;
00040         m_rasty->RemoveListSlot(this);
00041         delete this;
00042         return 0;
00043 }
00044 
00045 RAS_ListSlot::~RAS_ListSlot()
00046 {
00047         RemoveList();
00048 }
00049 
00050 
00051 void RAS_ListSlot::RemoveList()
00052 {
00053         if(m_list != 0) {
00054                 spit("Releasing display list (" << m_list << ")");
00055                 glDeleteLists((GLuint)m_list, 1);
00056                 m_list =0;
00057         }
00058 }
00059 
00060 void RAS_ListSlot::DrawList()
00061 {
00062         if(m_flag &LIST_STREAM || m_flag& LIST_NOCREATE) {
00063                 RemoveList();
00064                 return;
00065         }
00066         if(m_flag &LIST_MODIFY) {
00067                 if(m_flag &LIST_CREATE) {
00068                         if(m_list == 0) {
00069                                 m_list = (unsigned int)glGenLists(1);
00070                                 m_flag =  m_flag &~ LIST_CREATE;
00071                                 spit("Created display list (" << m_list << ")");
00072                         }
00073                 }
00074                 if(m_list != 0)
00075                         glNewList((GLuint)m_list, GL_COMPILE);
00076         
00077                 m_flag |= LIST_BEGIN;
00078                 return;
00079         }
00080         glCallList(m_list);
00081 }
00082 
00083 void RAS_ListSlot::EndList()
00084 {
00085         if(m_flag & LIST_BEGIN) {
00086                 glEndList();
00087                 m_flag = m_flag &~(LIST_BEGIN|LIST_MODIFY);
00088                 m_flag |= LIST_END;
00089                 glCallList(m_list);
00090         }
00091 }
00092 
00093 void RAS_ListSlot::SetModified(bool mod)
00094 {
00095         if(mod && !(m_flag & LIST_MODIFY)) {
00096                 spit("Modifying list (" << m_list << ")");
00097                 m_flag = m_flag &~ LIST_END;
00098                 m_flag |= LIST_STREAM;
00099         }
00100 }
00101 
00102 bool RAS_ListSlot::End()
00103 {
00104         return (m_flag &LIST_END)!=0;
00105 }
00106 
00107 
00108 
00109 RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock)
00110 :       RAS_VAOpenGLRasterizer(canvas, lock),
00111         mUseVertexArrays(useVertexArrays),
00112         mATI(false)
00113 {
00114         if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc."))
00115                 mATI = true;
00116 }
00117 
00118 RAS_ListRasterizer::~RAS_ListRasterizer() 
00119 {
00120         ReleaseAlloc();
00121 }
00122 
00123 void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list)
00124 {
00125         if (list->m_flag & LIST_DERIVEDMESH) {
00126                 RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin();
00127                 while(it != mDerivedMeshLists.end()) {
00128                         RAS_ListSlots *slots = it->second;
00129                         if (slots->size() > list->m_matnr && slots->at(list->m_matnr) == list) {
00130                                 (*slots)[list->m_matnr] = NULL;
00131                                 // check if all slots are NULL and if yes, delete the entry
00132                                 int i;
00133                                 for (i=slots->size(); i-- > 0; ) {
00134                                         if (slots->at(i) != NULL)
00135                                                 break;
00136                                 }
00137                                 if (i < 0) {
00138                                         slots->clear();
00139                                         delete slots;
00140                                         mDerivedMeshLists.erase(it);
00141                                 }
00142                                 break;
00143                         }
00144                         ++it;
00145                 }
00146         } else {
00147                 RAS_ArrayLists::iterator it = mArrayLists.begin();
00148                 while(it != mArrayLists.end()) {
00149                         if (it->second == list) {
00150                                 mArrayLists.erase(it);
00151                                 break;
00152                         }
00153                         it++;
00154                 }
00155         }
00156 }
00157 
00158 RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms)
00159 {
00160         /*
00161          Keep a copy of constant lists submitted for rendering,
00162                 this guards against (replicated)new...delete every frame,
00163                 and we can reuse lists!
00164                 :: sorted by mesh slot
00165         */
00166         RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList;
00167         if(!localSlot) {
00168                 if (ms.m_pDerivedMesh) {
00169                         // that means that we draw based on derived mesh, a display list is possible
00170                         // Note that we come here only for static derived mesh
00171                         int matnr = ms.m_bucket->GetPolyMaterial()->GetMaterialIndex();
00172                         RAS_ListSlot* nullSlot = NULL;
00173                         RAS_ListSlots *listVector;
00174                         RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.find(ms.m_pDerivedMesh);
00175                         if(it == mDerivedMeshLists.end()) {
00176                                 listVector = new RAS_ListSlots(matnr+4, nullSlot);
00177                                 localSlot = new RAS_ListSlot(this);
00178                                 localSlot->m_flag |= LIST_DERIVEDMESH;
00179                                 localSlot->m_matnr = matnr;
00180                                 listVector->at(matnr) = localSlot;
00181                                 mDerivedMeshLists.insert(std::pair<DerivedMesh*, RAS_ListSlots*>(ms.m_pDerivedMesh, listVector));
00182                         } else {
00183                                 listVector = it->second;
00184                                 if (listVector->size() <= matnr)
00185                                         listVector->resize(matnr+4, nullSlot);
00186                                 if ((localSlot = listVector->at(matnr)) == NULL) {
00187                                         localSlot = new RAS_ListSlot(this);
00188                                         localSlot->m_flag |= LIST_DERIVEDMESH;
00189                                         localSlot->m_matnr = matnr;
00190                                         listVector->at(matnr) = localSlot;
00191                                 } else {
00192                                         localSlot->AddRef();
00193                                 }
00194                         }
00195                 } else {
00196                         RAS_ArrayLists::iterator it = mArrayLists.find(ms.m_displayArrays);
00197                         if(it == mArrayLists.end()) {
00198                                 localSlot = new RAS_ListSlot(this);
00199                                 mArrayLists.insert(std::pair<RAS_DisplayArrayList, RAS_ListSlot*>(ms.m_displayArrays, localSlot));
00200                         } else {
00201                                 localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef());
00202                         }
00203                 }
00204         }
00205         MT_assert(localSlot);
00206         return localSlot;
00207 }
00208 
00209 void RAS_ListRasterizer::ReleaseAlloc()
00210 {
00211         for(RAS_ArrayLists::iterator it = mArrayLists.begin();it != mArrayLists.end();++it)
00212                 delete it->second;
00213         mArrayLists.clear();
00214         for (RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin();it != mDerivedMeshLists.end();++it) {
00215                 RAS_ListSlots* slots = it->second;
00216                 for (int i=slots->size(); i-- > 0; ) {
00217                         RAS_ListSlot* slot = slots->at(i);
00218                         if (slot)
00219                                 delete slot;
00220                 }
00221                 slots->clear();
00222                 delete slots;
00223         }
00224         mDerivedMeshLists.clear();
00225 }
00226 
00227 void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
00228 {
00229         RAS_ListSlot* localSlot =0;
00230 
00231         if(ms.m_bDisplayList) {
00232                 localSlot = FindOrAdd(ms);
00233                 localSlot->DrawList();
00234                 if(localSlot->End()) {
00235                         // save slot here too, needed for replicas and object using same mesh
00236                         // => they have the same vertexarray but different mesh slot
00237                         ms.m_DisplayList = localSlot;
00238                         return;
00239                 }
00240         }
00241         // derived mesh cannot use vertex array
00242         if (mUseVertexArrays && !ms.m_pDerivedMesh)
00243                 RAS_VAOpenGLRasterizer::IndexPrimitives(ms);
00244         else
00245                 RAS_OpenGLRasterizer::IndexPrimitives(ms);
00246 
00247         if(ms.m_bDisplayList) {
00248                 localSlot->EndList();
00249                 ms.m_DisplayList = localSlot;
00250         }
00251 }
00252 
00253 
00254 void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
00255 {
00256         RAS_ListSlot* localSlot =0;
00257 
00258         if(ms.m_bDisplayList) {
00259                 localSlot = FindOrAdd(ms);
00260                 localSlot->DrawList();
00261 
00262                 if(localSlot->End()) {
00263                         // save slot here too, needed for replicas and object using same mesh
00264                         // => they have the same vertexarray but different mesh slot
00265                         ms.m_DisplayList = localSlot;
00266                         return;
00267                 }
00268         }
00269 
00270         // workaround: note how we do not use vertex arrays for making display
00271         // lists, since glVertexAttribPointerARB doesn't seem to work correct
00272         // in display lists on ATI? either a bug in the driver or in Blender ..
00273         if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh)
00274                 RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms);
00275         else
00276                 RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
00277 
00278         if(ms.m_bDisplayList) {
00279                 localSlot->EndList();
00280                 ms.m_DisplayList = localSlot;
00281         }
00282 }
00283 
00284 bool RAS_ListRasterizer::Init(void)
00285 {
00286         if (mUseVertexArrays) {
00287                 return RAS_VAOpenGLRasterizer::Init();
00288         } else {
00289                 return RAS_OpenGLRasterizer::Init();
00290         }
00291 }
00292 
00293 void RAS_ListRasterizer::SetDrawingMode(int drawingmode)
00294 {
00295         if (mUseVertexArrays) {
00296                 RAS_VAOpenGLRasterizer::SetDrawingMode(drawingmode);
00297         } else {
00298                 RAS_OpenGLRasterizer::SetDrawingMode(drawingmode);
00299         }
00300 }
00301 
00302 void RAS_ListRasterizer::Exit()
00303 {
00304         if (mUseVertexArrays) {
00305                 RAS_VAOpenGLRasterizer::Exit();
00306         } else {
00307                 RAS_OpenGLRasterizer::Exit();
00308         }
00309 }
00310 
00311 // eof