]> git.cworth.org Git - vogl/blob - src/vogleditor/vogleditor_qframebufferexplorer.cpp
UI: Improved support for shared contexts and viewing shared state objects
[vogl] / src / vogleditor / vogleditor_qframebufferexplorer.cpp
1 #include "vogleditor_qframebufferexplorer.h"
2 #include "ui_vogleditor_qframebufferexplorer.h"
3
4 #include "vogleditor_qtextureexplorer.h"
5
6 #include "vogl_gl_object.h"
7 #include "vogl_gl_state_snapshot.h"
8 #include "vogl_fbo_state.h"
9
10 typedef struct
11 {
12     int index;
13     vogl_framebuffer_state* pFBOState;
14     vogl_default_framebuffer_state* pDefaultFBState;
15 } vogl_framebuffer_container;
16
17 Q_DECLARE_METATYPE(vogl_framebuffer_container);
18
19 vogleditor_QFramebufferExplorer::vogleditor_QFramebufferExplorer(QWidget *parent) :
20     QWidget(parent),
21     ui(new Ui::vogleditor_QFramebufferExplorer),
22     m_pDefaultFramebufferState(NULL)
23 {
24     ui->setupUi(this);
25
26     m_colorExplorerLayout = new QVBoxLayout();
27     m_depthExplorerLayout = new QVBoxLayout();
28     m_stencilExplorerLayout = new QVBoxLayout();
29
30     ui->colorBufferGroupBox->setLayout(m_colorExplorerLayout);
31
32     m_depthExplorer = new vogleditor_QTextureExplorer(ui->depthBufferGroupBox);
33     m_depthExplorerLayout->addWidget(m_depthExplorer);
34     ui->depthBufferGroupBox->setLayout(m_depthExplorerLayout);
35
36     m_stencilExplorer = new vogleditor_QTextureExplorer(ui->stencilBufferGroupBox);
37     m_stencilExplorerLayout->addWidget(m_stencilExplorer);
38     ui->stencilBufferGroupBox->setLayout(m_stencilExplorerLayout);
39
40     connect(ui->framebufferObjectListbox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectedFramebufferIndexChanged(int)));
41 }
42
43 vogleditor_QFramebufferExplorer::~vogleditor_QFramebufferExplorer()
44 {
45     clear();
46     delete ui;
47
48     delete m_colorExplorerLayout;
49     delete m_depthExplorerLayout;
50     delete m_stencilExplorerLayout;
51
52     delete m_depthExplorer;
53     m_depthExplorer = NULL;
54
55     delete m_stencilExplorer;
56     m_stencilExplorer = NULL;
57 }
58
59 void vogleditor_QFramebufferExplorer::clear()
60 {
61     m_objects.clear();
62     m_sharing_contexts.clear();
63     ui->framebufferObjectListbox->clear();
64
65     clearViewers();
66 }
67
68 void vogleditor_QFramebufferExplorer::clearViewers()
69 {
70     m_depthExplorer->clear();
71     m_stencilExplorer->clear();
72
73     for (vogleditor_QTextureExplorer** iter = m_viewers.begin(); iter != m_viewers.end(); iter++)
74     {
75         m_colorExplorerLayout->takeAt(0);
76         (*iter)->clear();
77         delete (*iter);
78         *iter = NULL;
79     }
80
81     m_viewers.clear();
82 }
83
84 uint vogleditor_QFramebufferExplorer::set_framebuffer_objects(vogl_context_snapshot* pContext, vogl::vector<vogl_context_snapshot*> sharingContexts, vogl_default_framebuffer_state* pDefaultFramebufferState)
85 {
86     clear();
87
88     m_sharing_contexts = sharingContexts;
89
90     uint framebufferCount = 0;
91
92     framebufferCount += set_default_framebuffer(pDefaultFramebufferState);
93
94     // framebuffers are not shared state objects, but they can reference shared objects,
95     // so only add the framebuffers from the main context
96     vogl_gl_object_state_ptr_vec framebufferObjects;
97     pContext->get_all_objects_of_category(cGLSTFramebuffer, framebufferObjects);
98     framebufferCount += add_framebuffer_objects(sharingContexts, framebufferObjects);
99
100     return framebufferCount;
101 }
102
103 uint vogleditor_QFramebufferExplorer::set_default_framebuffer(vogl_default_framebuffer_state* pDefaultFramebufferState)
104 {
105     int numAdded = 0;
106     if (pDefaultFramebufferState != NULL)
107     {
108         m_pDefaultFramebufferState = pDefaultFramebufferState;
109
110         // add default framebuffer
111         vogl_framebuffer_container defaultContainer;
112         defaultContainer.index = 0;
113         defaultContainer.pFBOState = NULL;
114         defaultContainer.pDefaultFBState = m_pDefaultFramebufferState;
115         ui->framebufferObjectListbox->addItem("Framebuffer 0 - (default framebuffer)", QVariant::fromValue(defaultContainer));
116         numAdded = 1;
117     }
118     return numAdded;
119 }
120
121 uint vogleditor_QFramebufferExplorer::add_framebuffer_objects(vogl::vector<vogl_context_snapshot*> sharingContexts, vogl_gl_object_state_ptr_vec objects)
122 {
123     m_objects.append(objects);
124
125     // add framebuffer objects
126     QString valueStr;
127     for (vogl_gl_object_state_ptr_vec::iterator iter = objects.begin(); iter != objects.end(); iter++)
128     {
129         vogl_framebuffer_state* pState = static_cast<vogl_framebuffer_state*>(*iter);
130
131         if (pState->get_attachments().size() > 0)
132         {
133             unsigned int width = 0;
134             unsigned int height = 0;
135             const vogl_framebuffer_attachment* pAttachment = &(pState->get_attachments().begin()->second);
136             if (pAttachment->get_type() == GL_TEXTURE)
137             {
138                 for (uint c = 0; c < sharingContexts.size(); c++)
139                 {
140                     vogl_texture_state* pTexState = this->get_texture_attachment(*(sharingContexts[c]), pAttachment->get_handle());
141                     if (pTexState != NULL)
142                     {
143                         width = pTexState->get_texture().get_width();
144                         height = pTexState->get_texture().get_height();
145                         break;
146                     }
147                 }
148             }
149             else if (pAttachment->get_type() == GL_RENDERBUFFER)
150             {
151                 for (uint c = 0; c < sharingContexts.size(); c++)
152                 {
153                     vogl_renderbuffer_state* pRbState = this->get_renderbuffer_attachment(*(sharingContexts[c]), pAttachment->get_handle());
154                     if (pRbState != NULL)
155                     {
156                         width = pRbState->get_texture().get_texture().get_width();
157                         height = pRbState->get_texture().get_texture().get_height();
158                         break;
159                     }
160                 }
161             }
162
163             valueStr = valueStr.sprintf("Framebuffer %" PRIu64 " - (%u x %u) %d attachments", pState->get_snapshot_handle(), width, height, pState->get_attachments().size());
164         }
165         else
166         {
167             valueStr = valueStr.sprintf("Framebuffer %" PRIu64 " - %d attachments", pState->get_snapshot_handle(), pState->get_attachments().size());
168         }
169
170         vogl_framebuffer_container container;
171         container.index = ui->framebufferObjectListbox->count();
172         container.pFBOState = pState;
173         container.pDefaultFBState = NULL;
174
175         ui->framebufferObjectListbox->addItem(valueStr, QVariant::fromValue(container));
176     }
177
178     return objects.size();
179 }
180
181 bool vogleditor_QFramebufferExplorer::set_active_framebuffer(unsigned long long framebufferHandle)
182 {
183     bool bDisplayedFramebuffer = false;
184
185     if (framebufferHandle == 0)
186     {
187         ui->framebufferObjectListbox->setCurrentIndex(0);
188         bDisplayedFramebuffer = true;
189     }
190     else
191     {
192         for (int index = 0; index < ui->framebufferObjectListbox->count(); index++)
193         {
194             vogl_framebuffer_container container = ui->framebufferObjectListbox->itemData(index).value<vogl_framebuffer_container>();
195             vogl_framebuffer_state* pState = container.pFBOState;
196             if (pState != NULL && pState->get_snapshot_handle() == framebufferHandle)
197             {
198                 ui->framebufferObjectListbox->setCurrentIndex(index);
199                 bDisplayedFramebuffer = true;
200                 break;
201             }
202         }
203     }
204     return bDisplayedFramebuffer;
205 }
206
207 void vogleditor_QFramebufferExplorer::selectedFramebufferIndexChanged(int index)
208 {
209     clearViewers();
210
211     if (index < 0 || index >= ui->framebufferObjectListbox->count())
212     {
213         return;
214     }
215
216     vogl_gl_object_state_ptr_vec colorVec;
217     vogl_gl_object_state_ptr_vec depthVec;
218     vogl_gl_object_state_ptr_vec stencilVec;
219
220 #define ADD_COLOR_BUFFER_VIEWER vogleditor_QTextureExplorer* pViewer = new vogleditor_QTextureExplorer(ui->colorBufferGroupBox); m_colorExplorerLayout->addWidget(pViewer); m_viewers.push_back(pViewer);
221
222     vogl_framebuffer_container container = ui->framebufferObjectListbox->itemData(index).value<vogl_framebuffer_container>();
223     if (index == 0)
224     {
225         vogl_default_framebuffer_state* pDefaultState = container.pDefaultFBState;
226
227         vogl_texture_state& rFrontLeft = pDefaultState->get_texture(cDefFramebufferFrontLeft);
228         vogl_texture_state& rBackLeft = pDefaultState->get_texture(cDefFramebufferBackLeft);
229         vogl_texture_state& rFrontRight = pDefaultState->get_texture(cDefFramebufferFrontRight);
230         vogl_texture_state& rBackRight = pDefaultState->get_texture(cDefFramebufferBackRight);
231         vogl_texture_state& rDepthStencil = pDefaultState->get_texture(cDefFramebufferDepthStencil);
232
233         if (rFrontLeft.is_valid())
234         {
235             colorVec.push_back(&rFrontLeft);
236             ADD_COLOR_BUFFER_VIEWER
237             pViewer->add_texture_object(rFrontLeft, "GL_FRONT_LEFT");
238         }
239         if (rBackLeft.is_valid())
240         {
241             colorVec.push_back(&rBackLeft);
242             ADD_COLOR_BUFFER_VIEWER
243             pViewer->add_texture_object(rBackLeft, "GL_BACK_LEFT");
244         }
245         if (rFrontRight.is_valid())
246         {
247             colorVec.push_back(&rFrontRight);
248             ADD_COLOR_BUFFER_VIEWER
249             pViewer->add_texture_object(rFrontRight, "GL_FRONT_RIGHT");
250         }
251         if (rBackRight.is_valid())
252         {
253             colorVec.push_back(&rBackRight);
254             ADD_COLOR_BUFFER_VIEWER
255             pViewer->add_texture_object(rBackRight, "GL_BACK_RIGHT");
256         }
257
258         if (rDepthStencil.is_valid()) { depthVec.push_back(&rDepthStencil); m_depthExplorer->add_texture_object(rDepthStencil, "GL_DEPTH"); }
259         if (rDepthStencil.is_valid()) { stencilVec.push_back(&rDepthStencil); m_stencilExplorer->add_texture_object(rDepthStencil, "GL_STENCIL"); }
260     }
261     else
262     {
263         vogl_framebuffer_state* pState = container.pFBOState;
264         if (pState != NULL)
265         {
266             const vogl_framebuffer_state::GLenum_to_attachment_map& rAttachments = pState->get_attachments();
267             for (vogl_framebuffer_state::GLenum_to_attachment_map::const_iterator iter = rAttachments.begin(); iter != rAttachments.end(); iter++)
268             {
269                 const vogl_framebuffer_attachment* pAttachment = &(iter->second);
270                 if (pAttachment->get_type() == GL_TEXTURE)
271                 {
272                     for (uint c = 0; c < m_sharing_contexts.size(); c++)
273                     {
274                         vogl_texture_state* pTexState = this->get_texture_attachment(*(m_sharing_contexts[c]), pAttachment->get_handle());
275                         if (pTexState != NULL)
276                         {
277                             if (iter->first == GL_DEPTH_ATTACHMENT ||
278                                 iter->first == GL_DEPTH)
279                             {
280                                 depthVec.push_back(pTexState);
281                             }
282                             else if (iter->first == GL_STENCIL_ATTACHMENT ||
283                                      iter->first == GL_STENCIL)
284                             {
285                                 stencilVec.push_back(pTexState);
286                             }
287                             else
288                             {
289                                 colorVec.push_back(pTexState);
290
291                                 ADD_COLOR_BUFFER_VIEWER
292                             }
293                             break;
294                         }
295                     }
296                 }
297                 else if (pAttachment->get_type() == GL_RENDERBUFFER)
298                 {
299                     for (uint c = 0; c < m_sharing_contexts.size(); c++)
300                     {
301                         vogl_renderbuffer_state* pRbState = this->get_renderbuffer_attachment(*(m_sharing_contexts[c]), pAttachment->get_handle());
302                         if (pRbState != NULL)
303                         {
304                             if (iter->first == GL_DEPTH_ATTACHMENT ||
305                                 iter->first == GL_DEPTH)
306                             {
307                                 depthVec.push_back(pRbState);
308                             }
309                             else if (iter->first == GL_STENCIL_ATTACHMENT ||
310                                      iter->first == GL_STENCIL)
311                             {
312                                 stencilVec.push_back(pRbState);
313                             }
314                             else
315                             {
316                                 colorVec.push_back(pRbState);
317
318                                 ADD_COLOR_BUFFER_VIEWER
319                             }
320                             break;
321                         }
322                     }
323                 }
324                 else
325                 {
326                     VOGL_ASSERT(!"Unhandled framebuffer attachment type");
327                 }
328             }
329         }
330     }
331
332 #undef ADD_COLOR_BUFFER_VIEWER
333
334     if (colorVec.size() == 0)
335     {
336         ui->colorBufferGroupBox->setMinimumHeight(50);
337     }
338     else
339     {
340         uint totalHeight = 0;
341         uint viewerIndex = 0;
342         for (vogleditor_QTextureExplorer** iter = m_viewers.begin(); iter != m_viewers.end(); iter++)
343         {
344             (*iter)->set_zoom_factor(0.2);
345
346             // use index which was passed in as parameter
347             if (index != 0)
348             {
349                 (*iter)->set_texture_objects(colorVec);
350                 (*iter)->set_active_texture(colorVec[viewerIndex]->get_snapshot_handle());
351             }
352
353             // for better visibility, adjust height based on combined preferred heights
354             totalHeight += (*iter)->get_preferred_height();
355             (*iter)->setFixedHeight((*iter)->get_preferred_height());
356             ++viewerIndex;
357
358             connect(*iter, SIGNAL(zoomFactorChanged(double)), this, SLOT(slot_zoomFactorChanged(double)));
359         }
360     }
361
362     if (depthVec.size() == 0)
363     {
364         m_depthExplorer->setVisible(false);
365         ui->depthBufferGroupBox->setMinimumHeight(50);
366     }
367     else
368     {
369         m_depthExplorer->setVisible(true);
370         m_depthExplorer->set_zoom_factor(0.2);
371         // use index which was passed in as parameter
372         if (index != 0)
373         {
374             m_depthExplorer->set_texture_objects(depthVec);
375             m_depthExplorer->set_active_texture(depthVec[0]->get_snapshot_handle());
376         }
377         connect(m_depthExplorer, SIGNAL(zoomFactorChanged(double)), this, SLOT(slot_zoomFactorChanged(double)));
378         m_depthExplorer->setMinimumHeight(m_depthExplorer->get_preferred_height());
379     }
380
381     if (stencilVec.size() == 0)
382     {
383         m_stencilExplorer->setVisible(false);
384         ui->stencilBufferGroupBox->setMinimumHeight(50);
385     }
386     else
387     {
388         m_stencilExplorer->setVisible(true);
389         m_stencilExplorer->set_zoom_factor(0.2);
390         // use index which was passed in as parameter
391         if (index != 0)
392         {
393             m_stencilExplorer->set_texture_objects(stencilVec);
394             m_stencilExplorer->set_active_texture(stencilVec[0]->get_snapshot_handle());
395         }
396         connect(m_stencilExplorer, SIGNAL(zoomFactorChanged(double)), this, SLOT(slot_zoomFactorChanged(double)));
397         m_stencilExplorer->setMinimumHeight(m_stencilExplorer->get_preferred_height());
398     }
399 }
400
401 vogl_texture_state* vogleditor_QFramebufferExplorer::get_texture_attachment(vogl_context_snapshot& context, unsigned int handle)
402 {
403     vogl_gl_object_state_ptr_vec textureVec;
404     context.get_all_objects_of_category(cGLSTTexture, textureVec);
405
406     vogl_texture_state* pTexState = NULL;
407     for (vogl_gl_object_state_ptr_vec::iterator texIter = textureVec.begin(); texIter != textureVec.end(); texIter++)
408     {
409         if ((*texIter)->get_snapshot_handle() == handle)
410         {
411             pTexState = static_cast<vogl_texture_state*>(*texIter);
412             break;
413         }
414     }
415
416     return pTexState;
417 }
418
419 vogl_renderbuffer_state* vogleditor_QFramebufferExplorer::get_renderbuffer_attachment(vogl_context_snapshot& context, unsigned int handle)
420 {
421     vogl_gl_object_state_ptr_vec renderbufferVec;
422     context.get_all_objects_of_category(cGLSTRenderbuffer, renderbufferVec);
423
424     vogl_renderbuffer_state* pRenderbufferState = NULL;
425     for (vogl_gl_object_state_ptr_vec::iterator texIter = renderbufferVec.begin(); texIter != renderbufferVec.end(); texIter++)
426     {
427         if ((*texIter)->get_snapshot_handle() == handle)
428         {
429             pRenderbufferState = static_cast<vogl_renderbuffer_state*>(*texIter);
430             break;
431         }
432     }
433
434     return pRenderbufferState;
435 }
436
437 void vogleditor_QFramebufferExplorer::slot_zoomFactorChanged(double zoomFactor)
438 {
439     VOGL_NOTE_UNUSED(zoomFactor);
440
441     uint totalHeight = 0;
442     for (vogleditor_QTextureExplorer** iter = m_viewers.begin(); iter != m_viewers.end(); iter++)
443     {
444         // for better visibility, adjust height based on combined preferred heights
445         totalHeight += (*iter)->get_preferred_height();
446         (*iter)->setFixedHeight((*iter)->get_preferred_height());
447     }
448
449     m_depthExplorer->setMinimumHeight(m_depthExplorer->get_preferred_height());
450     m_stencilExplorer->setMinimumHeight(m_stencilExplorer->get_preferred_height());
451 }