+
+int get_in_fd(void)
+{
+ static int fd = -1;
+
+ if(fd<0)
+ {
+ const char *var = getenv("GLWRAP_CTRL_FD");
+ if(var)
+ fd = strtol(var, NULL, 0);
+ else
+ fd = 0;
+ }
+
+ return fd;
+}
+
+static void receive_gldBreak(GlPacket *pkt)
+{
+ unsigned short func;
+ unsigned char flags_set;
+ unsigned char flags_clr;
+
+ packet_read_short(pkt, (short *)&func);
+ packet_read_char(pkt, (char *)&flags_set);
+ packet_read_char(pkt, (char *)&flags_clr);
+
+ if(func)
+ {
+ breakpoints[func] &= ~flags_clr;
+ breakpoints[func] |= flags_set;
+ }
+ else
+ break_any = flags_set;
+}
+
+static void receive_gldHold(GlPacket *pkt UNUSED)
+{
+ hold = 1;
+}
+
+static void receive_gldQueryViewport(GlPacket *pkt UNUSED)
+{
+ int viewport[4];
+
+ no_break = 1;
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ no_break = 0;
+}
+
+static void receive_gldReadPixels(GlPacket *pkt)
+{
+ GLint x, y;
+ GLsizei width, height;
+ GLenum format, type;
+ char *data;
+
+ packet_read_int(pkt, &x);
+ packet_read_int(pkt, &y);
+ packet_read_int(pkt, &width);
+ packet_read_int(pkt, &height);
+ packet_read_int(pkt, (int *)&format);
+ packet_read_int(pkt, (int *)&type);
+
+ data = (char *)malloc(width*height*typesize(type)*formatsize(format));
+ no_break = 1;
+ glReadPixels(x, y, width, height, format, type, data);
+ no_break = 0;
+ free(data);
+}
+
+static void receive(void)
+{
+ GlPacket *pkt;
+
+ while((pkt = packet_receive(get_in_fd())))
+ {
+ unsigned short func;
+
+ packet_read_short(pkt, (short *)&func);
+ switch(func)
+ {
+ case FUNC_GLDBREAK: receive_gldBreak(pkt); break;
+ case FUNC_GLDHOLD: receive_gldHold(pkt); break;
+ case FUNC_GLDQUERYVIEWPORT: receive_gldQueryViewport(pkt); break;
+ case FUNC_GLDREADPIXELS: receive_gldReadPixels(pkt); break;
+ default:;
+ }
+ }
+}
+
+void tracepoint(unsigned short func, int flag)
+{
+ int breakpoint;
+
+ if(no_break)
+ return;
+
+ receive();
+
+ breakpoint = (breakpoints[func]|break_any)&flag;
+ if(breakpoint || hold)
+ {
+ GlPacket *pkt;
+
+ if(breakpoint)
+ {
+ pkt = packet_begin(FUNC_GLDBREAK);
+ packet_write_short(pkt, func);
+ packet_write_char(pkt, flag);
+ packet_send(pkt, get_out_fd());
+ }
+
+ break_any = 0;
+
+ while(1)
+ {
+ hold = 0;
+ raise(SIGTRAP);
+ receive();
+ if(!hold)
+ break;
+ }
+ }
+}