]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_gl_utils.h
Initial vogl checkin
[vogl] / src / voglcommon / vogl_gl_utils.h
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_gl_utils.h
27 #ifndef VOGL_GL_UTILS_H
28 #define VOGL_GL_UTILS_H
29
30 // Loki
31 #include "TypeTraits.h"
32
33 #include "vogl_ctypes.h"
34
35 #include "vogl_hash_map.h"
36 #include "vogl_command_line_params.h"
37 #include "vogl_map.h"
38 #include "vogl_json.h"
39 #include "vogl_value.h"
40 #include "vogl_growable_array.h"
41 #include "vogl_matrix.h"
42
43 //----------------------------------------------------------------------------------------------------------------------
44 // Types
45 //----------------------------------------------------------------------------------------------------------------------
46 namespace vogl
47 {
48     class json_value;
49 }
50
51 class vogl_context_info;
52 class vogl_blob_manager;
53 class vogl_context_desc;
54
55 typedef vogl::map<GLenum, int> GLenum_to_int_map;
56
57 //----------------------------------------------------------------------------------------------------------------------
58 // Console output
59 //----------------------------------------------------------------------------------------------------------------------
60 #define vogl_printf vogl::console::info
61 #define vogl_message_printf vogl::console::message
62 #define vogl_debug_printf vogl::console::debug
63 #define vogl_warning_printf vogl::console::warning
64 #define vogl_error_printf vogl::console::error
65 #define vogl_log_printf vogl::console::info
66 #define vogl_header1_printf vogl::console::header1
67
68 #define vogl_printf_once(x, ...)                    \
69     {                                              \
70         static bool __printed_msg##__LINE__;       \
71         if (!__printed_msg##__LINE__)              \
72         {                                          \
73             __printed_msg##__LINE__ = true;        \
74             vogl::console::info(x, __VA_ARGS__); \
75         }                                          \
76     }
77 #define vogl_message_printf_once(x, ...)               \
78     {                                                 \
79         static bool __printed_msg##__LINE__;          \
80         if (!__printed_msg##__LINE__)                 \
81         {                                             \
82             __printed_msg##__LINE__ = true;           \
83             vogl::console::message(x, __VA_ARGS__); \
84         }                                             \
85     }
86 #define vogl_debug_printf_once(x, ...)               \
87     {                                               \
88         static bool __printed_msg##__LINE__;        \
89         if (!__printed_msg##__LINE__)               \
90         {                                           \
91             __printed_msg##__LINE__ = true;         \
92             vogl::console::debug(x, __VA_ARGS__); \
93         }                                           \
94     }
95 #define vogl_warning_printf_once(x, ...)               \
96     {                                                 \
97         static bool __printed_msg##__LINE__;          \
98         if (!__printed_msg##__LINE__)                 \
99         {                                             \
100             __printed_msg##__LINE__ = true;           \
101             vogl::console::warning(x, __VA_ARGS__); \
102         }                                             \
103     }
104 #define vogl_error_printf_once(x, ...)               \
105     {                                               \
106         static bool __printed_msg##__LINE__;        \
107         if (!__printed_msg##__LINE__)               \
108         {                                           \
109             __printed_msg##__LINE__ = true;         \
110             vogl::console::error(x, __VA_ARGS__); \
111         }                                           \
112     }
113 #define vogl_log_printf_once(x, ...)                \
114     {                                              \
115         static bool __printed_msg##__LINE__;       \
116         if (!__printed_msg##__LINE__)              \
117         {                                          \
118             __printed_msg##__LINE__ = true;        \
119             vogl::console::info(x, __VA_ARGS__); \
120         }                                          \
121     }
122
123 //----------------------------------------------------------------------------------------------------------------------
124 // cast_val_to_uint64
125 //----------------------------------------------------------------------------------------------------------------------
126 template <typename T>
127 static inline uint64_t cast_val_to_uint64(const T &value)
128 {
129     int64_t res = 0;
130     uint n = sizeof(T);
131     if (n > sizeof(uint64_t))
132         n = sizeof(uint64_t);
133     memcpy(&res, &value, n);
134     return res;
135 }
136
137 //----------------------------------------------------------------------------------------------------------------------
138 // type/format/texture helpers
139 //----------------------------------------------------------------------------------------------------------------------
140 uint32_t vogl_get_gl_type_size(uint32_t ogl_type);
141 uint vogl_get_image_format_channels(GLenum format);
142 void vogl_get_image_format_info(GLenum format, GLenum type, uint &num_channels, uint &bits_per_element, uint &bits_per_pixel);
143
144 // vogl_get_image_size() reads the current pixel unpack state!
145 size_t vogl_get_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth);
146 size_t vogl_get_tex_target_image_size(GLenum target, GLint level, GLenum format, GLenum type);
147 uint vogl_get_image_format_size_in_bytes(GLenum format, GLenum type);
148
149 size_t vogl_determine_glMap1_size(GLenum target, GLint stride, GLint order);
150 size_t vogl_determine_glMap2_size(GLenum target, GLint ustride, GLint uorder, GLint vstride, GLint vorder);
151
152 //----------------------------------------------------------------------------------------------------------------------
153 // struct vogl_enum_desc
154 //----------------------------------------------------------------------------------------------------------------------
155 struct vogl_enum_desc
156 {
157     inline vogl_enum_desc()
158     {
159     }
160
161     inline vogl_enum_desc(uint64_t value, const char *pPrefix, const char *pSpec_type, const char *pGL_type, const char *pMacro_name)
162         : m_value(value), m_prefix(pPrefix), m_spec_type(pSpec_type), m_gl_type(pGL_type), m_macro_name(pMacro_name)
163     {
164         VOGL_FUNC_TRACER
165     }
166
167     uint64_t m_value;
168     vogl::dynamic_string m_prefix;
169     vogl::dynamic_string m_spec_type;
170     vogl::dynamic_string m_gl_type;
171     vogl::dynamic_string m_macro_name;
172
173     // Priorities are only used when trying to determine the best enum string to return given a value.
174     // TODO: Move this to voglgen to avoid the runtime init cost.
175     enum sort_priority_t
176     {
177         cSCNone = 0,
178         cSCARB,
179         cSCEXT,
180         cSCVendor,
181         cSCOES
182     };
183
184     sort_priority_t m_sort_priority;
185
186     void init_sort_priority();
187
188     bool operator<(const vogl_enum_desc &rhs) const;
189 };
190
191 typedef vogl::vector<vogl_enum_desc> vogl_enum_desc_vec;
192
193 //----------------------------------------------------------------------------------------------------------------------
194 // vogl_spec_type_value_enum_key
195 //----------------------------------------------------------------------------------------------------------------------
196 struct vogl_spec_type_and_value_enum_key
197 {
198     inline vogl_spec_type_and_value_enum_key()
199     {
200     }
201
202     inline vogl_spec_type_and_value_enum_key(const char *pSpec_type, uint64_t value)
203         : m_spec_type(pSpec_type), m_value(value)
204     {
205         VOGL_FUNC_TRACER
206     }
207
208     vogl::dynamic_string m_spec_type;
209     uint64_t m_value;
210
211     inline bool operator==(const vogl_spec_type_and_value_enum_key &rhs) const
212     {
213         return (m_spec_type == rhs.m_spec_type) && (m_value == rhs.m_value);
214     }
215
216     inline operator size_t() const
217     {
218         return vogl::fast_hash_obj(m_value) ^ static_cast<size_t>(m_spec_type.get_hash());
219     }
220 };
221
222 //----------------------------------------------------------------------------------------------------------------------
223 // enum vogl_state_type
224 // TODO: Rename this to vogl_pname_type or something
225 //----------------------------------------------------------------------------------------------------------------------
226 enum vogl_state_type
227 {
228     // These enums MUST me consistent with the types in pname_defs.h
229     cSTInvalid = 'X',
230     cSTGLboolean = 'B',
231     cSTGLenum = 'E',
232     cSTInt32 = 'I',
233     cSTUInt32 = 'U',
234     cSTInt64 = 'i',
235     cSTUInt64 = 'u',
236     cSTFloat = 'F',
237     cSTDouble = 'D',
238     cSTPointer = 'P',
239     cTotalStateTypes = 9
240 };
241
242 //----------------------------------------------------------------------------------------------------------------------
243 // enum helpers
244 //----------------------------------------------------------------------------------------------------------------------
245 class gl_enums
246 {
247     VOGL_NO_COPY_OR_ASSIGNMENT_OP(gl_enums);
248
249 public:
250     gl_enums();
251
252     // pPreferred_prefix should usually be "gl", or it can be "glx", "wgl", etc.
253     // TODO: Add a helper that takes a GL entrypoint and param index from vogl_trace_packet::ctype_to_json_value()
254     const char *find_name(uint64_t gl_enum, const char *pPreferred_prefix = NULL) const;
255
256     const char *find_name(const char *pSpec_type, uint64_t gl_enum, const char *pPreferred_prefix = NULL) const;
257
258     const char *find_name(uint64_t gl_enum, gl_entrypoint_id_t entrypoint_id, int param_index) const;
259
260     const char *find_gl_name(uint64_t gl_enum) const
261     {
262         return find_name(gl_enum, "gl");
263     }
264     const char *find_glx_name(uint64_t gl_enum) const
265     {
266         return find_name(gl_enum, "glx");
267     }
268     const char *find_gl_error_name(GLenum gl_enum) const
269     {
270         return find_name("ErrorCode", gl_enum);
271     }
272
273     // Finds the name of a GL internal/base image format, if this fails then it just calls find_gl_name().
274     const char *find_gl_image_format_name(GLenum gl_enum) const;
275
276     // Returns -1 on failure
277     enum
278     {
279         cUnknownEnum = 0xFFFFFFFFFFFFFFF0ULL
280     };
281     uint64_t find_enum(const dynamic_string &str) const;
282
283     // This is driven via the pname table, but it may also call GL!
284     int get_pname_count(uint64_t gl_enum) const;
285
286     // This is driven via the pname table, but it may also call GL!
287     int get_pname_type(uint64_t gl_enum) const;
288
289     // Maps a GL enum to a pname definition index, or returns cInvalidIndex on failure.
290     int find_pname_def_index(uint64_t gl_enum) const;
291
292 private:
293     uint16_t m_gl_enum_to_pname_def_index[0x10000];
294
295     typedef vogl::hash_map<dynamic_string, uint64_t> gl_enum_name_hash_map;
296     gl_enum_name_hash_map m_enum_name_hash_map;
297
298     typedef vogl::hash_map<uint64_t, vogl_enum_desc_vec> gl_enum_value_to_enum_desc_hash_map;
299     gl_enum_value_to_enum_desc_hash_map m_enum_value_hash_map;
300
301     typedef vogl::hash_map<vogl_spec_type_and_value_enum_key, vogl_enum_desc_vec> gl_spec_type_and_value_to_enum_desc_hash_map_t;
302     gl_spec_type_and_value_to_enum_desc_hash_map_t m_spec_type_and_enum_value_hash_map;
303
304     typedef vogl::hash_map<GLenum, const char *> vogl_image_format_hashmap_t;
305     vogl_image_format_hashmap_t m_image_formats;
306
307     void init_enum_descs();
308     void add_enum(const char *pPrefix, const char *pSpec_type, const char *pGL_type, const char *pName, uint64_t value);
309     void init_image_formats();
310 };
311
312 extern gl_enums g_gl_enums;
313
314 GLenum vogl_get_json_value_as_enum(const json_node &node, const char *pKey, GLenum def = 0);
315 GLenum vogl_get_json_value_as_enum(const json_value &val, GLenum def = 0);
316
317 //----------------------------------------------------------------------------------------------------------------------
318 // Client side array tables
319 //----------------------------------------------------------------------------------------------------------------------
320 struct vogl_client_side_array_desc_t
321 {
322     gl_entrypoint_id_t m_entrypoint;
323     uint m_is_enabled;  // glIsEnabled
324     uint m_get_binding; // glGetIntegerv - this gets the snapshotted binding
325     uint m_get_pointer; // glGetPointerv
326     uint m_get_size;    // will be 0 if there is no associated glGet
327     uint m_get_stride;  // glGetIntegerv
328     uint m_get_type;    // glGetIntegerv
329 };
330
331 #define VOGL_CLIENT_SIDE_ARRAY_DESC(id, entrypoint, is_enabled, get_binding, get_pointer, get_size, get_stride, get_type) id,
332 enum vogl_client_side_array_desc_id_t
333 {
334 #include "vogl_client_side_array_descs.inc"
335     VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS
336 };
337 #undef VOGL_CLIENT_SIDE_ARRAY_DESC
338
339 extern const vogl_client_side_array_desc_t g_vogl_client_side_array_descs[];
340
341 //----------------------------------------------------------------------------------------------------------------------
342 // Misc GL helpers/wrappers
343 //----------------------------------------------------------------------------------------------------------------------
344 GLuint vogl_get_bound_gl_buffer(GLenum target);
345
346 // glGet() wrappers
347 GLint vogl_get_gl_integer(GLenum pname);
348 vec4I vogl_get_gl_vec4I(GLenum pname);
349 GLint vogl_get_gl_integer_indexed(GLenum pname, uint index);
350 GLint64 vogl_get_gl_integer64(GLenum pname);
351 GLint64 vogl_get_gl_integer64_indexed(GLenum pname, uint index);
352 GLboolean vogl_get_gl_boolean(GLenum pname);
353 GLboolean vogl_get_gl_boolean_indexed(GLenum pname, uint index);
354 GLfloat vogl_get_gl_float(GLenum pname);
355 vec4F vogl_get_gl_vec4F(GLenum pname);
356 matrix44F vogl_get_gl_matrix44F(GLenum pname);
357 GLdouble vogl_get_gl_double(GLenum pname);
358 vec4D vogl_get_gl_vec4D(GLenum pname);
359 matrix44D vogl_get_gl_matrix44D(GLenum pname);
360
361 void vogl_reset_pixel_store_states();
362 void vogl_reset_pixel_transfer_states();
363
364 bool vogl_copy_buffer_to_image(void *pDst, uint dst_size, uint width, uint height, GLuint format = GL_RGB, GLuint type = GL_UNSIGNED_BYTE, bool flip_image = false, GLuint framebuffer = 0, GLuint read_buffer = GL_BACK, GLuint pixel_pack_buffer = 0);
365
366 //----------------------------------------------------------------------------------------------------------------------
367 // Entrypoint helpers
368 //----------------------------------------------------------------------------------------------------------------------
369
370 inline bool vogl_is_make_current_entrypoint(gl_entrypoint_id_t id)
371 {
372     return (id == VOGL_ENTRYPOINT_glXMakeCurrent);
373 }
374
375 inline bool vogl_is_swap_buffers_entrypoint(gl_entrypoint_id_t id)
376 {
377     return (id == VOGL_ENTRYPOINT_glXSwapBuffers);
378 }
379
380 bool vogl_is_draw_entrypoint(gl_entrypoint_id_t id);
381 bool vogl_is_clear_entrypoint(gl_entrypoint_id_t id);
382
383 //----------------------------------------------------------------------------------------------------------------------
384 // Error helpers
385 //----------------------------------------------------------------------------------------------------------------------
386 extern bool g_gl_get_error_enabled;
387
388 // Returns *true* if there was an error.
389 bool vogl_check_gl_error_internal(bool suppress_error_message = false, const char *pFile = "", uint line = 0, const char *pFunc = "");
390 #define vogl_check_gl_error() (g_gl_get_error_enabled ? vogl_check_gl_error_internal(false, __FILE__, __LINE__, __PRETTY_FUNCTION__) : false)
391 #define vogl_check_gl_error_suppress_message() (g_gl_get_error_enabled ? vogl_check_gl_error_internal(true, __FILE__, __LINE__, __PRETTY_FUNCTION__) : false)
392
393 #define VOGL_CHECK_GL_ERROR                         \
394     do                                             \
395     {                                              \
396         bool prev_gl_error = vogl_check_gl_error(); \
397         VOGL_ASSERT(!prev_gl_error);             \
398         VOGL_NOTE_UNUSED(prev_gl_error);         \
399     } while (0)
400
401 void vogl_enable_gl_get_error();
402 void vogl_disable_gl_get_error();
403 bool vogl_is_gl_get_error_enabled();
404
405 //----------------------------------------------------------------------------------------------------------------------
406 // Binding helpers
407 //----------------------------------------------------------------------------------------------------------------------
408 GLenum vogl_get_binding_from_target(GLenum target);
409 GLenum vogl_get_object_category_from_binding(GLenum binding);
410 GLenum vogl_get_object_category_from_target(GLenum target);
411 GLenum vogl_get_target_from_binding(GLenum binding);
412
413 void vogl_bind_object(GLenum target, GLuint handle);
414 GLuint vogl_get_bound_object(GLenum target);
415
416 void vogl_debug_message_control(const vogl_context_info &context_info, GLenum err_code, bool enabled);
417
418 // NOTE: Don't use this for anything other than debugging!
419 GLenum vogl_determine_texture_target(const vogl_context_info &context_info, GLuint handle);
420
421 int vogl_gl_get_uniform_size_in_GLints(GLenum type);
422 int vogl_gl_get_uniform_size_in_bytes(GLenum type);
423 int vogl_gl_get_uniform_base_type(GLenum type);
424
425 //----------------------------------------------------------------------------------------------------------------------
426 // class vogl_binding_state
427 //----------------------------------------------------------------------------------------------------------------------
428 class vogl_binding_state
429 {
430     struct saved_binding
431     {
432         saved_binding()
433         {
434         }
435         saved_binding(GLenum target, GLenum handle)
436             : m_target(target), m_handle(handle)
437         {
438         }
439         void set(GLenum target, GLenum handle)
440         {
441             m_target = target;
442             m_handle = handle;
443         }
444
445         GLenum m_target;
446         GLuint m_handle;
447     };
448
449     vogl::growable_array<saved_binding, 16> m_bindings;
450
451 public:
452     vogl_binding_state()
453     {
454         VOGL_FUNC_TRACER
455     }
456     ~vogl_binding_state()
457     {
458         VOGL_FUNC_TRACER
459     }
460
461     void clear()
462     {
463         VOGL_FUNC_TRACER m_bindings.clear();
464     }
465
466     void save(GLenum target)
467     {
468         VOGL_FUNC_TRACER
469
470         GLuint handle = vogl_get_bound_object(target);
471         m_bindings.enlarge(1)->set(target, handle);
472     }
473
474     void save_textures()
475     {
476         VOGL_FUNC_TRACER
477
478         // TODO: the valid stuff to save depends on the context version, argh
479         // TODO: Add GL4 texture types!
480         static const GLenum s_texture_targets[] =
481             {
482                 GL_ACTIVE_TEXTURE,
483                 GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY,
484                 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
485                 GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BUFFER, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY
486             };
487
488         m_bindings.reserve(VOGL_ARRAY_SIZE(s_texture_targets) + 8);
489         for (uint i = 0; i < VOGL_ARRAY_SIZE(s_texture_targets); i++)
490             save(s_texture_targets[i]);
491     }
492
493     void save_buffers()
494     {
495         VOGL_FUNC_TRACER
496
497         static const GLenum s_buffer_targets[] =
498             {
499                 GL_ARRAY_BUFFER, GL_ATOMIC_COUNTER_BUFFER, GL_COPY_READ_BUFFER,
500                 GL_COPY_WRITE_BUFFER, GL_DRAW_INDIRECT_BUFFER, GL_DISPATCH_INDIRECT_BUFFER,
501                 GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER,
502                 GL_SHADER_STORAGE_BUFFER, GL_TEXTURE_BUFFER,
503                 GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER
504                 // TODO: GL_QUERY_BUFFER
505             };
506
507         m_bindings.reserve(VOGL_ARRAY_SIZE(s_buffer_targets) + 8);
508         for (uint i = 0; i < VOGL_ARRAY_SIZE(s_buffer_targets); i++)
509             save(s_buffer_targets[i]);
510     }
511
512     void restore()
513     {
514         VOGL_FUNC_TRACER
515
516         for (uint i = 0; i < m_bindings.size(); i++)
517             vogl_bind_object(m_bindings[i].m_target, m_bindings[i].m_handle);
518     }
519 };
520
521 //----------------------------------------------------------------------------------------------------------------------
522 // class vogl_scoped_binding_state
523 //----------------------------------------------------------------------------------------------------------------------
524 class vogl_scoped_binding_state
525 {
526     vogl_binding_state m_saved_state;
527
528 public:
529     vogl_scoped_binding_state()
530     {
531         VOGL_FUNC_TRACER
532     }
533     vogl_scoped_binding_state(GLenum target)
534     {
535         VOGL_FUNC_TRACER m_saved_state.save(target);
536     }
537     vogl_scoped_binding_state(GLenum target0, GLenum target1)
538     {
539         VOGL_FUNC_TRACER m_saved_state.save(target0);
540         m_saved_state.save(target1);
541     }
542     vogl_scoped_binding_state(GLenum target0, GLenum target1, GLenum target2)
543     {
544         VOGL_FUNC_TRACER m_saved_state.save(target0);
545         m_saved_state.save(target1);
546         m_saved_state.save(target2);
547     }
548     vogl_scoped_binding_state(GLenum target0, GLenum target1, GLenum target2, GLenum target3)
549     {
550         VOGL_FUNC_TRACER m_saved_state.save(target0);
551         m_saved_state.save(target1);
552         m_saved_state.save(target2);
553         m_saved_state.save(target3);
554     }
555
556     ~vogl_scoped_binding_state()
557     {
558         VOGL_FUNC_TRACER restore();
559     }
560
561     void clear()
562     {
563         VOGL_FUNC_TRACER m_saved_state.clear();
564     }
565
566     void save(GLenum target)
567     {
568         VOGL_FUNC_TRACER m_saved_state.save(target);
569     }
570
571     void save_textures()
572     {
573         VOGL_FUNC_TRACER m_saved_state.save_textures();
574     }
575     void save_buffers()
576     {
577         VOGL_FUNC_TRACER m_saved_state.save_buffers();
578     }
579
580     void restore()
581     {
582         VOGL_FUNC_TRACER m_saved_state.restore();
583         m_saved_state.clear();
584     }
585 };
586
587 //----------------------------------------------------------------------------------------------------------------------
588 // enum vogl_generic_state_types_t
589 //----------------------------------------------------------------------------------------------------------------------
590 enum vogl_generic_state_type
591 {
592     cGSTPixelStore,    // pixel pack, unpack
593     cGSTPixelTransfer, // GL_INDEX_OFFSET, RGBA scale/biases, etc.
594     cGSTReadBuffer,    // this is a per-framebuffer state!
595     cGSTDrawBuffer,    // this is a per-framebuffer state!
596     cGSTActiveTexture,
597     cGSTClientActiveTexture,
598     cGSTMatrixMode,
599     cGSTARBVertexProgram,
600     cGSTARBFragmentProgram,
601     cGSTTotalTypes
602 };
603
604 //----------------------------------------------------------------------------------------------------------------------
605 // class vogl_state_saver
606 //----------------------------------------------------------------------------------------------------------------------
607 class vogl_state_saver
608 {
609     struct saved_state
610     {
611         saved_state()
612         {
613             VOGL_FUNC_TRACER
614         }
615
616         template <typename T>
617         saved_state(vogl_generic_state_type state_type, GLenum pname, T data)
618             : m_state_type(state_type), m_pname(pname), m_value(data)
619         {
620             VOGL_FUNC_TRACER
621         }
622
623         template <typename T>
624         void set(vogl_generic_state_type state_type, GLenum pname, T data)
625         {
626             VOGL_FUNC_TRACER m_state_type = state_type;
627             m_pname = pname;
628             m_value = data;
629         }
630
631         vogl_generic_state_type m_state_type;
632
633         GLenum m_pname;
634         vogl::value m_value;
635     };
636
637 public:
638     vogl_state_saver()
639     {
640         VOGL_FUNC_TRACER
641     }
642
643     void clear()
644     {
645         VOGL_FUNC_TRACER m_states.clear();
646         m_draw_buffers.clear();
647     }
648
649     void save(vogl_generic_state_type type);
650     void restore();
651
652 private:
653     vogl::growable_array<saved_state, 64> m_states;
654     vogl::growable_array<GLenum, 32> m_draw_buffers;
655 };
656
657 //----------------------------------------------------------------------------------------------------------------------
658 // class vogl_scoped_state
659 //----------------------------------------------------------------------------------------------------------------------
660 class vogl_scoped_state_saver
661 {
662     vogl_state_saver m_state;
663
664 public:
665     vogl_scoped_state_saver()
666     {
667         VOGL_FUNC_TRACER
668     }
669     vogl_scoped_state_saver(vogl_generic_state_type type)
670     {
671         VOGL_FUNC_TRACER save(type);
672     }
673     vogl_scoped_state_saver(vogl_generic_state_type type0, vogl_generic_state_type type1)
674     {
675         VOGL_FUNC_TRACER save(type0);
676         save(type1);
677     }
678     vogl_scoped_state_saver(vogl_generic_state_type type0, vogl_generic_state_type type1, vogl_generic_state_type type2)
679     {
680         VOGL_FUNC_TRACER save(type0);
681         save(type1);
682         save(type2);
683     }
684     vogl_scoped_state_saver(vogl_generic_state_type type0, vogl_generic_state_type type1, vogl_generic_state_type type2, vogl_generic_state_type type3)
685     {
686         VOGL_FUNC_TRACER save(type0);
687         save(type1);
688         save(type2);
689         save(type3);
690     }
691
692     ~vogl_scoped_state_saver()
693     {
694         VOGL_FUNC_TRACER restore();
695     }
696
697     void clear()
698     {
699         VOGL_FUNC_TRACER m_state.clear();
700     }
701
702     void save(vogl_generic_state_type type)
703     {
704         VOGL_FUNC_TRACER m_state.save(type);
705     }
706     void restore()
707     {
708         VOGL_FUNC_TRACER m_state.restore();
709         clear();
710     }
711 };
712
713 //----------------------------------------------------------------------------------------------------------------------
714 // vogl_json_serialize_vec
715 //----------------------------------------------------------------------------------------------------------------------
716 template <typename T>
717 inline bool vogl_json_serialize_vec(json_node &node, vogl_blob_manager &blob_manager, const char *pKey, const T &vec)
718 {
719     VOGL_FUNC_TRACER
720
721     json_node &array_node = node.add_array(pKey);
722     for (uint i = 0; i < vec.size(); i++)
723     {
724         json_node &obj_node = array_node.add_object();
725         if (!vec[i].serialize(obj_node, blob_manager))
726             return false;
727     }
728     return true;
729 }
730
731 //----------------------------------------------------------------------------------------------------------------------
732 // vogl_json_serialize_ptr_vec
733 //----------------------------------------------------------------------------------------------------------------------
734 template <typename T>
735 inline bool vogl_json_serialize_ptr_vec(json_node &node, vogl_blob_manager &blob_manager, const char *pKey, const T &vec)
736 {
737     VOGL_FUNC_TRACER
738
739     json_node &array_node = node.add_array(pKey);
740     for (uint i = 0; i < vec.size(); i++)
741     {
742         json_node &obj_node = array_node.add_object();
743         if (vec[i])
744         {
745             if (!vec[i]->serialize(obj_node, blob_manager))
746                 return false;
747         }
748     }
749     return true;
750 }
751
752 //----------------------------------------------------------------------------------------------------------------------
753 // vogl_json_serialize_ptr_vec
754 //----------------------------------------------------------------------------------------------------------------------
755 template <typename T, typename U>
756 inline bool vogl_json_serialize_ptr_vec(json_node &node, vogl_blob_manager &blob_manager, const char *pKey, const T &vec, const U &p0)
757 {
758     VOGL_FUNC_TRACER
759
760     json_node &array_node = node.add_array(pKey);
761     for (uint i = 0; i < vec.size(); i++)
762     {
763         json_node &obj_node = array_node.add_object();
764         if (vec[i])
765         {
766             if (!vec[i]->serialize(obj_node, blob_manager, p0))
767                 return false;
768         }
769     }
770     return true;
771 }
772
773 //----------------------------------------------------------------------------------------------------------------------
774 // vogl_json_deserialize_vec
775 //----------------------------------------------------------------------------------------------------------------------
776 template <typename T>
777 inline bool vogl_json_deserialize_vec(const json_node &node, const vogl_blob_manager &blob_manager, const char *pKey, T &vec)
778 {
779     VOGL_FUNC_TRACER
780
781     const json_node *pArray_node = node.find_child_array(pKey);
782     if (!pArray_node)
783     {
784         vec.resize(0);
785         return false;
786     }
787
788     vec.resize(pArray_node->size());
789
790     for (uint i = 0; i < pArray_node->size(); i++)
791     {
792         const json_node *pObj_node = pArray_node->get_value_as_object(i);
793         if (!pObj_node)
794             return false;
795         if (!vec[i].deserialize(*pObj_node, blob_manager))
796             return false;
797     }
798     return true;
799 }
800
801 //----------------------------------------------------------------------------------------------------------------------
802 // vogl_json_deserialize_ptr_vec
803 //----------------------------------------------------------------------------------------------------------------------
804 template <typename T>
805 inline bool vogl_json_deserialize_ptr_vec(const json_node &node, const vogl_blob_manager &blob_manager, const char *pKey, T &vec)
806 {
807     VOGL_FUNC_TRACER
808
809     const json_node *pArray_node = node.find_child_array(pKey);
810     if (!pArray_node)
811     {
812         vec.resize(0);
813         return false;
814     }
815
816     vec.resize(0);
817
818     for (uint i = 0; i < pArray_node->size(); i++)
819     {
820         const json_node *pObj_node = pArray_node->get_value_as_object(i);
821         if (!pObj_node)
822             return false;
823
824         typename T::value_type pObj = vogl_new(typename Loki::TypeTraits<typename T::value_type>::PointeeType);
825
826         if (!pObj->deserialize(*pObj_node, blob_manager))
827         {
828             vogl_delete(pObj);
829             return false;
830         }
831
832         vec.push_back(pObj);
833     }
834     return true;
835 }
836
837 //----------------------------------------------------------------------------------------------------------------------
838 // vogl_json_deserialize_ptr_vec
839 //----------------------------------------------------------------------------------------------------------------------
840 template <typename T, typename U>
841 inline bool vogl_json_deserialize_ptr_vec(const json_node &node, const vogl_blob_manager &blob_manager, const char *pKey, T &vec, const U &p0)
842 {
843     VOGL_FUNC_TRACER
844
845     const json_node *pArray_node = node.find_child_array(pKey);
846     if (!pArray_node)
847     {
848         vec.resize(0);
849         return false;
850     }
851
852     vec.resize(0);
853
854     for (uint i = 0; i < pArray_node->size(); i++)
855     {
856         const json_node *pObj_node = pArray_node->get_value_as_object(i);
857         if (!pObj_node)
858             return false;
859
860         typename T::value_type pObj = vogl_new(typename Loki::TypeTraits<typename T::value_type>::PointeeType);
861
862         if (!pObj->deserialize(*pObj_node, blob_manager, p0))
863         {
864             vogl_delete(pObj);
865             return false;
866         }
867
868         vec.push_back(pObj);
869     }
870     return true;
871 }
872
873 //----------------------------------------------------------------------------------------------------------------------
874 // vogl_json_deserialize_obj
875 //----------------------------------------------------------------------------------------------------------------------
876 template <typename T>
877 bool vogl_json_deserialize_obj(const json_node &node, const vogl_blob_manager &blob_manager, const char *pKey, T &obj)
878 {
879     VOGL_FUNC_TRACER
880
881     const json_node *pNode = node.find_child_object(pKey);
882     if (!pNode)
883         return false;
884     return obj.deserialize(*pNode, blob_manager);
885 }
886
887 //----------------------------------------------------------------------------------------------------------------------
888 // vogl_json_deserialize_array
889 //----------------------------------------------------------------------------------------------------------------------
890 template <typename T>
891 bool vogl_json_deserialize_array(const json_node &node, const vogl_blob_manager &blob_manager, const char *pKey, T &obj)
892 {
893     VOGL_FUNC_TRACER
894
895     const json_node *pNode = node.find_child_array(pKey);
896     if (!pNode)
897         return false;
898     return obj.deserialize(*pNode, blob_manager);
899 }
900
901 //----------------------------------------------------------------------------------------------------------------------
902 // vogl_json_serialize_vec4F
903 // TODO: Add roundtrip checking, and/or move this to common code somewhere
904 //----------------------------------------------------------------------------------------------------------------------
905 inline bool vogl_json_serialize_vec4F(json_node &dst_node, const vec4F &vec)
906 {
907     VOGL_FUNC_TRACER
908
909     dst_node.init_array();
910     for (uint j = 0; j < 4; j++)
911         dst_node.add_value(vec[j]);
912     return true;
913 }
914
915 //----------------------------------------------------------------------------------------------------------------------
916 // vogl_json_deserialize_vec4
917 // TODO: Add roundtrip checking, and/or move this to common code somewhere
918 //----------------------------------------------------------------------------------------------------------------------
919 inline bool vogl_json_deserialize_vec4F(const json_node &src_node, vec4F &vec)
920 {
921     VOGL_FUNC_TRACER
922
923     if ((!src_node.is_array()) || (src_node.size() != 4))
924         return false;
925
926     for (uint j = 0; j < 4; j++)
927     {
928         if (src_node[j].is_object_or_array())
929             return false;
930         vec[j] = src_node[j].as_float();
931     }
932
933     return true;
934 }
935
936 //----------------------------------------------------------------------------------------------------------------------
937 // vogl_format_debug_output_arb
938 //----------------------------------------------------------------------------------------------------------------------
939 void vogl_format_debug_output_arb(char out_str[], size_t out_str_size, GLenum source, GLenum type, GLuint id, GLenum severity, const char *msg);
940 void vogl_generic_arb_debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param);
941 void vogl_enable_generic_context_debug_messages();
942
943 //----------------------------------------------------------------------------------------------------------------------
944 // Context helpers
945 //----------------------------------------------------------------------------------------------------------------------
946 typedef GLXContext vogl_gl_context;
947 typedef Display *vogl_gl_display;
948 typedef GLXFBConfig vogl_gl_fb_config;
949 typedef GLXDrawable vogl_gl_drawable;
950
951 enum
952 {
953     eCHCDebugContextFlag = 1,
954     cCHCCoreProfileFlag = 2,
955     cCHCCompatProfileFlag = 4,
956 };
957
958 vogl_gl_context vogl_create_context(vogl_gl_display display, vogl_gl_fb_config fb_config, vogl_gl_context share_context, uint major_ver, uint minor_ver, uint flags, vogl_context_desc *pDesc = NULL);
959 vogl_gl_context vogl_get_current_context();
960 vogl_gl_display vogl_get_current_display();
961 vogl_gl_drawable vogl_get_current_drawable();
962
963 // vogl_get_current_fb_config() assumes a context is current.
964 vogl_gl_fb_config vogl_get_current_fb_config(uint screen = 0);
965
966 void vogl_make_current(vogl_gl_display display, vogl_gl_drawable drawable, vogl_gl_context context);
967
968 void vogl_destroy_context(vogl_gl_display display, vogl_gl_context context);
969
970 //----------------------------------------------------------------------------------------------------------------------
971 // vogl_get_max_supported_mip_levels
972 //----------------------------------------------------------------------------------------------------------------------
973 int vogl_get_max_supported_mip_levels();
974
975 #endif // VOGL_GL_UTILS_H
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006