Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 4 additions & 34 deletions PltApp.H
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ private:
XEvent nextEvent;
int rWidth, rHeight, rStartX, rStartY;
Cursor cursor;

// double buffering for rubber band
Pixmap rubberBandBackup;
Pixmap rubberBandBuffer;

static string defaultPaletteString, initialDerived, initialFormatString;
static string defaultLightingFilename;
Expand Down Expand Up @@ -343,40 +347,6 @@ private:
};


// -------------------------------------------------------------------
class AVXGrab {
public:
AVXGrab(Display *display) : bIsGrabbed(true), cachedDisplay(display) {
XSync(cachedDisplay, False);
XGrabServer(display);
XSync(cachedDisplay, False);
}

~AVXGrab() {
if(bIsGrabbed) {
std::cout << "_______in ~AVXGrab: implicit ungrab." << std::endl;
}
XUngrabServer(cachedDisplay);
XSync(cachedDisplay, False);
bIsGrabbed = false;
}

void ExplicitUngrab() {
if(bIsGrabbed == false) {
std::cout << "_______in AVXGrab::ExplicitUngrab: server not grabbed."
<< std::endl;
}
XUngrabServer(cachedDisplay);
XSync(cachedDisplay, False);
bIsGrabbed = false;
}

private:
AVXGrab(); // not implemented
bool bIsGrabbed;
Display *cachedDisplay;
};
// -------------------------------------------------------------------


void SubregionPltApp(Widget toplevel, const amrex::Box &region, const amrex::IntVect &offset,
Expand Down
251 changes: 182 additions & 69 deletions PltApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ PltApp::~PltApp() {
if(datasetShowing) {
delete datasetPtr;
}

// Cleanup double buffering resources
if(rubberBandBackup != None) {
XFreePixmap(XtDisplay(wTopLevel), rubberBandBackup);
}
if(rubberBandBuffer != None) {
XFreePixmap(XtDisplay(wTopLevel), rubberBandBuffer);
}

XtDestroyWidget(wAmrVisTopLevel);

// delete all the call back parameter structs
Expand Down Expand Up @@ -832,6 +841,10 @@ void PltApp::PltAppInit(bool bSubVolume) {
rbgc = XCreateGC(display, gaPtr->PRoot(), 0, NULL);
XSetFunction(display, rbgc, GXxor);
cursor = XCreateFontCursor(display, XC_left_ptr);

// Initialize double buffering variables
rubberBandBackup = None;
rubberBandBuffer = None;

// No need to store these widgets in the class after this function is called.
Widget wMainArea, wPalFrame, wPlotFrame, wPalForm;
Expand Down Expand Up @@ -3598,7 +3611,59 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)
XChangeActivePointerGrab(display, PointerMotionHintMask |
ButtonMotionMask | ButtonReleaseMask |
OwnerGrabButtonMask, cursor, CurrentTime);
AVXGrab avxGrab(display);
XSync(display, False);

// Setup double buffering for rubber band - handle all 3D planes
Window activeWindow = amrPicturePtrArray[V]->PictureWindow();
int bufferWidth = amrPicturePtrArray[V]->ImageSizeH();
int bufferHeight = amrPicturePtrArray[V]->ImageSizeV();

// Create double buffering for main active plane
rubberBandBackup = XCreatePixmap(display, activeWindow, bufferWidth, bufferHeight,
DefaultDepth(display, DefaultScreen(display)));
rubberBandBuffer = XCreatePixmap(display, activeWindow, bufferWidth, bufferHeight,
DefaultDepth(display, DefaultScreen(display)));

// Create GC for copying (always create fresh for this operation)
GC copyGC = XCreateGC(display, activeWindow, 0, NULL);

// Copy original window contents to backup
XCopyArea(display, activeWindow, rubberBandBackup, copyGC,
0, 0, bufferWidth, bufferHeight, 0, 0);

// Declare 3D plane variables (needed for cleanup scope)
Pixmap planeBackup[amrex::Amrvis::NPLANES];
Pixmap planeBuffer[amrex::Amrvis::NPLANES];
GC planeGC[amrex::Amrvis::NPLANES];

// Initialize arrays to None
for(int i = 0; i < amrex::Amrvis::NPLANES; ++i) {
planeBackup[i] = None;
planeBuffer[i] = None;
planeGC[i] = None;
}

#if (BL_SPACEDIM == 3)
// Create double buffering for additional 3D planes

for(int plane = 0; plane < amrex::Amrvis::NPLANES; ++plane) {
if(plane != V) { // Skip the main plane, already handled above
Window planeWindow = amrPicturePtrArray[plane]->PictureWindow();
int planeWidth = amrPicturePtrArray[plane]->ImageSizeH();
int planeHeight = amrPicturePtrArray[plane]->ImageSizeV();

planeBackup[plane] = XCreatePixmap(display, planeWindow, planeWidth, planeHeight,
DefaultDepth(display, DefaultScreen(display)));
planeBuffer[plane] = XCreatePixmap(display, planeWindow, planeWidth, planeHeight,
DefaultDepth(display, DefaultScreen(display)));
planeGC[plane] = XCreateGC(display, planeWindow, 0, NULL);

// Copy original contents to backup
XCopyArea(display, planeWindow, planeBackup[plane], planeGC[plane],
0, 0, planeWidth, planeHeight, 0, 0);
}
}
#endif

if(servingButton == 1) {
if(bShiftDown) {
Expand All @@ -3619,47 +3684,7 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)

case MotionNotify:

if(rectDrawn) { // undraw the old rectangle(s)
rWidth = std::abs(oldX-anchorX);
rHeight = std::abs(oldY-anchorY);
rStartX = (anchorX < oldX) ? anchorX : oldX;
rStartY = (anchorY < oldY) ? anchorY : oldY;
XDrawRectangle(display, amrPicturePtrArray[V]->PictureWindow(),
rbgc, rStartX, rStartY, rWidth, rHeight);
#if (BL_SPACEDIM == 3)
// 3D sub domain selecting
switch (V) {
case Amrvis::ZPLANE:
XDrawRectangle(display, amrPicturePtrArray[Amrvis::YPLANE]->PictureWindow(),
rbgc, rStartX, startcutY[Amrvis::YPLANE], rWidth,
std::abs(finishcutY[Amrvis::YPLANE]-startcutY[Amrvis::YPLANE]));
rStartPlane = (anchorY < oldY) ? oldY : anchorY;
XDrawRectangle(display, amrPicturePtrArray[Amrvis::XPLANE]->PictureWindow(),
rbgc, imageHeight-rStartPlane, startcutY[Amrvis::XPLANE],
rHeight,
std::abs(finishcutY[Amrvis::XPLANE]-startcutY[Amrvis::XPLANE]));
break;
case Amrvis::YPLANE:
XDrawRectangle(display, amrPicturePtrArray[Amrvis::ZPLANE]->PictureWindow(),
rbgc, rStartX, startcutY[Amrvis::ZPLANE], rWidth,
std::abs(finishcutY[Amrvis::ZPLANE]-startcutY[Amrvis::ZPLANE]));
XDrawRectangle(display, amrPicturePtrArray[Amrvis::XPLANE]->PictureWindow(),
rbgc, startcutX[Amrvis::XPLANE], rStartY,
std::abs(finishcutX[Amrvis::XPLANE]-startcutX[Amrvis::XPLANE]),
rHeight);
break;
default: // Amrvis::XPLANE
rStartPlane = (anchorX < oldX) ? oldX : anchorX;
XDrawRectangle(display, amrPicturePtrArray[Amrvis::ZPLANE]->PictureWindow(),
rbgc, startcutX[Amrvis::ZPLANE], imageWidth-rStartPlane,
std::abs(finishcutX[Amrvis::ZPLANE]-startcutX[Amrvis::ZPLANE]), rWidth);
XDrawRectangle(display, amrPicturePtrArray[Amrvis::YPLANE]->PictureWindow(),
rbgc, startcutX[Amrvis::YPLANE], rStartY,
std::abs(finishcutX[Amrvis::YPLANE]-startcutX[Amrvis::YPLANE]),
rHeight);
}
#endif
}
// Double buffering approach - no need to "undraw" old rectangles

DoDrawPointerLocation(None, (XtPointer) static_cast<long>(V), &nextEvent);

Expand All @@ -3683,8 +3708,90 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)
rHeight = std::abs(newY-anchorY);
rStartX = (anchorX < newX) ? anchorX : newX;
rStartY = (anchorY < newY) ? anchorY : newY;
XDrawRectangle(display, amrPicturePtrArray[V]->PictureWindow(),
rbgc, rStartX, rStartY, rWidth, rHeight);

// Double buffering: restore original, draw rectangle, copy to window
XCopyArea(display, rubberBandBackup, rubberBandBuffer, copyGC,
0, 0, bufferWidth, bufferHeight, 0, 0);
XSetForeground(display, copyGC, pltPaletteptr->makePixel(120));
XDrawRectangle(display, rubberBandBuffer, copyGC, rStartX, rStartY, rWidth, rHeight);
XCopyArea(display, rubberBandBuffer, amrPicturePtrArray[V]->PictureWindow(), copyGC,
0, 0, bufferWidth, bufferHeight, 0, 0);

#if (BL_SPACEDIM == 3)
// Double buffering for additional 3D planes
switch (V) {
case Amrvis::ZPLANE: {
// Update YPLANE
XCopyArea(display, planeBackup[Amrvis::YPLANE], planeBuffer[Amrvis::YPLANE], planeGC[Amrvis::YPLANE],
0, 0, amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeV(), 0, 0);
XSetForeground(display, planeGC[Amrvis::YPLANE], pltPaletteptr->makePixel(120));
XDrawRectangle(display, planeBuffer[Amrvis::YPLANE], planeGC[Amrvis::YPLANE],
rStartX, startcutY[Amrvis::YPLANE], rWidth,
std::abs(finishcutY[Amrvis::YPLANE]-startcutY[Amrvis::YPLANE]));
XCopyArea(display, planeBuffer[Amrvis::YPLANE], amrPicturePtrArray[Amrvis::YPLANE]->PictureWindow(), planeGC[Amrvis::YPLANE],
0, 0, amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeV(), 0, 0);

// Update XPLANE
int rStartPlane = (anchorY < newY) ? newY : anchorY;
XCopyArea(display, planeBackup[Amrvis::XPLANE], planeBuffer[Amrvis::XPLANE], planeGC[Amrvis::XPLANE],
0, 0, amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeV(), 0, 0);
XSetForeground(display, planeGC[Amrvis::XPLANE], pltPaletteptr->makePixel(120));
XDrawRectangle(display, planeBuffer[Amrvis::XPLANE], planeGC[Amrvis::XPLANE],
imageHeight-rStartPlane, startcutY[Amrvis::XPLANE], rHeight,
std::abs(finishcutY[Amrvis::XPLANE]-startcutY[Amrvis::XPLANE]));
XCopyArea(display, planeBuffer[Amrvis::XPLANE], amrPicturePtrArray[Amrvis::XPLANE]->PictureWindow(), planeGC[Amrvis::XPLANE],
0, 0, amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeV(), 0, 0);
break;
}

case Amrvis::YPLANE: {
// Update ZPLANE
XCopyArea(display, planeBackup[Amrvis::ZPLANE], planeBuffer[Amrvis::ZPLANE], planeGC[Amrvis::ZPLANE],
0, 0, amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeV(), 0, 0);
XSetForeground(display, planeGC[Amrvis::ZPLANE], pltPaletteptr->makePixel(120));
XDrawRectangle(display, planeBuffer[Amrvis::ZPLANE], planeGC[Amrvis::ZPLANE],
rStartX, startcutY[Amrvis::ZPLANE], rWidth,
std::abs(finishcutY[Amrvis::ZPLANE]-startcutY[Amrvis::ZPLANE]));
XCopyArea(display, planeBuffer[Amrvis::ZPLANE], amrPicturePtrArray[Amrvis::ZPLANE]->PictureWindow(), planeGC[Amrvis::ZPLANE],
0, 0, amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeV(), 0, 0);

// Update XPLANE
XCopyArea(display, planeBackup[Amrvis::XPLANE], planeBuffer[Amrvis::XPLANE], planeGC[Amrvis::XPLANE],
0, 0, amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeV(), 0, 0);
XSetForeground(display, planeGC[Amrvis::XPLANE], pltPaletteptr->makePixel(120));
XDrawRectangle(display, planeBuffer[Amrvis::XPLANE], planeGC[Amrvis::XPLANE],
startcutX[Amrvis::XPLANE], rStartY,
std::abs(finishcutX[Amrvis::XPLANE]-startcutX[Amrvis::XPLANE]), rHeight);
XCopyArea(display, planeBuffer[Amrvis::XPLANE], amrPicturePtrArray[Amrvis::XPLANE]->PictureWindow(), planeGC[Amrvis::XPLANE],
0, 0, amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::XPLANE]->ImageSizeV(), 0, 0);
break;
}

default: { // Amrvis::XPLANE
// Update ZPLANE
int rStartPlane = (anchorX < newX) ? newX : anchorX;
XCopyArea(display, planeBackup[Amrvis::ZPLANE], planeBuffer[Amrvis::ZPLANE], planeGC[Amrvis::ZPLANE],
0, 0, amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeV(), 0, 0);
XSetForeground(display, planeGC[Amrvis::ZPLANE], pltPaletteptr->makePixel(120));
XDrawRectangle(display, planeBuffer[Amrvis::ZPLANE], planeGC[Amrvis::ZPLANE],
startcutX[Amrvis::ZPLANE], imageWidth-rStartPlane,
std::abs(finishcutX[Amrvis::ZPLANE]-startcutX[Amrvis::ZPLANE]), rWidth);
XCopyArea(display, planeBuffer[Amrvis::ZPLANE], amrPicturePtrArray[Amrvis::ZPLANE]->PictureWindow(), planeGC[Amrvis::ZPLANE],
0, 0, amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::ZPLANE]->ImageSizeV(), 0, 0);

// Update YPLANE
XCopyArea(display, planeBackup[Amrvis::YPLANE], planeBuffer[Amrvis::YPLANE], planeGC[Amrvis::YPLANE],
0, 0, amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeV(), 0, 0);
XSetForeground(display, planeGC[Amrvis::YPLANE], pltPaletteptr->makePixel(120));
XDrawRectangle(display, planeBuffer[Amrvis::YPLANE], planeGC[Amrvis::YPLANE],
startcutX[Amrvis::YPLANE], rStartY,
std::abs(finishcutX[Amrvis::YPLANE]-startcutX[Amrvis::YPLANE]), rHeight);
XCopyArea(display, planeBuffer[Amrvis::YPLANE], amrPicturePtrArray[Amrvis::YPLANE]->PictureWindow(), planeGC[Amrvis::YPLANE],
0, 0, amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeH(), amrPicturePtrArray[Amrvis::YPLANE]->ImageSizeV(), 0, 0);
break;
}
}
#endif
rectDrawn = true;

oldX = newX;
Expand All @@ -3702,41 +3809,24 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)
finishcutX[Amrvis::YPLANE] = finishcutX[V];
startcutX[Amrvis::XPLANE] = imageHeight - startcutY[V];
finishcutX[Amrvis::XPLANE] = imageHeight - finishcutY[V];
// draw in other planes
XDrawRectangle(display, amrPicturePtrArray[Amrvis::YPLANE]->PictureWindow(),
rbgc, rStartX, startcutY[Amrvis::YPLANE], rWidth,
std::abs(finishcutY[Amrvis::YPLANE]-startcutY[Amrvis::YPLANE]));
rStartPlane = (anchorY < newY) ? newY : anchorY;
XDrawRectangle(display, amrPicturePtrArray[Amrvis::XPLANE]->PictureWindow(),
rbgc, imageHeight-rStartPlane, startcutY[Amrvis::XPLANE],
rHeight,
std::abs(finishcutY[Amrvis::XPLANE]-startcutY[Amrvis::XPLANE]));
// 3D planes handled by double buffering now
// XDrawRectangle calls removed - double buffering handles all drawing
break;
case Amrvis::YPLANE:
startcutX[Amrvis::ZPLANE] = startcutX[V];
finishcutX[Amrvis::ZPLANE] = finishcutX[V];
startcutY[Amrvis::XPLANE] = startcutY[V];
finishcutY[Amrvis::XPLANE] = finishcutY[V];
XDrawRectangle(display, amrPicturePtrArray[Amrvis::ZPLANE]->PictureWindow(),
rbgc, rStartX, startcutY[Amrvis::ZPLANE], rWidth,
std::abs(finishcutY[Amrvis::ZPLANE]-startcutY[Amrvis::ZPLANE]));
XDrawRectangle(display, amrPicturePtrArray[Amrvis::XPLANE]->PictureWindow(),
rbgc, startcutX[Amrvis::XPLANE], rStartY,
std::abs(finishcutX[Amrvis::XPLANE]-startcutX[Amrvis::XPLANE]), rHeight);
// 3D planes handled by double buffering now
break;
default: // Amrvis::XPLANE
startcutY[Amrvis::YPLANE] = startcutY[V];
finishcutY[Amrvis::YPLANE] = finishcutY[V];
startcutY[Amrvis::ZPLANE] = imageWidth - startcutX[V];
finishcutY[Amrvis::ZPLANE] = imageWidth - finishcutX[V];
rStartPlane = (anchorX < newX) ? newX : anchorX;
XDrawRectangle(display, amrPicturePtrArray[Amrvis::ZPLANE]->PictureWindow(),
rbgc, startcutX[Amrvis::ZPLANE], imageWidth-rStartPlane,
std::abs(finishcutX[Amrvis::ZPLANE]-startcutX[Amrvis::ZPLANE]), rWidth);
XDrawRectangle(display, amrPicturePtrArray[Amrvis::YPLANE]->PictureWindow(),
rbgc, startcutX[Amrvis::YPLANE], rStartY,
std::abs(finishcutX[Amrvis::YPLANE]-startcutX[Amrvis::YPLANE]), rHeight);
// 3D planes handled by double buffering now
}
XSync(display, False);

#if defined(BL_VOLUMERENDER) || defined(BL_PARALLELVOLUMERENDER)
if( ! XmToggleButtonGetState(wAutoDraw))
Expand Down Expand Up @@ -3769,7 +3859,6 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)
break;

case ButtonRelease: {
avxGrab.ExplicitUngrab();

startX = (max(0, min(imageWidth, anchorX))) / scale;
startY = (max(0, min(imageHeight, anchorY))) / scale;
Expand Down Expand Up @@ -4072,6 +4161,32 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)
break;
} // end switch
} // end while(true)

// Cleanup double buffering resources
if(rubberBandBackup != None) {
XFreePixmap(display, rubberBandBackup);
rubberBandBackup = None;
}
if(rubberBandBuffer != None) {
XFreePixmap(display, rubberBandBuffer);
rubberBandBuffer = None;
}
XFreeGC(display, copyGC);

// Cleanup additional 3D plane resources
for(int plane = 0; plane < amrex::Amrvis::NPLANES; ++plane) {
if(planeBackup[plane] != None) {
XFreePixmap(display, planeBackup[plane]);
}
if(planeBuffer[plane] != None) {
XFreePixmap(display, planeBuffer[plane]);
}
if(planeGC[plane] != None) {
XFreeGC(display, planeGC[plane]);
}
}

XSync(display, False);
}


Expand Down Expand Up @@ -4152,7 +4267,6 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)
break;

case ButtonRelease:
avxGrab.ExplicitUngrab();
tempi = max(0, min(imageHeight, nextEvent.xbutton.y));
amrPicturePtrArray[V]->SetHLine(tempi);
#if (BL_SPACEDIM == 3)
Expand Down Expand Up @@ -4319,7 +4433,6 @@ void PltApp::DoRubberBanding(Widget, XtPointer client_data, XtPointer call_data)
break;

case ButtonRelease:
avxGrab.ExplicitUngrab();
tempi = max(0, min(imageWidth, nextEvent.xbutton.x));
amrPicturePtrArray[V]->SetVLine(tempi);
#if (BL_SPACEDIM == 3)
Expand Down
Loading
Loading