summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore8
-rw-r--r--Makefile.in74
-rw-r--r--README36
-rwxr-xr-xautogen.sh5
-rw-r--r--configure.ac21
-rw-r--r--res/argb.pngbin0 -> 180 bytes
-rw-r--r--res/ask.xml94
-rw-r--r--res/bgr.pngbin0 -> 183 bytes
-rw-r--r--res/main.xml267
-rw-r--r--res/rgb.pngbin0 -> 175 bytes
-rw-r--r--res/rgba.pngbin0 -> 176 bytes
-rw-r--r--res/rgbx.pngbin0 -> 175 bytes
-rw-r--r--res/s8z24.pngbin0 -> 181 bytes
-rw-r--r--res/screen.pngbin0 -> 471 bytes
-rw-r--r--res/shader_off_normal.pngbin0 -> 207 bytes
-rw-r--r--res/shader_off_replaced.pngbin0 -> 707 bytes
-rw-r--r--res/shader_on_normal.pngbin0 -> 207 bytes
-rw-r--r--res/shader_on_replaced.pngbin0 -> 705 bytes
-rw-r--r--res/x8z24.pngbin0 -> 181 bytes
-rw-r--r--res/xbgr.pngbin0 -> 182 bytes
-rw-r--r--res/xrgb.pngbin0 -> 175 bytes
-rw-r--r--res/z24s8.pngbin0 -> 180 bytes
-rw-r--r--res/z24x8.pngbin0 -> 181 bytes
-rw-r--r--src/ask.c93
-rw-r--r--src/context.c27
-rw-r--r--src/draw.c155
-rw-r--r--src/main.c341
-rw-r--r--src/program.h166
-rw-r--r--src/rbug.c119
-rw-r--r--src/shader.c352
-rw-r--r--src/texture.c550
31 files changed, 2308 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..472c399
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+.obj
+Makefile
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+rbug-gui
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..1d39e8b
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,74 @@
+# autoconf directories
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+# autoconf variables
+CC = @CC@
+MESA = @MESA_DIR@
+CFLAGS = @CFLAGS@ -Isrc @GTK_CFLAGS@ $(MESA_INCLUDES) -DDEBUG
+LDFLAGS = @LDFLAGS@ @GTK_LIBS@ $(MESA_LIBS)
+
+# Makefile hardcoded
+MESA_INCLUDES = \
+ -I$(MESA)src/gallium/include \
+ -I$(MESA)src/gallium/auxiliary \
+ -I$(MESA)src/gallium/drivers
+
+MESA_LIBS = \
+ $(MESA)src/gallium/auxiliary/rbug/librbug.a \
+ $(MESA)src/gallium/auxiliary/tgsi/libtgsi.a \
+ $(MESA)src/gallium/auxiliary/util/libutil.a
+
+
+
+TARGET := rbug-gui
+ODIR := .obj
+CDIR := src
+
+CFILES := $(wildcard $(CDIR)/*.c)
+OFILES := $(patsubst $(CDIR)/%.c,$(ODIR)/%.o,$(CFILES))
+DFILES := $(patsubst $(CDIR)/%.c,$(ODIR)/%.d,$(CFILES))
+
+all: $(TARGET)
+
+run: $(TARGET)
+ @./$(TARGET) localhost
+
+debug: $(TARGET)
+ @gdb ./$(TARGET)
+
+valgrind: $(TARGET)
+ @valgrind --leak-check=full --track-origins=yes ./$(TARGET)
+
+$(ODIR):
+ @echo " :: creating $@ directory"
+ @mkdir -p $@
+
+$(TARGET): $(OFILES)
+ @echo " :: linking $@"
+ @$(CC) $^ $(LDFLAGS) -o $@
+
+$(OFILES): $(ODIR)/%.o: $(CDIR)/%.c Makefile
+ @echo " :: compiling $<"
+ @$(CC) $(CFLAGS) -o $@ -c $< -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)"
+
+clean:
+ @echo " :: cleaning"
+ @-rm -rf $(ODIR) $(TARGET)
+
+distclean: clean
+ @-rm -rf aclocal.m4 autoscan.log autom4te.cache Makefile
+ @-rm -rf config.status config.log configure configure.scan
+
+install:
+ @echo " :: installing"
+ @install -d @exec_prefix@/bin
+ @install $(TARGET) @exec_prefix@/bin
+
+$(CFILES): $(ODIR)
+
+.PHONY: clean distclean run debug valgrind
+
+sinclude $(DFILES)
diff --git a/README b/README
new file mode 100644
index 0000000..3ebb100
--- /dev/null
+++ b/README
@@ -0,0 +1,36 @@
+ GALLIUM REMOTE DEBUGGING GUI
+
+= About =
+
+This is the gui interface to the Gallium Remote Debugger.
+It is written in C and uses gtk, gtkglext and Gallium.
+
+
+For information about protocol (de)marshaling see:
+$(MESA)src/gallium/auxiliary/rbug/README
+
+for information about driver integration look in:
+$(MESA)src/gallium/drivers/trace/README
+
+for information about applications look in:
+$(MESA)progs/rbug/README
+
+
+= Building =
+
+You need to have checked out a mesa repository in a sibling directory to this
+directory called mesa, as currently the build looks for mesa in ../mesa/.
+You also need to build a debug build of mesa with with gallium so that the
+needed libraries excist:
+
+ $(MESA)src/gallium/auxiliary/rbug/librbug.a
+ $(MESA)src/gallium/auxiliary/tgsi/libtgsi.a
+ $(MESA)src/gallium/auxiliary/util/libutil.a
+
+Then just do
+ ./autogen.sh
+ make
+
+
+--
+Jakob Bornecrantz <jakob@vmware.com>
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..e584d21
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+autoreconf -v || exit 1
+
+./configure "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..e76feab
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,21 @@
+AC_INIT(rbug-gui, 1)
+AC_PROG_CC
+
+PKG_PROG_PKG_CONFIG()
+PKG_CHECK_MODULES(GTK,[gtkglext-1.0])
+
+if test $CC = gcc; then
+ GCC_CFLAGS+=" -Wall -W -Werror -Wstrict-prototypes -Wmissing-prototypes"
+ GCC_CFLAGS+=" -fvisibility=hidden -fPIC"
+ GCC_LDFLAGS=""
+
+ CFLAGS+=$GCC_CFLAGS
+ LDFLAGS+=$GCC_LDFLAGS
+fi
+
+# Add option for this
+MESA_DIR="../mesa/"
+AC_SUBST([MESA_DIR])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/res/argb.png b/res/argb.png
new file mode 100644
index 0000000..b0b8cf8
--- /dev/null
+++ b/res/argb.png
Binary files differ
diff --git a/res/ask.xml b/res/ask.xml
new file mode 100644
index 0000000..a3055cc
--- /dev/null
+++ b/res/ask.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkWindow" id="window">
+ <property name="border_width">5</property>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkHBox" id="_hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkEntry" id="entry_host">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">&#x25CF;</property>
+ <property name="text" translatable="yes">localhost</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="entry_port">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">&#x25CF;</property>
+ <property name="adjustment">adjustment_port</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="_hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="connect">
+ <property name="label" translatable="yes">gtk-connect</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="quit">
+ <property name="label" translatable="yes">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkAdjustment" id="adjustment_port">
+ <property name="value">13370</property>
+ <property name="lower">13370</property>
+ <property name="upper">13379</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">1</property>
+ </object>
+</interface>
diff --git a/res/bgr.png b/res/bgr.png
new file mode 100644
index 0000000..13fd779
--- /dev/null
+++ b/res/bgr.png
Binary files differ
diff --git a/res/main.xml b/res/main.xml
new file mode 100644
index 0000000..7772398
--- /dev/null
+++ b/res/main.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkTreeStore" id="treestore">
+ <columns>
+ <!-- column-name id -->
+ <column type="guint64"/>
+ <!-- column-name type -->
+ <column type="gint"/>
+ <!-- column-name type_name -->
+ <column type="gchararray"/>
+ <!-- column-name pixbuf -->
+ <column type="GdkPixbuf"/>
+ </columns>
+ </object>
+ <object class="GtkWindow" id="window">
+ <property name="width_request">600</property>
+ <property name="height_request">600</property>
+ <child>
+ <object class="GtkVBox" id="_vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkToolButton" id="tool_refresh">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Rerfresh</property>
+ <property name="stock_id">gtk-refresh</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem" id="separator">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_back">
+ <property name="label" translatable="yes">Back</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-go-back</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_forward">
+ <property name="label" translatable="yes">Forward</property>
+ <property name="stock_id">gtk-go-forward</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_background">
+ <property name="label" translatable="yes">Background</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-select-color</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_alpha">
+ <property name="label" translatable="yes">Alpha Blend</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">format-text-bold</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_auto">
+ <property name="label" translatable="yes">Auto</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-execute</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_disable">
+ <property name="label" translatable="yes">Disable</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-no</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_enable">
+ <property name="label" translatable="yes">Enable</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-yes</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_save">
+ <property name="label" translatable="yes">Save</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-save</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_revert">
+ <property name="label" translatable="yes">Revert</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-revert-to-saved</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem" id="filler">
+ <property name="visible">True</property>
+ <property name="draw">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="tool_quit">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Quit</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-quit</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHPaned" id="_hpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="position">250</property>
+ <property name="position_set">True</property>
+ <child>
+ <object class="GtkScrolledWindow" id="_scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">treestore</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="col_string">
+ <property name="title">Name</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="col_id">
+ <property name="title">ID</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="col_icon">
+ <property name="sizing">autosize</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="_vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow" id="textview_scrolled">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTextView" id="textview">
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="draw"/>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkStatusbar" id="statusbar">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/res/rgb.png b/res/rgb.png
new file mode 100644
index 0000000..fb74e4f
--- /dev/null
+++ b/res/rgb.png
Binary files differ
diff --git a/res/rgba.png b/res/rgba.png
new file mode 100644
index 0000000..362ebf7
--- /dev/null
+++ b/res/rgba.png
Binary files differ
diff --git a/res/rgbx.png b/res/rgbx.png
new file mode 100644
index 0000000..2d06698
--- /dev/null
+++ b/res/rgbx.png
Binary files differ
diff --git a/res/s8z24.png b/res/s8z24.png
new file mode 100644
index 0000000..4df4bd8
--- /dev/null
+++ b/res/s8z24.png
Binary files differ
diff --git a/res/screen.png b/res/screen.png
new file mode 100644
index 0000000..bb4c73d
--- /dev/null
+++ b/res/screen.png
Binary files differ
diff --git a/res/shader_off_normal.png b/res/shader_off_normal.png
new file mode 100644
index 0000000..a5d6f64
--- /dev/null
+++ b/res/shader_off_normal.png
Binary files differ
diff --git a/res/shader_off_replaced.png b/res/shader_off_replaced.png
new file mode 100644
index 0000000..1424703
--- /dev/null
+++ b/res/shader_off_replaced.png
Binary files differ
diff --git a/res/shader_on_normal.png b/res/shader_on_normal.png
new file mode 100644
index 0000000..b09addf
--- /dev/null
+++ b/res/shader_on_normal.png
Binary files differ
diff --git a/res/shader_on_replaced.png b/res/shader_on_replaced.png
new file mode 100644
index 0000000..2b3d8cd
--- /dev/null
+++ b/res/shader_on_replaced.png
Binary files differ
diff --git a/res/x8z24.png b/res/x8z24.png
new file mode 100644
index 0000000..850cb99
--- /dev/null
+++ b/res/x8z24.png
Binary files differ
diff --git a/res/xbgr.png b/res/xbgr.png
new file mode 100644
index 0000000..c8173f0
--- /dev/null
+++ b/res/xbgr.png
Binary files differ
diff --git a/res/xrgb.png b/res/xrgb.png
new file mode 100644
index 0000000..cc80a5b
--- /dev/null
+++ b/res/xrgb.png
Binary files differ
diff --git a/res/z24s8.png b/res/z24s8.png
new file mode 100644
index 0000000..f8a14dd
--- /dev/null
+++ b/res/z24s8.png
Binary files differ
diff --git a/res/z24x8.png b/res/z24x8.png
new file mode 100644
index 0000000..c76ae2a
--- /dev/null
+++ b/res/z24x8.png
Binary files differ
diff --git a/src/ask.c b/src/ask.c
new file mode 100644
index 0000000..8e17649
--- /dev/null
+++ b/src/ask.c
@@ -0,0 +1,93 @@
+
+#include "program.h"
+#include "util/u_network.h"
+
+
+gboolean ask_connect(struct program *p)
+{
+ int socket;
+
+ socket = u_socket_connect(p->ask.host, p->ask.port);
+
+ if (socket < 0)
+ return false;
+
+ p->rbug.socket = socket;
+ p->rbug.con = rbug_from_socket(socket);
+
+ rbug_glib_io_watch(p);
+
+ main_window_create(p);
+
+ return true;
+}
+
+static void connect(GtkWidget *widget, gpointer data)
+{
+ struct program *p = (struct program *)data;
+ char *host;
+ uint16_t port;
+
+ (void)widget;
+
+ host = gtk_editable_get_chars(GTK_EDITABLE(p->ask.entry_host), 0, -1);
+ port = (uint16_t)gtk_adjustment_get_value(p->ask.adjustment_port);
+
+ p->ask.host = host;
+ p->ask.port = port;
+
+ if (!ask_connect(p))
+ return;
+
+ gtk_widget_destroy(p->ask.window);
+
+ p->ask.window = NULL;
+ p->ask.entry_host = NULL;
+ p->ask.entry_port = NULL;
+}
+
+static void destroy(GtkWidget *widget, gpointer data)
+{
+ struct program *p = (struct program *)data;
+ (void)widget;
+
+ if (!p->main.window)
+ main_quit(p);
+}
+
+void ask_window_create(struct program *p)
+{
+ GtkBuilder *builder;
+ GtkWidget *window;
+ GtkWidget *button;
+ GtkWidget *quit;
+ GtkWidget *entry_host;
+ GtkWidget *entry_port;
+ GtkAdjustment *adjustment_port;
+
+ builder = gtk_builder_new();
+
+ gtk_builder_add_from_file(builder, "res/ask.xml", NULL);
+ gtk_builder_connect_signals(builder, NULL);
+
+ window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+ button = GTK_WIDGET(gtk_builder_get_object(builder, "connect"));
+ quit = GTK_WIDGET(gtk_builder_get_object(builder, "quit"));
+ entry_host = GTK_WIDGET(gtk_builder_get_object(builder, "entry_host"));
+ entry_port = GTK_WIDGET(gtk_builder_get_object(builder, "entry_port"));
+ adjustment_port = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "adjustment_port"));
+
+ /* manualy set up signals */
+ g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(connect), p);
+ g_signal_connect(G_OBJECT(quit), "clicked", G_CALLBACK(destroy), p);
+ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), p);
+
+ gtk_widget_show(window);
+
+ p->ask.window = window;
+ p->ask.entry_host = entry_host;
+ p->ask.entry_port = entry_port;
+ p->ask.adjustment_port = adjustment_port;
+
+ gtk_adjustment_set_value(adjustment_port, 13370);
+}
diff --git a/src/context.c b/src/context.c
new file mode 100644
index 0000000..73e572b
--- /dev/null
+++ b/src/context.c
@@ -0,0 +1,27 @@
+
+#include "program.h"
+
+void context_list(GtkTreeStore *store, GtkTreeIter *parent, struct program *p)
+{
+ struct rbug_proto_context_list_reply *list;
+ struct rbug_connection *con = p->rbug.con;
+ struct rbug_header *header;
+ uint32_t i;
+
+ rbug_send_context_list(con, NULL);
+ header = rbug_get_message(con, NULL);
+ list = (struct rbug_proto_context_list_reply *)header;
+
+ for (i = 0; i < list->contexts_len; i++) {
+ GtkTreeIter iter;
+ gtk_tree_store_insert_with_values(store, &iter, parent, -1,
+ COLUMN_ID, list->contexts[i],
+ COLUMN_TYPE, TYPE_CONTEXT,
+ COLUMN_TYPENAME, "context",
+ -1);
+
+ shader_list(store, &iter, list->contexts[i], p);
+ }
+
+ rbug_free_header(header);
+}
diff --git a/src/draw.c b/src/draw.c
new file mode 100644
index 0000000..9765978
--- /dev/null
+++ b/src/draw.c
@@ -0,0 +1,155 @@
+
+
+#include "program.h"
+#include <GL/gl.h>
+
+static void realize(GtkWidget* widget, gpointer data)
+{
+#if 0
+ GdkGLContext* context = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable* drawable = gtk_widget_get_gl_drawable(widget);
+ (void)data;
+
+ if (!gdk_gl_drawable_gl_begin(drawable, context))
+ return;
+
+ gdk_gl_drawable_gl_end(drawable);
+#else
+ (void)widget;
+ (void)data;
+#endif
+}
+
+static gboolean configure(GtkWidget* widget, GdkEventConfigure* e, gpointer data)
+{
+#if 0
+ GdkGLContext* context = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable* drawable = gtk_widget_get_gl_drawable(widget);
+ (void)data;
+ (void)e;
+
+ if (!gdk_gl_drawable_gl_begin(drawable, context))
+ return FALSE;
+
+ gdk_gl_drawable_gl_end (drawable);
+#else
+ (void)widget;
+ (void)data;
+ (void)e;
+#endif
+ return TRUE;
+}
+
+static void draw_tri(struct program *p)
+{
+ glClearColor(0.3, 0.1, 0.3, 0.5);
+ glViewport(0, 0, (GLint)p->draw.width, (GLint)p->draw.height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glBegin(GL_TRIANGLES);
+ glColor3f(.8,0,0);
+ glVertex3f(-0.9, -0.9, -30.0);
+ glColor3f(0,.9,0);
+ glVertex3f( 0.9, -0.9, -30.0);
+ glColor3f(0,0,.7);
+ glVertex3f( 0.0, 0.9, -30.0);
+ glEnd();
+}
+
+gboolean draw_gl_begin(struct program *p)
+{
+ GtkWidget *widget = GTK_WIDGET(p->main.draw);
+ GdkGLContext* context = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable* drawable = gtk_widget_get_gl_drawable(widget);
+
+ return gdk_gl_drawable_gl_begin(drawable, context);
+}
+
+void draw_gl_end(struct program *p)
+{
+ GtkWidget *widget = GTK_WIDGET(p->main.draw);
+ GdkGLDrawable* drawable = gtk_widget_get_gl_drawable(widget);
+
+ gdk_gl_drawable_gl_end(drawable);
+}
+
+void draw_ortho_top_left(struct program *p)
+{
+ glViewport(0, 0, (GLint)p->draw.width, (GLint)p->draw.height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, p->draw.width, p->draw.height, 0.0, -0.5, 1000.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+void draw_checker(guint width, guint height, struct program *p)
+{
+ int x;
+ int y;
+ int i;
+
+ glClearColor(0.3, 0.3, 0.3, 0.5);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glColor3f(.8,.8,.8);
+ glBegin(GL_QUADS);
+ for (i = 0, x = 0; x < (int)p->draw.width; i++) {
+ x = (width * i) - (width / 2);
+ y = ((i % 2) * height) - (height / 2);
+ for (; y < (int)p->draw.height; y += height * 2) {
+ glVertex3f( x + 0.0, y + height, -30.0);
+ glVertex3f( x + width, y + height, -30.0);
+ glVertex3f( x + width, y + 0.0, -30.0);
+ glVertex3f( x + 0.0, y + 0.0, -30.0);
+ }
+ }
+ glEnd();
+}
+
+static gboolean expose(GtkWidget* widget, GdkEventExpose* e, gpointer data)
+{
+ struct program *p = (struct program *)data;
+ GdkGLContext* context = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable* drawable = gtk_widget_get_gl_drawable(widget);
+ (void)e;
+
+ p->draw.width = widget->allocation.width;
+ p->draw.height = widget->allocation.height;
+
+ if (!gdk_gl_drawable_gl_begin(drawable, context))
+ return FALSE;
+
+ if (p->selected.type == TYPE_TEXTURE)
+ texture_draw(p);
+ else
+ draw_tri(p);
+
+ if (gdk_gl_drawable_is_double_buffered (drawable))
+ gdk_gl_drawable_swap_buffers(drawable);
+ else
+ glFlush();
+
+ gdk_gl_drawable_gl_end(drawable);
+
+ return TRUE;
+}
+
+void draw_setup(GtkDrawingArea *draw, struct program *p)
+{
+ GObject *obj = G_OBJECT(draw);
+
+ gtk_widget_set_gl_capability(GTK_WIDGET(draw), p->draw.config, NULL,
+ TRUE, GDK_GL_RGBA_TYPE);
+
+ g_signal_connect_after(obj, "realize", G_CALLBACK(realize), p);
+ g_signal_connect(obj, "configure-event", G_CALLBACK(configure), p);
+ g_signal_connect(obj, "expose-event", G_CALLBACK(expose), p);
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..6cd6839
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,341 @@
+
+#include "program.h"
+#include "pipe/p_format.h"
+
+static gboolean main_idle(gpointer data)
+{
+ struct program *p = (struct program *)data;
+
+ if (!ask_connect(p))
+ main_quit(p);
+
+ return false;
+}
+
+int main(int argc, char *argv[])
+{
+ struct program *p = g_malloc(sizeof(*p));
+ memset(p, 0, sizeof(*p));
+
+ gtk_init(&argc, &argv);
+ gtk_gl_init(&argc, &argv);
+
+ p->draw.config = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB |
+ GDK_GL_MODE_ALPHA |
+ GDK_GL_MODE_DEPTH |
+ GDK_GL_MODE_DOUBLE);
+
+ /* connect to first non gnome argument */
+ if (argc > 1) {
+ int len = strlen(argv[1]) + 1;
+ p->ask.host = g_malloc(len);
+ memcpy(p->ask.host, argv[1], len);
+ p->ask.port = 13370;
+ gtk_idle_add(main_idle, p);
+ } else {
+ ask_window_create(p);
+ }
+
+ gtk_main();
+
+ g_free(p);
+
+ return 0;
+}
+
+static void destroy(GtkWidget *widget, gpointer data)
+{
+ struct program *p = (struct program *)data;
+ (void)widget;
+
+ main_quit(p);
+}
+
+static void foreach(GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ struct program *p = (struct program *)data;
+ GtkTreeIter parent;
+ GValue id;
+ GValue type;
+ GValue typename;
+ (void)path;
+ (void)data;
+
+ memset(&id, 0, sizeof(id));
+ memset(&type, 0, sizeof(type));
+ memset(&typename, 0, sizeof(typename));
+
+ gtk_tree_model_get_value(model, iter, COLUMN_ID, &id);
+ gtk_tree_model_get_value(model, iter, COLUMN_TYPE, &type);
+ gtk_tree_model_get_value(model, iter, COLUMN_TYPENAME, &typename);
+
+ g_assert(G_VALUE_HOLDS_UINT64(&id));
+ g_assert(G_VALUE_HOLDS_INT(&type));
+ g_assert(G_VALUE_HOLDS_STRING(&typename));
+
+ p->selected.iter = *iter;
+ p->selected.id = g_value_get_uint64(&id);
+ p->selected.type = g_value_get_int(&type);
+
+ if (gtk_tree_model_iter_parent(model, &parent, iter)) {
+ g_value_unset(&id);
+ gtk_tree_model_get_value(model, &parent, COLUMN_ID, &id);
+ g_assert(G_VALUE_HOLDS_UINT64(&id));
+
+ p->selected.parent = g_value_get_uint64(&id);
+ }
+}
+
+static void changed(GtkTreeSelection *s, gpointer data)
+{
+ struct program *p = (struct program *)data;
+ enum types old_type;
+ uint64_t old_id;
+ (void)s;
+ (void)p;
+
+ old_id = p->selected.id;
+ old_type = p->selected.type;
+
+ /* reset selected data */
+ memset(&p->selected, 0, sizeof(p->selected));
+
+ gtk_tree_selection_selected_foreach(s, foreach, p);
+
+ if (p->selected.id != old_id ||
+ p->selected.type != old_type) {
+ if (old_id) {
+ if (old_type == TYPE_SHADER)
+ shader_unselected(p);
+ else if (old_type == TYPE_TEXTURE)
+ texture_unselected(p);
+ }
+ if (p->selected.id) {
+ if (p->selected.type == TYPE_SHADER)
+ shader_selected(p);
+ else if (p->selected.type == TYPE_TEXTURE)
+ texture_selected(p);
+ }
+ }
+}
+
+static void refresh(GtkWidget *widget, gpointer data)
+{
+ struct program *p = (struct program *)data;
+ GtkTreeStore *store = p->main.treestore;
+ (void)widget;
+
+ if (p->selected.id != 0) {
+ if (p->selected.type == TYPE_TEXTURE)
+ texture_refresh(p);
+
+ return;
+ }
+
+ gtk_tree_store_clear(p->main.treestore);
+
+ gtk_tree_store_insert_with_values(store, &p->main.top, NULL, -1,
+ COLUMN_ID, 0,
+ COLUMN_TYPE, TYPE_SCREEN,
+ COLUMN_TYPENAME, "screen",
+ COLUMN_PIXBUF, icon_get("screen", p),
+ -1);
+
+ /* contexts */
+ context_list(store, &p->main.top, p);
+
+ /* textures */
+ texture_list(store, &p->main.top, p);
+
+ /* expend all rows */
+ gtk_tree_view_expand_all(p->main.treeview);
+}
+
+static void setup_cols(GtkBuilder *builder, GtkTreeView *view, struct program *p)
+{
+ GtkTreeViewColumn *col;
+ GtkCellRenderer *renderer;
+ (void)view;
+ (void)p;
+
+ /* column id */
+ col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "col_id"));
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(col, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_ID);
+
+ /* column format */
+ col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "col_string"));
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(col, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_TYPENAME);
+
+ /* column format */
+ col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "col_icon"));
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(col, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(col, renderer, "pixbuf", COLUMN_PIXBUF);
+
+ g_object_set(G_OBJECT(renderer), "xalign", (gfloat)0.0f, NULL);
+}
+
+static void icon_setup(struct program *p)
+{
+ p->icon.hash = g_hash_table_new(g_str_hash, g_str_equal);
+
+ icon_add("res/rgba.png", "rgba", p);
+ icon_add("res/rgbx.png", "rgbx", p);
+ icon_add("res/argb.png", "argb", p);
+ icon_add("res/xrgb.png", "xrgb", p);
+
+ icon_add("res/s8z24.png", "s8z24", p);
+ icon_add("res/x8z24.png", "x8z24", p);
+ icon_add("res/z24s8.png", "z24s8", p);
+ icon_add("res/z24x8.png", "z24x8", p);
+
+ icon_add("res/rgb.png", "rgb", p);
+ icon_add("res/rgb.png", "bgr", p);
+
+ icon_add("res/screen.png", "screen", p);
+
+ icon_add("res/shader_on_normal.png", "shader_on_normal", p);
+ icon_add("res/shader_on_replaced.png", "shader_on_replaced", p);
+ icon_add("res/shader_off_normal.png", "shader_off_normal", p);
+ icon_add("res/shader_off_replaced.png", "shader_off_replaced", p);
+}
+
+void main_window_create(struct program *p)
+{
+ GtkBuilder *builder;
+
+ GtkWidget *window;
+ GObject *selection;
+ GtkDrawingArea *draw;
+ GtkTextView *textview;
+ GtkWidget *textview_scrolled;
+ GtkTreeView *treeview;
+ GtkTreeStore *treestore;
+
+ GObject *tool_quit;
+ GObject *tool_refresh;
+
+ GObject *tool_back;
+ GObject *tool_forward;
+ GObject *tool_background;
+ GObject *tool_alpha;
+ GObject *tool_automatic;
+
+ GObject *tool_disable;
+ GObject *tool_enable;
+ GObject *tool_save;
+ GObject *tool_revert;
+
+ builder = gtk_builder_new();
+
+ gtk_builder_add_from_file(builder, "res/main.xml", NULL);
+ gtk_builder_connect_signals(builder, NULL);
+
+ draw = GTK_DRAWING_AREA(gtk_builder_get_object(builder, "draw"));
+ window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+ textview = GTK_TEXT_VIEW(gtk_builder_get_object(builder, "textview"));
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+ treestore = GTK_TREE_STORE(gtk_builder_get_object(builder, "treestore"));
+ selection = G_OBJECT(gtk_tree_view_get_selection(treeview));
+ textview_scrolled = GTK_WIDGET(gtk_builder_get_object(builder, "textview_scrolled"));
+
+
+ tool_quit = gtk_builder_get_object(builder, "tool_quit");
+ tool_refresh = gtk_builder_get_object(builder, "tool_refresh");
+
+ tool_back = gtk_builder_get_object(builder, "tool_back");
+ tool_forward = gtk_builder_get_object(builder, "tool_forward");
+ tool_background = gtk_builder_get_object(builder, "tool_background");
+ tool_alpha = gtk_builder_get_object(builder, "tool_alpha");
+ tool_automatic = gtk_builder_get_object(builder, "tool_auto");
+
+ tool_disable = gtk_builder_get_object(builder, "tool_disable");
+ tool_enable = gtk_builder_get_object(builder, "tool_enable");
+ tool_save = gtk_builder_get_object(builder, "tool_save");
+ tool_revert = gtk_builder_get_object(builder, "tool_revert");
+
+ setup_cols(builder, treeview, p);
+
+ /* manualy set up signals */
+ g_signal_connect(selection, "changed", G_CALLBACK(changed), p);
+ g_signal_connect(tool_quit, "clicked", G_CALLBACK(destroy), p);
+ g_signal_connect(tool_refresh, "clicked", G_CALLBACK(refresh), p);
+ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), p);
+
+ p->main.draw = draw;
+ p->main.window = window;
+ p->main.textview = textview;
+ p->main.treeview = treeview;
+ p->main.treestore = treestore;
+ p->main.textview_scrolled = textview_scrolled;
+
+ p->tool.back = GTK_WIDGET(tool_back);
+ p->tool.forward = GTK_WIDGET(tool_forward);
+ p->tool.background = GTK_WIDGET(tool_background);
+ p->tool.alpha = GTK_WIDGET(tool_alpha);
+ p->tool.automatic = GTK_WIDGET(tool_automatic);
+
+ p->tool.disable = GTK_WIDGET(tool_disable);
+ p->tool.enable = GTK_WIDGET(tool_enable);
+ p->tool.save = GTK_WIDGET(tool_save);
+ p->tool.revert = GTK_WIDGET(tool_revert);
+
+ draw_setup(draw, p);
+
+ gtk_widget_hide(p->tool.back);
+ gtk_widget_hide(p->tool.forward);
+ gtk_widget_hide(p->tool.background);
+ gtk_widget_hide(p->tool.alpha);
+
+ gtk_widget_hide(p->tool.disable);
+ gtk_widget_hide(p->tool.enable);
+ gtk_widget_hide(p->tool.save);
+ gtk_widget_hide(p->tool.revert);
+
+ gtk_widget_hide(p->main.textview_scrolled);
+ gtk_widget_hide(GTK_WIDGET(p->main.textview));
+ gtk_widget_hide(GTK_WIDGET(p->main.draw));
+
+ gtk_widget_show(window);
+
+ icon_setup(p);
+
+ /* do a refresh */
+ refresh(GTK_WIDGET(tool_refresh), p);
+}
+
+void main_quit(struct program *p)
+{
+ if (p->rbug.con) {
+ rbug_disconnect(p->rbug.con);
+ g_io_channel_unref(p->rbug.channel);
+ g_source_remove(p->rbug.event);
+ g_hash_table_unref(p->rbug.hash);
+ }
+
+ g_free(p->ask.host);
+
+ gtk_main_quit();
+}
+
+void icon_add(const char *filename, const char *name, struct program *p)
+{
+ GdkPixbuf *icon = gdk_pixbuf_new_from_file(filename, NULL);
+
+ if (!icon)
+ return;
+
+ g_hash_table_insert(p->icon.hash, (char*)name, icon);
+}
+
+GdkPixbuf * icon_get(const char *name, struct program *p)
+{
+ return (GdkPixbuf *)g_hash_table_lookup(p->icon.hash, name);
+}
diff --git a/src/program.h b/src/program.h
new file mode 100644
index 0000000..d8b8180
--- /dev/null
+++ b/src/program.h
@@ -0,0 +1,166 @@
+
+#ifndef _RBUG_GUI_PROGRAM_H_
+#define _RBUG_GUI_PROGRAM_H_
+
+#include <gtk/gtk.h>
+#include <gtk/gtkgl.h>
+
+#include "rbug/rbug.h"
+
+struct texture_action_read;
+struct shader_action_info;
+
+enum columns {
+ COLUMN_ID = 0,
+ COLUMN_TYPE,
+ COLUMN_TYPENAME,
+ COLUMN_PIXBUF,
+};
+
+enum types {
+ TYPE_NONE = 0,
+ TYPE_SCREEN,
+ TYPE_CONTEXT,
+ TYPE_TEXTURE,
+ TYPE_SHADER,
+};
+
+struct program
+{
+ struct {
+ GtkWidget *window;
+ GtkWidget *entry_host;
+ GtkWidget *entry_port;
+ GtkAdjustment *adjustment_port;
+
+ char *host;
+ uint16_t port;
+ } ask;
+
+ struct {
+ uint32_t width;
+ uint32_t height;
+ GdkGLConfig *config;
+ } draw;
+
+ struct {
+ GtkWidget *window;
+ GtkTextView *textview;
+ GtkWidget *textview_scrolled;
+ GtkTreeView *treeview;
+ GtkTreeStore *treestore;
+ GtkDrawingArea *draw;
+
+ GtkTreeIter top;
+ } main;
+
+ struct {
+ GtkTreeIter iter;
+ enum types type;
+ guint64 parent;
+ guint64 id;
+ } selected;
+
+ struct {
+ GtkWidget *back;
+ GtkWidget *forward;
+ GtkWidget *background;
+ GtkWidget *alpha;
+ GtkWidget *automatic;
+
+ GtkWidget *enable;
+ GtkWidget *disable;
+ GtkWidget *save;
+ GtkWidget *revert;
+ } tool;
+
+ struct {
+ gulong id[8];
+
+ struct shader_action_info *info;
+ } shader;
+
+ struct {
+ struct texture_action_read *read;
+
+ /* current texture loaded */
+ gboolean alpha;
+ rbug_texture_t id;
+ unsigned width;
+ unsigned height;
+
+ gulong tid[3];
+ gboolean automatic;
+ int back;
+
+ int levels[16];
+ } texture;
+
+ struct {
+ int socket;
+ struct rbug_connection *con;
+ GIOChannel *channel;
+ gint event;
+ GHashTable *hash;
+ } rbug;
+
+ struct {
+ GHashTable *hash;
+ } icon;
+};
+
+struct rbug_event
+{
+ void (*func)(struct rbug_event *, struct rbug_header *, struct program *);
+};
+
+
+/* src/ask.c */
+void ask_window_create(struct program *p);
+gboolean ask_connect(struct program *p);
+
+
+/* src/main.c */
+void main_window_create(struct program *p);
+void main_quit(struct program *p);
+void icon_add(const char *filename, const char *name, struct program *p);
+GdkPixbuf* icon_get(const char *name, struct program *p);
+
+
+/* src/rbug.c */
+void rbug_add_event(struct rbug_event *e, uint32_t serial, struct program *p);
+void rbug_glib_io_watch(struct program *p);
+void rbug_finish_and_emit_events(struct program *p);
+
+
+/* src/context.c */
+void context_list(GtkTreeStore *store,
+ GtkTreeIter *parent,
+ struct program *p);
+
+/* src/texture.c */
+void texture_list(GtkTreeStore *store, GtkTreeIter *parent, struct program *p);
+void texture_unselected(struct program *p);
+void texture_selected(struct program *p);
+void texture_refresh(struct program *p);
+void texture_draw(struct program *p);
+
+
+/* src/shader.c */
+void shader_unselected(struct program *p);
+void shader_selected(struct program *p);
+void shader_list(GtkTreeStore *store,
+ GtkTreeIter *parent,
+ rbug_context_t ctx,
+ struct program *p);
+
+
+/* src/draw.c */
+void draw_setup(GtkDrawingArea *draw, struct program *p);
+gboolean draw_gl_begin(struct program *p);
+void draw_gl_end(struct program *p);
+void draw_checker(guint width, guint height, struct program *p);
+void draw_ortho_top_left(struct program *p);
+
+
+#endif
diff --git a/src/rbug.c b/src/rbug.c
new file mode 100644
index 0000000..27d70d0
--- /dev/null
+++ b/src/rbug.c
@@ -0,0 +1,119 @@
+
+#include "program.h"
+
+#define SERIAL2KEY(s) ((void*)(unsigned long)s)
+#define KEY2SERIAL(k) ((uint32_t)(unsigned long)k)
+
+static guint hash_func(gconstpointer key)
+{
+ return KEY2SERIAL(key);
+}
+
+static gboolean equal_func(gconstpointer a, gconstpointer b)
+{
+ return KEY2SERIAL(a) == KEY2SERIAL(b);
+}
+
+static void rbug_handle_header(struct rbug_header *header, struct program *p)
+{
+ struct rbug_event *e;
+ uint32_t serial;
+ void *ptr;
+
+ g_assert(header->opcode < 0);
+ serial = *(uint32_t*)&header[1];
+
+ ptr = g_hash_table_lookup(p->rbug.hash, SERIAL2KEY(serial));
+ g_hash_table_remove(p->rbug.hash, SERIAL2KEY(serial));
+
+ if (!ptr) {
+ g_print("lost message with id %u\n", serial);
+ return;
+ }
+
+ e = (struct rbug_event *)ptr;
+ e->func(e, header, p);
+
+ rbug_free_header(header);
+}
+
+static gboolean rbug_event(GIOChannel *channel, GIOCondition c, gpointer data)
+{
+ struct program *p = (struct program *)data;
+ struct rbug_connection *con = p->rbug.con;
+ struct rbug_header *header;
+ (void)channel;
+
+ if (c & (G_IO_IN | G_IO_PRI)) {
+ header = rbug_get_message(con, NULL);
+ if (!header) {
+ main_quit(p);
+ return false;
+ }
+
+ rbug_handle_header(header, p);
+ }
+
+ if (c & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ main_quit(p);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * exported
+ */
+
+void rbug_finish_and_emit_events(struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ struct rbug_header *header;
+ uint32_t serial;
+
+ rbug_send_ping(con, &serial);
+
+ do {
+ header = rbug_get_message(con, NULL);
+
+ if (!header) {
+ g_print("Connection problems\n");
+ break;
+ }
+
+ if (header->opcode < 0) {
+ uint32_t s =*(uint32_t*)(&header[1]);
+ if (s == serial) {
+ break;
+ } else if (s > serial) {
+ g_print("Bad bad bad lost message that we waited for\n");
+ break;
+ }
+ }
+
+ rbug_handle_header(header, p);
+ header = NULL;
+ } while (1);
+
+ if (header && header->opcode != RBUG_OP_PING_REPLY) {
+ g_print("Bad bad bad reply which we waited for was not ping\n");
+ }
+
+ rbug_free_header(header);
+}
+
+void rbug_add_event(struct rbug_event *e, uint32_t serial, struct program *p)
+{
+ g_hash_table_insert(p->rbug.hash, SERIAL2KEY(serial), e);
+}
+
+void rbug_glib_io_watch(struct program *p)
+{
+ gint mask = (G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
+
+ p->rbug.channel = g_io_channel_unix_new(p->rbug.socket);
+ p->rbug.event = g_io_add_watch(p->rbug.channel, mask, rbug_event, p);
+ g_io_channel_set_encoding(p->rbug.channel, NULL, NULL);
+ p->rbug.hash = g_hash_table_new(hash_func, equal_func);
+}
diff --git a/src/shader.c b/src/shader.c
new file mode 100644
index 0000000..88b3ada
--- /dev/null
+++ b/src/shader.c
@@ -0,0 +1,352 @@
+
+#include "program.h"
+
+#include "tgsi/tgsi_text.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_parse.h"
+
+
+
+/*
+ * Actions
+ */
+
+
+static struct shader_action_info *
+shader_start_info_action(rbug_context_t c,
+ rbug_shader_t s,
+ GtkTreeIter *iter,
+ struct program *p);
+static void shader_stop_info_action(struct shader_action_info *info, struct program *p);
+
+static void shader_start_list_action(GtkTreeStore *store, GtkTreeIter *parent,
+ rbug_context_t ctx, struct program *p);
+
+
+/*
+ * Internal
+ */
+
+
+static void disable(GtkWidget *widget, struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ (void)widget;
+
+ g_assert(p->selected.type == TYPE_SHADER);
+
+ rbug_finish_and_emit_events(p);
+ rbug_send_shader_disable(con, p->selected.parent, p->selected.id, true, NULL);
+ rbug_finish_and_emit_events(p);
+
+ gtk_widget_hide(p->tool.disable);
+ gtk_widget_show(p->tool.enable);
+
+ shader_start_info_action(p->selected.parent, p->selected.id, &p->selected.iter, p);
+}
+
+static void enable(GtkWidget *widget, struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ (void)widget;
+
+ g_assert(p->selected.type == TYPE_SHADER);
+
+ rbug_finish_and_emit_events(p);
+ rbug_send_shader_disable(con, p->selected.parent, p->selected.id, false, NULL);
+ rbug_finish_and_emit_events(p);
+
+ gtk_widget_show(p->tool.disable);
+ gtk_widget_hide(p->tool.enable);
+
+ shader_start_info_action(p->selected.parent, p->selected.id, &p->selected.iter, p);
+}
+
+static void update_text(struct rbug_proto_shader_info_reply *info, struct program *p)
+{
+ GtkTextBuffer *buffer;
+ gchar text[2048];
+
+ /* just in case */
+ g_assert(sizeof(struct tgsi_token) == 4);
+
+ if (info->replaced_len > 0)
+ tgsi_dump_str((struct tgsi_token *)info->replaced, 0, text, 2048);
+ else
+ tgsi_dump_str((struct tgsi_token *)info->original, 0, text, 2048);
+
+ /* just in case */
+ text[2047] = 0;
+
+ buffer = gtk_text_view_get_buffer(p->main.textview);
+ gtk_text_buffer_set_text(buffer, text, -1);
+}
+
+static void revert(GtkWidget *widget, struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ (void)widget;
+
+ g_assert(p->selected.type == TYPE_SHADER);
+
+ rbug_finish_and_emit_events(p);
+ rbug_send_shader_replace(con, p->selected.parent, p->selected.id, NULL, 0, NULL);
+ rbug_finish_and_emit_events(p);
+
+ shader_start_info_action(p->selected.parent, p->selected.id, &p->selected.iter, p);
+}
+
+static void save(GtkWidget *widget, struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ struct tgsi_token tokens[300];
+ GtkTextBuffer *buffer;
+ GtkTextIter start;
+ GtkTextIter end;
+ gboolean result;
+ char *text = 0;
+ unsigned num;
+ (void)widget;
+
+ g_assert(p->selected.type == TYPE_SHADER);
+ g_assert(sizeof(struct tgsi_token) == 4);
+
+ rbug_finish_and_emit_events(p);
+
+ buffer = gtk_text_view_get_buffer(p->main.textview);
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ result = tgsi_text_translate(text, tokens, 300);
+
+ if (!result) {
+ goto out;
+ }
+
+ num = tgsi_num_tokens(tokens);
+
+ rbug_send_shader_replace(con, p->selected.parent, p->selected.id,
+ (uint32_t*)tokens, num, NULL);
+
+ gtk_widget_show(p->tool.revert);
+
+ rbug_finish_and_emit_events(p);
+
+ shader_start_info_action(p->selected.parent, p->selected.id, &p->selected.iter, p);
+
+out:
+ g_free(text);
+}
+
+void shader_selected(struct program *p)
+{
+ g_assert(p->selected.type == TYPE_SHADER);
+
+ p->shader.id[0] = g_signal_connect(p->tool.save, "clicked", G_CALLBACK(save), p);
+ p->shader.id[1] = g_signal_connect(p->tool.revert, "clicked", G_CALLBACK(revert), p);
+ p->shader.id[2] = g_signal_connect(p->tool.enable, "clicked", G_CALLBACK(enable), p);
+ p->shader.id[3] = g_signal_connect(p->tool.disable, "clicked", G_CALLBACK(disable), p);
+
+ gtk_widget_show(GTK_WIDGET(p->main.textview));
+ gtk_widget_show(p->main.textview_scrolled);
+
+ if (p->shader.info)
+ shader_stop_info_action(p->shader.info, p);
+
+ shader_start_info_action(p->selected.parent, p->selected.id, &p->selected.iter, p);
+}
+
+void shader_unselected(struct program *p)
+{
+ g_signal_handler_disconnect(p->tool.save, p->shader.id[0]);
+ g_signal_handler_disconnect(p->tool.revert, p->shader.id[1]);
+ g_signal_handler_disconnect(p->tool.enable, p->shader.id[2]);
+ g_signal_handler_disconnect(p->tool.disable, p->shader.id[3]);
+
+ gtk_widget_hide(p->tool.enable);
+ gtk_widget_hide(p->tool.disable);
+ gtk_widget_hide(p->tool.save);
+ gtk_widget_hide(p->tool.revert);
+ gtk_widget_hide(GTK_WIDGET(p->main.textview));
+ gtk_widget_hide(p->main.textview_scrolled);
+}
+
+void shader_list(GtkTreeStore *store, GtkTreeIter *parent,
+ rbug_context_t ctx, struct program *p)
+{
+ shader_start_list_action(store, parent, ctx, p);
+}
+
+
+/*
+ * Action fuctions
+ */
+
+struct shader_action_info
+{
+ struct rbug_event e;
+
+ rbug_context_t cid;
+ rbug_shader_t sid;
+
+ GtkTreeIter iter;
+
+ gboolean running;
+ gboolean pending;
+};
+
+static void shader_action_info_clean(struct shader_action_info *action, struct program *p)
+{
+ if (!action)
+ return;
+
+ if (p->shader.info == action)
+ p->shader.info = NULL;
+
+ g_free(action);
+}
+
+static void shader_action_info_info(struct rbug_event *e,
+ struct rbug_header *header,
+ struct program *p)
+{
+ struct rbug_proto_shader_info_reply *info;
+ struct shader_action_info *action;
+ GdkPixbuf *buf = NULL;
+
+ info = (struct rbug_proto_shader_info_reply *)header;
+ action = (struct shader_action_info *)e;
+
+ /* ack pending message */
+ action->pending = FALSE;
+
+ if (info->disabled) {
+ if (info->replaced_len == 0)
+ buf = icon_get("shader_off_normal", p);
+ else
+ buf = icon_get("shader_off_replaced", p);
+ } else {
+ if (info->replaced_len == 0)
+ buf = icon_get("shader_on_normal", p);
+ else
+ buf = icon_get("shader_on_replaced", p);
+ }
+ gtk_tree_store_set(p->main.treestore, &action->iter, COLUMN_PIXBUF, buf, -1);
+
+ if (p->selected.id != action->sid)
+ goto out;
+
+ update_text(info, p);
+
+ if (info->disabled) {
+ gtk_widget_hide(p->tool.disable);
+ gtk_widget_show(p->tool.enable);
+ } else {
+ gtk_widget_show(p->tool.disable);
+ gtk_widget_hide(p->tool.enable);
+ }
+ gtk_widget_show(p->tool.save);
+ if (info->replaced_len > 0)
+ gtk_widget_show(p->tool.revert);
+
+out:
+ shader_action_info_clean(action, p);
+}
+
+static struct shader_action_info *
+shader_start_info_action(rbug_context_t c,
+ rbug_shader_t s,
+ GtkTreeIter *iter,
+ struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ struct shader_action_info *action;
+ uint32_t serial = 0;
+
+ action = g_malloc(sizeof(*action));
+ memset(action, 0, sizeof(*action));
+
+ rbug_send_shader_info(con, c, s, &serial);
+
+ action->e.func = shader_action_info_info;
+ action->cid = c;
+ action->sid = s;
+ action->iter = *iter;
+ action->pending = TRUE;
+ action->running = TRUE;
+
+ rbug_add_event(&action->e, serial, p);
+
+ return action;
+}
+
+static void shader_stop_info_action(struct shader_action_info *action, struct program *p)
+{
+ action->running = FALSE;
+
+ if (p->shader.info == action)
+ p->shader.info = NULL;
+
+ if (!action->pending)
+ shader_action_info_clean(action, p);
+}
+
+struct shader_action_list
+{
+ struct rbug_event e;
+
+ rbug_context_t ctx;
+
+ GtkTreeStore *store;
+ GtkTreeIter parent;
+};
+
+static void shader_action_list_list(struct rbug_event *e,
+ struct rbug_header *header,
+ struct program *p)
+{
+
+ struct rbug_proto_shader_list_reply *list;
+ struct shader_action_list *action;
+ GtkTreeStore *store;
+ GtkTreeIter *parent;
+ uint32_t i;
+
+ action = (struct shader_action_list *)e;
+ list = (struct rbug_proto_shader_list_reply *)header;
+ parent = &action->parent;
+ store = action->store;
+
+ for (i = 0; i < list->shaders_len; i++) {
+ GtkTreeIter iter;
+ gtk_tree_store_insert_with_values(store, &iter, parent, -1,
+ COLUMN_ID, list->shaders[i],
+ COLUMN_TYPE, TYPE_SHADER,
+ COLUMN_TYPENAME, "shader",
+ -1);
+
+ shader_start_info_action(action->ctx, list->shaders[i], &iter, p);
+ }
+
+ g_free(action);
+}
+
+static void shader_start_list_action(GtkTreeStore *store, GtkTreeIter *parent,
+ rbug_context_t ctx, struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ struct shader_action_list *action;
+ uint32_t serial = 0;
+
+ action = g_malloc(sizeof(*action));
+ memset(action, 0, sizeof(*action));
+
+ rbug_send_shader_list(con, ctx, &serial);
+
+ action->e.func = shader_action_list_list;
+ action->ctx = ctx;
+ action->store = store;
+ action->parent = *parent;
+
+ rbug_add_event(&action->e, serial, p);
+}
diff --git a/src/texture.c b/src/texture.c
new file mode 100644
index 0000000..d9e7237
--- /dev/null
+++ b/src/texture.c
@@ -0,0 +1,550 @@
+
+#include "program.h"
+
+#include "GL/gl.h"
+
+#include "pipe/p_format.h"
+
+/* needed for u_tile */
+#include "pipe/p_state.h"
+#include "util/u_tile.h"
+
+enum {
+ BACK_MIN = 0,
+ BACK_CHECKER = 0,
+ BACK_BLACK,
+ BACK_WHITE,
+ BACK_MAX,
+};
+
+
+/*
+ * Actions
+ */
+
+
+static void texture_stop_read_action(struct texture_action_read *action,
+ struct program *p);
+static void texture_start_if_new_read_action(rbug_texture_t t,
+ GtkTreeIter *iter,
+ struct program *p);
+static struct texture_action_read *
+texture_start_read_action(rbug_texture_t t,
+ GtkTreeIter *iter,
+ struct program *p);
+
+static void texture_start_list_action(GtkTreeStore *store,
+ GtkTreeIter *parent,
+ struct program *p);
+
+
+/*
+ * Private
+ */
+
+
+static void alpha(GtkWidget *widget, struct program *p)
+{
+ (void)widget;
+
+ p->texture.alpha = !p->texture.alpha;
+
+ gtk_widget_queue_draw(GTK_WIDGET(p->main.draw));
+}
+
+static void automatic(GtkWidget *widget, struct program *p)
+{
+ (void)widget;
+
+ p->texture.automatic = !p->texture.automatic;
+
+ if (p->texture.automatic)
+ texture_start_if_new_read_action(p->selected.id, &p->selected.iter, p);
+}
+
+static void background(GtkWidget *widget, struct program *p)
+{
+ (void)widget;
+ (void)p;
+
+ if (++p->texture.back >= BACK_MAX)
+ p->texture.back = BACK_MIN;
+
+ gtk_widget_queue_draw(GTK_WIDGET(p->main.draw));
+}
+
+
+/*
+ * Exported
+ */
+
+
+void texture_list(GtkTreeStore *store, GtkTreeIter *parent, struct program *p)
+{
+ texture_start_list_action(store, parent, p);
+}
+
+void texture_refresh(struct program *p)
+{
+ texture_start_if_new_read_action(p->selected.id, &p->selected.iter, p);
+}
+
+void texture_draw(struct program *p)
+{
+ uint32_t w, h;
+
+ draw_ortho_top_left(p);
+
+ switch (p->texture.back) {
+ case BACK_CHECKER:
+ draw_checker(60, 60, p);
+ break;
+ case BACK_BLACK:
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ break;
+ case BACK_WHITE:
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ break;
+ default:
+ break;
+ }
+
+ if (p->texture.id != p->selected.id)
+ return;
+
+ w = p->texture.width;
+ h = p->texture.height;
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if (p->texture.alpha)
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+
+ glColor3f(1.0, 1.0, 1.0);
+ glBegin(GL_QUADS);
+ glTexCoord2f( 0, 1);
+ glVertex2f (10 , 10 + h);
+ glTexCoord2f( 1, 1);
+ glVertex2f (10 + w, 10 + h);
+ glTexCoord2f( 1, 0);
+ glVertex2f (10 + w, 10 );
+ glTexCoord2f( 0, 0);
+ glVertex2f (10 , 10 );
+ glEnd();
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+ if (p->texture.automatic)
+ texture_start_if_new_read_action(p->selected.id, &p->selected.iter, p);
+}
+
+void texture_unselected(struct program *p)
+{
+ (void)p;
+
+ gtk_widget_hide(p->tool.alpha);
+ gtk_widget_hide(p->tool.automatic);
+ gtk_widget_hide(p->tool.background);
+ gtk_widget_hide(GTK_WIDGET(p->main.draw));
+
+ p->texture.alpha = TRUE;
+ p->texture.automatic = FALSE;
+ p->texture.back = BACK_CHECKER;
+
+ g_signal_handler_disconnect(p->tool.alpha, p->texture.tid[0]);
+ g_signal_handler_disconnect(p->tool.automatic, p->texture.tid[1]);
+ g_signal_handler_disconnect(p->tool.background, p->texture.tid[2]);
+}
+
+void texture_selected(struct program *p)
+{
+ g_assert(p->selected.type == TYPE_TEXTURE);
+
+ texture_start_if_new_read_action(p->selected.id, &p->selected.iter, p);
+
+ gtk_widget_show(p->tool.alpha);
+ gtk_widget_show(p->tool.automatic);
+ gtk_widget_show(p->tool.background);
+ gtk_widget_show(GTK_WIDGET(p->main.draw));
+
+ p->texture.alpha = TRUE;
+ p->texture.automatic = FALSE;
+ p->texture.back = BACK_CHECKER;
+
+ p->texture.tid[0] = g_signal_connect(p->tool.alpha, "clicked", G_CALLBACK(alpha), p);
+ p->texture.tid[1] = g_signal_connect(p->tool.automatic, "clicked", G_CALLBACK(automatic), p);
+ p->texture.tid[2] = g_signal_connect(p->tool.background, "clicked", G_CALLBACK(background), p);
+}
+
+/*
+ * Actions
+ */
+
+struct texture_action_read
+{
+ struct rbug_event e;
+
+ rbug_texture_t id;
+
+ GtkTreeIter iter;
+
+ gboolean running;
+ gboolean pending;
+
+ unsigned width;
+ unsigned height;
+ unsigned stride;
+ enum pipe_format format;
+ struct pipe_format_block block;
+ void *data;
+};
+
+static void texture_action_read_clean(struct texture_action_read *action,
+ struct program *p)
+{
+ if (!action)
+ return;
+
+ if (p->texture.read == action)
+ p->texture.read = NULL;
+
+ g_free(action->data);
+ g_free(action);
+}
+
+static void texture_action_read_upload(struct texture_action_read *action,
+ struct program *p)
+{
+#if 0
+ GLint format, internal_format, type;
+ unsigned needed_stride;
+ uint32_t w, h, i;
+
+ if (!action)
+ return;
+
+ w = action->width;
+ h = action->height;
+
+ if (action->block.size != 4)
+ return;
+
+ if (pf_has_alpha(action->format)) {
+ internal_format = 4;
+ format = GL_BGRA;
+ type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ } else {
+ internal_format = 3;
+ format = GL_BGR;
+ type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+
+ needed_stride = pf_get_nblocksx(&action->block, w) * action->block.size;
+
+ if (action->stride % action->block.size)
+ g_print("warning stride not mupltiple of block.size\n");
+ if (w % action->block.width)
+ g_print("warning width not multiple of block.width\n");
+ if (h % action->block.height)
+ g_print("warning height not multiple of block.height\n");
+
+ /* bad stride */
+ if (action->stride > needed_stride) {
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
+ w, h, 0,
+ format, type, NULL);
+
+ for (i = 0; i < h; i += action->block.height) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, i, w, action->block.height,
+ format, type, action->data + action->stride * i);
+ }
+ } else if (action->stride == needed_stride) {
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
+ w, h, 0,
+ format, type, action->data);
+ } else {
+ g_assert(0);
+ }
+#endif
+ GLint format, internal_format, type;
+ uint32_t w, h, step_h, i;
+ uint32_t dst_stride, src_stride;
+ float *rgba;
+ void *data;
+
+ if (!action)
+ return;
+
+ data = action->data;
+ w = action->width;
+ h = action->height;
+ step_h = action->block.height;
+ src_stride = action->stride;
+ dst_stride = 4 * 4 * w;
+ rgba = g_malloc(dst_stride * h);
+
+ for (i = 0; i < h; i += step_h) {
+ pipe_tile_raw_to_rgba(action->format, data + src_stride * i,
+ w, step_h,
+ &rgba[w * 4 * i], dst_stride);
+ }
+
+ internal_format = 4;
+ format = GL_RGBA;
+ type = GL_FLOAT;
+
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
+ w, h, 0,
+ format, type, rgba);
+
+ g_free(rgba);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ p->texture.id = action->id;
+ p->texture.width = action->width;
+ p->texture.height = action->height;
+}
+
+static void texture_action_read_read(struct rbug_event *e,
+ struct rbug_header *header,
+ struct program *p)
+{
+ struct rbug_proto_texture_read_reply *read;
+ struct texture_action_read *action;
+ size_t size;
+
+ read = (struct rbug_proto_texture_read_reply *)header;
+ action = (struct texture_action_read *)e;
+
+ /* ack pending message */
+ action->pending = FALSE;
+
+ if (header->opcode != RBUG_OP_TEXTURE_READ_REPLY) {
+ g_print("warning failed to read from texture\n");
+ goto error;
+ }
+
+ /* no longer interested in this action */
+ if (!action->running)
+ goto error;
+
+ /* calculate needed size */
+ size = pf_get_nblocksy(&action->block, action->height) * read->stride;
+
+ if (read->data_len < size)
+ goto error;
+
+ action->stride = read->stride;
+ action->data = g_malloc(size);
+ memcpy(action->data, read->data, size);
+
+ if (draw_gl_begin(p)) {
+ texture_action_read_upload(action, p);
+ draw_gl_end(p);
+ gtk_widget_queue_draw(GTK_WIDGET(p->main.draw));
+
+ texture_action_read_clean(action, p);
+ } else {
+ g_assert(0);
+ texture_action_read_clean(action, p);
+ }
+
+ return;
+
+error:
+ texture_stop_read_action(action, p);
+}
+
+static void texture_action_read_info(struct rbug_event *e,
+ struct rbug_header *header,
+ struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ struct rbug_proto_texture_info_reply *info;
+ struct texture_action_read *action;
+ uint32_t serial = 0;
+
+ info = (struct rbug_proto_texture_info_reply *)header;
+ action = (struct texture_action_read *)e;
+
+ /* ack pending message */
+ action->pending = FALSE;
+
+ if (header->opcode != RBUG_OP_TEXTURE_INFO_REPLY) {
+ g_print("warning failed to get info from texture\n");
+ goto error;
+ }
+
+ if (pf_layout(info->format) == PIPE_FORMAT_LAYOUT_RGBAZS) {
+ GdkPixbuf *buf = NULL;
+
+ int swz = (info->format >> 2) & 0xFFF;
+ if (!swz)
+ ;
+ else if (swz == _PIPE_FORMAT_RGBA)
+ buf = icon_get("rgba", p);
+ else if (swz == _PIPE_FORMAT_RGB1)
+ buf = icon_get("rgbx", p);
+ else if (swz == _PIPE_FORMAT_ARGB)
+ buf = icon_get("argb", p);
+ else if (swz == _PIPE_FORMAT_1RGB)
+ buf = icon_get("xrgb", p);
+ else if (swz == _PIPE_FORMAT_000R)
+ buf = icon_get("rgba", p);
+
+ else if (swz == _PIPE_FORMAT_SZ00)
+ buf = icon_get("s8z24", p);
+ else if (swz == _PIPE_FORMAT_0Z00)
+ buf = icon_get("x8z24", p);
+ else if (swz == _PIPE_FORMAT_ZS00)
+ buf = icon_get("z24s8", p);
+ else if (swz == _PIPE_FORMAT_Z000)
+ buf = icon_get("z24x8", p);
+
+ gtk_tree_store_set(p->main.treestore, &action->iter, COLUMN_PIXBUF, buf, -1);
+ }
+
+ /* no longer interested in this action */
+ if (!action->running || p->texture.read != action)
+ goto error;
+
+ action->width = info->width[0];
+ action->height = info->height[0];
+ action->block.width = info->blockw;
+ action->block.height = info->blockh;
+ action->block.size = info->blocksize;
+ action->format = info->format;
+
+ rbug_send_texture_read(con, action->id,
+ 0, 0, 0,
+ 0, 0, action->width, action->height,
+ &serial);
+ /* new message pending */
+ action->pending = TRUE;
+
+ /* hock up event callback */
+ action->e.func = texture_action_read_read;
+ rbug_add_event(&action->e, serial, p);
+
+ return;
+
+error:
+ texture_stop_read_action(action, p);
+}
+
+static void texture_stop_read_action(struct texture_action_read *action, struct program *p)
+{
+ if (p->texture.read == action)
+ p->texture.read = NULL;
+
+ action->running = FALSE;
+
+ /* no actions pending that will call into this action clean it */
+ if (!action->pending)
+ texture_action_read_clean(action, p);
+}
+
+static void texture_start_if_new_read_action(rbug_texture_t t,
+ GtkTreeIter *iter,
+ struct program *p)
+{
+ /* are we currently trying download anything? */
+ if (p->texture.read) {
+ /* ok we are downloading something, but is it the one we want? */
+ if (p->texture.read->id == p->selected.id) {
+ /* don't need to do anything */
+ return;
+ } else {
+ texture_stop_read_action(p->texture.read, p);
+ }
+ }
+
+ p->texture.read = texture_start_read_action(t, iter, p);
+}
+
+static struct texture_action_read *
+texture_start_read_action(rbug_texture_t t, GtkTreeIter *iter, struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ struct texture_action_read *action;
+ uint32_t serial = 0;
+
+ action = g_malloc(sizeof(*action));
+ memset(action, 0, sizeof(*action));
+
+ rbug_send_texture_info(con, t, &serial);
+
+ action->e.func = texture_action_read_info;
+ action->id = t;
+ action->iter = *iter;
+ action->pending = TRUE;
+ action->running = TRUE;
+
+ rbug_add_event(&action->e, serial, p);
+
+ return action;
+}
+
+struct texture_action_list
+{
+ struct rbug_event e;
+
+ GtkTreeStore *store;
+ GtkTreeIter parent;
+};
+
+static void texture_action_list_list(struct rbug_event *e,
+ struct rbug_header *header,
+ struct program *p)
+{
+
+ struct rbug_proto_texture_list_reply *list;
+ struct texture_action_list *action;
+ GtkTreeStore *store;
+ GtkTreeIter *parent;
+ uint32_t i;
+
+ action = (struct texture_action_list *)e;
+ list = (struct rbug_proto_texture_list_reply *)header;
+ parent = &action->parent;
+ store = action->store;
+
+ for (i = 0; i < list->textures_len; i++) {
+ GtkTreeIter iter;
+ gtk_tree_store_insert_with_values(store, &iter, parent, -1,
+ COLUMN_ID, list->textures[i],
+ COLUMN_TYPE, TYPE_TEXTURE,
+ COLUMN_TYPENAME, "texture",
+ -1);
+
+ texture_start_read_action(list->textures[i], &iter, p);
+ }
+
+ g_free(action);
+}
+
+static void texture_start_list_action(GtkTreeStore *store, GtkTreeIter *parent, struct program *p)
+{
+ struct rbug_connection *con = p->rbug.con;
+ struct texture_action_list *action;
+ uint32_t serial = 0;
+
+ action = g_malloc(sizeof(*action));
+ memset(action, 0, sizeof(*action));
+
+ rbug_send_texture_list(con, &serial);
+
+ action->e.func = texture_action_list_list;
+ action->store = store;
+ action->parent = *parent;
+
+ rbug_add_event(&action->e, serial, p);
+}