diff options
Diffstat (limited to 'third_party/webrender/debugger/src')
12 files changed, 630 insertions, 0 deletions
diff --git a/third_party/webrender/debugger/src/App.vue b/third_party/webrender/debugger/src/App.vue new file mode 100644 index 00000000000..01d303e79e5 --- /dev/null +++ b/third_party/webrender/debugger/src/App.vue @@ -0,0 +1,55 @@ +<template> + <div> + <app-navbar></app-navbar> + <div class="section"> + <div class="container"> + <div class="columns"> + <div class="column is-3"> + <app-navmenu></app-navmenu> + </div> + <div class="column"> + <app-options v-if="page == 'options'"></app-options> + <app-passview v-if="page == 'passes'"></app-passview> + <app-rendertaskview v-if="page == 'render_tasks'"></app-rendertaskview> + <app-documentview v-if="page == 'documents'"></app-documentview> + <app-clipscrolltreeview v-if="page == 'clip_scroll_tree'"></app-clipscrolltreeview> + <app-screenshotview v-if="page == 'screenshot'"></app-screenshotview> + </div> + </div> + </div> + </div> + </div> +</template> + +<script> +import NavBar from './components/NavBar.vue' +import NavMenu from './components/NavMenu.vue' +import OptionsPage from './components/OptionsPage.vue' +import PassViewPage from './components/PassViewPage.vue' +import RenderTaskViewPage from './components/RenderTaskViewPage.vue' +import DocumentViewPage from './components/DocumentViewPage.vue' +import ClipScrollTreeViewPage from './components/ClipScrollTreeViewPage.vue' +import ScreenshotPage from './components/ScreenshotPage.vue' + +export default { + name: 'app', + components: { + 'app-navbar': NavBar, + 'app-navmenu': NavMenu, + 'app-options': OptionsPage, + 'app-passview': PassViewPage, + 'app-rendertaskview': RenderTaskViewPage, + 'app-documentview': DocumentViewPage, + 'app-clipscrolltreeview': ClipScrollTreeViewPage, + 'app-screenshotview': ScreenshotPage, + }, + computed: { + page() { + return this.$store.state.page; + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/ClipScrollTreeViewPage.vue b/third_party/webrender/debugger/src/components/ClipScrollTreeViewPage.vue new file mode 100644 index 00000000000..66a1edaf304 --- /dev/null +++ b/third_party/webrender/debugger/src/components/ClipScrollTreeViewPage.vue @@ -0,0 +1,37 @@ +<template> + <div class="box"> + <h1 class="title">Clip-Scroll Tree <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1> + <hr/> + <div> + <ul> + <app-treeview :model=clip_scroll_tree></app-treeview> + </ul> + </div> + </div> +</template> + +<script> +import TreeView from './TreeView.vue' + +export default { + components: { + 'app-treeview': TreeView, + }, + methods: { + fetch: function() { + this.$store.dispatch('sendMessage', "fetch_clip_scroll_tree"); + } + }, + computed: { + disabled() { + return !this.$store.state.connected + }, + clip_scroll_tree() { + return this.$store.state.clip_scroll_tree + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/DocumentViewPage.vue b/third_party/webrender/debugger/src/components/DocumentViewPage.vue new file mode 100644 index 00000000000..6d5f02da735 --- /dev/null +++ b/third_party/webrender/debugger/src/components/DocumentViewPage.vue @@ -0,0 +1,37 @@ +<template> + <div class="box"> + <h1 class="title">Documents <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1> + <hr/> + <div> + <ul> + <app-treeview :model=documents></app-treeview> + </ul> + </div> + </div> +</template> + +<script> +import TreeView from './TreeView.vue' + +export default { + components: { + 'app-treeview': TreeView, + }, + methods: { + fetch: function() { + this.$store.dispatch('sendMessage', "fetch_documents"); + } + }, + computed: { + disabled() { + return !this.$store.state.connected + }, + documents() { + return this.$store.state.documents + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/NavBar.vue b/third_party/webrender/debugger/src/components/NavBar.vue new file mode 100644 index 00000000000..2f8008d67d4 --- /dev/null +++ b/third_party/webrender/debugger/src/components/NavBar.vue @@ -0,0 +1,41 @@ +<template> + <nav class="navbar has-shadow"> + <div class="navbar-brand"> + <a class="navbar-item" href="#">WebRender Debugger</a> + </div> + + <div class="navbar-menu"> + <div class="navbar-start"></div> + + <div class="navbar-end"> + <div class="navbar-item"> + <p class="control"> + <button v-if="isConnected" @click="disconnect" class="button is-danger">Disconnect</button> + <button v-else @click="connect" class="button is-success">Connect</button> + </p> + </div> + </div> + </div> + </nav> +</template> + +<script> +export default { + computed: { + isConnected() { + return this.$store.state.connected; + }, + }, + methods: { + connect() { + this.$store.dispatch('connect'); + }, + disconnect() { + this.$store.dispatch('disconnect'); + }, + } +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/NavMenu.vue b/third_party/webrender/debugger/src/components/NavMenu.vue new file mode 100644 index 00000000000..5a7cc3512a4 --- /dev/null +++ b/third_party/webrender/debugger/src/components/NavMenu.vue @@ -0,0 +1,33 @@ +<template> + <aside class="menu"> + <p class="menu-label"> + Pages + </p> + <ul class="menu-list"> + <li><a @click="setPage('options')" :class="{ 'is-active': page == 'options' }">Debug Options</a></li> + <li><a @click="setPage('passes')" :class="{ 'is-active': page == 'passes' }">Passes</a></li> + <li><a @click="setPage('render_tasks')" :class="{ 'is-active': page == 'render_tasks' }">Render Tasks</a></li> + <li><a @click="setPage('documents')" :class="{ 'is-active': page == 'documents' }">Documents</a></li> + <li><a @click="setPage('clip_scroll_tree')" v-bind:class="{ 'is-active': page == 'clip_scroll_tree' }">Clip-Scroll Tree</a></li> + <li><a @click="setPage('screenshot')" v-bind:class="{ 'is-active': page == 'screenshot' }">Screenshot</a></li> + </ul> + </aside> +</template> + +<script> +export default { + methods: { + setPage(name) { + this.$store.commit('setPage', name); + }, + }, + computed: { + page() { + return this.$store.state.page; + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/OptionsPage.vue b/third_party/webrender/debugger/src/components/OptionsPage.vue new file mode 100644 index 00000000000..fd8288c42cc --- /dev/null +++ b/third_party/webrender/debugger/src/components/OptionsPage.vue @@ -0,0 +1,162 @@ +<template> + <div class="box"> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setProfiler($event.target.checked)"> + Profiler + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setTextureCacheDebugger($event.target.checked)"> + Texture cache debugger + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setRenderTargetDebugger($event.target.checked)"> + Render target debugger + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setAlphaRectsDebugger($event.target.checked)"> + Alpha primitive rects debugger + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setGpuTimeQueries($event.target.checked)"> + Enable GPU time queries + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setGpuSampleQueries($event.target.checked)"> + Enable GPU sample queries + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setOpaquePass(!$event.target.checked)"> + Disable opaque pass + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setAlphaPass(!$event.target.checked)"> + Disable alpha pass + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setClipMasks(!$event.target.checked)"> + Disable clip masks + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setTextPrims(!$event.target.checked)"> + Disable text primitives + </label> + </div> + <div class="field"> + <label class="checkbox"> + <input type="checkbox" :disabled="disabled" v-on:click="setGradientPrims(!$event.target.checked)"> + Disable gradient primitives + </label> + </div> + </div> +</template> + +<script> +export default { + computed: { + disabled() { + return !this.$store.state.connected + } + }, + methods: { + setProfiler(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_profiler"); + } else { + this.$store.dispatch('sendMessage', "disable_profiler"); + } + }, + setTextureCacheDebugger(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_texture_cache_debug"); + } else { + this.$store.dispatch('sendMessage', "disable_texture_cache_debug"); + } + }, + setRenderTargetDebugger(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_render_target_debug"); + } else { + this.$store.dispatch('sendMessage', "disable_render_target_debug"); + } + }, + setAlphaRectsDebugger(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_alpha_rects_debug"); + } else { + this.$store.dispatch('sendMessage', "disable_alpha_rects_debug"); + } + }, + setGpuTimeQueries(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_gpu_time_queries"); + } else { + this.$store.dispatch('sendMessage', "disable_gpu_time_queries"); + } + }, + setGpuSampleQueries(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_gpu_sample_queries"); + } else { + this.$store.dispatch('sendMessage', "disable_gpu_sample_queries"); + } + }, + setOpaquePass(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_opaque_pass"); + } else { + this.$store.dispatch('sendMessage', "disable_opaque_pass"); + } + }, + setAlphaPass(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_alpha_pass"); + } else { + this.$store.dispatch('sendMessage', "disable_alpha_pass"); + } + }, + setClipMasks(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_clip_masks"); + } else { + this.$store.dispatch('sendMessage', "disable_clip_masks"); + } + }, + setTextPrims(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_text_prims"); + } else { + this.$store.dispatch('sendMessage', "disable_text_prims"); + } + }, + setGradientPrims(enabled) { + if (enabled) { + this.$store.dispatch('sendMessage', "enable_gradient_prims"); + } else { + this.$store.dispatch('sendMessage', "disable_gradient_prims"); + } + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/PassViewPage.vue b/third_party/webrender/debugger/src/components/PassViewPage.vue new file mode 100644 index 00000000000..0ab6d7c4464 --- /dev/null +++ b/third_party/webrender/debugger/src/components/PassViewPage.vue @@ -0,0 +1,37 @@ +<template> + <div class="box"> + <h1 class="title">Passes <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1> + <hr/> + <div v-for="(pass, pass_index) in passes"> + <p class="has-text-black-bis">Pass {{pass_index}}</p> + <div v-for="(target, target_index) in pass.targets"> + <p style="text-indent: 2em;" class="has-text-grey-dark">Target {{target_index}} ({{target.kind}})</p> + <div v-for="(batch, batch_index) in target.batches"> + <p style="text-indent: 4em;" class="has-text-grey">Batch {{batch_index}} ({{batch.description}}, {{batch.kind}}, {{batch.count}} instances)</p> + </div> + </div> + <hr/> + </div> + </div> +</template> + +<script> +export default { + methods: { + fetch: function() { + this.$store.dispatch('sendMessage', "fetch_passes"); + } + }, + computed: { + disabled() { + return !this.$store.state.connected + }, + passes() { + return this.$store.state.passes + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/RenderTaskViewPage.vue b/third_party/webrender/debugger/src/components/RenderTaskViewPage.vue new file mode 100644 index 00000000000..c3937fe0ce2 --- /dev/null +++ b/third_party/webrender/debugger/src/components/RenderTaskViewPage.vue @@ -0,0 +1,37 @@ +<template> + <div class="box"> + <h1 class="title">Render Tasks <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1> + <hr/> + <div> + <ul> + <app-treeview :model=render_tasks></app-treeview> + </ul> + </div> + </div> +</template> + +<script> +import TreeView from './TreeView.vue' + +export default { + components: { + 'app-treeview': TreeView, + }, + methods: { + fetch: function() { + this.$store.dispatch('sendMessage', "fetch_render_tasks"); + } + }, + computed: { + disabled() { + return !this.$store.state.connected + }, + render_tasks() { + return this.$store.state.render_tasks + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/ScreenshotPage.vue b/third_party/webrender/debugger/src/components/ScreenshotPage.vue new file mode 100644 index 00000000000..8d4017856e4 --- /dev/null +++ b/third_party/webrender/debugger/src/components/ScreenshotPage.vue @@ -0,0 +1,32 @@ +<template> + <div class="box"> + <h1 class="title">Screenshot <a :disabled="disabled" v-on:click="fetch" class="button is-info">Refresh</a></h1> + <hr/> + <div> + <ul> + <img v-if="screenshot.length > 0" style="transform: scaleY(-1); width: 1024px; height:768px" :src="'data:image/png;base64,' + screenshot" /> + </ul> + </div> + </div> +</template> + +<script> +export default { + computed: { + disabled() { + return !this.$store.state.connected + }, + screenshot() { + return this.$store.state.screenshot + }, + }, + methods: { + fetch: function() { + this.$store.dispatch('sendMessage', "fetch_screenshot"); + } + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/components/TreeView.vue b/third_party/webrender/debugger/src/components/TreeView.vue new file mode 100644 index 00000000000..bde473bda2f --- /dev/null +++ b/third_party/webrender/debugger/src/components/TreeView.vue @@ -0,0 +1,40 @@ +<template> + <li> + <div v-on:click="toggle"> + <span v-if="isFolder">[{{open ? '-' : '+'}}]</span> + {{model.description}} + </div> + <ul style="padding-left: 1em; line-height: 1.5em;" v-show="open" v-if="isFolder"> + <treeview v-for="model in model.children" :model="model"></treeview> + </ul> + </li> +</template> + +<script> +export default { + name: 'treeview', + props: [ + 'model', + ], + data: function () { + return { + open: false + } + }, + computed: { + isFolder: function () { + return this.model.children && this.model.children.length + } + }, + methods: { + toggle: function () { + if (this.isFolder) { + this.open = !this.open + } + }, + }, +} +</script> + +<style> +</style> diff --git a/third_party/webrender/debugger/src/main.js b/third_party/webrender/debugger/src/main.js new file mode 100644 index 00000000000..1259c32a0f3 --- /dev/null +++ b/third_party/webrender/debugger/src/main.js @@ -0,0 +1,14 @@ +import Vue from 'vue'; +import Buefy from 'buefy'; +import 'buefy/dist/buefy.css'; +import "vue-material-design-icons/styles.css"; +import App from './App.vue'; +import store from './store'; + +Vue.use(Buefy); + +new Vue({ + el: '#app', + store, + render: h => h(App) +}) diff --git a/third_party/webrender/debugger/src/store/index.js b/third_party/webrender/debugger/src/store/index.js new file mode 100644 index 00000000000..7749d7a8416 --- /dev/null +++ b/third_party/webrender/debugger/src/store/index.js @@ -0,0 +1,105 @@ +import Vue from 'vue' +import Vuex from 'vuex' + +Vue.use(Vuex) + +class Connection { + constructor() { + this.ws = null; + } + + connect(context) { + var ws = new WebSocket("ws://127.0.0.1:3583"); + + ws.onopen = function() { + context.commit('setConnected', true); + } + + ws.onmessage = function(evt) { + var json = JSON.parse(evt.data); + if (json['kind'] == "passes") { + context.commit('setPasses', json['passes']); + } else if (json['kind'] == "render_tasks") { + context.commit('setRenderTasks', json['root']); + } else if (json['kind'] == "documents") { + context.commit('setDocuments', json['root']); + } else if (json['kind'] == "clip_scroll_tree") { + context.commit('setClipScrollTree', json['root']); + } else if (json['kind'] == "screenshot") { + context.commit('setScreenshot', json['data']); + } else { + console.warn("unknown message kind: " + json['kind']); + } + } + + ws.onclose = function() { + context.commit('setConnected', false); + } + + this.ws = ws; + } + + send(msg) { + if (this.ws !== null) { + this.ws.send(msg); + } + } + + disconnect() { + if (this.ws !== null) { + this.ws.close(); + this.ws = null; + } + } +} + +var connection = new Connection(); + +const store = new Vuex.Store({ + strict: true, + state: { + connected: false, + page: 'options', + passes: [], + render_tasks: [], + documents: [], + clip_scroll_tree: [], + screenshot: [], + }, + mutations: { + setConnected(state, connected) { + state.connected = connected; + }, + setPage(state, name) { + state.page = name; + }, + setPasses(state, passes) { + state.passes = passes; + }, + setRenderTasks(state, render_tasks) { + state.render_tasks = render_tasks; + }, + setDocuments(state, documents) { + state.documents = documents; + }, + setClipScrollTree(state, clip_scroll_tree) { + state.clip_scroll_tree = clip_scroll_tree; + }, + setScreenshot(state, screenshot) { + state.screenshot = screenshot; + }, + }, + actions: { + connect(context) { + connection.connect(context); + }, + disconnect(context) { + connection.disconnect(); + }, + sendMessage(context, msg) { + connection.send(msg); + } + } +}); + +export default store; |