Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

371 lines (292 sloc) 9.104 kb
//////////////////////////////////////////////////////////////////////
// //
// VideoDisplay - Cheap and cheeful way of creating a GL X //
// display //
// //
// Tom Drummong & Paul Smith 2002 //
// //
//////////////////////////////////////////////////////////////////////
#include "cvd/videodisplay.h"
//#include <cmath>
//#include <cstdlib>
//#include <iostream>
//#include <cassert>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
using namespace std;
using namespace CVD;
CVD::Exceptions::VideoDisplay::InitialisationError::InitialisationError(string w)
{
what="VideoDisplay inintialisation error: " + w;
}
CVD::Exceptions::VideoDisplay::RuntimeError::RuntimeError(string w)
{
what="VideoDisplay error: " + w;
}
//namespace CVD {
int CVD::defAttr[] = {GLX_RGBA,
GLX_RED_SIZE, 3,
GLX_GREEN_SIZE, 3,
GLX_BLUE_SIZE, 2,
GLX_DOUBLEBUFFER, 0,
// GLX_DEPTH_SIZE, 8,
// GLX_STENCIL_SIZE, 8,
0};
CVD::VideoDisplay::VideoDisplay(double left, double top, double right, double bottom, double scale, int* visualAttr, bool map) :
my_left(left),
my_top(top),
my_right(right),
my_bottom(bottom),
my_scale(scale),
my_orig_left(left),
my_orig_top(top),
my_orig_right(right),
my_orig_bottom(bottom),
my_orig_scale(scale)
{
init(my_left, my_top, my_right, my_bottom, scale, visualAttr, map);
}
CVD::VideoDisplay::VideoDisplay(ImageRef s, double scale, int* visualAttr) :
my_left(0),
my_top(0),
my_right(s.x),
my_bottom(s.y),
my_scale(scale),
my_orig_left(0),
my_orig_top(0),
my_orig_right(s.x),
my_orig_bottom(s.y),
my_orig_scale(scale)
{
init(my_left, my_top, my_right, my_bottom, scale, visualAttr, true);
}
CVD::VideoDisplay::VideoDisplay(ImageRef s, const DoNotMapStruct&, int* visualAttr) :
my_left(0),
my_top(0),
my_right(s.x),
my_bottom(s.y),
my_scale(1.0),
my_orig_left(0),
my_orig_top(0),
my_orig_right(s.x),
my_orig_bottom(s.y),
my_orig_scale(1.0)
{
init(my_left, my_top, my_right, my_bottom, 1.0, visualAttr, false);
}
void CVD::VideoDisplay::init(double left, double top, double right, double bottom, double scale, int* visualAttr, bool map)
{
// Need these for converting mouse clicks efficiently
// (This stays the same even when zooming)
my_positive_right = right > left;
my_positive_down = bottom > top;
my_display = XOpenDisplay(NULL);
if (my_display == NULL)
throw Exceptions::VideoDisplay::InitialisationError(string("Can't connect to display ") + getenv("DISPLAY"));
// get an appropriate visual
my_visual = glXChooseVisual(my_display, DefaultScreen(my_display), visualAttr);
if (my_visual == NULL)
throw Exceptions::VideoDisplay::InitialisationError(string("No matching visual on display ") + getenv("DISPLAY"));
// check I got an rgba visual (32 bit)
int isRgba;
(void) glXGetConfig(my_display, my_visual, GLX_RGBA, &isRgba);
assert(isRgba);
// create a GLX context
if ((my_glx_context = glXCreateContext(my_display, my_visual, 0, GL_TRUE)) == NULL)
throw Exceptions::VideoDisplay::InitialisationError(string("Cannot create GL context on ") + getenv("DISPLAY"));
// create a colormap (it's empty for rgba visuals)
my_cmap = XCreateColormap(my_display,
RootWindow(my_display, my_visual->screen),
my_visual->visual,
AllocNone);
// set the attributes for the window
XSetWindowAttributes swa;
swa.colormap = my_cmap;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
// Work out how big the display is
int xsize = static_cast<int>(fabs(right - left) * scale);
int ysize = static_cast<int>(fabs(bottom - top) * scale);
// create a window
my_window = XCreateWindow(my_display,
RootWindow(my_display, my_visual->screen),
0, // init_x
0, // init_y
xsize,
ysize,
0,
my_visual->depth,
InputOutput,
my_visual->visual,
CWBorderPixel | CWColormap | CWEventMask, &swa);
if (my_window == 0)
throw Exceptions::VideoDisplay::InitialisationError(string("Cannot create a window on ") + getenv("DISPLAY"));
set_title("Video Display");
if(map)
{
XMapWindow(my_display, my_window);
// discard all event up to the MapNotify
XEvent ev;
do
{
XNextEvent(my_display,&ev);
}
while (ev.type != MapNotify);
}
// Connect the GLX context to the window
if (!glXMakeCurrent(my_display, my_window, my_glx_context))
throw Exceptions::VideoDisplay::InitialisationError("Cannot make window current to GL context");
XSelectInput(my_display,
my_window,
ButtonPressMask |
ButtonReleaseMask |
Button1MotionMask |
PointerMotionHintMask |
KeyPressMask);
// Sort out the GL scaling
glLoadIdentity();
glViewport(0, 0, xsize, ysize);
glColor3f(1.0, 1.0, 1.0);
glDrawBuffer(GL_FRONT); // On Vino, we only use the front buffer
set_zoom(left, top, right, bottom, scale);
}
void CVD::VideoDisplay::set_zoom(double left, double top, double right, double bottom, double scale)
{
// Make sure that this is the current window
make_current();
my_left = left;
my_top = top;
my_right = right;
my_bottom = bottom;
my_scale = scale;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(left, right, bottom, top, -1 , 1); // If the origin is the top left
glRasterPos2f(left, top);
// video is now the same way as upside down to graphics!
glPixelZoom(scale, -scale);
//glPixelZoom(1,-1);
}
void CVD::VideoDisplay::zoom_in(double cx, double cy, double factor)
{
double width = my_right - my_left;
double height = my_bottom - my_top;
//Work out the new half-widths
width = width / 2 / factor;
height = height / 2 / factor;
// Work out the new image corners. scale is how much things are zoomed up, so
// this is just multipled by the factor
set_zoom(cx - width, cy - height, cx + width, cy + height, my_scale * factor);
}
CVD::VideoDisplay::~VideoDisplay()
{
glXMakeCurrent(my_display, None, NULL);
glXDestroyContext(my_display, my_glx_context);
XUnmapWindow(my_display, my_window);
XDestroyWindow(my_display, my_window);
XFlush(my_display);
XCloseDisplay(my_display);
}
void CVD::VideoDisplay::set_title(const string& s)
{
// give the window a name
XStoreName(my_display, my_window, s.c_str());
}
void CVD::VideoDisplay::select_events(long event_mask){
XSelectInput(my_display, my_window, event_mask);
XFlush(my_display);
}
void CVD::VideoDisplay::flush(){
XFlush(my_display);
}
void CVD::VideoDisplay::get_event(XEvent* event){
XNextEvent(my_display, event);
}
int CVD::VideoDisplay::pending()
{
return XPending(my_display);
}
void CVD::VideoDisplay::make_current()
{
// Connect the GLX context to the window
if (!glXMakeCurrent(my_display, my_window, my_glx_context))
throw Exceptions::VideoDisplay::InitialisationError("Cannot make window current to GL context");
}
//
// DISPLAY TO VIDEO
// Converts a point on the display to the video's coordinates
//
void CVD::VideoDisplay::display_to_video(int dx, int dy, double& vx, double& vy)
{
vx = dx / my_scale;
if(my_positive_right)
vx = my_left + vx;
else
vx = my_left - vx;
vy = dy / my_scale;
if(my_positive_down)
vy = my_top + vy;
else
vy = my_top - vy;
}
//
// VIDEO TO DISPLAY
// Converts a point on the display to the video's coordinates
//
void CVD::VideoDisplay::video_to_display(double vx, double vy, int& dx, int& dy)
{
double ix, iy;
if(my_positive_right)
ix = vx - my_left;
else
ix = my_left - vx;
ix = ix * my_scale;
if(my_positive_down)
iy = vy - my_top;
else
iy = my_top - vy;
iy = iy * my_scale;
dx = static_cast<int>(ix);
dy = static_cast<int>(iy);
}
//
// LOCATE DISPLAY POINTER
// Where is the pointer in the window?
//
void CVD::VideoDisplay::locate_display_pointer(int& x, int& y)
{
Window root_return;
Window child_return;
int root_x_return;
int root_y_return;
unsigned int mask_return;
XQueryPointer(my_display,
my_window,
&root_return,
&child_return,
&root_x_return,
&root_y_return,
&x,
&y,
&mask_return);
}
//
// LOCATE DISPLAY POINTER
// Where is the pointer in the video frame?
//
void CVD::VideoDisplay::locate_video_pointer(double& x, double& y)
{
int dx, dy;
locate_display_pointer(dx, dy);
display_to_video(dx, dy, x, y);
}
void CVD::VideoDisplay::swap_buffers()
{
glXSwapBuffers(my_display, glXGetCurrentDrawable());
}
//} // namespace CVD
const VideoDisplay::DoNotMapStruct VideoDisplay::DoNotMap;
Jump to Line
Something went wrong with that request. Please try again.