/* * 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() { Disable(); } 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; } } } } } } }