├── .drone.yml ├── .gitmodules ├── .travis.yml ├── Docker ├── ubuntu1604.dockerfile └── ubuntu1804.dockerfile ├── LICENSE ├── README.md ├── configure_ubuntu_16.sh ├── doc ├── auto-contrast.svg ├── link-views.svg ├── location.svg └── sample_window.png ├── gdb-imagewatch.pro ├── resources ├── gdb-imagewatch.py ├── giwscripts │ ├── __init__.py │ ├── debuggers │ │ ├── __init__.py │ │ ├── gdbbridge.py │ │ └── interfaces.py │ ├── events.py │ ├── giwtypes │ │ ├── __init__.py │ │ ├── eigen3.py │ │ ├── interface.py │ │ └── opencv.py │ ├── giwwindow.py │ ├── ides │ │ ├── __init__.py │ │ └── qtcreator.py │ ├── symbols.py │ ├── sysinfo.py │ ├── test.py │ └── typebridge.py ├── icons │ ├── LICENSE.txt │ ├── config.json │ ├── fontello.ttf │ ├── label_alpha_channel.svg │ ├── label_blue_channel.svg │ ├── label_green_channel.svg │ ├── label_red_channel.svg │ ├── lower_upper_bound.svg │ ├── x.svg │ └── y.svg ├── matlab │ └── giw_load.m └── resources.qrc ├── src ├── .clang-format ├── debuggerinterface │ ├── buffer_request_message.cpp │ ├── buffer_request_message.h │ ├── managed_pointer.cpp │ ├── managed_pointer.h │ ├── preprocessor_directives.h │ ├── python_native_interface.cpp │ └── python_native_interface.h ├── giw_window.cpp ├── giw_window.h ├── io │ ├── buffer_exporter.cpp │ └── buffer_exporter.h ├── math │ ├── assorted.cpp │ ├── assorted.h │ ├── linear_algebra.cpp │ └── linear_algebra.h ├── thirdparty │ └── Khronos │ │ └── GL │ │ ├── gl.h │ │ ├── glcorearb.h │ │ └── glext.h ├── ui │ ├── decorated_line_edit.cpp │ ├── decorated_line_edit.h │ ├── gl_canvas.cpp │ ├── gl_canvas.h │ ├── gl_text_renderer.cpp │ ├── gl_text_renderer.h │ ├── go_to_widget.cpp │ ├── go_to_widget.h │ ├── main_window │ │ ├── auto_contrast.cpp │ │ ├── initialization.cpp │ │ ├── main_window.cpp │ │ ├── main_window.h │ │ └── ui_events.cpp │ ├── symbol_completer.cpp │ ├── symbol_completer.h │ ├── symbol_search_input.cpp │ └── symbol_search_input.h └── visualization │ ├── components │ ├── background.cpp │ ├── background.h │ ├── buffer.cpp │ ├── buffer.h │ ├── buffer_values.cpp │ ├── buffer_values.h │ ├── camera.cpp │ ├── camera.h │ ├── component.cpp │ └── component.h │ ├── events.cpp │ ├── events.h │ ├── game_object.cpp │ ├── game_object.h │ ├── shader.cpp │ ├── shader.h │ ├── shaders │ ├── background_fs.cpp │ ├── background_vs.cpp │ ├── buffer_fs.cpp │ ├── buffer_vs.cpp │ ├── giw_shaders.h │ ├── text_fs.cpp │ └── text_vs.cpp │ ├── stage.cpp │ └── stage.h ├── testbench ├── main.cpp └── testbench.pro └── ui └── main_window.ui /.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: ubuntu1604 3 | 4 | steps: 5 | - name: submodules 6 | image: docker:git 7 | commands: 8 | - git submodule update --init --recursive --remote 9 | 10 | - name: build 11 | image: brunorosa/gdb-imagewatch_env:ubuntu1604 12 | pull: always 13 | commands: 14 | - mkdir build 15 | - cd build 16 | - qmake .. 17 | - make -j4 18 | 19 | --- 20 | 21 | kind: pipeline 22 | name: ubuntu1804 23 | 24 | steps: 25 | - name: submodules 26 | image: docker:git 27 | commands: 28 | - git submodule update --init --recursive --remote 29 | 30 | - name: build 31 | image: brunorosa/gdb-imagewatch_env:ubuntu1804 32 | pull: always 33 | commands: 34 | - mkdir build 35 | - cd build 36 | - qmake .. 37 | - make -j4 38 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/thirdparty/Eigen"] 2 | path = src/thirdparty/Eigen 3 | url = https://github.com/csantosbh/eigen.git 4 | branch = v3.4 5 | [submodule "resources/giwscripts/thirdparty/pysigset"] 6 | path = resources/giwscripts/thirdparty/pysigset 7 | url = https://github.com/csantosbh/pysigset.git 8 | branch = v0.3 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | matrix: 4 | include: 5 | - os: osx 6 | 7 | - os: linux 8 | dist: xenial 9 | 10 | - os: linux 11 | dist: bionic 12 | 13 | addons: 14 | homebrew: 15 | packages: 16 | - qt5 17 | update: true 18 | apt: 19 | packages: 20 | - qt5-default 21 | - libqt5opengl5-dev 22 | - python3-dev 23 | - pkg-config 24 | update: true 25 | 26 | before_install: 27 | # Allow qmake to be called via CLI on MacOS 28 | - if [ $TRAVIS_OS_NAME = osx ]; then brew link qt5 --force; fi 29 | 30 | script: 31 | - mkdir build && cd build 32 | - qmake .. 33 | - make -j4 34 | -------------------------------------------------------------------------------- /Docker/ubuntu1604.dockerfile: -------------------------------------------------------------------------------- 1 | # prebuilt image of Ubuntu 16.04 with qt5 2 | FROM frostasm/qt:qt5.12-desktop 3 | USER root 4 | # adding python3-dev 5 | RUN apt update -y && apt -f install -y && apt upgrade -y && apt install -y python3-dev 6 | -------------------------------------------------------------------------------- /Docker/ubuntu1804.dockerfile: -------------------------------------------------------------------------------- 1 | # prebuilt image of Ubuntu 18.04 2 | FROM ubuntu:bionic 3 | 4 | # install dependencies 5 | RUN apt update -y && apt upgrade -y && apt install -y \ 6 | python3-dev \ 7 | qt5-default \ 8 | build-essential \ 9 | git \ 10 | pkg-config 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 GDB ImageWatch contributors (github.com/csantosbh/gdb-imagewatch/) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /configure_ubuntu_16.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo -e "\tThis version of GDB ImageWatch requires Qt 5.6 (or more recent)." 3 | echo -e "\tIf you don't have it, please download it from https://www.qt.io/download" 4 | echo "Starting GDB ImageWatch configuration for Ubuntu 16.04." 5 | git submodule init 6 | git submodule update 7 | set -e 8 | sudo apt-get -y install libpython3-dev python3-dev 9 | mkdir build 10 | cd build 11 | export QT_SELECT=5 12 | qmake .. 13 | make -j$(nproc) 14 | make install 15 | cd .. 16 | echo "source $(pwd)/build/gdb-imagewatch.py" > ~/.gdbinit 17 | echo "Completed configuration of GDB ImageWatch." 18 | -------------------------------------------------------------------------------- /doc/auto-contrast.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 57 | 60 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /doc/link-views.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 57 | 60 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /doc/location.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 57 | 60 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /doc/sample_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csantosbh/gdb-imagewatch/95853220a5ae55d85cb106eb55e5a5f7b5d5b5b2/doc/sample_window.png -------------------------------------------------------------------------------- /gdb-imagewatch.pro: -------------------------------------------------------------------------------- 1 | # BUILD_MODE variable can be either release or debug 2 | isEmpty(BUILD_MODE) { 3 | BUILD_MODE = release 4 | } 5 | 6 | message(GDB-ImageWatch build mode: $$BUILD_MODE) 7 | 8 | CONFIG += $$BUILD_MODE 9 | 10 | # Prevent strip from producing spurious error messages 11 | QMAKE_STRIP = echo "strip disabled: " 12 | 13 | QT += \ 14 | core \ 15 | gui \ 16 | opengl \ 17 | widgets \ 18 | gui 19 | 20 | QMAKE_CXXFLAGS += \ 21 | -fPIC \ 22 | -fvisibility=hidden \ 23 | -pthread 24 | 25 | QMAKE_LFLAGS += \ 26 | # If you have an error "cannot find -lGL", uncomment the following line and 27 | # replace the folder by the location of your libGL.so 28 | #-L/path/to/your/opengl/folder \ 29 | -Wl,--exclude-libs,ALL 30 | 31 | SOURCES += \ 32 | src/giw_window.cpp \ 33 | src/debuggerinterface/buffer_request_message.cpp \ 34 | src/debuggerinterface/managed_pointer.cpp \ 35 | src/debuggerinterface/python_native_interface.cpp \ 36 | src/io/buffer_exporter.cpp \ 37 | src/math/assorted.cpp \ 38 | src/math/linear_algebra.cpp \ 39 | src/ui/gl_canvas.cpp \ 40 | src/ui/symbol_completer.cpp \ 41 | src/ui/symbol_search_input.cpp \ 42 | src/ui/main_window/main_window.cpp \ 43 | src/ui/main_window/initialization.cpp \ 44 | src/ui/main_window/auto_contrast.cpp \ 45 | src/ui/main_window/ui_events.cpp \ 46 | src/visualization/events.cpp \ 47 | src/visualization/game_object.cpp \ 48 | src/visualization/shader.cpp \ 49 | src/visualization/stage.cpp \ 50 | src/visualization/components/background.cpp \ 51 | src/visualization/components/buffer.cpp \ 52 | src/visualization/components/buffer_values.cpp \ 53 | src/visualization/components/camera.cpp\ 54 | src/visualization/components/component.cpp\ 55 | src/visualization/shaders/background_fs.cpp \ 56 | src/visualization/shaders/background_vs.cpp \ 57 | src/visualization/shaders/buffer_fs.cpp \ 58 | src/visualization/shaders/buffer_vs.cpp \ 59 | src/visualization/shaders/text_fs.cpp \ 60 | src/visualization/shaders/text_vs.cpp \ 61 | src/ui/gl_text_renderer.cpp \ 62 | src/ui/go_to_widget.cpp \ 63 | src/ui/decorated_line_edit.cpp 64 | 65 | # Qt related headers 66 | HEADERS += \ 67 | src/debuggerinterface/preprocessor_directives.h \ 68 | src/ui/gl_canvas.h \ 69 | src/ui/main_window/main_window.h \ 70 | src/ui/symbol_completer.h \ 71 | src/ui/symbol_search_input.h \ 72 | src/ui/gl_text_renderer.h \ 73 | src/ui/go_to_widget.h \ 74 | src/ui/decorated_line_edit.h 75 | 76 | # Copy resource files to build folder 77 | copydata.commands = \ 78 | $(COPY_DIR) \"$$shell_path($$PWD\\resources\\giwscripts)\" \"$$shell_path($$OUT_PWD)\"; \ 79 | $(COPY_DIR) \"$$shell_path($$PWD\\resources\\matlab)\" \"$$shell_path($$OUT_PWD)\"; \ 80 | $(COPY_FILE) \"$$shell_path($$PWD\\resources\\gdb-imagewatch.py)\" \"$$shell_path($$OUT_PWD)\" 81 | 82 | first.depends = $(first) copydata 83 | export(first.depends) 84 | export(copydata.commands) 85 | QMAKE_EXTRA_TARGETS += first copydata 86 | 87 | # Instalation instructions 88 | isEmpty(PREFIX) { 89 | PREFIX = /usr/local 90 | } 91 | 92 | VERSION = 1.2 93 | TARGET = giwwindow 94 | TEMPLATE = lib 95 | target.path = $$PREFIX/bin/gdb-imagewatch/ 96 | 97 | install_debugger_scripts.path = $$PREFIX/bin/gdb-imagewatch/ 98 | install_debugger_scripts.files = \ 99 | resources/gdb-imagewatch.py \ 100 | resources/giwscripts 101 | 102 | install_fonts.path = $$PREFIX/bin/gdb-imagewatch/fonts/ 103 | install_fonts.files = resources/fonts/* 104 | 105 | install_matlab_scripts.path = $$PREFIX/bin/gdb-imagewatch/matlab 106 | install_matlab_scripts.files = resources/matlab/* 107 | 108 | INSTALLS += \ 109 | install_fonts \ 110 | install_matlab_scripts \ 111 | install_debugger_scripts \ 112 | target 113 | 114 | # Assorted configuration 115 | INCLUDEPATH += \ 116 | $$PWD/src \ 117 | $$PWD/src/thirdparty/Khronos/ 118 | 119 | CONFIG += \ 120 | link_pkgconfig \ 121 | warn_on \ 122 | c++11 \ 123 | no_keywords 124 | 125 | PKGCONFIG += python3 126 | 127 | FORMS += ui/main_window.ui 128 | 129 | RESOURCES += resources/resources.qrc 130 | 131 | -------------------------------------------------------------------------------- /resources/gdb-imagewatch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # -*- coding: utf-8 -*- 4 | 5 | """ 6 | GDB-ImageWatch entry point. Can be called with --test for opening the watcher 7 | window with a couple of sample buffers; otherwise, should be invoked by the 8 | debugger (GDB). 9 | """ 10 | 11 | import argparse 12 | import os 13 | import sys 14 | 15 | 16 | def get_debugger_bridge(): 17 | """ 18 | Instantiate the debugger bridge. If we ever decide to support other 19 | debuggers, this will be the place to instantiate its bridge object. 20 | """ 21 | from giwscripts.debuggers import gdbbridge 22 | from giwscripts import typebridge 23 | 24 | try: 25 | return gdbbridge.GdbBridge(typebridge.TypeBridge()) 26 | except Exception as err: 27 | print(err) 28 | 29 | print('[gdb-imagewatch] Error: Could not instantiate any debugger bridge') 30 | exit(1) 31 | 32 | 33 | def main(): 34 | """ 35 | Main entry point. 36 | """ 37 | # Add script path to Python PATH so submodules can be found 38 | script_path = os.path.dirname(os.path.realpath(__file__)) 39 | sys.path.append(script_path) 40 | 41 | # Load dependency modules 42 | from giwscripts import events 43 | from giwscripts import giwwindow 44 | from giwscripts import test 45 | from giwscripts.ides import qtcreator 46 | 47 | parser = argparse.ArgumentParser() 48 | parser.add_argument('--test', 49 | help='Open a test window with sample buffers', 50 | action='store_true') 51 | args = parser.parse_args() 52 | 53 | if args.test: 54 | # Test application 55 | test.giwtest(script_path) 56 | else: 57 | # Setup GDB interface 58 | debugger = get_debugger_bridge() 59 | window = giwwindow.GdbImageWatchWindow(script_path, debugger) 60 | event_handler = events.GdbImageWatchEvents(window, debugger) 61 | 62 | qtcreator.register_symbol_fetch_hook(event_handler.refresh_handler) 63 | debugger.register_event_handlers(event_handler) 64 | 65 | 66 | main() 67 | -------------------------------------------------------------------------------- /resources/giwscripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csantosbh/gdb-imagewatch/95853220a5ae55d85cb106eb55e5a5f7b5d5b5b2/resources/giwscripts/__init__.py -------------------------------------------------------------------------------- /resources/giwscripts/debuggers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csantosbh/gdb-imagewatch/95853220a5ae55d85cb106eb55e5a5f7b5d5b5b2/resources/giwscripts/debuggers/__init__.py -------------------------------------------------------------------------------- /resources/giwscripts/debuggers/gdbbridge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Code responsible with directly interacting with GDB 5 | """ 6 | 7 | import gdb 8 | 9 | from giwscripts import sysinfo 10 | from giwscripts.debuggers.interfaces import BridgeInterface 11 | 12 | 13 | class GdbBridge(BridgeInterface): 14 | """ 15 | GDB Bridge class, exposing the common expected interface for the ImageWatch 16 | to access the required buffer data and interact with the debugger. 17 | """ 18 | def __init__(self, type_bridge): 19 | self._type_bridge = type_bridge 20 | self._commands = dict(plot=PlotterCommand(self)) 21 | 22 | def queue_request(self, callable_request): 23 | return gdb.post_event(callable_request) 24 | 25 | def get_buffer_metadata(self, variable): 26 | picked_obj = gdb.parse_and_eval(variable) 27 | 28 | buffer_metadata = self._type_bridge.get_buffer_metadata( 29 | variable, picked_obj, self) 30 | 31 | bufsize = sysinfo.get_buffer_size( 32 | buffer_metadata['height'], 33 | buffer_metadata['channels'], 34 | buffer_metadata['type'], 35 | buffer_metadata['row_stride'] 36 | ) 37 | 38 | # Check if buffer is initialized 39 | if buffer_metadata['pointer'] == 0x0: 40 | raise Exception('Invalid null buffer pointer') 41 | if bufsize == 0: 42 | raise Exception('Invalid buffer of zero bytes') 43 | elif bufsize >= sysinfo.get_memory_usage()['free'] / 10: 44 | raise Exception('Invalid buffer size larger than available memory') 45 | 46 | # Check if buffer is valid. If it isn't, this function will throw an 47 | # exception 48 | gdb.execute('x '+str(int(buffer_metadata['pointer']))) 49 | 50 | inferior = gdb.selected_inferior() 51 | buffer_metadata['variable_name'] = variable 52 | buffer_metadata['pointer'] = inferior.read_memory( 53 | buffer_metadata['pointer'], bufsize) 54 | 55 | return buffer_metadata 56 | 57 | def register_event_handlers(self, event_handler): 58 | gdb.events.stop.connect(event_handler.stop_handler) 59 | gdb.events.exited.connect(event_handler.exit_handler) 60 | self._commands['plot'].set_command_listener(event_handler.plot_handler) 61 | 62 | def get_fields_from_type(self, this_type, observable_symbols): 63 | """ 64 | Given a class/struct type "this_type", fetch all members of that 65 | particular type and test them against the observable buffer check. 66 | """ 67 | for field_name, field_val in this_type.iteritems(): 68 | if field_val.is_base_class: 69 | type_fields = self.get_fields_from_type(field_val.type, 70 | observable_symbols) 71 | observable_symbols.update(type_fields) 72 | elif ((field_name not in observable_symbols) and 73 | (self._type_bridge.is_symbol_observable(field_val, field_name))): 74 | try: 75 | observable_symbols.add(field_name) 76 | except Exception: 77 | print('[gdb-imagewatch] Info: Member %s is not observable' 78 | % field_name) 79 | return observable_symbols 80 | 81 | def get_casted_pointer(self, typename, gdb_object): 82 | typename_obj = gdb.lookup_type(typename) 83 | typename_pointer_obj = typename_obj.pointer() 84 | return gdb_object.cast(typename_pointer_obj) 85 | 86 | def get_available_symbols(self): 87 | frame = gdb.selected_frame() 88 | block = frame.block() 89 | observable_symbols = set() 90 | 91 | while block is not None: 92 | for symbol in block: 93 | if symbol.is_argument or symbol.is_variable: 94 | name = symbol.name 95 | 96 | # Get struct/class fields 97 | if name == 'this': 98 | # The GDB API is a bit convoluted, so I have to do some 99 | # contortion in order to get the class type from the 100 | # this object so I can iterate over its fields 101 | this_type = gdb.parse_and_eval(symbol.name) \ 102 | .dereference().type 103 | type_fields = self.get_fields_from_type( 104 | this_type, 105 | observable_symbols) 106 | observable_symbols.update(type_fields) 107 | elif ((name not in observable_symbols) and 108 | (self._type_bridge.is_symbol_observable(symbol, name))): 109 | try: 110 | observable_symbols.add(name) 111 | except Exception: 112 | print('[gdb-imagewatch] Info: Field %s is not' 113 | 'observable' % name) 114 | 115 | block = block.superblock 116 | 117 | return observable_symbols 118 | 119 | 120 | class PlotterCommand(gdb.Command): 121 | """ 122 | Implements the 'plot' command for the GDB command line mode 123 | """ 124 | def __init__(self, gdb_bridge): 125 | super(PlotterCommand, self).__init__("plot", 126 | gdb.COMMAND_DATA, 127 | gdb.COMPLETE_SYMBOL) 128 | self._gdb_bridge = gdb_bridge 129 | self._command_listener = None 130 | 131 | def set_command_listener(self, callback): 132 | """ 133 | Called by the GDB bridge in order to configure which callback must be 134 | called when the user calls the function 'plot' in the debugger console. 135 | """ 136 | self._command_listener = callback 137 | 138 | def invoke(self, arg, from_tty): 139 | """ 140 | Called by GDB whenever the plot command is invoked. 141 | """ 142 | args = gdb.string_to_argv(arg) 143 | var_name = str(args[0]) 144 | 145 | if self._command_listener is not None: 146 | self._command_listener(var_name) 147 | -------------------------------------------------------------------------------- /resources/giwscripts/debuggers/interfaces.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Interfaces to be implemented by code that shall interact with the debugger 5 | """ 6 | 7 | 8 | class BridgeInterface(): 9 | """ 10 | This interface defines the methods to be implemented by a debugger bridge 11 | """ 12 | def queue_request(self, callable_request): 13 | """ 14 | Given a callable object 'callable_request', request the debugger 15 | backend to execute this object in its main execution thread. 16 | If the debugger backend is thread safe (which is not the case for GDB), 17 | this may simply execute the 'callable_request' object. 18 | """ 19 | raise NotImplementedError("Method is not implemented") 20 | 21 | def get_buffer_metadata(self, variable): 22 | """ 23 | Given a string defining a variable name, must return the following 24 | information about it: 25 | 26 | [mem, width, height, channels, type, step, pixel_layout] 27 | """ 28 | raise NotImplementedError("Method is not implemented") 29 | 30 | def register_event_handlers(self, events): 31 | """ 32 | Register (callable) listeners to events defined in the dict 'events': 33 | 'stop': When a breakpoint is hit 34 | """ 35 | raise NotImplementedError("Method is not implemented") 36 | 37 | def get_casted_pointer(self, typename, debugger_object): 38 | """ 39 | Given the string 'typename' specifying any arbitrary type name of the 40 | program being debugger, and an object referring to a pointer object, 41 | this function shall return the corresponding object from the underlying 42 | debugger API corresponding to the cast of the input pointer to a 43 | pointer of the specified type. 44 | """ 45 | raise NotImplementedError("Method is not implemented") 46 | 47 | def get_available_symbols(self): 48 | """ 49 | Get all visible symbols in the current context of debugging. 50 | """ 51 | raise NotImplementedError("Method is not implemented") 52 | 53 | 54 | class BridgeEventHandlerInterface(): 55 | """ 56 | This interface defines the events that can be raised by the debugger bridge 57 | """ 58 | def stop_handler(self, event): 59 | """ 60 | Handler to be called whenever the debugger stops (e.g. when a 61 | breakpoint is hit). 62 | """ 63 | raise NotImplementedError("Method is not implemented") 64 | 65 | def exit_handler(self, event): 66 | """ 67 | Event raised whenever the inferior has exited. 68 | """ 69 | raise NotImplementedError("Method is not implemented") 70 | 71 | def refresh_handler(self, event): 72 | """ 73 | Handler to be called by the IDE whenever the user performs some action 74 | during a debug session that may require the list of available variables 75 | to change (such as changing position in the stack). 76 | """ 77 | raise NotImplementedError("Method is not implemented") 78 | 79 | def plot_handler(self, variable_name): 80 | """ 81 | Handler to be called whenever the user actively calls the 'plot' 82 | command from the debugger console. 83 | """ 84 | raise NotImplementedError("Method is not implemented") 85 | -------------------------------------------------------------------------------- /resources/giwscripts/events.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Implementation of handlers for events raised by the debugger 5 | """ 6 | 7 | import time 8 | 9 | from giwscripts.debuggers.interfaces import BridgeEventHandlerInterface 10 | 11 | 12 | class GdbImageWatchEvents(BridgeEventHandlerInterface): 13 | """ 14 | Handles events raised by the debugger bridge 15 | """ 16 | def __init__(self, window, debugger): 17 | self._window = window 18 | self._debugger = debugger 19 | 20 | def _set_symbol_complete_list(self): 21 | """ 22 | Retrieve the list of available symbols and provide it to the GIW window 23 | for autocompleting. 24 | """ 25 | observable_symbols = list(self._debugger.get_available_symbols()) 26 | if self._window.is_ready(): 27 | self._window.set_available_symbols(observable_symbols) 28 | 29 | def refresh_handler(self, event): 30 | self._set_symbol_complete_list() 31 | 32 | def exit_handler(self, event): 33 | self._window.terminate() 34 | 35 | def stop_handler(self, event): 36 | """ 37 | The debugger has stopped (e.g. a breakpoint was hit). We must list all 38 | available buffers and pass it to the imagewatch window. 39 | """ 40 | # Block until the window is up and running 41 | if not self._window.is_ready(): 42 | self._window.initialize_window() 43 | while not self._window.is_ready(): 44 | time.sleep(0.1) 45 | 46 | # Update buffers being visualized 47 | observed_buffers = self._window.get_observed_buffers() 48 | for buffer_name in observed_buffers: 49 | self._window.plot_variable(buffer_name) 50 | 51 | # Set list of available symbols 52 | self._set_symbol_complete_list() 53 | 54 | def plot_handler(self, variable_name): 55 | """ 56 | Command window to plot variable_name if user requests from debugger log 57 | """ 58 | self._window.plot_variable(variable_name) 59 | -------------------------------------------------------------------------------- /resources/giwscripts/giwtypes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csantosbh/gdb-imagewatch/95853220a5ae55d85cb106eb55e5a5f7b5d5b5b2/resources/giwscripts/giwtypes/__init__.py -------------------------------------------------------------------------------- /resources/giwscripts/giwtypes/eigen3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | This module is concerned with the analysis of each variable found by the 5 | debugger, as well as identifying and describing the buffers that should be 6 | plotted in the ImageWatch window. 7 | """ 8 | 9 | import re 10 | 11 | from giwscripts import symbols 12 | from giwscripts.giwtypes import interface 13 | 14 | 15 | class EigenXX(interface.TypeInspectorInterface): 16 | """ 17 | Implementation for inspecting Eigen::Matrix and Eigen::Map 18 | """ 19 | def get_buffer_metadata(self, obj_name, picked_obj, debugger_bridge): 20 | """ 21 | Gets the buffer meta data from types of the Eigen Library 22 | Note that it only implements single channel matrix display, 23 | which should be quite common in Eigen. 24 | """ 25 | 26 | type_str = str(picked_obj.type) 27 | is_eigen_map = 'Map' in type_str 28 | # First we need the python object for the actual matrix type. When 29 | # parsing a Map, the type is the first template parameter of the 30 | # wrapper type. Otherwise, it is the type field of the picked_obj 31 | if is_eigen_map: 32 | matrix_type_obj = picked_obj.type.template_argument(0) 33 | else: 34 | matrix_type_obj = picked_obj.type 35 | 36 | current_type = str(matrix_type_obj.template_argument(0)) 37 | height = int(matrix_type_obj.template_argument(1)) 38 | width = int(matrix_type_obj.template_argument(2)) 39 | matrix_flag = int(matrix_type_obj.template_argument(3)) 40 | transpose_buffer = ((matrix_flag&0x1) == 0) 41 | dynamic_buffer = False 42 | 43 | if height <= 0: 44 | # Buffer has dynamic width 45 | if is_eigen_map: 46 | height = int(picked_obj['m_rows']['m_value']) 47 | else: 48 | height = int(picked_obj['m_storage']['m_rows']) 49 | dynamic_buffer = True 50 | 51 | if width <= 0: 52 | # Buffer has dynamic height 53 | if is_eigen_map: 54 | width = int(picked_obj['m_cols']['m_value']) 55 | else: 56 | width = int(picked_obj['m_storage']['m_cols']) 57 | dynamic_buffer = True 58 | 59 | if transpose_buffer: 60 | width, height = height, width 61 | 62 | # Assign the GIW type according to underlying type 63 | if current_type == 'short': 64 | type_value = symbols.GIW_TYPES_INT16 65 | elif current_type == 'float': 66 | type_value = symbols.GIW_TYPES_FLOAT32 67 | elif current_type == 'double': 68 | type_value = symbols.GIW_TYPES_FLOAT64 69 | elif current_type == 'int': 70 | type_value = symbols.GIW_TYPES_INT32 71 | 72 | # Differentiate between Map and dynamic/static Matrices 73 | if is_eigen_map: 74 | buffer = debugger_bridge.get_casted_pointer(current_type, 75 | picked_obj['m_data']) 76 | elif dynamic_buffer: 77 | buffer = debugger_bridge.get_casted_pointer( 78 | current_type, picked_obj['m_storage']) 79 | else: 80 | buffer = debugger_bridge.get_casted_pointer( 81 | current_type, picked_obj['m_storage']['m_data']['array']) 82 | 83 | if buffer == 0x0: 84 | raise Exception('Received null buffer!') 85 | 86 | # Set row stride and pixel layout 87 | pixel_layout = 'bgra' 88 | row_stride = width 89 | 90 | return { 91 | 'display_name': obj_name + ' (' + str(matrix_type_obj) + ')', 92 | 'pointer': buffer, 93 | 'width': width, 94 | 'height': height, 95 | 'channels': 1, 96 | 'type': type_value, 97 | 'row_stride': row_stride, 98 | 'pixel_layout': pixel_layout, 99 | 'transpose_buffer': transpose_buffer 100 | } 101 | 102 | def is_symbol_observable(self, symbol, symbol_name): 103 | """ 104 | Returns true if the given symbol is of observable type (the type of the 105 | buffer you are working with). Make sure to check for pointers of your 106 | type as well 107 | """ 108 | # Check if symbol type is the expected buffer 109 | symbol_type = str(symbol.type) 110 | type_regex = r'(const\s+)?Eigen::(\s+?[*&])?' 111 | return re.match(type_regex, symbol_type) is not None 112 | -------------------------------------------------------------------------------- /resources/giwscripts/giwtypes/interface.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | This module is concerned with the analysis of each variable found by the 5 | debugger, as well as identifying and describing the buffers that should be 6 | plotted in the ImageWatch window. 7 | """ 8 | 9 | import abc 10 | 11 | def debug_buffer_metadata(func): 12 | def wrapper(self, obj_name, picked_obj, debugger_bridge): 13 | try: 14 | metadata = func(self, obj_name, picked_obj, debugger_bridge) 15 | 16 | print('[%s] [%s] was parsed by giwtype [%s]' % 17 | (str(picked_obj.type), obj_name, type(self).__name__)) 18 | except Exception as error: 19 | print('[%s] [%s] raised exception when parsed by giwtype [%s]:' % 20 | (str(picked_obj.type), obj_name, type(self).__name__)) 21 | print(' %s' % str(error)) 22 | 23 | raise error 24 | 25 | return wrapper 26 | 27 | def debug_symbol_observable(func): 28 | def wrapper(self, symbol_obj, symbol_name): 29 | is_observable = func(self, symbol_obj, symbol_name) 30 | 31 | if is_observable: 32 | is_observable_str = 'is observable' 33 | else: 34 | is_observable_str = 'is NOT observable' 35 | 36 | print('[' + str(symbol_obj.type) + '] [' + symbol_name + '] ' + 37 | is_observable_str + ' by [' + type(self).__name__ + ']') 38 | 39 | return is_observable 40 | 41 | return wrapper 42 | 43 | class TypeInspectorInterface(): 44 | """ 45 | This interface defines methods to be implemented by type inspectors that 46 | extract information required for plotting buffers. 47 | """ 48 | @abc.abstractmethod 49 | def get_buffer_metadata(self, obj_name, picked_obj, debugger_bridge): 50 | """ 51 | Given the variable name obj_name (str), the debugger object with its 52 | internl fields and type picked_obj and the debugger bridge object 53 | debugger_bridge (which implement the methods in 54 | giwscripts.debuggers.interface.BridgeInterface), this method must 55 | return a dict containing the following fields: 56 | 57 | * display_name 58 | * pointer 59 | * width 60 | * height 61 | * channels 62 | * type 63 | * row_stride 64 | * pixel_layout 65 | * transpose_buffer 66 | 67 | For information about these fields, consult the documentation for 68 | giw_plot_buffer in the file $ROOT/src/giw_window.h. The module 69 | giwtypes.opencv shows an example implementation for the OpenCV Mat 70 | type. 71 | """ 72 | pass 73 | 74 | @abc.abstractmethod 75 | def is_symbol_observable(self, symbol_obj, symbol_name): 76 | """ 77 | Given the debugger with its internal fields and type symbol_obj, and 78 | its name symbol_name, this method must return True if symbol_obj 79 | corresponds to an observable variable (i.e. if its type corresponds to 80 | the type of the buffers that you want to plot). 81 | """ 82 | pass 83 | -------------------------------------------------------------------------------- /resources/giwscripts/giwtypes/opencv.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | This module is concerned with the analysis of each variable found by the 5 | debugger, as well as identifying and describing the buffers that should be 6 | plotted in the ImageWatch window. 7 | """ 8 | 9 | import re 10 | 11 | from giwscripts import symbols 12 | from giwscripts.giwtypes import interface 13 | 14 | 15 | # OpenCV constants 16 | CV_CN_MAX = 512 17 | CV_CN_SHIFT = 3 18 | CV_MAT_CN_MASK = ((CV_CN_MAX - 1) << CV_CN_SHIFT) 19 | CV_DEPTH_MAX = (1 << CV_CN_SHIFT) 20 | CV_MAT_TYPE_MASK = (CV_DEPTH_MAX * CV_CN_MAX - 1) 21 | 22 | 23 | class Mat(interface.TypeInspectorInterface): 24 | """ 25 | Implementation for inspecting OpenCV Mat classes 26 | """ 27 | def get_buffer_metadata(self, obj_name, picked_obj, debugger_bridge): 28 | buffer = debugger_bridge.get_casted_pointer('char', picked_obj['data']) 29 | if buffer == 0x0: 30 | raise Exception('Received null buffer!') 31 | 32 | width = int(picked_obj['cols']) 33 | height = int(picked_obj['rows']) 34 | flags = int(picked_obj['flags']) 35 | 36 | channels = ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1) 37 | row_stride = int(int(picked_obj['step']['buf'][0])/channels) 38 | 39 | if channels >= 3: 40 | pixel_layout = 'bgra' 41 | else: 42 | pixel_layout = 'rgba' 43 | 44 | cvtype = ((flags) & CV_MAT_TYPE_MASK) 45 | 46 | type_value = (cvtype & 7) 47 | 48 | if (type_value == symbols.GIW_TYPES_UINT16 or 49 | type_value == symbols.GIW_TYPES_INT16): 50 | row_stride = int(row_stride / 2) 51 | elif (type_value == symbols.GIW_TYPES_INT32 or 52 | type_value == symbols.GIW_TYPES_FLOAT32): 53 | row_stride = int(row_stride / 4) 54 | elif type_value == symbols.GIW_TYPES_FLOAT64: 55 | row_stride = int(row_stride / 8) 56 | 57 | return { 58 | 'display_name': obj_name + ' (' + str(picked_obj.type) + ')', 59 | 'pointer': buffer, 60 | 'width': width, 61 | 'height': height, 62 | 'channels': channels, 63 | 'type': type_value, 64 | 'row_stride': row_stride, 65 | 'pixel_layout': pixel_layout, 66 | 'transpose_buffer' : False 67 | } 68 | 69 | def is_symbol_observable(self, symbol, symbol_name): 70 | """ 71 | Returns true if the given symbol is of observable type (the type of the 72 | buffer you are working with). Make sure to check for pointers of your 73 | type as well 74 | """ 75 | # Check if symbol type is the expected buffer 76 | symbol_type = str(symbol.type) 77 | type_regex = r'(const\s+)?cv::Mat(\s+?[*&])?' 78 | return re.match(type_regex, symbol_type) is not None 79 | 80 | class CvMat(interface.TypeInspectorInterface): 81 | """ 82 | Implementation for inspecting OpenCV CvMat structs 83 | """ 84 | def get_buffer_metadata(self, obj_name, picked_obj, debugger_bridge): 85 | buffer = debugger_bridge.get_casted_pointer('char', picked_obj['data']) 86 | if buffer == 0x0: 87 | raise Exception('Received null buffer!') 88 | 89 | width = int(picked_obj['cols']) 90 | height = int(picked_obj['rows']) 91 | flags = int(picked_obj['type']) 92 | 93 | channels = ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1) 94 | row_stride = int(int(picked_obj['step'])/channels) 95 | 96 | if channels >= 3: 97 | pixel_layout = 'bgra' 98 | else: 99 | pixel_layout = 'rgba' 100 | 101 | cvtype = ((flags) & CV_MAT_TYPE_MASK) 102 | 103 | type_value = (cvtype & 7) 104 | 105 | if (type_value == symbols.GIW_TYPES_UINT16 or 106 | type_value == symbols.GIW_TYPES_INT16): 107 | row_stride = int(row_stride / 2) 108 | elif (type_value == symbols.GIW_TYPES_INT32 or 109 | type_value == symbols.GIW_TYPES_FLOAT32): 110 | row_stride = int(row_stride / 4) 111 | elif type_value == symbols.GIW_TYPES_FLOAT64: 112 | row_stride = int(row_stride / 8) 113 | 114 | return { 115 | 'display_name': obj_name + ' (' + str(picked_obj.type) + ')', 116 | 'pointer': buffer, 117 | 'width': width, 118 | 'height': height, 119 | 'channels': channels, 120 | 'type': type_value, 121 | 'row_stride': row_stride, 122 | 'pixel_layout': pixel_layout, 123 | 'transpose_buffer': False 124 | } 125 | 126 | def is_symbol_observable(self, symbol, symbol_name): 127 | symbol_type = str(symbol.type) 128 | type_regex = r'(const\s+)?CvMat(\s+?[*&])?' 129 | return re.match(type_regex, symbol_type) is not None 130 | -------------------------------------------------------------------------------- /resources/giwscripts/giwwindow.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Classes related to exposing an interface to the ImageWatch window 5 | """ 6 | 7 | import ctypes 8 | import ctypes.util 9 | import signal 10 | import threading 11 | 12 | from giwscripts.thirdparty.pysigset import pysigset 13 | 14 | 15 | FETCH_BUFFER_CBK_TYPE = ctypes.CFUNCTYPE(ctypes.c_int, 16 | ctypes.c_char_p) 17 | 18 | 19 | class GdbImageWatchWindow(): 20 | """ 21 | Python interface for the imagewatch window, which is implemented as a 22 | shared library. 23 | """ 24 | def __init__(self, script_path, bridge): 25 | self._bridge = bridge 26 | 27 | # Request ctypes to load libGL before the native giwwindow does; this 28 | # fixes an issue on Ubuntu machines with nvidia drivers. For more 29 | # information, please refer to 30 | # https://github.com/csantosbh/gdb-imagewatch/issues/28 31 | ctypes.CDLL(ctypes.util.find_library('GL'), ctypes.RTLD_GLOBAL) 32 | 33 | # Load imagewatch library and set up its API 34 | self._lib = ctypes.cdll.LoadLibrary( 35 | script_path + '/libgiwwindow.so') 36 | 37 | # libgiw API 38 | self._lib.giw_initialize.argtypes = [] 39 | self._lib.giw_initialize.restype = ctypes.c_void_p 40 | 41 | self._lib.giw_cleanup.argtypes = [ctypes.c_void_p] 42 | self._lib.giw_cleanup.restype = None 43 | 44 | self._lib.giw_terminate.argtypes = [] 45 | self._lib.giw_terminate.restype = None 46 | 47 | self._lib.giw_exec.argtypes = [ctypes.c_void_p] 48 | self._lib.giw_exec.restype = None 49 | 50 | self._lib.giw_create_window.argtypes = [FETCH_BUFFER_CBK_TYPE] 51 | self._lib.giw_create_window.restype = ctypes.c_void_p 52 | 53 | self._lib.giw_destroy_window.argtypes = [ctypes.c_void_p] 54 | self._lib.giw_destroy_window.restype = ctypes.c_int 55 | 56 | self._lib.giw_is_window_ready.argtypes = [ctypes.c_void_p] 57 | self._lib.giw_is_window_ready.restype = ctypes.c_bool 58 | 59 | self._lib.giw_get_observed_buffers.argtypes = [ctypes.c_void_p] 60 | self._lib.giw_get_observed_buffers.restype = ctypes.py_object 61 | 62 | self._lib.giw_set_available_symbols.argtypes = [ 63 | ctypes.c_void_p, 64 | ctypes.py_object 65 | ] 66 | self._lib.giw_set_available_symbols.restype = None 67 | 68 | self._lib.giw_plot_buffer.argtypes = [ 69 | ctypes.c_void_p, 70 | ctypes.py_object 71 | ] 72 | self._lib.giw_plot_buffer.restype = None 73 | 74 | # UI handler 75 | self._window_handler = None 76 | 77 | def plot_variable(self, requested_symbol): 78 | """ 79 | Plot a variable whose name is 'requested_symbol'. 80 | 81 | This will result in the creation of a callable object of type 82 | DeferredVariablePlotter, where the actual code for plotting the buffer 83 | will be executed. This object will be given to the debugger bridge so 84 | that it can schedule its execution in a thread safe context. 85 | """ 86 | if self._bridge is None: 87 | print('[gdb-imagewatch] Could not plot symbol %s: Not a debugging' 88 | ' session.' % requested_symbol) 89 | return 0 90 | 91 | try: 92 | if not isinstance(requested_symbol, str): 93 | variable = requested_symbol.decode('utf-8') 94 | else: 95 | variable = requested_symbol 96 | 97 | plot_callable = DeferredVariablePlotter(variable, 98 | self._lib, 99 | self._bridge, 100 | self._window_handler) 101 | self._bridge.queue_request(plot_callable) 102 | return 1 103 | except Exception as err: 104 | print('[gdb-imagewatch] Error: Could not plot variable') 105 | print(err) 106 | 107 | return 0 108 | 109 | def is_ready(self): 110 | """ 111 | Returns True if the ImageWatch window has been loaded; False otherwise. 112 | """ 113 | if self._window_handler is None: 114 | return False 115 | 116 | return self._lib.giw_is_window_ready(self._window_handler) 117 | 118 | def terminate(self): 119 | """ 120 | Request GIW to terminate application and close all windows 121 | """ 122 | self._lib.giw_terminate() 123 | 124 | def set_available_symbols(self, observable_symbols): 125 | """ 126 | Set the autocomplete list of symbols with the list of string 127 | 'observable_symbols' 128 | """ 129 | self._lib.giw_set_available_symbols( 130 | self._window_handler, 131 | observable_symbols) 132 | 133 | def get_observed_buffers(self): 134 | """ 135 | Get a list with the currently observed symbols in the giw window 136 | """ 137 | return self._lib.giw_get_observed_buffers(self._window_handler) 138 | 139 | def _ui_thread(self, plot_callback): 140 | # Initialize GIW lib 141 | app_handler = self._lib.giw_initialize() 142 | self._window_handler = self._lib.giw_create_window(plot_callback) 143 | # Run UI loop 144 | self._lib.giw_exec(app_handler) 145 | # Cleanup GIW lib 146 | self._lib.giw_destroy_window(self._window_handler) 147 | self._lib.giw_cleanup(app_handler) 148 | 149 | def initialize_window(self): 150 | """ 151 | Launch the ImageWatch window. 152 | """ 153 | ## 154 | # Initialize imagewatch window 155 | with pysigset.suspended_signals(signal.SIGCHLD): 156 | # By default, my new threads will be the ones receiving the 157 | # precious signals from the operating system. These signals should 158 | # go to GDB so it could do its thing, and since it doesnt get them, 159 | # my thread will make gdb hang. The solution is to configure the 160 | # new thread to forward the signal back to the main thread, which 161 | # is done by pysigset. 162 | wnd_thread_instance = threading.Thread( 163 | target=self._ui_thread, 164 | args=(FETCH_BUFFER_CBK_TYPE(self.plot_variable),) 165 | ) 166 | wnd_thread_instance.daemon = True 167 | wnd_thread_instance.start() 168 | 169 | 170 | class DeferredVariablePlotter(): 171 | """ 172 | Instances of this class are callable objects whose __call__ method triggers 173 | a buffer plot command. Useful for deferring the plot command to a safe 174 | thread. 175 | """ 176 | def __init__(self, variable, lib, bridge, window_handler): 177 | self._variable = variable 178 | self._lib = lib 179 | self._bridge = bridge 180 | self._window_handler = window_handler 181 | 182 | def __call__(self): 183 | try: 184 | buffer_metadata = self._bridge.get_buffer_metadata(self._variable) 185 | 186 | if buffer_metadata is not None: 187 | self._lib.giw_plot_buffer( 188 | self._window_handler, 189 | buffer_metadata) 190 | except Exception as err: 191 | import traceback 192 | print('[gdb-imagewatch] Error: Could not plot variable') 193 | print(err) 194 | traceback.print_exc() 195 | -------------------------------------------------------------------------------- /resources/giwscripts/ides/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csantosbh/gdb-imagewatch/95853220a5ae55d85cb106eb55e5a5f7b5d5b5b2/resources/giwscripts/ides/__init__.py -------------------------------------------------------------------------------- /resources/giwscripts/ides/qtcreator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | QtCreator integration module. 5 | """ 6 | 7 | 8 | def register_symbol_fetch_hook(retrieve_symbols_callback): 9 | """ 10 | Hacks into Dumper and changes its fetchVariables method to a wrapper that 11 | calls stop_event_handler. This allows us to retrieve the list of locals 12 | every time the user changes the local stack frame during a debug session 13 | from QtCreator interface. 14 | """ 15 | try: 16 | imp = __import__('gdbbridge') 17 | 18 | original_fetch_variables = None 19 | 20 | def fetch_variables_wrapper(self, args): 21 | """ 22 | Acts as a proxy to QTCreator 'fetchVariables' method, calling the 23 | event handler 'stop' method everytime 'fetchVariables' is called. 24 | """ 25 | ret = original_fetch_variables(self, args) 26 | 27 | retrieve_symbols_callback(None) 28 | 29 | return ret 30 | 31 | original_fetch_variables = imp.Dumper.fetchVariables 32 | imp.Dumper.fetchVariables = fetch_variables_wrapper 33 | return True 34 | 35 | except Exception as err: 36 | print('[gdb-imagewatch] Error: Exception thrown in qtcreator' 37 | ' integration module') 38 | print(err) 39 | return False 40 | -------------------------------------------------------------------------------- /resources/giwscripts/symbols.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Definition of global constants and symbols. 5 | """ 6 | 7 | # Enum values for supported buffer types 8 | GIW_TYPES_UINT8 = 0 9 | GIW_TYPES_UINT16 = 2 10 | GIW_TYPES_INT16 = 3 11 | GIW_TYPES_INT32 = 4 12 | GIW_TYPES_FLOAT32 = 5 13 | GIW_TYPES_FLOAT64 = 6 14 | -------------------------------------------------------------------------------- /resources/giwscripts/sysinfo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | System and memory related methods 5 | """ 6 | 7 | from giwscripts import symbols 8 | 9 | 10 | def get_memory_usage(): 11 | """ 12 | Get node total memory and memory usage, in bytes 13 | """ 14 | with open('/proc/meminfo', 'r') as mem: 15 | ret = {} 16 | tmp = 0 17 | for i in mem: 18 | sline = i.split() 19 | if str(sline[0]) == 'MemTotal:': 20 | ret['total'] = int(sline[1]) * 1024 21 | elif str(sline[0]) in ('MemFree:', 'Buffers:', 'Cached:'): 22 | tmp += int(sline[1]) * 1024 23 | ret['free'] = tmp 24 | ret['used'] = int(ret['total']) - int(ret['free']) 25 | return ret 26 | 27 | 28 | def get_buffer_size(height, channels, typevalue, rowstride): 29 | """ 30 | Compute the buffer size in bytes 31 | """ 32 | channel_size = 1 33 | if (typevalue == symbols.GIW_TYPES_UINT16 or 34 | typevalue == symbols.GIW_TYPES_INT16): 35 | channel_size = 2 # 2 bytes per element 36 | elif (typevalue == symbols.GIW_TYPES_INT32 or 37 | typevalue == symbols.GIW_TYPES_FLOAT32): 38 | channel_size = 4 # 4 bytes per element 39 | elif typevalue == symbols.GIW_TYPES_FLOAT64: 40 | channel_size = 8 # 8 bytes per element 41 | 42 | return channel_size * channels * rowstride * height 43 | -------------------------------------------------------------------------------- /resources/giwscripts/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Module developed for quick testing the ImageWatch shared library 5 | """ 6 | 7 | import math 8 | import time 9 | import threading 10 | import queue 11 | import array 12 | 13 | from giwscripts import giwwindow 14 | from giwscripts import symbols 15 | from giwscripts.debuggers.interfaces import BridgeInterface 16 | 17 | 18 | def giwtest(script_path): 19 | """ 20 | Entry point for the testing mode. 21 | """ 22 | 23 | dummy_debugger = DummyDebugger() 24 | 25 | window = giwwindow.GdbImageWatchWindow(script_path, dummy_debugger) 26 | window.initialize_window() 27 | 28 | try: 29 | # Wait for window to initialize 30 | while not window.is_ready(): 31 | time.sleep(0.1) 32 | 33 | window.set_available_symbols(dummy_debugger.get_available_symbols()) 34 | 35 | for buffer in dummy_debugger.get_available_symbols(): 36 | window.plot_variable(buffer) 37 | 38 | while window.is_ready(): 39 | time.sleep(0.5) 40 | 41 | except KeyboardInterrupt: 42 | window.terminate() 43 | exit(0) 44 | 45 | dummy_debugger.kill() 46 | 47 | 48 | def _gen_color(pos, k, f_a, f_b): 49 | """ 50 | Generates a color for the pixel at (pos[0], pos[1]) with coefficients k[0] 51 | and k[1], and colouring functions f_a and f_b that map R->[-1, 1]. 52 | """ 53 | return (f_a(pos[0] * f_b(pos[1]/k[0])/k[1]) + 1) * 255 / 2 54 | 55 | 56 | def _gen_buffers(width, height): 57 | """ 58 | Generate sample buffers 59 | """ 60 | channels = [3, 1] 61 | 62 | types = [{'array': 'B', 'giw': symbols.GIW_TYPES_UINT8}, 63 | {'array': 'f', 'giw': symbols.GIW_TYPES_FLOAT32}] 64 | 65 | tex1 = [0] * width * height * channels[0] 66 | tex2 = [0] * width * height * channels[1] 67 | 68 | c_x = width * 2.0 / 3.0 69 | c_y = height * 0.5 70 | scale = 3.0 / width 71 | 72 | for pos_y in range(0, height): 73 | for pos_x in range(0, width): 74 | # Buffer 1: Coloured set 75 | pixel_pos = [pos_x, pos_y] 76 | 77 | buffer_pos = pos_y * channels[0] * width + channels[0] * pos_x 78 | 79 | tex1[buffer_pos + 0] = _gen_color( 80 | pixel_pos, [20, 80], math.cos, math.cos) 81 | tex1[buffer_pos + 1] = _gen_color( 82 | pixel_pos, [50, 200], math.sin, math.cos) 83 | tex1[buffer_pos + 2] = _gen_color( 84 | pixel_pos, [30, 120], math.cos, math.cos) 85 | 86 | # Buffer 2: Mandelbrot set 87 | pixel_pos = complex((pos_x-c_x), (pos_y-c_y)) * scale 88 | buffer_pos = pos_y * channels[1] * width + channels[1] * pos_x 89 | 90 | mandel_z = complex(0, 0) 91 | for _ in range(0, 20): 92 | mandel_z = mandel_z * mandel_z + pixel_pos 93 | 94 | z_norm_squared = mandel_z.real * mandel_z.real +\ 95 | mandel_z.imag * mandel_z.imag 96 | z_threshold = 5.0 97 | 98 | for channel in range(0, channels[1]): 99 | tex2[buffer_pos + channel] = z_threshold - min(z_threshold, 100 | z_norm_squared) 101 | 102 | tex_arr1 = array.array(types[0]['array'], [int(val) for val in tex1]) 103 | tex_arr2 = array.array(types[1]['array'], tex2) 104 | mem1 = memoryview(tex_arr1) 105 | mem2 = memoryview(tex_arr2) 106 | rowstride = width 107 | 108 | return { 109 | 'sample_buffer_1': { 110 | 'variable_name': 'sample_buffer_1', 111 | 'display_name': 'uint8* sample_buffer_1', 112 | 'pointer': mem1, 113 | 'width': width, 114 | 'height': height, 115 | 'channels': channels[0], 116 | 'type': types[0]['giw'], 117 | 'row_stride': rowstride, 118 | 'pixel_layout': 'rgba', 119 | 'transpose_buffer': False 120 | }, 121 | 'sample_buffer_2': { 122 | 'variable_name': 'sample_buffer_2', 123 | 'display_name': 'float* sample_buffer_2', 124 | 'pointer': mem2, 125 | 'width': width, 126 | 'height': height, 127 | 'channels': channels[1], 128 | 'type': types[1]['giw'], 129 | 'row_stride': rowstride, 130 | 'pixel_layout': 'rgba', 131 | 'transpose_buffer': False 132 | } 133 | } 134 | 135 | 136 | class DummyDebugger(BridgeInterface): 137 | """ 138 | Very simple implementation of a debugger bridge for the sake of the test 139 | mode. 140 | """ 141 | def __init__(self): 142 | width = 400 143 | height = 200 144 | self._buffers = _gen_buffers(width, height) 145 | self._buffer_names = [name for name in self._buffers] 146 | 147 | self._is_running = True 148 | self._request_queue = queue.Queue() 149 | self._request_consumer_thread = threading.Thread( 150 | target=self._request_consumer, 151 | daemon=True) 152 | self._request_consumer_thread.start() 153 | 154 | def _request_consumer(self): 155 | while self._is_running: 156 | latest_request = self._request_queue.get(block=True, timeout=None) 157 | latest_request() 158 | 159 | def kill(self): 160 | """ 161 | Request consumer thread to finish its execution 162 | """ 163 | self._is_running = False 164 | 165 | def get_casted_pointer(self, typename, debugger_object): 166 | """ 167 | No need to cast anything in this example 168 | """ 169 | return debugger_object 170 | 171 | def register_event_handlers(self, events): 172 | """ 173 | No need to register events in this example 174 | """ 175 | pass 176 | 177 | def get_available_symbols(self): 178 | """ 179 | Return the names of the available sample buffers 180 | """ 181 | return self._buffer_names 182 | 183 | def get_buffer_metadata(self, var_name): 184 | """ 185 | Search in the list of available buffers and return the requested one 186 | """ 187 | if var_name in self._buffers: 188 | return self._buffers[var_name] 189 | 190 | return None 191 | 192 | def queue_request(self, callable_request): 193 | self._request_queue.put(callable_request) 194 | -------------------------------------------------------------------------------- /resources/giwscripts/typebridge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | This module is the bridge between all type modules defined in giwtypes and the 5 | debugger. For every symbol found by the debugger, this module queries for a 6 | candidate giwtype and forwards the required calls from the debugger to it. 7 | """ 8 | 9 | import importlib 10 | import pkgutil 11 | 12 | from giwscripts import giwtypes 13 | from giwscripts.giwtypes.interface import TypeInspectorInterface 14 | 15 | 16 | class TypeBridge: 17 | """ 18 | Class responsible for loading and interfacing with all modules implementing 19 | the TypeInspectorInterface 20 | """ 21 | def __init__(self): 22 | self._type_inspectors = [] 23 | 24 | # Import all modules within giwtypes 25 | for (_, mod_name, _) in pkgutil.iter_modules(giwtypes.__path__): 26 | importlib.import_module('.giwtypes.' + mod_name, __package__) 27 | 28 | # Save instances of all TypeInspector implementations 29 | for inspector_class in TypeInspectorInterface.__subclasses__(): 30 | self._type_inspectors.append(inspector_class()) 31 | 32 | def get_buffer_metadata(self, symbol_name, picked_obj, debugger_bridge): 33 | """ 34 | Returns the metadata related to a variable, which are required for the 35 | purpose of plotting it in the giwwindow 36 | """ 37 | for module in self._type_inspectors: 38 | if module.is_symbol_observable(picked_obj, symbol_name): 39 | return module.get_buffer_metadata(symbol_name, 40 | picked_obj, 41 | debugger_bridge) 42 | 43 | return None 44 | 45 | def is_symbol_observable(self, symbol_obj, symbol_name): 46 | """ 47 | Returns true if any available module is able to process this particular 48 | symbol 49 | """ 50 | for module in self._type_inspectors: 51 | if module.is_symbol_observable(symbol_obj, symbol_name): 52 | return True 53 | 54 | return False 55 | -------------------------------------------------------------------------------- /resources/icons/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Font license info 2 | 3 | 4 | ## Typicons 5 | 6 | (c) Stephen Hutchings 2012 7 | 8 | Author: Stephen Hutchings 9 | License: SIL (http://scripts.sil.org/OFL) 10 | Homepage: http://typicons.com/ 11 | 12 | 13 | ## Font Awesome 14 | 15 | Copyright (C) 2016 by Dave Gandy 16 | 17 | Author: Dave Gandy 18 | License: SIL () 19 | Homepage: http://fortawesome.github.com/Font-Awesome/ 20 | 21 | 22 | ## Entypo 23 | 24 | Copyright (C) 2012 by Daniel Bruce 25 | 26 | Author: Daniel Bruce 27 | License: SIL (http://scripts.sil.org/OFL) 28 | Homepage: http://www.entypo.com 29 | 30 | 31 | ## MFG Labs 32 | 33 | Copyright (C) 2012 by Daniel Bruce 34 | 35 | Author: MFG Labs 36 | License: SIL (http://scripts.sil.org/OFL) 37 | Homepage: http://www.mfglabs.com/ 38 | 39 | 40 | -------------------------------------------------------------------------------- /resources/icons/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "css_prefix_text": "icon-", 4 | "css_use_suffix": false, 5 | "hinting": true, 6 | "units_per_em": 1000, 7 | "ascent": 850, 8 | "glyphs": [ 9 | { 10 | "uid": "8d2bc2d959a55e76466bbef6e84c8373", 11 | "css": "resize-normal", 12 | "code": 59392, 13 | "src": "typicons" 14 | }, 15 | { 16 | "uid": "bc71f4c6e53394d5ba46b063040014f1", 17 | "css": "cw", 18 | "code": 59393, 19 | "src": "fontawesome" 20 | }, 21 | { 22 | "uid": "f9c3205df26e7778abac86183aefdc99", 23 | "css": "ccw", 24 | "code": 59394, 25 | "src": "fontawesome" 26 | }, 27 | { 28 | "uid": "ccddff8e8670dcd130e3cb55fdfc2fd0", 29 | "css": "down-open", 30 | "code": 59395, 31 | "src": "fontawesome" 32 | }, 33 | { 34 | "uid": "ca90da02d2c6a3183f2458e4dc416285", 35 | "css": "adjust", 36 | "code": 59396, 37 | "src": "fontawesome" 38 | }, 39 | { 40 | "uid": "0ddd3e8201ccc7d41f7b7c9d27eca6c1", 41 | "css": "link", 42 | "code": 59397, 43 | "src": "fontawesome" 44 | }, 45 | { 46 | "uid": "e8239f8188c76c925be4bd1bbcc013ac", 47 | "css": "erase", 48 | "code": 59400, 49 | "src": "entypo" 50 | }, 51 | { 52 | "uid": "291e2e127efe7a6bc580af6d3ead3771", 53 | "css": "location", 54 | "code": 61489, 55 | "src": "mfglabs" 56 | } 57 | ] 58 | } -------------------------------------------------------------------------------- /resources/icons/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csantosbh/gdb-imagewatch/95853220a5ae55d85cb106eb55e5a5f7b5d5b5b2/resources/icons/fontello.ttf -------------------------------------------------------------------------------- /resources/icons/label_alpha_channel.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 70 | 74 | 76 | 81 | 86 | 87 | 90 | 95 | 100 | 101 | 102 | 106 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /resources/icons/label_blue_channel.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 63 | 66 | 72 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /resources/icons/label_green_channel.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 57 | 60 | 66 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /resources/icons/label_red_channel.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 57 | 60 | 66 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /resources/icons/lower_upper_bound.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 65 | 68 | 74 | 75 | 82 | 85 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /resources/icons/x.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 63 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /resources/icons/y.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 63 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /resources/matlab/giw_load.m: -------------------------------------------------------------------------------- 1 | %% 2 | % Loads a binary file saved from gdb-imagewatch. 3 | 4 | function buffer = giw_load(fname) 5 | 6 | fid = fopen(fname, 'r'); 7 | 8 | type = fgets(fid); 9 | dimensions = fread(fid, 3, 'int32')'; 10 | 11 | buffer = fread(fid, prod(dimensions), type(1:length(type)-1)); 12 | 13 | rows = dimensions(1); 14 | cols = dimensions(2); 15 | channels = dimensions(3); 16 | 17 | buffer_t = reshape(reshape(buffer, channels, rows*cols)', [cols,rows,channels]); 18 | 19 | buffer = zeros(dimensions); 20 | for c = 1:channels 21 | buffer(:, :, c) = buffer_t(:, :, c)'; 22 | end 23 | 24 | fclose(fid); 25 | 26 | -------------------------------------------------------------------------------- /resources/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/fontello.ttf 4 | icons/label_red_channel.svg 5 | icons/label_green_channel.svg 6 | icons/label_blue_channel.svg 7 | icons/label_alpha_channel.svg 8 | icons/lower_upper_bound.svg 9 | icons/x.svg 10 | icons/y.svg 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/.clang-format: -------------------------------------------------------------------------------- 1 | BinPackParameters: false 2 | AllowAllParametersOfDeclarationOnNextLine: false 3 | ColumnLimit: 80 4 | IndentWidth: 4 5 | UseTab: Never 6 | AlignConsecutiveAssignments: true 7 | PointerBindsToType: true 8 | Cpp11BracedListStyle: true 9 | AlignAfterOpenBracket: Align 10 | AlignEscapedNewlinesLeft: true 11 | AllowShortBlocksOnASingleLine: false 12 | AllowShortCaseLabelsOnASingleLine: false 13 | AllowShortFunctionsOnASingleLine: false 14 | BinPackArguments: false 15 | AlwaysBreakTemplateDeclarations: true 16 | AllowShortFunctionsOnASingleLine: false 17 | AllowShortCaseLabelsOnASingleLine: false 18 | AllowShortBlocksOnASingleLine: false 19 | AlignOperands: true 20 | BraceWrapping: 21 | AfterFunction: true 22 | AfterNamespace: true 23 | AfterClass: true 24 | AfterStruct: true 25 | AfterUnion: true 26 | BreakBeforeBraces: Custom 27 | MaxEmptyLinesToKeep: 2 28 | SortIncludes: true 29 | SpaceBeforeAssignmentOperators: true 30 | BreakConstructorInitializers: BeforeComma 31 | -------------------------------------------------------------------------------- /src/debuggerinterface/buffer_request_message.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include "buffer_request_message.h" 27 | 28 | 29 | void copy_py_string(std::string& dst, PyObject* src) 30 | { 31 | if (PyUnicode_Check(src)) { 32 | // Unicode sring 33 | PyObject* src_bytes = PyUnicode_AsEncodedString(src, "ASCII", "strict"); 34 | dst = PyBytes_AS_STRING(src_bytes); 35 | Py_DECREF(src_bytes); 36 | } else { 37 | assert(PyBytes_Check(src)); 38 | dst = PyBytes_AS_STRING(src); 39 | } 40 | } 41 | 42 | 43 | BufferRequestMessage::BufferRequestMessage(const BufferRequestMessage& buff) 44 | : py_buffer(buff.py_buffer) 45 | , variable_name_str(buff.variable_name_str) 46 | , display_name_str(buff.display_name_str) 47 | , width_i(buff.width_i) 48 | , height_i(buff.height_i) 49 | , channels(buff.channels) 50 | , type(buff.type) 51 | , step(buff.step) 52 | , pixel_layout(buff.pixel_layout) 53 | , transpose_buffer(buff.transpose_buffer) 54 | { 55 | Py_INCREF(py_buffer); 56 | } 57 | 58 | 59 | BufferRequestMessage::BufferRequestMessage(PyObject* pybuffer, 60 | PyObject* variable_name, 61 | PyObject* display_name, 62 | int buffer_width_i, 63 | int buffer_height_i, 64 | int channels, 65 | int type, 66 | int step, 67 | PyObject* pixel_layout, 68 | bool transpose) 69 | : py_buffer(pybuffer) 70 | , width_i(buffer_width_i) 71 | , height_i(buffer_height_i) 72 | , channels(channels) 73 | , type(static_cast(type)) 74 | , step(step) 75 | , transpose_buffer(transpose) 76 | { 77 | Py_INCREF(py_buffer); 78 | 79 | copy_py_string(this->variable_name_str, variable_name); 80 | copy_py_string(this->display_name_str, display_name); 81 | copy_py_string(this->pixel_layout, pixel_layout); 82 | } 83 | 84 | 85 | BufferRequestMessage::~BufferRequestMessage() 86 | { 87 | Py_DECREF(py_buffer); 88 | } 89 | 90 | 91 | int BufferRequestMessage::get_visualized_width() const 92 | { 93 | if (!transpose_buffer) { 94 | return width_i; 95 | } else { 96 | return height_i; 97 | } 98 | } 99 | 100 | 101 | int BufferRequestMessage::get_visualized_height() const 102 | { 103 | if (!transpose_buffer) { 104 | return height_i; 105 | } else { 106 | return width_i; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/debuggerinterface/buffer_request_message.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef BUFFER_REQUEST_MESSAGE_H_ 27 | #define BUFFER_REQUEST_MESSAGE_H_ 28 | 29 | #include 30 | 31 | #include 32 | 33 | #include "visualization/components/buffer.h" 34 | 35 | 36 | void copy_py_string(std::string& dst, PyObject* src); 37 | 38 | struct BufferRequestMessage 39 | { 40 | PyObject* py_buffer; 41 | std::string variable_name_str; 42 | std::string display_name_str; 43 | int width_i; 44 | int height_i; 45 | int channels; 46 | Buffer::BufferType type; 47 | int step; 48 | std::string pixel_layout; 49 | bool transpose_buffer; 50 | 51 | BufferRequestMessage(const BufferRequestMessage& buff); 52 | 53 | BufferRequestMessage(PyObject* pybuffer, 54 | PyObject* variable_name, 55 | PyObject* display_name, 56 | int buffer_width_i, 57 | int buffer_height_i, 58 | int channels, 59 | int type, 60 | int step, 61 | PyObject* pixel_layout, 62 | bool transpose); 63 | 64 | ~BufferRequestMessage(); 65 | 66 | BufferRequestMessage() = delete; 67 | 68 | BufferRequestMessage& operator=(const BufferRequestMessage&) = delete; 69 | 70 | /** 71 | * Returns buffer width taking into account its transposition flag 72 | */ 73 | int get_visualized_width() const; 74 | 75 | /** 76 | * Returns buffer height taking into account its transposition flag 77 | */ 78 | int get_visualized_height() const; 79 | }; 80 | 81 | #endif // BUFFER_REQUEST_MESSAGE_H_ 82 | -------------------------------------------------------------------------------- /src/debuggerinterface/managed_pointer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include "managed_pointer.h" 29 | 30 | 31 | using namespace std; 32 | 33 | 34 | shared_ptr make_shared_py_object(PyObject* obj) 35 | { 36 | Py_INCREF(obj); 37 | 38 | return shared_ptr( 39 | reinterpret_cast(obj), 40 | [](uint8_t* obj) { Py_DECREF(reinterpret_cast(obj)); }); 41 | } 42 | 43 | 44 | shared_ptr make_float_buffer_from_double(double* buff, int length) 45 | { 46 | shared_ptr result( 47 | reinterpret_cast(new float[length]), 48 | [](uint8_t* buff) { delete[] reinterpret_cast(buff); }); 49 | 50 | // Cast from double to float 51 | float* dst = reinterpret_cast(result.get()); 52 | for (int i = 0; i < length; ++i) { 53 | dst[i] = static_cast(buff[i]); 54 | } 55 | 56 | return result; 57 | } 58 | -------------------------------------------------------------------------------- /src/debuggerinterface/managed_pointer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef MANAGED_POINTER_H_ 27 | #define MANAGED_POINTER_H_ 28 | 29 | #include 30 | 31 | #include 32 | 33 | 34 | std::shared_ptr make_shared_py_object(PyObject* obj); 35 | 36 | std::shared_ptr make_float_buffer_from_double(double* buff, 37 | int length); 38 | 39 | #endif // MANAGED_POINTER_H_ 40 | -------------------------------------------------------------------------------- /src/debuggerinterface/preprocessor_directives.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef PREPROCESSOR_DIRECTIVES_H_ 27 | #define PREPROCESSOR_DIRECTIVES_H_ 28 | 29 | #define RAISE_PY_EXCEPTION(exception_type, msg) \ 30 | PyGILState_STATE gstate = PyGILState_Ensure(); \ 31 | PyErr_SetString(exception_type, msg); \ 32 | PyGILState_Release(gstate); 33 | 34 | 35 | #define RAISE_PY_EXCEPTION(exception_type, msg) \ 36 | PyGILState_STATE gstate = PyGILState_Ensure(); \ 37 | PyErr_SetString(exception_type, msg); \ 38 | PyGILState_Release(gstate); 39 | 40 | 41 | #define CHECK_FIELD_PROVIDED(name, current_ctx_name) \ 42 | if (py_##name == nullptr) { \ 43 | RAISE_PY_EXCEPTION( \ 44 | PyExc_KeyError, \ 45 | "Missing key in dictionary provided to " current_ctx_name \ 46 | ": Was expecting <" #name "> key"); \ 47 | return; \ 48 | } 49 | 50 | 51 | #define CHECK_FIELD_TYPE(name, type_checker_funct, current_ctx_name) \ 52 | if (type_checker_funct(py_##name) == 0) { \ 53 | RAISE_PY_EXCEPTION( \ 54 | PyExc_TypeError, \ 55 | "Key " #name " provided to " current_ctx_name " does not " \ 56 | "have the expected type (" #type_checker_funct " failed)"); \ 57 | return; \ 58 | } 59 | 60 | 61 | #define FALSE 0 62 | 63 | #define TRUE (!FALSE) 64 | 65 | #endif // PREPROCESSOR_DIRECTIVES_H_ 66 | -------------------------------------------------------------------------------- /src/debuggerinterface/python_native_interface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include "python_native_interface.h" 27 | 28 | 29 | int get_py_int(PyObject* obj) 30 | { 31 | return PyLong_AS_LONG(obj); 32 | } 33 | 34 | 35 | int check_py_string_type(PyObject* obj) 36 | { 37 | return PyUnicode_Check(obj) == 1 ? 1 : PyBytes_Check(obj); 38 | } 39 | 40 | 41 | void* get_c_ptr_from_py_buffer(PyObject* obj) 42 | { 43 | assert(PyMemoryView_Check(obj)); 44 | return PyMemoryView_GET_BUFFER(obj)->buf; 45 | } 46 | -------------------------------------------------------------------------------- /src/debuggerinterface/python_native_interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef PYTHON_NATIVE_INTERFACE_H_ 27 | #define PYTHON_NATIVE_INTERFACE_H_ 28 | 29 | #include 30 | 31 | 32 | int get_py_int(PyObject* obj); 33 | 34 | 35 | int check_py_string_type(PyObject* obj); 36 | 37 | 38 | void* get_c_ptr_from_py_buffer(PyObject* obj); 39 | 40 | #endif // PYTHON_NATIVE_INTERFACE_H_ 41 | -------------------------------------------------------------------------------- /src/giw_window.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch (github.com/csantosbh/gdb-imagewatch/) 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 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell 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 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef GIW_WINDOW_H_ 26 | #define GIW_WINDOW_H_ 27 | 28 | #include 29 | 30 | #ifndef GIW_API 31 | # if __GNUC__ >= 4 32 | # define GIW_API __attribute__((visibility("default"))) 33 | # else 34 | # define GIW_API 35 | # endif 36 | #endif 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | 43 | typedef void* AppHandler; 44 | typedef void* WindowHandler; 45 | 46 | 47 | /** 48 | * Initialize GIW application 49 | * 50 | * The thread in which this function will be called will become the GUI thread; 51 | * all later functions (with exception of giw_terminate()) must be called 52 | * in the same thread. 53 | * 54 | * @return Application context 55 | */ 56 | GIW_API 57 | AppHandler giw_initialize(); 58 | 59 | /** 60 | * Cleanup GIW application 61 | * 62 | * This function should be called prior to the application shutdown, in order to 63 | * release some of the resources acquired by the underlying GUI library. 64 | * 65 | * @param handler Application context generated by giw_initialize() 66 | */ 67 | GIW_API 68 | void giw_cleanup(AppHandler handler); 69 | 70 | /** 71 | * Request GIW application to be terminated 72 | * 73 | * This function will close all windows, making the method giw_exec() to finish 74 | * executing. This function can be called from any thread. 75 | */ 76 | GIW_API 77 | void giw_terminate(); 78 | 79 | /** 80 | * Execute GUI loop 81 | * 82 | * This methods blocks the caller until the GIW window is closed. If 83 | * non-blocking behavior is desired, it must be called from a dedicated thread. 84 | * Notice that it must also be called in the same thread as giw_initialize(). 85 | * 86 | * @param handler Application context 87 | */ 88 | GIW_API 89 | void giw_exec(AppHandler handler); 90 | 91 | /** 92 | * Create and open new window 93 | * 94 | * Must be called after giw_initialize(), in the same thread as it was called. 95 | * 96 | * @param plot_callback Callback function to be called when the user requests 97 | * a symbol name from the giw window 98 | * 99 | * @return Window context 100 | */ 101 | GIW_API 102 | WindowHandler giw_create_window(int (*plot_callback)(const char*)); 103 | 104 | /** 105 | * Check if the given window is open 106 | * 107 | * @param handler Window handler, generated by giw_create_window() 108 | * @return Returns 1 if the window has been fully initialized, 0 otherwise. 109 | */ 110 | GIW_API 111 | int giw_is_window_ready(WindowHandler handler); 112 | 113 | /** 114 | * Clean up GIW window 115 | * 116 | * This function should be called prior to the application shutdown, in order to 117 | * release some of the resources acquired by the underlying GUI library. 118 | * 119 | * @param handler Window handler, generated by giw_create_window() 120 | */ 121 | GIW_API 122 | void giw_destroy_window(WindowHandler handler); 123 | 124 | /** 125 | * Get a list of the names of all buffers being visualized 126 | * 127 | * Returns a python list object with the names of all buffers present in the 128 | * visualization list. 129 | * 130 | * @param handler Window handler, generated by giw_create_window() 131 | * @return Python list object containing python str objects with the names of 132 | * all buffers being visualized. 133 | */ 134 | GIW_API 135 | PyObject* giw_get_observed_buffers(WindowHandler handler); 136 | 137 | /** 138 | * Set list of symbols available in the current context 139 | * 140 | * Sets a list of names of variables available for plotting in the current 141 | * context. This list will serve as base for the autocomplete mechanism in the 142 | * symbol searcher input. 143 | * 144 | * @param handler Window handler, generated by giw_create_window() 145 | * @param available_set Python list of python str objects containing the names 146 | * of all available symbols in the current context. 147 | */ 148 | GIW_API 149 | void giw_set_available_symbols(WindowHandler handler, 150 | PyObject* available_vars); 151 | 152 | /** 153 | * Add a buffer to the plot list 154 | * 155 | * @param handler Handler of the window where the buffer should be plotted 156 | * @param buffer_metadata Python dictionary with the following elements: 157 | * - [pointer ] PyMemoryView object wrapping the target buffer 158 | * - [display_name] Variable name as it shall be displayed 159 | * - [width ] Buffer width, in pixels 160 | * - [height ] Buffer height, in pixels 161 | * - [channels ] Number of channels (1 to 4) 162 | * - [type ] Buffer type (see symbols.py for details) 163 | * - [row_stride ] Row stride, in pixels 164 | * - [pixel_layout] String defining pixel channel layout (e.g. 'rgba') 165 | * */ 166 | GIW_API 167 | void giw_plot_buffer(WindowHandler handler, PyObject* bufffer_metadata); 168 | 169 | #ifdef __cplusplus 170 | } 171 | #endif 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /src/io/buffer_exporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef BUFFER_EXPORTER_H_ 27 | #define BUFFER_EXPORTER_H_ 28 | 29 | #include "visualization/components/buffer.h" 30 | 31 | 32 | class BufferExporter 33 | { 34 | public: 35 | enum class OutputType { Bitmap, OctaveMatrix }; 36 | 37 | static void export_buffer(const Buffer* buffer, 38 | const std::string& path, 39 | OutputType type); 40 | }; 41 | 42 | #endif // BUFFER_EXPORTER_H_ 43 | -------------------------------------------------------------------------------- /src/math/assorted.cpp: -------------------------------------------------------------------------------- 1 | #include "assorted.h" 2 | -------------------------------------------------------------------------------- /src/math/assorted.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef ASSORTED_H_ 27 | #define ASSORTED_H_ 28 | 29 | #include 30 | 31 | template 32 | int clamp(T value, T lower, T upper) 33 | { 34 | return std::min(std::max(value, lower), upper); 35 | } 36 | 37 | #endif // ASSORTED_H_ 38 | -------------------------------------------------------------------------------- /src/math/linear_algebra.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include "linear_algebra.h" 29 | 30 | 31 | vec4::vec4() 32 | { 33 | } 34 | 35 | 36 | vec4::vec4(float x, float y, float z, float w) 37 | : vec(x, y, z, w) 38 | { 39 | } 40 | 41 | 42 | void vec4::operator=(const vec4& b) 43 | { 44 | vec = b.vec; 45 | } 46 | 47 | 48 | vec4& vec4::operator+=(const vec4& b) 49 | { 50 | for (int i = 0; i < 4; ++i) 51 | vec[i] += b.vec[i]; 52 | return *this; 53 | } 54 | 55 | 56 | vec4 vec4::operator+(const vec4& b) const 57 | { 58 | return vec4(vec[0] + b.vec[0], 59 | vec[1] + b.vec[1], 60 | vec[2] + b.vec[2], 61 | vec[3] + b.vec[3]); 62 | } 63 | 64 | 65 | vec4 vec4::operator-(const vec4& b) const 66 | { 67 | return vec4(vec[0] - b.vec[0], 68 | vec[1] - b.vec[1], 69 | vec[2] - b.vec[2], 70 | vec[3] - b.vec[3]); 71 | } 72 | 73 | 74 | vec4 vec4::operator*(float scalar) const 75 | { 76 | vec4 result(*this); 77 | result.vec *= scalar; 78 | 79 | return result; 80 | } 81 | 82 | 83 | void vec4::print() const 84 | { 85 | std::cout << vec.transpose() << std::endl; 86 | } 87 | 88 | 89 | float* vec4::data() 90 | { 91 | return vec.data(); 92 | } 93 | 94 | 95 | float& vec4::x() 96 | { 97 | return vec[0]; 98 | } 99 | 100 | 101 | float& vec4::y() 102 | { 103 | return vec[1]; 104 | } 105 | 106 | 107 | float& vec4::z() 108 | { 109 | return vec[2]; 110 | } 111 | 112 | 113 | float& vec4::w() 114 | { 115 | return vec[3]; 116 | } 117 | 118 | 119 | const float& vec4::x() const 120 | { 121 | return vec[0]; 122 | } 123 | 124 | 125 | const float& vec4::y() const 126 | { 127 | return vec[1]; 128 | } 129 | 130 | 131 | const float& vec4::z() const 132 | { 133 | return vec[2]; 134 | } 135 | 136 | 137 | const float& vec4::w() const 138 | { 139 | return vec[3]; 140 | } 141 | 142 | 143 | vec4 vec4::zero() 144 | { 145 | return vec4(0, 0, 0, 0); 146 | } 147 | 148 | 149 | vec4 operator-(const vec4& vector) 150 | { 151 | return {-vector.x(), -vector.y(), -vector.z(), -vector.w()}; 152 | } 153 | 154 | 155 | void mat4::set_identity() 156 | { 157 | // clang-format off 158 | *this << std::initializer_list{ 159 | 1, 0, 0, 0, 160 | 0, 1, 0, 0, 161 | 0, 0, 1, 0, 162 | 0, 0, 0, 1 163 | }; 164 | // clang-format on 165 | } 166 | 167 | 168 | void mat4::set_from_st(float scaleX, 169 | float scaleY, 170 | float scaleZ, 171 | float x, 172 | float y, 173 | float z) 174 | { 175 | float* data = this->data(); 176 | 177 | data[0] = scaleX, data[5] = scaleY, data[10] = scaleZ; 178 | data[12] = x, data[13] = y, data[14] = z; 179 | 180 | data[1] = data[2] = data[3] = data[4] = 0.0; 181 | data[6] = data[7] = data[8] = data[9] = 0.0; 182 | data[11] = 0.0; 183 | data[15] = 1.0; 184 | } 185 | 186 | 187 | void mat4::set_from_srt(float scaleX, 188 | float scaleY, 189 | float scaleZ, 190 | float rZ, 191 | float x, 192 | float y, 193 | float z) 194 | { 195 | using Eigen::Affine3f; 196 | using Eigen::AngleAxisf; 197 | using Eigen::Vector3f; 198 | 199 | Affine3f t = Affine3f::Identity(); 200 | t.translate(Vector3f(x, y, z)) 201 | .rotate(AngleAxisf(rZ, Vector3f(0, 0, 1))) 202 | .scale(Vector3f(scaleX, scaleY, scaleZ)); 203 | this->mat_ = t.matrix(); 204 | } 205 | 206 | 207 | float* mat4::data() 208 | { 209 | return mat_.data(); 210 | } 211 | 212 | 213 | void mat4::operator<<(const std::initializer_list& data) 214 | { 215 | memcpy(mat_.data(), data.begin(), sizeof(float) * data.size()); 216 | } 217 | 218 | 219 | mat4 mat4::rotation(float angle) 220 | { 221 | using Eigen::Affine3f; 222 | using Eigen::AngleAxisf; 223 | using Eigen::Vector3f; 224 | 225 | mat4 result; 226 | Affine3f t = Affine3f::Identity(); 227 | t.rotate(AngleAxisf(angle, Vector3f(0, 0, 1))); 228 | 229 | result.mat_ = t.matrix(); 230 | return result; 231 | } 232 | 233 | 234 | mat4 mat4::translation(const vec4& vector) 235 | { 236 | using Eigen::Affine3f; 237 | using Eigen::Vector3f; 238 | 239 | mat4 result; 240 | 241 | Affine3f t = Affine3f::Identity(); 242 | t.translate(Vector3f(vector.x(), vector.y(), vector.z())); 243 | result.mat_ = t.matrix(); 244 | 245 | return result; 246 | } 247 | 248 | 249 | mat4 mat4::scale(const vec4& factor) 250 | { 251 | using Eigen::Affine3f; 252 | using Eigen::Vector3f; 253 | 254 | mat4 result; 255 | 256 | Affine3f t = Affine3f::Identity(); 257 | t.scale(Vector3f(factor.x(), factor.y(), factor.z())); 258 | result.mat_ = t.matrix(); 259 | 260 | return result; 261 | } 262 | 263 | 264 | void mat4::set_ortho_projection(float right, float top, float near, float far) 265 | { 266 | float* data = this->data(); 267 | 268 | data[0] = 1.0 / right; 269 | data[5] = -1.0 / top; 270 | data[10] = -2.0 / (far - near); 271 | data[14] = -(far + near) / (far - near); 272 | 273 | data[1] = data[2] = data[3] = data[4] = 0.0; 274 | data[6] = data[7] = data[8] = data[9] = 0.0; 275 | data[11] = data[12] = data[13] = 0.0; 276 | data[15] = 1.0; 277 | } 278 | 279 | 280 | void mat4::print() const 281 | { 282 | std::cout << mat_ << std::endl; 283 | } 284 | 285 | 286 | mat4 mat4::inv() const 287 | { 288 | mat4 res; 289 | res.mat_ = this->mat_.inverse(); 290 | 291 | return res; 292 | } 293 | 294 | 295 | vec4 mat4::operator*(const vec4& b) const 296 | { 297 | vec4 res; 298 | res.vec = this->mat_ * b.vec; 299 | 300 | return res; 301 | } 302 | 303 | 304 | float&mat4::operator()(int row, int col) { 305 | return mat_(row, col); 306 | } 307 | 308 | 309 | mat4 mat4::operator*(const mat4& b) const 310 | { 311 | mat4 res; 312 | 313 | res.mat_ = this->mat_ * b.mat_; 314 | 315 | return res; 316 | } 317 | -------------------------------------------------------------------------------- /src/math/linear_algebra.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef LINEAR_ALGEBRA_H_ 27 | #define LINEAR_ALGEBRA_H_ 28 | 29 | #include 30 | #include 31 | 32 | #include "thirdparty/Eigen/Eigen" 33 | 34 | 35 | class mat4; 36 | 37 | 38 | class vec4 39 | { 40 | friend class mat4; 41 | 42 | public: 43 | vec4(); 44 | void operator=(const vec4& b); 45 | 46 | vec4& operator+=(const vec4& b); 47 | 48 | vec4 operator+(const vec4& b) const; 49 | 50 | vec4 operator-(const vec4& b) const; 51 | 52 | vec4 operator*(float scalar) const; 53 | 54 | vec4(float x, float y, float z, float w); 55 | 56 | void print() const; 57 | 58 | float* data(); 59 | 60 | float& x(); 61 | float& y(); 62 | float& z(); 63 | float& w(); 64 | 65 | const float& x() const; 66 | const float& y() const; 67 | const float& z() const; 68 | const float& w() const; 69 | 70 | static vec4 zero(); 71 | 72 | private: 73 | Eigen::Vector4f vec; 74 | }; 75 | 76 | vec4 operator-(const vec4& vector); 77 | 78 | 79 | class mat4 80 | { 81 | public: 82 | void set_identity(); 83 | 84 | void set_from_srt(float scaleX, 85 | float scaleY, 86 | float scaleZ, 87 | float rZ, 88 | float x, 89 | float y, 90 | float z); 91 | 92 | void set_from_st(float scaleX, 93 | float scaleY, 94 | float scaleZ, 95 | float x, 96 | float y, 97 | float z); 98 | 99 | float* data(); 100 | 101 | void operator<<(const std::initializer_list& data); 102 | 103 | void set_ortho_projection(float right, float top, float near, float far); 104 | 105 | void print() const; 106 | 107 | mat4 inv() const; 108 | 109 | mat4 operator*(const mat4& b) const; 110 | 111 | vec4 operator*(const vec4& b) const; 112 | 113 | float& operator()(int row, int col); 114 | 115 | static mat4 rotation(float angle); 116 | 117 | static mat4 translation(const vec4& vector); 118 | 119 | static mat4 scale(const vec4& factor); 120 | 121 | private: 122 | Eigen::Matrix4f mat_; 123 | }; 124 | 125 | #endif // LINEAR_ALGEBRA_H_ 126 | -------------------------------------------------------------------------------- /src/thirdparty/Khronos/GL/gl.h: -------------------------------------------------------------------------------- 1 | #ifndef __gl_h_ 2 | #define __gl_h_ 1 3 | 4 | #define GL_GLEXT_PROTOTYPES 5 | #include "GL/glcorearb.h" 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /src/ui/decorated_line_edit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "decorated_line_edit.h" 9 | 10 | 11 | DecoratedLineEdit::DecoratedLineEdit(const char* icon_path, 12 | const char* tooltip, 13 | QWidget* parent) 14 | : QLineEdit(parent) 15 | { 16 | QIcon label_icon(icon_path); 17 | QAction* label_widget = new QAction(label_icon, tooltip, this); 18 | addAction(label_widget, QLineEdit::ActionPosition::LeadingPosition); 19 | } 20 | -------------------------------------------------------------------------------- /src/ui/decorated_line_edit.h: -------------------------------------------------------------------------------- 1 | #ifndef DECORATED_LINE_EDIT_H_ 2 | #define DECORATED_LINE_EDIT_H_ 3 | 4 | #include 5 | #include 6 | 7 | class DecoratedLineEdit : public QLineEdit 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | DecoratedLineEdit(const char* icon_path, 13 | const char* tooltip, 14 | QWidget* parent = nullptr); 15 | 16 | private: 17 | }; 18 | 19 | #endif // DECORATED_LINE_EDIT_H_ 20 | -------------------------------------------------------------------------------- /src/ui/gl_canvas.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include "gl_canvas.h" 27 | 28 | #include "main_window/main_window.h" 29 | #include "ui/gl_text_renderer.h" 30 | #include "visualization/components/camera.h" 31 | #include "visualization/game_object.h" 32 | 33 | 34 | using namespace std; 35 | 36 | 37 | GLCanvas::GLCanvas(QWidget* parent) 38 | : QOpenGLWidget(parent) 39 | , QOpenGLFunctions() 40 | , mouse_x_(0) 41 | , mouse_y_(0) 42 | , initialized_(false) 43 | , text_renderer_(new GLTextRenderer(this)) 44 | { 45 | mouse_down_[0] = mouse_down_[1] = false; 46 | } 47 | 48 | 49 | GLCanvas::~GLCanvas() 50 | { 51 | } 52 | 53 | 54 | void GLCanvas::mouseMoveEvent(QMouseEvent* ev) 55 | { 56 | int last_mouse_x = mouse_x_; 57 | int last_mouse_y = mouse_y_; 58 | 59 | mouse_x_ = ev->localPos().x(); 60 | mouse_y_ = ev->localPos().y(); 61 | 62 | if (mouse_down_[0]) { 63 | main_window_->mouse_drag_event(mouse_x_ - last_mouse_x, 64 | mouse_y_ - last_mouse_y); 65 | } else { 66 | main_window_->mouse_move_event(mouse_x_ - last_mouse_x, 67 | mouse_y_ - last_mouse_y); 68 | } 69 | } 70 | 71 | 72 | void GLCanvas::mousePressEvent(QMouseEvent* ev) 73 | { 74 | if (ev->button() == Qt::LeftButton) 75 | mouse_down_[0] = true; 76 | 77 | if (ev->button() == Qt::RightButton) 78 | mouse_down_[1] = true; 79 | } 80 | 81 | 82 | void GLCanvas::mouseReleaseEvent(QMouseEvent* ev) 83 | { 84 | if (ev->button() == Qt::LeftButton) 85 | mouse_down_[0] = false; 86 | 87 | if (ev->button() == Qt::RightButton) 88 | mouse_down_[1] = false; 89 | } 90 | 91 | 92 | void GLCanvas::initializeGL() 93 | { 94 | this->makeCurrent(); 95 | initializeOpenGLFunctions(); 96 | 97 | glEnable(GL_BLEND); 98 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 99 | glClearColor(0.1f, 0.1f, 0.1f, 1.0f); 100 | 101 | /// 102 | // Texture for generating icons 103 | assert(main_window_ != nullptr); 104 | QSizeF icon_size = main_window_->get_icon_size(); 105 | int icon_width = icon_size.width(); 106 | int icon_height = icon_size.height(); 107 | glGenTextures(1, &icon_texture_); 108 | glBindTexture(GL_TEXTURE_2D, icon_texture_); 109 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 110 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 111 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 112 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 113 | glTexImage2D(GL_TEXTURE_2D, 114 | 0, 115 | GL_RGB8, 116 | icon_width, 117 | icon_height, 118 | 0, 119 | GL_RGB, 120 | GL_UNSIGNED_BYTE, 121 | NULL); 122 | 123 | // Generate FBO 124 | glGenFramebuffers(1, &icon_fbo_); 125 | glBindFramebuffer(GL_FRAMEBUFFER, icon_fbo_); 126 | 127 | // Attach 2D texture to this FBO 128 | glFramebufferTexture2D( 129 | GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, icon_texture_, 0); 130 | 131 | // Check if the GPU won't freak out about our FBO 132 | GLenum status; 133 | status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 134 | switch (status) { 135 | case GL_FRAMEBUFFER_COMPLETE: 136 | break; 137 | default: 138 | cerr << "Error: FBO configuration is not supported -- sorry mate!" 139 | << endl; 140 | break; 141 | } 142 | 143 | glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); 144 | 145 | // Initialize text renderer 146 | text_renderer_->initialize(); 147 | 148 | initialized_ = true; 149 | } 150 | 151 | 152 | void GLCanvas::paintGL() 153 | { 154 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 155 | main_window_->draw(); 156 | } 157 | 158 | 159 | void GLCanvas::wheelEvent(QWheelEvent* ev) 160 | { 161 | main_window_->scroll_callback(ev->delta() / 120.0f); 162 | } 163 | 164 | 165 | const GLTextRenderer* GLCanvas::get_text_renderer() 166 | { 167 | return text_renderer_.get(); 168 | } 169 | 170 | 171 | void GLCanvas::render_buffer_icon(Stage* stage, int icon_width, int icon_height) 172 | { 173 | glBindFramebuffer(GL_FRAMEBUFFER_EXT, icon_fbo_); 174 | 175 | glViewport(0, 0, icon_width, icon_height); 176 | 177 | GameObject* camera = stage->get_game_object("camera"); 178 | Camera* cam = camera->get_component("camera_component"); 179 | 180 | // Save original camera pose 181 | Camera original_pose = *cam; 182 | 183 | // Adapt camera to the thumbnail dimentions 184 | cam->window_resized(icon_width, icon_height); 185 | // Flips the projected image along the horizontal axis 186 | cam->projection.set_ortho_projection( 187 | icon_width / 2.0, -icon_height / 2.0, -1.0f, 1.0f); 188 | // Reposition buffer in the center of the canvas 189 | cam->recenter_camera(); 190 | 191 | stage->draw(); 192 | stage->buffer_icon.resize(3 * icon_width * icon_height); 193 | glPixelStorei(GL_PACK_ALIGNMENT, 1); 194 | glReadPixels(0, 195 | 0, 196 | icon_width, 197 | icon_height, 198 | GL_RGB, 199 | GL_UNSIGNED_BYTE, 200 | stage->buffer_icon.data()); 201 | 202 | // Reset stage camera 203 | glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); 204 | glViewport(0, 0, width(), height()); 205 | *cam = original_pose; 206 | cam->window_resized(width(), height()); 207 | } 208 | 209 | 210 | void GLCanvas::resizeGL(int w, int h) 211 | { 212 | glViewport(0, 0, w, h); 213 | main_window_->resize_callback(w, h); 214 | } 215 | 216 | 217 | void GLCanvas::set_main_window(MainWindow* mw) 218 | { 219 | main_window_ = mw; 220 | } 221 | 222 | 223 | void list_gl_extensions() 224 | { 225 | GLint num_exts = 0; 226 | glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts); 227 | 228 | cout << "Supported OpenGL extensions:" << glGetString(GL_EXTENSIONS) 229 | << endl; 230 | } 231 | -------------------------------------------------------------------------------- /src/ui/gl_canvas.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef GL_CANVAS_H_ 27 | #define GL_CANVAS_H_ 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | class MainWindow; 37 | class Stage; 38 | class GLTextRenderer; 39 | 40 | 41 | class GLCanvas : public QOpenGLWidget, public QOpenGLFunctions 42 | { 43 | Q_OBJECT 44 | public: 45 | explicit GLCanvas(QWidget* parent = 0); 46 | 47 | ~GLCanvas(); 48 | 49 | void mouseMoveEvent(QMouseEvent* ev); 50 | 51 | void mousePressEvent(QMouseEvent* ev); 52 | 53 | void mouseReleaseEvent(QMouseEvent* ev); 54 | 55 | void initializeGL(); 56 | 57 | void paintGL(); 58 | 59 | void resizeGL(int w, int h); 60 | 61 | void wheelEvent(QWheelEvent* ev); 62 | 63 | int mouse_x() 64 | { 65 | return mouse_x_; 66 | } 67 | 68 | int mouse_y() 69 | { 70 | return mouse_y_; 71 | } 72 | 73 | bool is_mouse_down() 74 | { 75 | return mouse_down_[0]; 76 | } 77 | 78 | bool is_ready() 79 | { 80 | return initialized_; 81 | } 82 | 83 | const GLTextRenderer* get_text_renderer(); 84 | 85 | void set_main_window(MainWindow* mw); 86 | 87 | void render_buffer_icon(Stage* stage, int icon_width, int icon_height); 88 | 89 | private: 90 | bool mouse_down_[2]; 91 | 92 | int mouse_x_; 93 | int mouse_y_; 94 | 95 | MainWindow* main_window_; 96 | 97 | GLuint icon_texture_; 98 | GLuint icon_fbo_; 99 | 100 | bool initialized_; 101 | 102 | std::unique_ptr text_renderer_; 103 | 104 | void generate_icon_texture(); 105 | }; 106 | 107 | #endif // GL_CANVAS_H_ 108 | -------------------------------------------------------------------------------- /src/ui/gl_text_renderer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef GL_TEXT_RENDERER_H_ 27 | #define GL_TEXT_RENDERER_H_ 28 | 29 | #include "math/linear_algebra.h" 30 | #include "ui/gl_canvas.h" 31 | #include "visualization/shader.h" 32 | 33 | 34 | class GLTextRenderer 35 | { 36 | public: 37 | static constexpr float font_size = 96.0f; 38 | 39 | QFont font; 40 | GLuint text_vbo; 41 | GLuint text_tex; 42 | 43 | int text_texture_offsets[256][2]; 44 | int text_texture_advances[256][2]; 45 | int text_texture_sizes[256][2]; 46 | int text_texture_tls[256][2]; 47 | 48 | GLTextRenderer(GLCanvas* gl_canvas); 49 | ~GLTextRenderer(); 50 | 51 | bool initialize(); 52 | 53 | void generate_glyphs_texture(); 54 | 55 | ShaderProgram text_prog; 56 | 57 | float text_texture_width; 58 | float text_texture_height; 59 | 60 | private: 61 | GLCanvas* gl_canvas_; 62 | }; 63 | 64 | #endif // GL_TEXT_RENDERER_H_ 65 | -------------------------------------------------------------------------------- /src/ui/go_to_widget.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "go_to_widget.h" 33 | 34 | GoToWidget::GoToWidget(QWidget* parent) 35 | : QWidget(parent) 36 | { 37 | QHBoxLayout* layout = new QHBoxLayout(this); 38 | layout->setMargin(0); 39 | layout->setSpacing(0); 40 | 41 | x_coordinate_ = new DecoratedLineEdit( 42 | ":resources/icons/x.svg", "Horizontal coordinate", this); 43 | x_coordinate_->setValidator(new QIntValidator(x_coordinate_)); 44 | 45 | y_coordinate_ = new DecoratedLineEdit( 46 | ":resources/icons/y.svg", "Vertical coordinate", this); 47 | y_coordinate_->setValidator(new QIntValidator(y_coordinate_)); 48 | 49 | layout->addWidget(x_coordinate_); 50 | layout->addWidget(y_coordinate_); 51 | 52 | setVisible(false); 53 | } 54 | 55 | 56 | void GoToWidget::keyPressEvent(QKeyEvent* e) 57 | { 58 | switch (e->key()) { 59 | case Qt::Key_Escape: 60 | toggle_visible(); 61 | e->accept(); 62 | 63 | return; 64 | case Qt::Key_Enter: 65 | case Qt::Key_Return: 66 | toggle_visible(); 67 | e->accept(); 68 | Q_EMIT(go_to_requested(x_coordinate_->text().toFloat() + 0.5f, 69 | y_coordinate_->text().toFloat() + 0.5f)); 70 | return; // Let the completer do default behavior 71 | } 72 | } 73 | 74 | 75 | void GoToWidget::toggle_visible() 76 | { 77 | QWidget* parent_widget = static_cast(parent()); 78 | 79 | if (isVisible()) { 80 | hide(); 81 | 82 | parent_widget->setFocus(); 83 | } else { 84 | show(); 85 | 86 | this->move(parent_widget->width() - this->width(), 87 | parent_widget->height() - this->height()); 88 | 89 | x_coordinate_->setFocus(); 90 | x_coordinate_->selectAll(); 91 | } 92 | } 93 | 94 | 95 | void GoToWidget::set_defaults(float default_x, float default_y) 96 | { 97 | x_coordinate_->setText(QString::number(std::round(default_x - 0.5f))); 98 | y_coordinate_->setText(QString::number(std::round(default_y - 0.5f))); 99 | } 100 | -------------------------------------------------------------------------------- /src/ui/go_to_widget.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef GO_TO_WIDGET_H_ 27 | #define GO_TO_WIDGET_H_ 28 | 29 | #include 30 | #include 31 | 32 | #include "decorated_line_edit.h" 33 | 34 | 35 | class GoToWidget : public QWidget 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | explicit GoToWidget(QWidget* parent = nullptr); 41 | void toggle_visible(); 42 | void set_defaults(float default_x, float default_y); 43 | 44 | Q_SIGNALS: 45 | void go_to_requested(float x, float y); 46 | 47 | public Q_SLOTS: 48 | 49 | protected: 50 | void keyPressEvent(QKeyEvent* e); 51 | 52 | 53 | private: 54 | DecoratedLineEdit* x_coordinate_; 55 | DecoratedLineEdit* y_coordinate_; 56 | }; 57 | 58 | #endif // GO_TO_WIDGET_H_ 59 | -------------------------------------------------------------------------------- /src/ui/main_window/main_window.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef MAIN_WINDOW_H_ 27 | #define MAIN_WINDOW_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "debuggerinterface/buffer_request_message.h" 41 | #include "math/linear_algebra.h" 42 | #include "ui/go_to_widget.h" 43 | #include "ui/symbol_completer.h" 44 | #include "visualization/stage.h" 45 | 46 | 47 | namespace Ui 48 | { 49 | class MainWindowUi; 50 | } 51 | 52 | 53 | class MainWindow : public QMainWindow 54 | { 55 | Q_OBJECT 56 | 57 | public: 58 | /// 59 | // Constructor / destructor 60 | explicit MainWindow(QWidget* parent = 0); 61 | 62 | ~MainWindow(); 63 | 64 | /// 65 | // Assorted methods - implemented in main_window.cpp 66 | void show(); 67 | 68 | void draw(); 69 | 70 | GLCanvas* gl_canvas(); 71 | 72 | QSizeF get_icon_size(); 73 | 74 | // External interface 75 | void set_plot_callback(int (*plot_cbk)(const char*)); 76 | 77 | void plot_buffer(const BufferRequestMessage& buffer_metadata); 78 | 79 | std::deque get_observed_symbols(); 80 | 81 | bool is_window_ready(); 82 | 83 | void set_available_symbols(const std::deque& available_set); 84 | 85 | /// 86 | // Auto contrast pane - implemented in auto_contrast.cpp 87 | void reset_ac_min_labels(); 88 | 89 | void reset_ac_max_labels(); 90 | 91 | /// 92 | // General UI Events - implemented in ui_events.cpp 93 | void resize_callback(int w, int h); 94 | 95 | void scroll_callback(float delta); 96 | 97 | void mouse_drag_event(int mouse_x, int mouse_y); 98 | 99 | void mouse_move_event(int mouse_x, int mouse_y); 100 | 101 | // Window change events - only called after the event is finished 102 | bool eventFilter(QObject* target, QEvent* event); 103 | 104 | void resizeEvent(QResizeEvent*); 105 | 106 | void moveEvent(QMoveEvent*); 107 | 108 | void closeEvent(QCloseEvent*); 109 | 110 | public Q_SLOTS: 111 | /// 112 | // Assorted methods - slots - implemented in main_window.cpp 113 | void loop(); 114 | 115 | void request_render_update(); 116 | 117 | /// 118 | // Auto contrast pane - slots - implemented in auto_contrast.cpp 119 | void ac_red_min_update(); 120 | 121 | void ac_green_min_update(); 122 | 123 | void ac_blue_min_update(); 124 | 125 | void ac_alpha_min_update(); 126 | 127 | void ac_red_max_update(); 128 | 129 | void ac_green_max_update(); 130 | 131 | void ac_blue_max_update(); 132 | 133 | void ac_alpha_max_update(); 134 | 135 | void ac_min_reset(); 136 | 137 | void ac_max_reset(); 138 | 139 | void ac_toggle(); 140 | 141 | /// 142 | // General UI Events - slots - implemented in ui_events.cpp 143 | void recenter_buffer(); 144 | 145 | void link_views_toggle(); 146 | 147 | void rotate_90_cw(); 148 | 149 | void rotate_90_ccw(); 150 | 151 | void buffer_selected(QListWidgetItem* item); 152 | 153 | void remove_selected_buffer(); 154 | 155 | void symbol_selected(); 156 | 157 | void symbol_completed(QString str); 158 | 159 | void export_buffer(); 160 | 161 | void show_context_menu(const QPoint& pos); 162 | 163 | void toggle_go_to_dialog(); 164 | 165 | void go_to_pixel(float x, float y); 166 | 167 | private Q_SLOTS: 168 | /// 169 | // Assorted methods - private slots - implemented in main_window.cpp 170 | void persist_settings(); 171 | 172 | private: 173 | bool is_window_ready_; 174 | bool request_render_update_; 175 | bool completer_updated_; 176 | bool ac_enabled_; 177 | bool link_views_enabled_; 178 | 179 | const int icon_width_base_; 180 | const int icon_height_base_; 181 | 182 | double render_framerate_; 183 | 184 | QTimer settings_persist_timer_; 185 | QTimer update_timer_; 186 | 187 | QString default_export_suffix_; 188 | 189 | Stage* currently_selected_stage_; 190 | 191 | std::map> held_buffers_; 192 | std::map> stages_; 193 | 194 | std::set previous_session_buffers_; 195 | std::set removed_buffer_names_; 196 | 197 | std::deque pending_updates_; 198 | 199 | QStringList available_vars_; 200 | 201 | std::mutex ui_mutex_; 202 | 203 | SymbolCompleter* symbol_completer_; 204 | 205 | Ui::MainWindowUi* ui_; 206 | 207 | QLabel* status_bar_; 208 | GoToWidget* go_to_widget_; 209 | 210 | int (*plot_callback_)(const char*); 211 | 212 | /// 213 | // Assorted methods - private - implemented in main_window.cpp 214 | void update_status_bar(); 215 | 216 | qreal get_screen_dpi_scale(); 217 | 218 | std::string get_type_label(Buffer::BufferType type, int channels); 219 | 220 | void persist_settings_deferred(); 221 | 222 | void set_currently_selected_stage(Stage* stage); 223 | 224 | vec4 get_stage_coordinates(float pos_window_x, float pos_window_y); 225 | 226 | /// 227 | // Auto contrast pane - private - implemented in auto_contrast.cpp 228 | void set_ac_min_value(int idx, float value); 229 | 230 | void set_ac_max_value(int idx, float value); 231 | 232 | /// 233 | // Initialization - private - implemented in initialization.cpp 234 | void initialize_ui_icons(); 235 | 236 | void initialize_timers(); 237 | 238 | void initialize_shortcuts(); 239 | 240 | void initialize_symbol_completer(); 241 | 242 | void initialize_auto_contrast_form(); 243 | 244 | void initialize_toolbar(); 245 | 246 | void initialize_left_pane(); 247 | 248 | void initialize_status_bar(); 249 | 250 | void initialize_visualization_pane(); 251 | 252 | void initialize_settings(); 253 | 254 | void initialize_go_to_widget(); 255 | }; 256 | 257 | #endif // MAIN_WINDOW_H_ 258 | -------------------------------------------------------------------------------- /src/ui/symbol_completer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include "symbol_completer.h" 27 | 28 | 29 | SymbolCompleter::SymbolCompleter(QObject* parent) 30 | : QCompleter(parent) 31 | , list_() 32 | , model_() 33 | { 34 | setModel(&model_); 35 | } 36 | 37 | 38 | void SymbolCompleter::update(const QString& word) 39 | { 40 | QStringList filtered = list_.filter(word, caseSensitivity()); 41 | model_.setStringList(filtered); 42 | word_ = word; 43 | complete(); 44 | } 45 | 46 | 47 | void SymbolCompleter::update_symbol_list(const QStringList& symbols) 48 | { 49 | list_ = symbols; 50 | } 51 | 52 | 53 | const QString& SymbolCompleter::word() const 54 | { 55 | return word_; 56 | } 57 | -------------------------------------------------------------------------------- /src/ui/symbol_completer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef SYMBOL_COMPLETER_H_ 27 | #define SYMBOL_COMPLETER_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | class SymbolCompleter : public QCompleter 35 | { 36 | Q_OBJECT 37 | 38 | public: 39 | SymbolCompleter(QObject* parent = nullptr); 40 | 41 | void update(const QString& word); 42 | 43 | void update_symbol_list(const QStringList& symbols); 44 | 45 | const QString& word() const; 46 | 47 | private: 48 | QStringList list_; 49 | QStringListModel model_; 50 | QString word_; 51 | }; 52 | 53 | 54 | #endif // SYMBOL_COMPLETER_H_ 55 | -------------------------------------------------------------------------------- /src/ui/symbol_search_input.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Advanced search completer based on: 3 | * http://www.qtcentre.org/threads/23518 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "symbol_search_input.h" 10 | 11 | 12 | SymbolSearchInput::SymbolSearchInput(QWidget* parent) 13 | : QLineEdit(parent) 14 | , completer_(nullptr) 15 | { 16 | } 17 | 18 | 19 | SymbolSearchInput::~SymbolSearchInput() 20 | { 21 | } 22 | 23 | 24 | void SymbolSearchInput::set_completer(SymbolCompleter* completer) 25 | { 26 | if (completer_) { 27 | QObject::disconnect(completer_, 0, this, 0); 28 | } 29 | 30 | completer_ = completer; 31 | 32 | if (!completer_) { 33 | return; 34 | } 35 | 36 | completer_->setWidget(this); 37 | connect(completer, 38 | SIGNAL(activated(const QString&)), 39 | this, 40 | SLOT(insert_completion(const QString&))); 41 | } 42 | 43 | 44 | SymbolCompleter* SymbolSearchInput::completer() const 45 | { 46 | return completer_; 47 | } 48 | 49 | 50 | void SymbolSearchInput::insert_completion(const QString& completion) 51 | { 52 | setText(completion); 53 | selectAll(); 54 | } 55 | 56 | 57 | void SymbolSearchInput::keyPressEvent(QKeyEvent* e) 58 | { 59 | // The following keys are forwarded by the completer to the widget 60 | switch (e->key()) { 61 | case Qt::Key_Escape: 62 | clearFocus(); 63 | e->accept(); 64 | return; 65 | case Qt::Key_Tab: 66 | case Qt::Key_Backtab: 67 | case Qt::Key_Enter: 68 | case Qt::Key_Return: 69 | e->ignore(); 70 | return; // Let the completer do default behavior 71 | } 72 | 73 | bool is_shortcut = 74 | (e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E; 75 | if (!is_shortcut) 76 | QLineEdit::keyPressEvent( 77 | e); // Don't send the shortcut (CTRL-E) to the text edit. 78 | 79 | if (!completer_) 80 | return; 81 | 82 | bool ctrl_or_shift = 83 | e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier); 84 | 85 | if (!is_shortcut && !ctrl_or_shift && e->modifiers() != Qt::NoModifier) { 86 | completer_->popup()->hide(); 87 | return; 88 | } 89 | 90 | completer_->update(text()); 91 | completer_->popup()->setCurrentIndex( 92 | completer_->completionModel()->index(0, 0)); 93 | } 94 | -------------------------------------------------------------------------------- /src/ui/symbol_search_input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Advanced search completer based on: 3 | * http://www.qtcentre.org/threads/23518 4 | */ 5 | 6 | #ifndef SYMBOL_SEARCH_INPUT_H_ 7 | #define SYMBOL_SEARCH_INPUT_H_ 8 | 9 | #include 10 | 11 | #include "ui/symbol_completer.h" 12 | 13 | 14 | class SymbolSearchInput : public QLineEdit 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | SymbolSearchInput(QWidget* parent = 0); 20 | ~SymbolSearchInput(); 21 | 22 | void set_completer(SymbolCompleter* completer_); 23 | 24 | SymbolCompleter* completer() const; 25 | 26 | protected: 27 | void keyPressEvent(QKeyEvent* e); 28 | 29 | private Q_SLOTS: 30 | void insert_completion(const QString& completion); 31 | 32 | private: 33 | SymbolCompleter* completer_; 34 | }; 35 | 36 | 37 | #endif // SYMBOL_SEARCH_INPUT_H_ 38 | -------------------------------------------------------------------------------- /src/visualization/components/background.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include "background.h" 27 | 28 | #include "math/linear_algebra.h" 29 | #include "visualization/game_object.h" 30 | #include "visualization/shader.h" 31 | #include "visualization/shaders/giw_shaders.h" 32 | #include "visualization/stage.h" 33 | 34 | 35 | Background::Background(GameObject* game_object, GLCanvas* gl_canvas) 36 | : Component(game_object, gl_canvas) 37 | , background_prog(gl_canvas) 38 | { 39 | } 40 | 41 | 42 | Background::~Background() 43 | { 44 | gl_canvas_->glDeleteBuffers(1, &background_vbo); 45 | } 46 | 47 | 48 | bool Background::initialize() 49 | { 50 | background_prog.create(shader::background_vert_shader, 51 | shader::background_frag_shader, 52 | ShaderProgram::FormatR, 53 | "rgba", 54 | {}); 55 | 56 | // Generate square VBO 57 | // clang-format off 58 | static const GLfloat vertex_buffer_data[] = { 59 | -1, -1, 60 | 1, -1, 61 | 1, 1, 62 | 1, 1, 63 | -1, 1, 64 | -1, -1, 65 | }; 66 | // clang-format on 67 | gl_canvas_->glGenBuffers(1, &background_vbo); 68 | 69 | gl_canvas_->glBindBuffer(GL_ARRAY_BUFFER, background_vbo); 70 | gl_canvas_->glBufferData(GL_ARRAY_BUFFER, 71 | sizeof(vertex_buffer_data), 72 | vertex_buffer_data, 73 | GL_STATIC_DRAW); 74 | 75 | return true; 76 | } 77 | 78 | 79 | void Background::draw(const mat4&, const mat4&) 80 | { 81 | background_prog.use(); 82 | 83 | gl_canvas_->glEnableVertexAttribArray(0); 84 | gl_canvas_->glBindBuffer(GL_ARRAY_BUFFER, background_vbo); 85 | gl_canvas_->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); 86 | gl_canvas_->glDrawArrays(GL_TRIANGLES, 0, 6); 87 | } 88 | 89 | 90 | int Background::render_index() const 91 | { 92 | return -100; 93 | } 94 | -------------------------------------------------------------------------------- /src/visualization/components/background.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef BACKGROUND_H_ 27 | #define BACKGROUND_H_ 28 | 29 | #include "component.h" 30 | #include "visualization/shader.h" 31 | 32 | 33 | class Background : public Component 34 | { 35 | public: 36 | Background(GameObject* game_object, GLCanvas* gl_canvas); 37 | 38 | virtual ~Background(); 39 | 40 | virtual bool initialize(); 41 | 42 | virtual void update() 43 | { 44 | } 45 | 46 | virtual void draw(const mat4& projection, const mat4& view_inv); 47 | 48 | virtual int render_index() const; 49 | 50 | private: 51 | ShaderProgram background_prog; 52 | GLuint background_vbo; 53 | }; 54 | 55 | #endif // BACKGROUND_H_ 56 | -------------------------------------------------------------------------------- /src/visualization/components/buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef BUFFER_H_ 27 | #define BUFFER_H_ 28 | 29 | #include 30 | #include 31 | 32 | #include "component.h" 33 | #include "visualization/shader.h" 34 | 35 | 36 | class Buffer : public Component 37 | { 38 | public: 39 | Buffer(GameObject* game_object, GLCanvas* gl_canvas); 40 | 41 | enum class BufferType { 42 | UnsignedByte = 0, 43 | UnsignedShort = 2, 44 | Short = 3, 45 | Int32 = 4, 46 | Float32 = 5, 47 | Float64 = 6 48 | }; 49 | 50 | const int max_texture_size = 2048; 51 | 52 | std::vector buff_tex; 53 | 54 | static const float no_ac_params[8]; 55 | 56 | float buffer_width_f; 57 | float buffer_height_f; 58 | 59 | int channels; 60 | int step; 61 | 62 | BufferType type; 63 | 64 | uint8_t* buffer; 65 | 66 | bool transpose; 67 | 68 | ~Buffer(); 69 | 70 | bool buffer_update(); 71 | 72 | void recompute_min_color_values(); 73 | 74 | void recompute_max_color_values(); 75 | 76 | void reset_contrast_brightness_parameters(); 77 | 78 | void compute_contrast_brightness_parameters(); 79 | 80 | int sub_texture_id_at_coord(int x, int y); 81 | 82 | void set_pixel_layout(const std::string& pixel_layout); 83 | 84 | const char* get_pixel_layout() const; 85 | 86 | float tile_coord_x(int x); 87 | float tile_coord_y(int y); 88 | 89 | bool initialize(); 90 | 91 | void update(); 92 | 93 | void draw(const mat4& projection, const mat4& viewInv); 94 | 95 | int num_textures_x; 96 | int num_textures_y; 97 | 98 | float* min_buffer_values(); 99 | 100 | float* max_buffer_values(); 101 | 102 | const float* auto_buffer_contrast_brightness() const; 103 | 104 | void set_min_buffer_values(); 105 | void set_max_buffer_values(); 106 | 107 | void get_pixel_info(std::stringstream& output, int x, int y); 108 | 109 | void rotate(float angle); 110 | 111 | private: 112 | void create_shader_program(); 113 | 114 | void setup_gl_buffer(); 115 | 116 | void update_object_pose(); 117 | 118 | char pixel_layout_[4] = {'r', 'g', 'b', 'a'}; 119 | 120 | float min_buffer_values_[4]; 121 | float max_buffer_values_[4]; 122 | float auto_buffer_contrast_brightness_[8] = 123 | {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0}; 124 | float angle_ = 0.f; 125 | 126 | ShaderProgram buff_prog; 127 | GLuint vbo; 128 | }; 129 | 130 | #endif // BUFFER_H_ 131 | -------------------------------------------------------------------------------- /src/visualization/components/buffer_values.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef BUFFER_VALUES_H_ 27 | #define BUFFER_VALUES_H_ 28 | 29 | #include 30 | 31 | #include 32 | 33 | #include "component.h" 34 | #include "ui/gl_text_renderer.h" 35 | 36 | class BufferValues : public Component 37 | { 38 | public: 39 | BufferValues(GameObject* game_object, 40 | GLCanvas* gl_canvas); 41 | 42 | virtual ~BufferValues(); 43 | 44 | virtual void update() 45 | { 46 | } 47 | 48 | virtual int render_index() const; 49 | 50 | virtual void draw(const mat4& projection, const mat4& view_inv); 51 | 52 | private: 53 | float text_pixel_scale = 1.0; 54 | static float constexpr padding = 0.125f; // Must be smaller than 0.5 55 | 56 | void generate_glyphs_texture(); 57 | 58 | void draw_text(const mat4& projection, 59 | const mat4& view_inv, 60 | const mat4& buffer_pose, 61 | const char* text, 62 | float x, 63 | float y, 64 | float y_offset, 65 | float channels); 66 | }; 67 | 68 | #endif // BUFFER_VALUES_H_ 69 | -------------------------------------------------------------------------------- /src/visualization/components/camera.h: -------------------------------------------------------------------------------- 1 | #ifndef CAMERA_H_ 2 | #define CAMERA_H_ 3 | 4 | #include "component.h" 5 | #include "math/linear_algebra.h" 6 | 7 | 8 | class Camera : public Component 9 | { 10 | public: 11 | Camera(GameObject* game_object, GLCanvas* gl_canvas); 12 | 13 | static constexpr float zoom_factor = 1.1; 14 | mat4 projection; 15 | 16 | vec4 mouse_position = vec4::zero(); 17 | 18 | Camera& operator=(const Camera& cam); 19 | 20 | virtual void update(); 21 | 22 | virtual void draw(const mat4&, const mat4&) 23 | { 24 | } 25 | 26 | virtual bool post_buffer_update(); 27 | 28 | virtual bool post_initialize(); 29 | 30 | virtual EventProcessCode key_press_event(int key_code); 31 | 32 | void window_resized(int w, int h); 33 | 34 | void scroll_callback(float delta); 35 | 36 | void recenter_camera(); 37 | 38 | void mouse_drag_event(int mouse_x, int mouse_y); 39 | 40 | float compute_zoom(); 41 | 42 | void move_to(float x, float y); 43 | 44 | vec4 get_position(); 45 | 46 | private: 47 | void update_object_pose(); 48 | 49 | void scale_at(const vec4& center_ndc, float delta); 50 | 51 | void set_initial_zoom(); 52 | 53 | void handle_key_events(); 54 | 55 | float zoom_power_ = 0.0f; 56 | float camera_pos_x_ = 0.0f; 57 | float camera_pos_y_ = 0.0f; 58 | 59 | int canvas_width_; 60 | int canvas_height_; 61 | 62 | mat4 scale_; 63 | }; 64 | 65 | #endif // CAMERA_H_ 66 | -------------------------------------------------------------------------------- /src/visualization/components/component.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include "component.h" 27 | 28 | 29 | Component::Component(GameObject* game_object, GLCanvas* gl_canvas) 30 | : game_object_(game_object) 31 | , gl_canvas_(gl_canvas) 32 | { 33 | } 34 | 35 | 36 | Component::~Component() 37 | { 38 | } 39 | 40 | 41 | bool Component::initialize() 42 | { 43 | return true; 44 | } 45 | 46 | 47 | bool Component::buffer_update() 48 | { 49 | return true; 50 | } 51 | 52 | 53 | bool Component::post_buffer_update() 54 | { 55 | return true; 56 | } 57 | 58 | 59 | int Component::render_index() const 60 | { 61 | return 0; 62 | } 63 | 64 | 65 | 66 | 67 | 68 | bool Component::post_initialize() 69 | { 70 | return true; 71 | } 72 | -------------------------------------------------------------------------------- /src/visualization/components/component.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef COMPONENT_H_ 27 | #define COMPONENT_H_ 28 | 29 | #include "src/visualization/events.h" 30 | 31 | class GameObject; 32 | class GLCanvas; 33 | class mat4; 34 | 35 | 36 | class Component 37 | { 38 | public: 39 | Component(GameObject* game_object, GLCanvas* gl_canvas); 40 | 41 | virtual bool initialize(); 42 | 43 | virtual bool buffer_update(); 44 | 45 | virtual bool post_buffer_update(); 46 | 47 | virtual int render_index() const; 48 | 49 | // Called after all components are initialized 50 | virtual bool post_initialize(); 51 | 52 | virtual void update() = 0; 53 | 54 | virtual void draw(const mat4& projection, const mat4& viewInv) = 0; 55 | 56 | /// 57 | // Events 58 | virtual EventProcessCode key_press_event(int /* key_code */) 59 | { 60 | return EventProcessCode::IGNORED; 61 | } 62 | 63 | virtual void mouse_drag_event(int /* mouse_x */, int /* mouse_y */) 64 | { 65 | } 66 | 67 | virtual void mouse_move_event(int /* mouse_x */, int /* mouse_y */) 68 | { 69 | } 70 | 71 | virtual ~Component(); 72 | 73 | protected: 74 | GameObject* game_object_; 75 | 76 | GLCanvas* gl_canvas_; 77 | }; 78 | 79 | #endif // COMPONENT_H_ 80 | -------------------------------------------------------------------------------- /src/visualization/events.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "events.h" 7 | 8 | 9 | std::set KeyboardState::pressed_keys_; 10 | 11 | 12 | bool KeyboardState::is_modifier_key_pressed(ModifierKey key) 13 | { 14 | switch (key) { 15 | case ModifierKey::Alt: 16 | return (QApplication::keyboardModifiers() & Qt::AltModifier) != 0; 17 | case ModifierKey::Control: 18 | return (QApplication::keyboardModifiers() & Qt::ControlModifier) != 0; 19 | case ModifierKey::Shift: 20 | return (QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0; 21 | default: 22 | assert(!"Invalid modifier key"); 23 | return false; 24 | } 25 | } 26 | 27 | 28 | bool KeyboardState::is_key_pressed(Key key) 29 | { 30 | switch (key) { 31 | case Key::Left: 32 | return pressed_keys_.find(Qt::Key_Left) != pressed_keys_.end(); 33 | case Key::Right: 34 | return pressed_keys_.find(Qt::Key_Right) != pressed_keys_.end(); 35 | case Key::Up: 36 | return pressed_keys_.find(Qt::Key_Up) != pressed_keys_.end(); 37 | case Key::Down: 38 | return pressed_keys_.find(Qt::Key_Down) != pressed_keys_.end(); 39 | case Key::Plus: 40 | return pressed_keys_.find(Qt::Key_Plus) != pressed_keys_.end(); 41 | case Key::Minus: 42 | return pressed_keys_.find(Qt::Key_Minus) != pressed_keys_.end(); 43 | default: 44 | assert(!"Invalid key requested"); 45 | return false; 46 | } 47 | } 48 | 49 | 50 | void KeyboardState::update_keyboard_state(const QEvent* event) 51 | { 52 | if (event->type() == QEvent::KeyPress) { 53 | pressed_keys_.insert(static_cast(event)->key()); 54 | } else if (event->type() == QEvent::KeyRelease) { 55 | pressed_keys_.erase(static_cast(event)->key()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/visualization/events.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef EVENTS_H_ 27 | #define EVENTS_H_ 28 | 29 | #include 30 | 31 | enum class EventProcessCode { IGNORED, INTERCEPTED }; 32 | 33 | class MainWindow; 34 | class QEvent; 35 | 36 | class KeyboardState 37 | { 38 | public: 39 | friend class MainWindow; 40 | 41 | enum class ModifierKey { Control, Alt, Shift }; 42 | enum class Key { Left, Right, Up, Down, Plus, Minus }; 43 | 44 | static bool is_modifier_key_pressed(ModifierKey key); 45 | 46 | static bool is_key_pressed(Key key); 47 | 48 | private: 49 | static void update_keyboard_state(const QEvent* event); 50 | 51 | static std::set pressed_keys_; 52 | }; 53 | 54 | #endif // EVENTS_H_ 55 | -------------------------------------------------------------------------------- /src/visualization/game_object.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "game_object.h" 30 | 31 | #include "ui/main_window/main_window.h" 32 | #include "visualization/components/camera.h" 33 | #include "visualization/components/component.h" 34 | #include "visualization/stage.h" 35 | 36 | 37 | GameObject::GameObject() 38 | { 39 | pose_.set_identity(); 40 | } 41 | 42 | 43 | bool GameObject::initialize() 44 | { 45 | for (const auto& comp : all_components_) { 46 | if (!comp.second->initialize()) { 47 | return false; 48 | } 49 | } 50 | return true; 51 | } 52 | 53 | 54 | bool GameObject::post_initialize() 55 | { 56 | for (const auto& comp : all_components_) { 57 | if (!comp.second->post_initialize()) { 58 | return false; 59 | } 60 | } 61 | return true; 62 | } 63 | 64 | 65 | void GameObject::update() 66 | { 67 | for (const auto& comp : all_components_) { 68 | comp.second->update(); 69 | } 70 | } 71 | 72 | void GameObject::add_component(const std::string& component_name, 73 | std::shared_ptr component) 74 | { 75 | all_components_[component_name] = component; 76 | } 77 | 78 | 79 | mat4 GameObject::get_pose() 80 | { 81 | return pose_; 82 | } 83 | 84 | 85 | void GameObject::set_pose(const mat4& pose) 86 | { 87 | pose_ = pose; 88 | } 89 | 90 | 91 | void GameObject::request_render_update() 92 | { 93 | stage->main_window->request_render_update(); 94 | } 95 | 96 | 97 | void GameObject::mouse_drag_event(int mouse_x, int mouse_y) 98 | { 99 | for (const auto& comp : all_components_) { 100 | comp.second->mouse_drag_event(mouse_x, mouse_y); 101 | } 102 | } 103 | 104 | 105 | void GameObject::mouse_move_event(int mouse_x, int mouse_y) 106 | { 107 | for (const auto& comp : all_components_) { 108 | comp.second->mouse_move_event(mouse_x, mouse_y); 109 | } 110 | } 111 | 112 | 113 | EventProcessCode GameObject::key_press_event(int key_code) 114 | { 115 | EventProcessCode event_intercepted = EventProcessCode::IGNORED; 116 | 117 | for (const auto& comp : all_components_) { 118 | EventProcessCode event_intercepted_component = 119 | comp.second->key_press_event(key_code); 120 | 121 | if (event_intercepted_component == EventProcessCode::INTERCEPTED) { 122 | event_intercepted = EventProcessCode::INTERCEPTED; 123 | } 124 | } 125 | 126 | return event_intercepted; 127 | } 128 | 129 | 130 | const std::map>& 131 | GameObject::get_components() 132 | { 133 | return all_components_; 134 | } 135 | -------------------------------------------------------------------------------- /src/visualization/game_object.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef GAME_OBJECT_H_ 27 | #define GAME_OBJECT_H_ 28 | 29 | #include 30 | 31 | #include "events.h" 32 | #include "math/linear_algebra.h" 33 | 34 | 35 | class GLCanvas; 36 | class Stage; 37 | class Component; 38 | 39 | 40 | class GameObject 41 | { 42 | public: 43 | Stage* stage; 44 | 45 | GameObject(); 46 | 47 | template 48 | T* get_component(std::string tag) 49 | { 50 | if (all_components_.find(tag) == all_components_.end()) 51 | return nullptr; 52 | return dynamic_cast(all_components_[tag].get()); 53 | } 54 | 55 | bool initialize(); 56 | 57 | bool post_initialize(); 58 | 59 | void update(); 60 | 61 | void add_component(const std::string& component_name, 62 | std::shared_ptr component); 63 | 64 | mat4 get_pose(); 65 | 66 | void set_pose(const mat4& pose); 67 | 68 | void request_render_update(); 69 | 70 | void mouse_drag_event(int mouse_x, int mouse_y); 71 | 72 | void mouse_move_event(int mouse_x, int mouse_y); 73 | 74 | EventProcessCode key_press_event(int key_code); 75 | 76 | const std::map>& get_components(); 77 | 78 | private: 79 | std::map> all_components_; 80 | mat4 pose_; 81 | }; 82 | 83 | #endif // GAME_OBJECT_H_ 84 | -------------------------------------------------------------------------------- /src/visualization/shader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include "shader.h" 29 | 30 | 31 | ShaderProgram::ShaderProgram(GLCanvas* gl_canvas) 32 | : program_(0) 33 | , gl_canvas_(gl_canvas) 34 | { 35 | } 36 | 37 | 38 | ShaderProgram::~ShaderProgram() 39 | { 40 | gl_canvas_->glDeleteProgram(program_); 41 | } 42 | 43 | 44 | bool ShaderProgram::is_shader_outdated(TexelChannels texel_format, 45 | const std::vector& uniforms, 46 | const char* pixel_layout) 47 | { 48 | // If the texel format or the uniform container size changed, 49 | // the program must be created again 50 | if (texel_format != texel_format_ || uniforms.size() != uniforms_.size()) { 51 | return true; 52 | } 53 | 54 | // The program must also be created again if an uniform name 55 | // changed 56 | for (const auto& uniform_name : uniforms) { 57 | if (uniforms_.find(uniform_name) == uniforms_.end()) { 58 | return true; 59 | } 60 | } 61 | 62 | for (int i = 0; i < 4; ++i) { 63 | if (pixel_layout[i] != pixel_layout_[i]) { 64 | return true; 65 | } 66 | } 67 | 68 | // Otherwise, it must not change 69 | return false; 70 | } 71 | 72 | bool ShaderProgram::create(const char* v_source, 73 | const char* f_source, 74 | TexelChannels texel_format, 75 | const char* pixel_layout, 76 | const std::vector& uniforms) 77 | { 78 | if (program_ != 0) { 79 | // Check if the program needs to be recompiled 80 | if (!is_shader_outdated(texel_format, uniforms, pixel_layout)) { 81 | return true; 82 | } 83 | // Delete old program 84 | gl_canvas_->glDeleteProgram(program_); 85 | } 86 | 87 | texel_format_ = texel_format; 88 | memcpy(pixel_layout_, pixel_layout, 4); 89 | pixel_layout_[4] = '\0'; 90 | GLuint vertex_shader = compile(GL_VERTEX_SHADER, v_source); 91 | GLuint fragment_shader = compile(GL_FRAGMENT_SHADER, f_source); 92 | 93 | if (vertex_shader == 0 || fragment_shader == 0) { 94 | return false; 95 | } 96 | 97 | program_ = gl_canvas_->glCreateProgram(); 98 | gl_canvas_->glAttachShader(program_, vertex_shader); 99 | gl_canvas_->glAttachShader(program_, fragment_shader); 100 | gl_canvas_->glLinkProgram(program_); 101 | 102 | // Delete shaders. We don't need them anymore. 103 | gl_canvas_->glDeleteShader(vertex_shader); 104 | gl_canvas_->glDeleteShader(fragment_shader); 105 | 106 | // Get uniform locations 107 | for (const auto& name : uniforms) { 108 | GLuint loc = gl_canvas_->glGetUniformLocation(program_, name.c_str()); 109 | uniforms_[name] = loc; 110 | } 111 | 112 | return true; 113 | } 114 | 115 | 116 | void ShaderProgram::uniform1i(const std::string& name, int value) const 117 | { 118 | gl_canvas_->glUniform1i(uniforms_.at(name), value); 119 | } 120 | 121 | 122 | void ShaderProgram::uniform2f(const std::string& name, float x, float y) const 123 | { 124 | gl_canvas_->glUniform2f(uniforms_.at(name), x, y); 125 | } 126 | 127 | 128 | void ShaderProgram::uniform3fv(const std::string& name, 129 | int count, 130 | const float* data) const 131 | { 132 | gl_canvas_->glUniform3fv(uniforms_.at(name), count, data); 133 | } 134 | 135 | 136 | void ShaderProgram::uniform4fv(const std::string& name, 137 | int count, 138 | const float* data) const 139 | { 140 | gl_canvas_->glUniform4fv(uniforms_.at(name), count, data); 141 | } 142 | 143 | 144 | void ShaderProgram::uniform_matrix4fv(const std::string& name, 145 | int count, 146 | GLboolean transpose, 147 | const float* value) const 148 | { 149 | gl_canvas_->glUniformMatrix4fv(uniforms_.at(name), count, transpose, value); 150 | } 151 | 152 | 153 | void ShaderProgram::use() const 154 | { 155 | gl_canvas_->glUseProgram(program_); 156 | } 157 | 158 | 159 | GLuint ShaderProgram::compile(GLuint type, GLchar const* source) 160 | { 161 | GLuint shader = gl_canvas_->glCreateShader(type); 162 | 163 | const char* src[] = { 164 | "#version 120\n", 165 | 166 | // clang-format off 167 | texel_format_ == FormatR ? "#define FORMAT_R\n" : 168 | texel_format_ == FormatRG ? "#define FORMAT_RG\n" : 169 | texel_format_ == FormatRGB ? "#define FORMAT_RGB\n" : 170 | "", 171 | // clang-format on 172 | 173 | "#define PIXEL_LAYOUT ", 174 | pixel_layout_, 175 | 176 | source}; 177 | 178 | gl_canvas_->glShaderSource(shader, 5, src, NULL); 179 | gl_canvas_->glCompileShader(shader); 180 | 181 | GLint compiled; 182 | gl_canvas_->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 183 | 184 | if (!compiled) { 185 | GLint length; 186 | gl_canvas_->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); 187 | std::string log(length, ' '); 188 | gl_canvas_->glGetShaderInfoLog(shader, length, &length, &log[0]); 189 | std::cerr << "Failed to compile shadertype: " + get_shader_type(type) 190 | << std::endl 191 | << log << std::endl; 192 | return false; 193 | } 194 | return shader; 195 | } 196 | 197 | 198 | std::string ShaderProgram::get_shader_type(GLuint type) 199 | { 200 | std::string name; 201 | switch (type) { 202 | case GL_VERTEX_SHADER: 203 | name = "Vertex Shader"; 204 | break; 205 | case GL_FRAGMENT_SHADER: 206 | name = "Fragment Shader"; 207 | break; 208 | default: 209 | name = "Unknown Shader type"; 210 | break; 211 | } 212 | return name; 213 | } 214 | -------------------------------------------------------------------------------- /src/visualization/shader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef SHADER_H_ 27 | #define SHADER_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "GL/gl.h" 35 | 36 | #include "ui/gl_canvas.h" 37 | 38 | 39 | class ShaderProgram 40 | { 41 | public: 42 | enum TexelChannels { FormatR, FormatRG, FormatRGB, FormatRGBA }; 43 | 44 | ShaderProgram(GLCanvas* gl_canvas); 45 | 46 | ~ShaderProgram(); 47 | 48 | bool create(const char* v_source, 49 | const char* f_source, 50 | TexelChannels texel_format, 51 | const char* pixel_layout, 52 | const std::vector& uniforms); 53 | 54 | // Uniform handlers 55 | void uniform1i(const std::string& name, int value) const; 56 | 57 | void uniform2f(const std::string& name, float x, float y) const; 58 | 59 | void 60 | uniform3fv(const std::string& name, int count, const float* data) const; 61 | 62 | void 63 | uniform4fv(const std::string& name, int count, const float* data) const; 64 | 65 | void uniform_matrix4fv(const std::string& name, 66 | int count, 67 | GLboolean transpose, 68 | const float* value) const; 69 | 70 | // Program utility 71 | void use() const; 72 | 73 | private: 74 | GLuint program_; 75 | 76 | GLCanvas* gl_canvas_; 77 | 78 | TexelChannels texel_format_; 79 | 80 | std::map uniforms_; 81 | 82 | char pixel_layout_[5]; 83 | 84 | GLuint compile(GLuint type, GLchar const* source); 85 | 86 | std::string get_shader_type(GLuint type); 87 | 88 | bool is_shader_outdated(TexelChannels texel_format, 89 | const std::vector& uniforms, 90 | const char* pixel_layout); 91 | }; 92 | 93 | #endif // SHADER_H_ 94 | -------------------------------------------------------------------------------- /src/visualization/shaders/background_fs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | namespace shader 27 | { 28 | 29 | const char* background_frag_shader = R"( 30 | 31 | void main() 32 | { 33 | const int tile_size = 10; 34 | float intensity = mod(floor(gl_FragCoord.x / tile_size) + 35 | floor(gl_FragCoord.y / tile_size), 2); 36 | intensity = intensity * 0.2 + 0.4; 37 | gl_FragColor = vec4(vec3(intensity), 1); 38 | } 39 | 40 | )"; 41 | 42 | } // namespace shader 43 | -------------------------------------------------------------------------------- /src/visualization/shaders/background_vs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | namespace shader 27 | { 28 | 29 | const char* background_vert_shader = R"( 30 | 31 | attribute vec2 input_position; 32 | 33 | void main(void) { 34 | gl_Position = vec4(input_position, 0.0, 1.0); 35 | } 36 | 37 | )"; 38 | 39 | } // namespace shader 40 | -------------------------------------------------------------------------------- /src/visualization/shaders/buffer_fs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | namespace shader 27 | { 28 | 29 | const char* buff_frag_shader = R"( 30 | 31 | uniform sampler2D sampler; 32 | uniform vec4 brightness_contrast[2]; 33 | uniform vec2 buffer_dimension; 34 | uniform int enable_borders; 35 | 36 | // Ouput data 37 | varying vec2 uv; 38 | 39 | void main() 40 | { 41 | vec4 color; 42 | 43 | #if defined(FORMAT_R) 44 | // Output color = grayscale 45 | color = texture2D(sampler, uv).rrra; 46 | color.rgb = color.rgb * brightness_contrast[0].xxx + 47 | brightness_contrast[1].xxx; 48 | #elif defined(FORMAT_RG) 49 | // Output color = two channels 50 | color = texture2D(sampler, uv); 51 | color.rg = color.rg * brightness_contrast[0].xy + 52 | brightness_contrast[1].xy; 53 | color.b = 0.0; 54 | #elif defined(FORMAT_RGB) 55 | // Output color = rgb 56 | color = texture2D(sampler, uv); 57 | color.rgb = color.rgb * brightness_contrast[0].xyz + 58 | brightness_contrast[1].xyz; 59 | #else 60 | // Output color = rgba 61 | color = texture2D(sampler, uv); 62 | color = color * brightness_contrast[0] + 63 | brightness_contrast[1]; 64 | #endif 65 | 66 | vec2 buffer_position = uv * buffer_dimension; 67 | 68 | if(enable_borders == 1) { 69 | float alpha = max(abs(dFdx(buffer_position.x)), 70 | abs(dFdx(buffer_position.y))); 71 | 72 | float x_ = fract(buffer_position.x); 73 | float y_ = fract(buffer_position.y); 74 | 75 | float vertical_border = clamp(abs(-1.0 / alpha * x_ + 0.5 / alpha) - 76 | (0.5 / alpha - 1.0), 0.0, 1.0); 77 | 78 | float horizontal_border = clamp(abs(-1.0 / alpha * y_ + 0.5 / alpha) - 79 | (0.5 / alpha - 1.0), 0.0, 1.0); 80 | 81 | color.rgb += vec3(vertical_border + 82 | horizontal_border); 83 | } 84 | 85 | gl_FragColor = color.PIXEL_LAYOUT; 86 | } 87 | 88 | )"; 89 | 90 | } // namespace shader 91 | -------------------------------------------------------------------------------- /src/visualization/shaders/buffer_vs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | namespace shader 27 | { 28 | 29 | const char* buff_vert_shader = R"( 30 | 31 | attribute vec2 input_position; 32 | varying vec2 uv; 33 | 34 | uniform mat4 mvp; 35 | 36 | void main(void) { 37 | uv = input_position + vec2(0.5, 0.5); 38 | gl_Position = mvp*vec4(input_position, 0.0, 1.0); 39 | } 40 | 41 | )"; 42 | 43 | } // namespace shader 44 | -------------------------------------------------------------------------------- /src/visualization/shaders/giw_shaders.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef GIW_SHADERS_H_ 27 | #define GIW_SHADERS_H_ 28 | 29 | 30 | namespace shader 31 | { 32 | 33 | extern const char* buff_frag_shader; 34 | extern const char* buff_vert_shader; 35 | extern const char* text_frag_shader; 36 | extern const char* text_vert_shader; 37 | extern const char* background_vert_shader; 38 | extern const char* background_frag_shader; 39 | 40 | } // namespace shader 41 | 42 | #endif // GIW_SHADERS_H_ 43 | -------------------------------------------------------------------------------- /src/visualization/shaders/text_fs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | namespace shader 27 | { 28 | 29 | const char* text_frag_shader = R"( 30 | 31 | uniform sampler2D buff_sampler; 32 | uniform sampler2D text_sampler; 33 | uniform vec2 pix_coord; 34 | uniform vec4 brightness_contrast[2]; 35 | 36 | 37 | // Ouput data 38 | varying vec2 uv; 39 | 40 | 41 | float round_float(float f) { 42 | return float(int(f + 0.5)); 43 | } 44 | 45 | 46 | bool giw_isnan(float val) { 47 | return (val < 0.0 || 0.0 < val || val == 0.0) ? false : true; 48 | } 49 | 50 | 51 | void main() 52 | { 53 | vec4 color; 54 | // Output color = red 55 | float buff_color = texture2D(buff_sampler, pix_coord).r; 56 | buff_color = buff_color * brightness_contrast[0].x + 57 | brightness_contrast[1].x; 58 | 59 | if (giw_isnan(buff_color)) { 60 | buff_color = 0.0; 61 | } 62 | 63 | float text_color = texture2D(text_sampler, uv).r; 64 | float pix_intensity = round_float(1.0 - buff_color); 65 | 66 | color = vec4(vec3(pix_intensity), text_color); 67 | 68 | gl_FragColor = color; 69 | } 70 | 71 | )"; 72 | 73 | } // namespace shader 74 | -------------------------------------------------------------------------------- /src/visualization/shaders/text_vs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | namespace shader 27 | { 28 | 29 | const char* text_vert_shader = R"( 30 | 31 | attribute vec4 input_position; 32 | varying vec2 uv; 33 | 34 | uniform mat4 mvp; 35 | 36 | void main(void) { 37 | gl_Position = mvp * vec4(input_position.xy, 0.0, 1.0); 38 | uv = input_position.zw; 39 | } 40 | 41 | )"; 42 | 43 | } // namespace shader 44 | -------------------------------------------------------------------------------- /src/visualization/stage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2017 GDB ImageWatch contributors 5 | * (github.com/csantosbh/gdb-imagewatch/) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to 9 | * deal in the Software without restriction, including without limitation the 10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | * sell copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | * IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef STAGE_H_ 27 | #define STAGE_H_ 28 | 29 | #include 30 | #include 31 | 32 | #include "visualization/components/buffer.h" 33 | 34 | 35 | class GameObject; 36 | 37 | 38 | class Stage 39 | { 40 | public: 41 | bool contrast_enabled; 42 | std::vector buffer_icon; 43 | MainWindow* main_window; 44 | 45 | Stage(MainWindow* main_window); 46 | 47 | bool initialize(uint8_t* buffer, 48 | int buffer_width_i, 49 | int buffer_height_i, 50 | int channels, 51 | Buffer::BufferType type, 52 | int step, 53 | const std::string& pixel_layout, 54 | bool transpose_buffer); 55 | 56 | bool buffer_update(uint8_t* buffer, 57 | int buffer_width_i, 58 | int buffer_height_i, 59 | int channels, 60 | Buffer::BufferType type, 61 | int step, 62 | const std::string& pixel_layout, 63 | bool transpose_buffer); 64 | 65 | GameObject* get_game_object(std::string tag); 66 | 67 | void update(); 68 | 69 | void draw(); 70 | 71 | void scroll_callback(float delta); 72 | 73 | void resize_callback(int w, int h); 74 | 75 | void mouse_drag_event(int mouse_x, int mouse_y); 76 | 77 | void mouse_move_event(int mouse_x, int mouse_y); 78 | 79 | EventProcessCode key_press_event(int key_code); 80 | 81 | void go_to_pixel(float x, float y); 82 | 83 | private: 84 | std::map> all_game_objects; 85 | }; 86 | 87 | #endif // STAGE_H_ 88 | -------------------------------------------------------------------------------- /testbench/testbench.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++11 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | LIBS += -lpthread 6 | 7 | SOURCES += main.cpp 8 | --------------------------------------------------------------------------------