diff --git a/src/util/debugwindow.cpp b/src/util/debugwindow.cpp new file mode 100644 index 0000000..349fadc --- /dev/null +++ b/src/util/debugwindow.cpp @@ -0,0 +1,238 @@ +/* + * bitvis + * Copyright (C) Bob 2013 + * + * bitvis is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * bitvis is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "debugwindow.h" +#include "lock.h" +#include "log.h" +#include "timeutils.h" +#include "inclstdint.h" + +#include +#include + +CDebugWindow::CDebugWindow() +{ + m_scale = 0; + m_dpy = NULL; + m_width = 0; + m_height = 0; + m_pixmap = None; + m_srcformat = NULL; + m_dstformat = NULL; + m_srcpicture = None; + m_dstpicture = None; + memset(&m_pictattr, 0, sizeof(m_pictattr)); + memset(&m_transform, 0, sizeof(m_transform)); + memset(&m_rootattr, 0, sizeof(m_rootattr)); + m_xim = NULL; + m_window = None; + m_rootwin = None; + m_gc = None; +} + +CDebugWindow::~CDebugWindow() +{ +} + +void CDebugWindow::Enable(int width, int height, int scale) +{ + Disable(); + + m_width = width; + m_height = height; + m_scale = scale; + + StartThread(); +} + +void CDebugWindow::Disable() +{ + AsyncStopThread(); + m_condition.Signal(); + StopThread(); +} + +void CDebugWindow::DisplayFrame(CTcpData& data) +{ + if (m_running) + { + CLock lock(m_condition); + m_data = data; + m_condition.Signal(); + } +} + +void CDebugWindow::Process() +{ + if (!Setup()) + { + Cleanup(); + return; + } + + ProcessInternal(); + Cleanup(); +} + +bool CDebugWindow::Setup() +{ + m_dpy = XOpenDisplay(NULL); + if (m_dpy == NULL) + { + LogError("Unable to open display"); + return false; + } + + m_window = XCreateSimpleWindow(m_dpy, RootWindow(m_dpy, DefaultScreen(m_dpy)), + 0, 0, m_width * m_scale, m_height * m_scale, 0, 0, 0); + XMapWindow(m_dpy, m_window); + XFlush(m_dpy); + + m_rootwin = RootWindow(m_dpy, DefaultScreen(m_dpy)); + XGetWindowAttributes(m_dpy, m_rootwin, &m_rootattr); + m_gc = XCreateGC(m_dpy, m_window, 0, NULL); + m_pixmap = XCreatePixmap(m_dpy, m_rootwin, m_width, m_height, m_rootattr.depth); + m_srcformat = XRenderFindVisualFormat(m_dpy, m_rootattr.visual); + m_dstformat = XRenderFindVisualFormat(m_dpy, m_rootattr.visual); + m_srcpicture = XRenderCreatePicture(m_dpy, m_pixmap, m_srcformat, CPRepeat, &m_pictattr); + m_dstpicture = XRenderCreatePicture(m_dpy, m_window, m_dstformat, CPRepeat, &m_pictattr); + XRenderSetPictureFilter(m_dpy, m_srcpicture, "nearest", NULL, 0); + + m_xim = XCreateImage(m_dpy, m_rootattr.visual, m_rootattr.depth, ZPixmap, 0, NULL, m_width, m_height, 8, m_width * 4); + m_xim->data = (char*)malloc(m_width * m_height * 4); + memset(m_xim->data, 0, m_width * m_height * 4); + + m_transform.matrix[0][0] = m_width; + m_transform.matrix[1][1] = m_width; + m_transform.matrix[2][2] = m_width * m_scale; + + return true; +} + +void CDebugWindow::Cleanup() +{ + if (m_xim) + { + XDestroyImage(m_xim); + m_xim = NULL; + } + + if (m_dstpicture != None) + { + XRenderFreePicture(m_dpy, m_dstpicture); + m_dstpicture = None; + } + + if (m_srcpicture != None) + { + XRenderFreePicture(m_dpy, m_srcpicture); + m_srcpicture = None; + } + + if (m_pixmap != None) + { + XFreePixmap(m_dpy, m_pixmap); + m_pixmap = None; + } + + if (m_gc != None) + { + XFreeGC(m_dpy, m_gc); + m_gc = None; + } + + if (m_window != None) + { + XDestroyWindow(m_dpy, m_window); + m_window = None; + } + + if (m_dpy) + { + XCloseDisplay(m_dpy); + m_dpy = NULL; + } +} + +void CDebugWindow::ProcessInternal() +{ + bool render = true; + int count = -3; + int xcount = 0; + int ycount = 0; + while (!m_stop) + { + if (render) + { + XPutImage(m_dpy, m_pixmap, m_gc, m_xim, 0, 0, 0, 0, m_width, m_height); + + XRenderSetPictureTransform (m_dpy, m_srcpicture, &m_transform); + XRenderComposite(m_dpy, PictOpSrc, m_srcpicture, None, m_dstpicture, + 0, 0, 0, 0, 0, 0, m_width * m_scale, m_height * m_scale); + + XFlush(m_dpy); + render = false; + } + + CLock lock(m_condition); + m_condition.Wait(); + CTcpData data = m_data; + lock.Leave(); + + int size = m_data.GetSize(); + uint8_t* dataptr = (uint8_t*)m_data.GetData(); + for (int i = 0; i < size; i++) + { + if (count == -3) + { + if (dataptr[i] == ':') + count++; + } + else if (count == -2 || count == -1) + { + if (dataptr[i] == '0') + count++; + else + count = -3; + } + else + { + uint8_t* pixelptr = (uint8_t*)m_xim->data + ycount * m_xim->bytes_per_line + xcount * 4; + for (int j = 0; j < 4; j++) + { + pixelptr++; + *(pixelptr++) = ((dataptr[i] >> (j * 2)) & 1) ? 0xFF : 0; + *(pixelptr++) = ((dataptr[i] >> (j * 2 + 1)) & 1) ? 0xFF : 0; + pixelptr++; + xcount++; + if (xcount == m_width) + { + xcount = 0; + ycount++; + if (ycount == m_height) + { + render = true; + count = -3; + ycount = 0; + } + } + } + } + } + } +} diff --git a/src/util/debugwindow.h b/src/util/debugwindow.h new file mode 100644 index 0000000..95631b5 --- /dev/null +++ b/src/util/debugwindow.h @@ -0,0 +1,67 @@ +/* + * bitvis + * Copyright (C) Bob 2013 + * + * bitvis is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * bitvis is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef DEBUGWINDOW_H +#define DEBUGWINDOW_H + +#include "thread.h" +#include "condition.h" +#include "tcpsocket.h" + +#include +#include + +class CDebugWindow : public CThread +{ + public: + CDebugWindow(); + ~CDebugWindow(); + + void Enable(int width, int height, int scale); + void Disable(); + void DisplayFrame(CTcpData& data); + + void Process(); + + private: + bool Setup(); + void ProcessInternal(); + void Cleanup(); + + int m_scale; + CCondition m_condition; + CTcpData m_data; + + Display* m_dpy; + int m_width; + int m_height; + Window m_rootwin; + XWindowAttributes m_rootattr; + Pixmap m_pixmap; + XRenderPictFormat* m_srcformat; + XRenderPictFormat* m_dstformat; + Picture m_srcpicture; + Picture m_dstpicture; + XRenderPictureAttributes m_pictattr; + XTransform m_transform; + XImage* m_xim; + Window m_window; + GC m_gc; +}; + +#endif //DEBUGWINDOW_H diff --git a/wscript b/wscript index 09eeb64..5321822 100644 --- a/wscript +++ b/wscript @@ -61,11 +61,14 @@ def build(bld): bld.program(source='src/bitx11/main.cpp\ src/bitx11/bitx11.cpp\ + src/util/debugwindow.cpp\ src/util/log.cpp\ src/util/misc.cpp\ src/util/mutex.cpp\ src/util/timeutils.cpp\ - src/util/tcpsocket.cpp', + src/util/condition.cpp\ + src/util/tcpsocket.cpp\ + src/util/thread.cpp', use=['m', 'rt', 'X11', 'Xrender', 'Xext'], includes='./src', cxxflags='-Wall -g -DUTILNAMESPACE=BitX11Util',