f5324c6fbc93358b9f835f95bfffded679037f56
[blender-staging.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_ListRasterizer.cpp
1 //
2 #include <iostream>
3
4 #include "RAS_ListRasterizer.h"
5
6 #ifdef WIN32
7 #include <windows.h>
8 #endif // WIN32
9
10 #include "GL/glew.h"
11
12 #include "RAS_MaterialBucket.h"
13 #include "RAS_TexVert.h"
14 #include "MT_assert.h"
15
16 //#ifndef NDEBUG
17 //#ifdef WIN32
18 //#define spit(x) std::cout << x << std::endl;
19 //#endif //WIN32
20 //#else
21 #define spit(x)
22 //#endif
23
24 RAS_ListSlot::RAS_ListSlot(RAS_ListRasterizer* rasty)
25 :       KX_ListSlot(),
26         m_list(0),
27         m_flag(LIST_MODIFY|LIST_CREATE),
28         m_rasty(rasty)
29 {
30 }
31
32 int RAS_ListSlot::Release()
33 {
34         if (--m_refcount > 0)
35                 return m_refcount;
36         m_rasty->RemoveListSlot(this);
37         delete this;
38         return 0;
39 }
40
41 RAS_ListSlot::~RAS_ListSlot()
42 {
43         RemoveList();
44 }
45
46
47 void RAS_ListSlot::RemoveList()
48 {
49         if(m_list != 0) {
50                 spit("Releasing display list (" << m_list << ")");
51                 glDeleteLists((GLuint)m_list, 1);
52                 m_list =0;
53         }
54 }
55
56 void RAS_ListSlot::DrawList()
57 {
58         if(m_flag &LIST_STREAM || m_flag& LIST_NOCREATE) {
59                 RemoveList();
60                 return;
61         }
62         if(m_flag &LIST_MODIFY) {
63                 if(m_flag &LIST_CREATE) {
64                         if(m_list == 0) {
65                                 m_list = (unsigned int)glGenLists(1);
66                                 m_flag =  m_flag &~ LIST_CREATE;
67                                 spit("Created display list (" << m_list << ")");
68                         }
69                 }
70                 if(m_list != 0)
71                         glNewList((GLuint)m_list, GL_COMPILE);
72         
73                 m_flag |= LIST_BEGIN;
74                 return;
75         }
76         glCallList(m_list);
77 }
78
79 void RAS_ListSlot::EndList()
80 {
81         if(m_flag & LIST_BEGIN) {
82                 glEndList();
83                 m_flag = m_flag &~(LIST_BEGIN|LIST_MODIFY);
84                 m_flag |= LIST_END;
85                 glCallList(m_list);
86         }
87 }
88
89 void RAS_ListSlot::SetModified(bool mod)
90 {
91         if(mod && !(m_flag & LIST_MODIFY)) {
92                 spit("Modifying list (" << m_list << ")");
93                 m_flag = m_flag &~ LIST_END;
94                 m_flag |= LIST_STREAM;
95         }
96 }
97
98 bool RAS_ListSlot::End()
99 {
100         return (m_flag &LIST_END)!=0;
101 }
102
103
104
105 RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock)
106 :       RAS_VAOpenGLRasterizer(canvas, lock),
107         mUseVertexArrays(useVertexArrays),
108         mATI(false)
109 {
110         if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc."))
111                 mATI = true;
112 }
113
114 RAS_ListRasterizer::~RAS_ListRasterizer() 
115 {
116         ReleaseAlloc();
117 }
118
119 void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list)
120 {
121         if (list->m_flag & LIST_STANDALONE)
122                 return ;
123         
124         RAS_ArrayLists::iterator it = mArrayLists.begin();
125         while(it != mArrayLists.end()) {
126                 if (it->second == list) {
127                         mArrayLists.erase(it);
128                         break;
129                 }
130                 it++;
131         }
132 }
133
134 RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms)
135 {
136         /*
137          Keep a copy of constant lists submitted for rendering,
138                 this guards against (replicated)new...delete every frame,
139                 and we can reuse lists!
140                 :: sorted by mesh slot
141         */
142         RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList;
143         if(!localSlot) {
144                 if (ms.m_pDerivedMesh) {
145                         // that means that we draw based on derived mesh, a display list is possible
146                         // but it's unique to this mesh slot
147                         localSlot = new RAS_ListSlot(this);
148                         localSlot->m_flag |= LIST_STANDALONE;
149                 } else {
150                         RAS_ArrayLists::iterator it = mArrayLists.find(ms.m_displayArrays);
151                         if(it == mArrayLists.end()) {
152                                 localSlot = new RAS_ListSlot(this);
153                                 mArrayLists.insert(std::pair<RAS_DisplayArrayList, RAS_ListSlot*>(ms.m_displayArrays, localSlot));
154                         } else {
155                                 localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef());
156                         }
157                 }
158         }
159         MT_assert(localSlot);
160         return localSlot;
161 }
162
163 void RAS_ListRasterizer::ReleaseAlloc()
164 {
165         RAS_ArrayLists::iterator it = mArrayLists.begin();
166         while(it != mArrayLists.end()) {
167                 delete it->second;
168                 it++;
169         }
170         mArrayLists.clear();
171 }
172
173 void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
174 {
175         RAS_ListSlot* localSlot =0;
176
177         if(ms.m_bDisplayList) {
178                 localSlot = FindOrAdd(ms);
179                 localSlot->DrawList();
180                 if(localSlot->End()) {
181                         // save slot here too, needed for replicas and object using same mesh
182                         // => they have the same vertexarray but different mesh slot
183                         ms.m_DisplayList = localSlot;
184                         return;
185                 }
186         }
187         // derived mesh cannot use vertex array
188         if (mUseVertexArrays && !ms.m_pDerivedMesh)
189                 RAS_VAOpenGLRasterizer::IndexPrimitives(ms);
190         else
191                 RAS_OpenGLRasterizer::IndexPrimitives(ms);
192
193         if(ms.m_bDisplayList) {
194                 localSlot->EndList();
195                 ms.m_DisplayList = localSlot;
196         }
197 }
198
199
200 void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
201 {
202         RAS_ListSlot* localSlot =0;
203
204         if(ms.m_bDisplayList) {
205                 localSlot = FindOrAdd(ms);
206                 localSlot->DrawList();
207
208                 if(localSlot->End()) {
209                         // save slot here too, needed for replicas and object using same mesh
210                         // => they have the same vertexarray but different mesh slot
211                         ms.m_DisplayList = localSlot;
212                         return;
213                 }
214         }
215
216         // workaround: note how we do not use vertex arrays for making display
217         // lists, since glVertexAttribPointerARB doesn't seem to work correct
218         // in display lists on ATI? either a bug in the driver or in Blender ..
219         if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh)
220                 RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms);
221         else
222                 RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
223
224         if(ms.m_bDisplayList) {
225                 localSlot->EndList();
226                 ms.m_DisplayList = localSlot;
227         }
228 }
229
230 bool RAS_ListRasterizer::Init(void)
231 {
232         if (mUseVertexArrays) {
233                 return RAS_VAOpenGLRasterizer::Init();
234         } else {
235                 return RAS_OpenGLRasterizer::Init();
236         }
237 }
238
239 void RAS_ListRasterizer::SetDrawingMode(int drawingmode)
240 {
241         if (mUseVertexArrays) {
242                 RAS_VAOpenGLRasterizer::SetDrawingMode(drawingmode);
243         } else {
244                 RAS_OpenGLRasterizer::SetDrawingMode(drawingmode);
245         }
246 }
247
248 void RAS_ListRasterizer::Exit()
249 {
250         if (mUseVertexArrays) {
251                 RAS_VAOpenGLRasterizer::Exit();
252         } else {
253                 RAS_OpenGLRasterizer::Exit();
254         }
255 }
256
257 // eof