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