Blender V2.61 - r43446

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