]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_renderbuffer_state.cpp
Fixing various issues that were showing up when trying to snapshot/restore Cube 2:
[vogl] / src / voglcommon / vogl_renderbuffer_state.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 // File: vogl_renderbuffer_state.cpp
27 #include "vogl_common.h"
28 #include "vogl_renderbuffer_state.h"
29 #include "vogl_texture_format.h"
30
31 vogl_renderbuffer_desc::vogl_renderbuffer_desc()
32 {
33     VOGL_FUNC_TRACER
34
35     clear();
36 }
37
38 vogl_renderbuffer_desc::~vogl_renderbuffer_desc()
39 {
40     VOGL_FUNC_TRACER
41 }
42
43 void vogl_renderbuffer_desc::clear()
44 {
45     VOGL_FUNC_TRACER
46     m_width = 0;
47     m_height = 0;
48     m_samples = 0;
49     m_internal_format = 0;
50     m_red_size = 0;
51     m_green_size = 0;
52     m_blue_size = 0;
53     m_alpha_size = 0;
54     m_depth_size = 0;
55     m_stencil_size = 0;
56 }
57
58 bool vogl_renderbuffer_desc::snapshot(const vogl_context_info &context_info)
59 {
60     VOGL_FUNC_TRACER
61
62     VOGL_ASSERT(context_info.get_version() >= VOGL_GL_VERSION_3_0);
63     VOGL_NOTE_UNUSED(context_info);
64
65     VOGL_CHECK_GL_ERROR;
66
67 #define GET_STATE(e, x)                                                                               \
68     do                                                                                                \
69     {                                                                                                 \
70         GL_ENTRYPOINT(glGetRenderbufferParameteriv)(GL_RENDERBUFFER, e, reinterpret_cast<int *>(&x)); \
71         VOGL_CHECK_GL_ERROR;                                                                           \
72     } while (0)
73     GET_STATE(GL_RENDERBUFFER_WIDTH, m_width);
74     GET_STATE(GL_RENDERBUFFER_HEIGHT, m_height);
75     GET_STATE(GL_RENDERBUFFER_SAMPLES, m_samples);
76     GET_STATE(GL_RENDERBUFFER_INTERNAL_FORMAT, m_internal_format);
77     GET_STATE(GL_RENDERBUFFER_RED_SIZE, m_red_size);
78     GET_STATE(GL_RENDERBUFFER_GREEN_SIZE, m_green_size);
79     GET_STATE(GL_RENDERBUFFER_BLUE_SIZE, m_blue_size);
80     GET_STATE(GL_RENDERBUFFER_ALPHA_SIZE, m_alpha_size);
81     GET_STATE(GL_RENDERBUFFER_DEPTH_SIZE, m_depth_size);
82     GET_STATE(GL_RENDERBUFFER_STENCIL_SIZE, m_stencil_size);
83 #undef GET_STATE
84
85     return true;
86 }
87
88 bool vogl_renderbuffer_desc::restore(const vogl_context_info &context_info) const
89 {
90     VOGL_FUNC_TRACER
91
92     VOGL_NOTE_UNUSED(context_info);
93
94     if (!m_width)
95         return false;
96
97     VOGL_ASSERT(context_info.get_version() >= VOGL_GL_VERSION_3_0);
98
99     VOGL_CHECK_GL_ERROR;
100
101     GL_ENTRYPOINT(glRenderbufferStorageMultisample)(GL_RENDERBUFFER, m_samples, m_internal_format, m_width, m_height);
102
103     bool prev_gl_error = vogl_check_gl_error();
104     VOGL_ASSERT(!prev_gl_error);
105
106     return !prev_gl_error;
107 }
108
109 bool vogl_renderbuffer_desc::serialize(json_node &node) const
110 {
111     VOGL_FUNC_TRACER
112
113     node.add_key_value("width", m_width);
114     node.add_key_value("height", m_height);
115     node.add_key_value("internal_format", g_gl_enums.find_name(m_internal_format, "gl"));
116     node.add_key_value("samples", m_samples);
117     node.add_key_value("red_size", m_red_size);
118     node.add_key_value("green_size", m_green_size);
119     node.add_key_value("blue_size", m_blue_size);
120     node.add_key_value("alpha_size", m_alpha_size);
121     node.add_key_value("depth_size", m_depth_size);
122     node.add_key_value("stencil_size", m_stencil_size);
123
124     return true;
125 }
126
127 bool vogl_renderbuffer_desc::deserialize(const json_node &node)
128 {
129     VOGL_FUNC_TRACER
130
131     clear();
132
133     m_width = node.value_as_int("width");
134     m_height = node.value_as_int("height");
135     m_samples = node.value_as_int("samples");
136     m_red_size = node.value_as_int("red_size");
137     m_green_size = node.value_as_int("green_size");
138     m_blue_size = node.value_as_int("blue_size");
139     m_alpha_size = node.value_as_int("alpha_size");
140     m_depth_size = node.value_as_int("depth_size");
141     m_stencil_size = node.value_as_int("stencil_size");
142
143     const char *pFmt = node.value_as_string_ptr("internal_format");
144     if (!pFmt)
145     {
146         VOGL_ASSERT_ALWAYS;
147         return false;
148     }
149
150     uint64_t enum_val = g_gl_enums.find_enum(pFmt);
151     VOGL_ASSERT(enum_val != gl_enums::cUnknownEnum);
152     if (enum_val == gl_enums::cUnknownEnum)
153         return false;
154     if (enum_val > cUINT32_MAX)
155     {
156         VOGL_ASSERT_ALWAYS;
157         return false;
158     }
159     m_internal_format = static_cast<GLenum>(enum_val);
160
161     return true;
162 }
163
164 bool vogl_renderbuffer_desc::operator==(const vogl_renderbuffer_desc &rhs) const
165 {
166     VOGL_FUNC_TRACER
167
168 #define COMP(x)     \
169     if (x != rhs.x) \
170         return false;
171     COMP(m_width);
172     COMP(m_height);
173     COMP(m_samples);
174     COMP(m_internal_format);
175     COMP(m_red_size);
176     COMP(m_green_size);
177     COMP(m_blue_size);
178     COMP(m_alpha_size);
179     COMP(m_depth_size);
180     COMP(m_stencil_size);
181
182 #undef COMP
183     return true;
184 }
185
186 bool vogl_renderbuffer_desc::get_int(GLenum enum_val, int *pVals, uint n) const
187 {
188     VOGL_FUNC_TRACER
189
190     int result = 0;
191
192     if (n < 1)
193         return false;
194
195     switch (enum_val)
196     {
197         case GL_RENDERBUFFER_WIDTH:
198         {
199             result = m_width;
200             break;
201         }
202         case GL_RENDERBUFFER_HEIGHT:
203         {
204             result = m_height;
205             break;
206         }
207         case GL_RENDERBUFFER_SAMPLES:
208         {
209             result = m_samples;
210             break;
211         }
212         case GL_RENDERBUFFER_INTERNAL_FORMAT:
213         {
214             result = m_internal_format;
215             break;
216         }
217         case GL_RENDERBUFFER_RED_SIZE:
218         {
219             result = m_red_size;
220             break;
221         }
222         case GL_RENDERBUFFER_GREEN_SIZE:
223         {
224             result = m_green_size;
225             break;
226         }
227         case GL_RENDERBUFFER_BLUE_SIZE:
228         {
229             result = m_blue_size;
230             break;
231         }
232         case GL_RENDERBUFFER_ALPHA_SIZE:
233         {
234             result = m_alpha_size;
235             break;
236         }
237         case GL_RENDERBUFFER_DEPTH_SIZE:
238         {
239             result = m_depth_size;
240             break;
241         }
242         case GL_RENDERBUFFER_STENCIL_SIZE:
243         {
244             result = m_stencil_size;
245             break;
246         }
247         default:
248         {
249             VOGL_ASSERT_ALWAYS;
250             *pVals = 0;
251             return false;
252         }
253     }
254
255     *pVals = result;
256     return true;
257 }
258
259 vogl_renderbuffer_state::vogl_renderbuffer_state()
260     : m_snapshot_handle(0),
261       m_is_valid(false)
262 {
263     VOGL_FUNC_TRACER
264 }
265
266 vogl_renderbuffer_state::~vogl_renderbuffer_state()
267 {
268     VOGL_FUNC_TRACER
269
270     clear();
271 }
272
273 bool vogl_renderbuffer_state::snapshot(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 handle, GLenum target)
274 {
275     VOGL_FUNC_TRACER
276
277     VOGL_NOTE_UNUSED(remapper);
278     VOGL_ASSERT(context_info.get_version() >= VOGL_GL_VERSION_3_0);
279     VOGL_CHECK_GL_ERROR;
280     VOGL_NOTE_UNUSED(target);
281
282     clear();
283
284     VOGL_ASSERT(handle <= cUINT32_MAX);
285
286     m_snapshot_handle = static_cast<GLuint>(handle);
287
288     vogl_scoped_binding_state orig_renderbuffer(GL_RENDERBUFFER);
289
290     GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, m_snapshot_handle);
291     VOGL_CHECK_GL_ERROR;
292
293     if (!m_desc.snapshot(context_info))
294         return false;
295
296     if ((!m_desc.m_width) || (!m_desc.m_height) || (!m_desc.m_internal_format))
297     {
298         // Renderbuffer was only genned - no need to spit out warning
299         //vogl_warning_printf("%s: Unable to retrieve description renderbuffer %" PRIu64 "\n", VOGL_METHOD_NAME, static_cast<uint64_t>(handle));
300     }
301     else
302     {
303         vogl_scoped_state_saver framebuffer_state_saver(cGSTReadBuffer, cGSTDrawBuffer);
304         vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_TEXTURE_2D, GL_TEXTURE_2D_MULTISAMPLE);
305
306         const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
307
308         bool capture_status = false;
309
310         GLenum internal_fmt = m_desc.m_internal_format;
311         const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt);
312         if ((pInternal_tex_fmt) && (pInternal_tex_fmt->m_optimum_get_image_fmt != GL_NONE) && (pInternal_tex_fmt->m_optimum_get_image_type != GL_NONE))
313         {
314             // Create texture
315             GLuint tex_handle = 0;
316             GL_ENTRYPOINT(glGenTextures)(1, &tex_handle);
317             VOGL_CHECK_GL_ERROR;
318
319             GL_ENTRYPOINT(glBindTexture)(tex_target, tex_handle);
320             VOGL_CHECK_GL_ERROR;
321
322             if (m_desc.m_samples > 1)
323             {
324                 GL_ENTRYPOINT(glTexImage2DMultisample)(tex_target,
325                     m_desc.m_samples,
326                     internal_fmt,
327                     m_desc.m_width,
328                     m_desc.m_height,
329                     GL_TRUE);
330             }
331             else
332             {
333                 GL_ENTRYPOINT(glTexImage2D)(tex_target,
334                     0,
335                     internal_fmt,
336                     m_desc.m_width,
337                     m_desc.m_height,
338                     0,
339                     pInternal_tex_fmt->m_optimum_get_image_fmt,
340                     pInternal_tex_fmt->m_optimum_get_image_type,
341                     NULL);
342             }
343
344             if (!vogl_check_gl_error_internal())
345             {
346                 GL_ENTRYPOINT(glTexParameteri)(tex_target, GL_TEXTURE_MAX_LEVEL, 0);
347                 VOGL_CHECK_GL_ERROR;
348
349                 GLenum attachment = GL_COLOR_ATTACHMENT0;
350                 GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0;
351                 GLenum blit_type = GL_COLOR_BUFFER_BIT;
352
353                 if ((m_desc.m_depth_size) && (m_desc.m_stencil_size))
354                 {
355                     attachment = GL_DEPTH_STENCIL_ATTACHMENT;
356                     draw_and_read_buf = GL_NONE;
357                     blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
358                 }
359                 else if (m_desc.m_depth_size)
360                 {
361                     attachment = GL_DEPTH_ATTACHMENT;
362                     draw_and_read_buf = GL_NONE;
363                     blit_type = GL_DEPTH_BUFFER_BIT;
364                 }
365                 else if (m_desc.m_stencil_size)
366                 {
367                     attachment = GL_STENCIL_ATTACHMENT;
368                     draw_and_read_buf = GL_NONE;
369                     blit_type = GL_STENCIL_BUFFER_BIT;
370                 }
371
372                 GLuint src_fbo_handle = 0, dst_fbo_handle = 0;
373
374                 // Source FBO
375                 GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle);
376                 VOGL_CHECK_GL_ERROR;
377
378                 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle);
379                 VOGL_CHECK_GL_ERROR;
380
381                 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_READ_FRAMEBUFFER, attachment, GL_RENDERBUFFER, m_snapshot_handle);
382                 VOGL_CHECK_GL_ERROR;
383
384                 GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf);
385                 VOGL_CHECK_GL_ERROR;
386
387                 // Dest FBO
388                 GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle);
389                 VOGL_CHECK_GL_ERROR;
390
391                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle);
392                 VOGL_CHECK_GL_ERROR;
393
394                 GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment, tex_target, tex_handle, 0);
395                 VOGL_CHECK_GL_ERROR;
396
397                 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf);
398                 VOGL_CHECK_GL_ERROR;
399
400                 GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER);
401                 VOGL_CHECK_GL_ERROR;
402
403                 GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
404                 VOGL_CHECK_GL_ERROR;
405
406                 if ((read_status == GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE))
407                 {
408                     GL_ENTRYPOINT(glBlitFramebuffer)(
409                         0, 0, m_desc.m_width, m_desc.m_height,
410                         0, 0, m_desc.m_width, m_desc.m_height,
411                         blit_type,
412                         GL_NEAREST);
413
414                     if (!vogl_check_gl_error_internal())
415                     {
416                         vogl_handle_remapper def_handle_remapper;
417                         if (m_texture.snapshot(context_info, def_handle_remapper, tex_handle, tex_target))
418                             capture_status = true;
419                     }
420                 }
421
422                 // Delete FBO
423                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
424                 VOGL_CHECK_GL_ERROR;
425
426                 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle);
427                 VOGL_CHECK_GL_ERROR;
428
429                 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0);
430                 VOGL_CHECK_GL_ERROR;
431
432                 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle);
433                 VOGL_CHECK_GL_ERROR;
434             }
435
436             GL_ENTRYPOINT(glBindTexture)(tex_target, 0);
437             VOGL_CHECK_GL_ERROR;
438
439             GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle);
440             VOGL_CHECK_GL_ERROR;
441         }
442
443         if (!capture_status)
444         {
445             vogl_error_printf("%s: Failed blitting renderbuffer data to texture for renderbuffer %" PRIu64 "\n", VOGL_METHOD_NAME, static_cast<uint64_t>(handle));
446         }
447     }
448
449     m_is_valid = true;
450
451     return true;
452 }
453
454 bool vogl_renderbuffer_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLuint64 &handle) const
455 {
456     VOGL_FUNC_TRACER
457
458     VOGL_ASSERT(context_info.get_version() >= VOGL_GL_VERSION_3_0);
459
460     if (!m_is_valid)
461         return false;
462
463     vogl_scoped_binding_state orig_renderbuffer(GL_RENDERBUFFER);
464
465     bool created_handle = false;
466
467     if (!handle)
468     {
469         GLuint handle32 = 0;
470         GL_ENTRYPOINT(glGenRenderbuffers)(1, &handle32);
471         if ((vogl_check_gl_error()) || (!handle32))
472             return false;
473         handle = handle32;
474
475         remapper.declare_handle(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle, handle, GL_NONE);
476         VOGL_ASSERT(remapper.remap_handle(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle) == handle);
477
478         created_handle = true;
479     }
480
481     GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, static_cast<GLuint>(handle));
482     if (vogl_check_gl_error())
483         goto handle_error;
484
485     if ((m_desc.m_width) && (m_desc.m_height) && (m_desc.m_internal_format))
486     {
487         if (!m_desc.restore(context_info))
488             goto handle_error;
489
490         if (m_texture.is_valid())
491         {
492             GLenum attachment = GL_COLOR_ATTACHMENT0;
493             GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0;
494             GLenum blit_type = GL_COLOR_BUFFER_BIT;
495
496             if ((m_desc.m_depth_size) && (m_desc.m_stencil_size))
497             {
498                 attachment = GL_DEPTH_STENCIL_ATTACHMENT;
499                 draw_and_read_buf = GL_NONE;
500                 blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
501             }
502             else if (m_desc.m_depth_size)
503             {
504                 attachment = GL_DEPTH_ATTACHMENT;
505                 draw_and_read_buf = GL_NONE;
506                 blit_type = GL_DEPTH_BUFFER_BIT;
507             }
508             else if (m_desc.m_stencil_size)
509             {
510                 attachment = GL_STENCIL_ATTACHMENT;
511                 draw_and_read_buf = GL_NONE;
512                 blit_type = GL_STENCIL_BUFFER_BIT;
513             }
514
515             bool restore_status = false;
516
517             GLuint64 tex_handle64 = 0;
518             vogl_handle_remapper def_handle_remapper;
519             if (m_texture.restore(context_info, def_handle_remapper, tex_handle64))
520             {
521                 GLuint tex_handle = static_cast<GLuint>(tex_handle64);
522
523                 const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
524
525                 GLuint src_fbo_handle = 0, dst_fbo_handle = 0;
526
527                 // Source FBO
528                 GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle);
529                 VOGL_CHECK_GL_ERROR;
530
531                 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle);
532                 VOGL_CHECK_GL_ERROR;
533
534                 GL_ENTRYPOINT(glFramebufferTexture2D)(GL_READ_FRAMEBUFFER, attachment, tex_target, tex_handle, 0);
535                 VOGL_CHECK_GL_ERROR;
536
537                 GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf);
538                 VOGL_CHECK_GL_ERROR;
539
540                 // Dest FBO
541                 GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle);
542                 VOGL_CHECK_GL_ERROR;
543
544                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle);
545                 VOGL_CHECK_GL_ERROR;
546
547                 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, static_cast<GLuint>(handle));
548                 VOGL_CHECK_GL_ERROR;
549
550                 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf);
551                 VOGL_CHECK_GL_ERROR;
552
553                 GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER);
554                 VOGL_CHECK_GL_ERROR;
555
556                 GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
557                 VOGL_CHECK_GL_ERROR;
558
559                 if ((read_status = GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE))
560                 {
561     #if 0
562                     // HACK HACK HACK
563                     if (m_texture.get_num_samples() > 1)
564                     {
565                         uint base_level = m_texture.get_params().get_value<GLenum>(GL_TEXTURE_BASE_LEVEL);
566
567                         if (base_level < m_texture.get_num_levels())
568                         {
569                             const vogl_state_vector &state_vec = m_texture.get_level_params(0, base_level);
570
571                             uint clear_mask = 0;
572                             if (state_vec.get_value<GLenum>(GL_TEXTURE_DEPTH_SIZE))
573                             {
574                                 clear_mask |= GL_DEPTH_BUFFER_BIT;
575                             }
576                             if (state_vec.get_value<GLenum>(GL_TEXTURE_STENCIL_SIZE))
577                             {
578                                 clear_mask |= GL_STENCIL_BUFFER_BIT;
579                             }
580                             if (state_vec.get_value<GLenum>(GL_TEXTURE_RED_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_GREEN_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_BLUE_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_ALPHA_SIZE) +
581                                 state_vec.get_value<GLenum>(GL_TEXTURE_INTENSITY_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_LUMINANCE_SIZE))
582                             {
583                                 clear_mask |= GL_COLOR_BUFFER_BIT;
584                             }
585
586                             GL_ENTRYPOINT(glClearColor)(1.0f, 0.0f, 1.0f, 1.0f);
587                             GL_ENTRYPOINT(glClearDepth)(.5f);
588                             GL_ENTRYPOINT(glClearStencil)(128);
589                             GL_ENTRYPOINT(glClear)(clear_mask);
590
591                             VOGL_CHECK_GL_ERROR;
592                         }
593                     }
594                     else
595     #endif
596                     {
597                         GL_ENTRYPOINT(glBlitFramebuffer)(
598                             0, 0, m_desc.m_width, m_desc.m_height,
599                             0, 0, m_desc.m_width, m_desc.m_height,
600                             blit_type,
601                             GL_NEAREST);
602
603                         if (!vogl_check_gl_error_internal())
604                         {
605                             restore_status = true;
606                         }
607                     }
608                 }
609
610                 // Delete FBO
611                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
612                 VOGL_CHECK_GL_ERROR;
613
614                 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle);
615                 VOGL_CHECK_GL_ERROR;
616
617                 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0);
618                 VOGL_CHECK_GL_ERROR;
619
620                 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle);
621                 VOGL_CHECK_GL_ERROR;
622
623                 GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle);
624                 VOGL_CHECK_GL_ERROR;
625             }
626
627             if (!restore_status)
628             {
629                 vogl_error_printf("%s: Failed restoring contents of renderbuffer %u\n", VOGL_METHOD_NAME, static_cast<GLuint>(handle));
630             }
631         }
632     }
633
634     return true;
635
636 handle_error:
637     if (created_handle)
638     {
639         GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
640         VOGL_CHECK_GL_ERROR;
641
642         remapper.delete_handle_and_object(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle, handle);
643
644         //GLuint handle32 = static_cast<GLuint>(handle);
645         //GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &handle32);
646         //VOGL_CHECK_GL_ERROR;
647
648         handle = 0;
649     }
650
651     return false;
652 }
653
654 bool vogl_renderbuffer_state::remap_handles(vogl_handle_remapper &remapper)
655 {
656     VOGL_FUNC_TRACER
657
658     if (!m_is_valid)
659         return false;
660
661     m_snapshot_handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_RENDER_BUFFERS, m_snapshot_handle));
662
663     return true;
664 }
665
666 void vogl_renderbuffer_state::clear()
667 {
668     VOGL_FUNC_TRACER
669
670     m_snapshot_handle = 0;
671
672     m_desc.clear();
673     m_texture.clear();
674
675     m_is_valid = false;
676 }
677
678 bool vogl_renderbuffer_state::serialize(json_node &node, vogl_blob_manager &blob_manager) const
679 {
680     VOGL_FUNC_TRACER
681
682     VOGL_NOTE_UNUSED(blob_manager);
683
684     if (!m_is_valid)
685         return false;
686
687     node.add_key_value("handle", m_snapshot_handle);
688
689     if (!m_desc.serialize(node))
690         return false;
691
692     if (m_texture.is_valid())
693     {
694         if (!m_texture.serialize(node.add_object("texture"), blob_manager))
695             return false;
696     }
697
698     return true;
699 }
700
701 bool vogl_renderbuffer_state::deserialize(const json_node &node, const vogl_blob_manager &blob_manager)
702 {
703     VOGL_FUNC_TRACER
704
705     VOGL_NOTE_UNUSED(blob_manager);
706
707     clear();
708
709     m_snapshot_handle = node.value_as_int("handle");
710
711     if (!m_desc.deserialize(node))
712         return false;
713
714     if (node.has_object("texture"))
715     {
716         if (!m_texture.deserialize(*node.find_child_object("texture"), blob_manager))
717             return false;
718     }
719
720     m_is_valid = true;
721
722     return true;
723 }
724
725 bool vogl_renderbuffer_state::compare_restorable_state(const vogl_gl_object_state &rhs_obj) const
726 {
727     VOGL_FUNC_TRACER
728
729     if ((!m_is_valid) || (!rhs_obj.is_valid()))
730         return false;
731
732     if (rhs_obj.get_type() != cGLSTRenderbuffer)
733         return false;
734
735     const vogl_renderbuffer_state &rhs = static_cast<const vogl_renderbuffer_state &>(rhs_obj);
736
737     if (this == &rhs)
738         return true;
739
740     return (m_desc == rhs.m_desc) && (m_texture.compare_restorable_state(rhs.m_texture));
741 }
742