Skip to content

Commit

Permalink
Add panning support, using a quadtree to cull blocks that lie outside…
Browse files Browse the repository at this point in the history
… the

rendered region.


git-svn-id: svn+ssh://truffle/home/andrew/repo/memview@36 6d4121a9-3ab8-48c6-8db9-97dca464e206
  • Loading branch information
ajclinto committed Dec 11, 2011
1 parent 31c3271 commit 4729526
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 68 deletions.
13 changes: 13 additions & 0 deletions Loader.C
Expand Up @@ -39,6 +39,9 @@ Loader::~Loader()
bool
Loader::openPipe(int argc, char *argv[])
{
if (mySource == TEST)
return true;

if (mySource == MEMVIEW_SHM)
{
int shm_fd;
Expand Down Expand Up @@ -150,6 +153,9 @@ Loader::run()
bool rval = false;
switch (mySource)
{
case TEST:
rval = loadFromTest();
break;
case LACKEY:
rval = loadFromLackey(10000);
break;
Expand Down Expand Up @@ -301,4 +307,11 @@ Loader::loadFromSharedMemory()
return count == theBlockSize;
}

bool
Loader::loadFromTest()
{
for (int i = 0; i < 1024*16; i++)
myState->updateAddress(i, 4, 'L');
return false;
}

4 changes: 3 additions & 1 deletion Loader.h
Expand Up @@ -23,6 +23,7 @@ class Loader : public QThread {
bool loadFromLackey(int max_read);
bool loadFromPipe();
bool loadFromSharedMemory();
bool loadFromTest();

private:
MemoryState *myState;
Expand All @@ -40,7 +41,8 @@ class Loader : public QThread {
enum LoadSource {
LACKEY,
MEMVIEW_PIPE,
MEMVIEW_SHM
MEMVIEW_SHM,
TEST
};

LoadSource mySource;
Expand Down
12 changes: 8 additions & 4 deletions Math.h
Expand Up @@ -5,19 +5,23 @@ typedef unsigned short uint16;
typedef unsigned uint32;
typedef unsigned long long uint64;

inline uint32 SYSmax(uint32 a, uint32 b)
template <typename T>
inline T SYSmax(T a, T b)
{
return a > b ? a : b;
}
inline uint32 SYSmin(uint32 a, uint32 b)
template <typename T>
inline T SYSmin(T a, T b)
{
return a < b ? a : b;
}
inline uint32 SYSclamp(uint32 v, uint32 a, uint32 b)
template <typename T>
inline T SYSclamp(T v, T a, T b)
{
return v < a ? a : (v > b ? b : v);
}
inline float SYSlerp(float v1, float v2, float bias)
template <typename T>
inline T SYSlerp(T v1, T v2, T bias)
{
return v1 + bias*(v2-v1);
}
Expand Down
168 changes: 109 additions & 59 deletions MemoryState.C
Expand Up @@ -144,12 +144,11 @@ putNextPixel(int &r, int &c, GLImage &image, uint32 val)
static const int theBlockSpacing = 1;

void
MemoryState::fillLinear(GLImage &image) const
MemoryState::fillLinear(GLImage &image, const QPoint &) const
{
int r = 0;
int c = 0;

// Assume that the stack occupies the top half of memory
StateIterator it(this);
for (it.rewind(); !it.atEnd(); it.advance())
{
Expand Down Expand Up @@ -261,101 +260,152 @@ private:

static BlockLUT theBlockLUT;

static const int theMinBlockWidth = 32;
static const int theMinBlockSize = theMinBlockWidth*theMinBlockWidth;

static bool
plotBlock(int &roff, int &coff, int &maxheight,
GLImage &image, const std::vector<uint32> &data)
void
MemoryState::QuadTree::addChild(int level, int r, int c, StateArray *arr)
{
// Determine the width and height of the result block
int bwidth, bheight;

getBlockSize(bwidth, bheight, data.size());

// Force a minimum size
bwidth = SYSmax(bwidth, theMinBlockWidth);
bheight = SYSmax(bheight, theMinBlockWidth);

// Does the block fit horizontally?
if (coff + bwidth > image.width())
if (level)
{
roff += maxheight + theBlockSpacing;
coff = 0;
maxheight = bheight;
int idx;

level--;
idx = r&(1<<level) ? 2 : 0;
idx |= c&(1<<level) ? 1 : 0;
if (!mySubtree[idx])
mySubtree[idx] = new QuadTree;
mySubtree[idx]->addChild(level, r, c, arr);
}
else
{
maxheight = SYSmax(maxheight, bheight);
myLeaf = arr;
}
}

if (roff > image.height())
return false;
QSize
MemoryState::QuadTree::computeWSize(int off)
{
QSize size(0, 0);
if (mySubtree[off])
{
size = mySubtree[off]->computeSize();
}
if (mySubtree[off+1])
{
QSize tmp(mySubtree[off+1]->computeSize());
size = QSize(size.width() + tmp.width(),
SYSmax(size.height(), tmp.height()));
}
return size;
}

// Display the block
for (int i = 0; i < (int)data.size(); i++)
QSize
MemoryState::QuadTree::computeSize()
{
if (myLeaf)
{
int r, c;
theBlockLUT.lookup(r, c, i);
r += roff;
c += coff;
if (r < image.height() && c < image.width())
image.setPixel(r, c, data[i]);
int width = 1<<(theBottomBits>>1);
mySize = QSize(width, width);
}
else
{
QSize tmp;

coff += bwidth + theBlockSpacing;
mySize = computeWSize(0);
tmp = computeWSize(2);

return true;
mySize = QSize(SYSmax(mySize.width(), tmp.width()),
mySize.height() + tmp.height());
}
return mySize;
}

void
MemoryState::fillRecursiveBlock(GLImage &image) const
MemoryState::QuadTree::render(GLImage &image,
const QPoint &off, const MemoryState &state) const
{
int r = 0;
int c = 0;
int maxheight = 0;
std::vector<uint32> pending;
QRect box(off, mySize);
QRect ibox(0, 0, image.width(), image.height());

StateIterator it(this);
for (it.rewind(); !it.atEnd(); it.advance())
// Culling
if (!box.intersects(ibox))
return;

if (myLeaf)
{
if (it.nempty() >= (uint64)theMinBlockSize)
// Display the block
for (uint32 i = 0; i < theBottomSize; i++)
{
if (pending.size())
if (myLeaf->myState[i])
{
// Plot the pending block
if (!plotBlock(r, c, maxheight, image, pending))
return;

// Reset
pending.clear();
int r, c;
theBlockLUT.lookup(r, c, i);
r += off.y();
c += off.x();
if (r >= 0 && r < image.height() &&
c >= 0 && c < image.width())
image.setPixel(r, c,
state.mapColor(myLeaf->myState[i],
myLeaf->myType[i]));
}
}
else
}
else
{
QPoint xoff = off;
QPoint yoff = off;
if (mySubtree[0])
{
pending.insert(pending.end(), it.nempty(), theBlack);
mySubtree[0]->render(image, off, state);
xoff = QPoint(off.x()+mySubtree[0]->getSize().width(), off.y());
yoff = QPoint(off.x(), off.y()+mySubtree[0]->getSize().height());
}

pending.push_back(mapColor(it.state(), it.type()));
if (mySubtree[1])
{
mySubtree[1]->render(image, xoff, state);
yoff = QPoint(off.x(), SYSmax(yoff.y(),
off.y()+mySubtree[1]->getSize().height()));
}
if (mySubtree[2])
{
mySubtree[2]->render(image, yoff, state);
yoff = QPoint(yoff.x()+mySubtree[2]->getSize().width(), yoff.y());
}
if (mySubtree[3])
mySubtree[3]->render(image, yoff, state);
}
}

if (pending.size())
plotBlock(r, c, maxheight, image, pending);
void
MemoryState::fillRecursiveBlock(GLImage &image, const QPoint &off) const
{
QuadTree tree;

// Build the quad-tree
for (uint32 i = 0; i < theTopSize; i++)
{
if (myTable[i])
{
int r, c;
theBlockLUT.lookup(r, c, i);
tree.addChild(theTopBits>>1, r, c, myTable[i]);
}
}
tree.computeSize();
tree.render(image, off, *this);
}

void
MemoryState::fillImage(GLImage &image) const
MemoryState::fillImage(GLImage &image, const QPoint &off) const
{
//StopWatch timer;
image.fill(theBlack);

switch (myVisualization)
{
case LINEAR:
fillLinear(image);
fillLinear(image, off);
break;
case BLOCK:
fillRecursiveBlock(image);
fillRecursiveBlock(image, off);
break;
}
}
Expand Down
35 changes: 32 additions & 3 deletions MemoryState.h
Expand Up @@ -20,7 +20,7 @@ class MemoryState {
};
void setVisualization(Visualization vis)
{ myVisualization = vis; }
void fillImage(GLImage &image) const;
void fillImage(GLImage &image, const QPoint &off) const;

void updateAddress(uint64 addr, int size, char type)
{
Expand All @@ -33,8 +33,8 @@ class MemoryState {
void incrementTime(int inc);

private:
void fillLinear(GLImage &image) const;
void fillRecursiveBlock(GLImage &image) const;
void fillLinear(GLImage &image, const QPoint &off) const;
void fillRecursiveBlock(GLImage &image, const QPoint &off) const;

typedef uint32 State;

Expand Down Expand Up @@ -178,6 +178,35 @@ class MemoryState {
uint64 myEmptyCount;
};

class QuadTree {
public:
QuadTree()
: myLeaf(0)
{
memset(mySubtree, 0, 4*sizeof(QuadTree *));
}
~QuadTree()
{
for (int i = 0; i < 4; i++)
delete mySubtree[i];
}

void addChild(int level, int r, int c, StateArray *arr);
QSize computeSize();
QSize getSize() const { return mySize; }

void render(GLImage &image, const QPoint &off, const
MemoryState &state) const;

private:
QSize computeWSize(int off);

private:
QuadTree *mySubtree[4];
StateArray *myLeaf;
QSize mySize;
};

private:
// Raw memory state
StateArray *myTable[theTopSize];
Expand Down
26 changes: 25 additions & 1 deletion Window.C
Expand Up @@ -83,7 +83,7 @@ MemViewWidget::paintGL()
{
//StopWatch timer;

myState->fillImage(myImage);
myState->fillImage(myImage, myRenderPos);

glDrawPixels(myImage.width(), myImage.height(), GL_BGRA,
GL_UNSIGNED_BYTE, myImage.data());
Expand All @@ -100,6 +100,30 @@ MemViewWidget::resizeEvent(QResizeEvent *)
}
}

void
MemViewWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
myDragPos = event->pos();
}

void
MemViewWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
myRenderPos += event->pos() - myDragPos;
myDragPos = event->pos();
}
}

void
MemViewWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
myRenderPos += event->pos() - myDragPos;
}

void
MemViewWidget::tick()
{
Expand Down

0 comments on commit 4729526

Please sign in to comment.