Subject:
Re: Panning and double buffering
From:
"Jordan Crouse" ####@####.####
Date:
24 Apr 2006 23:18:03 +0100
Message-Id: <20060424222150.GH25101@cosmic.amd.com>
On 24/04/06 13:54 -0600, Jordan Crouse wrote:
> Ok - as promised, here is the patch.
I've been informed that I hit send a little bit too quickly. Lets try
that again, shall we?
Jordan
Index: microwin/src/drivers/scr_bios.c
===================================================================
--- microwin.orig/src/drivers/scr_bios.c
+++ microwin/src/drivers/scr_bios.c
@@ -235,8 +235,8 @@ VGA_close(PSD psd)
static void
VGA_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_debug.c
===================================================================
--- microwin.orig/src/drivers/scr_debug.c
+++ microwin/src/drivers/scr_debug.c
@@ -76,8 +76,8 @@ DBG_close(PSD psd)
static void
DBG_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_djgr.c
===================================================================
--- microwin.orig/src/drivers/scr_djgr.c
+++ microwin/src/drivers/scr_djgr.c
@@ -107,8 +107,8 @@ DJGR_close(PSD psd)
static void
DJGR_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_ecos.c
===================================================================
--- microwin.orig/src/drivers/scr_ecos.c
+++ microwin/src/drivers/scr_ecos.c
@@ -357,8 +357,8 @@ setfadelevel(PSD psd, int f)
static void
gen_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_em84xx.c
===================================================================
--- microwin.orig/src/drivers/scr_em84xx.c
+++ microwin/src/drivers/scr_em84xx.c
@@ -247,8 +247,8 @@ EM8400_close(PSD psd)
static void
EM8400_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_fb.c
===================================================================
--- microwin.orig/src/drivers/scr_fb.c
+++ microwin/src/drivers/scr_fb.c
@@ -43,10 +43,10 @@ static void fb_close(PSD psd);
static void fb_setportrait(PSD psd, int portraitmode);
static void fb_setpalette(PSD psd,int first, int count, MWPALENTRY *palette);
static void gen_getscreeninfo(PSD psd,PMWSCREENINFO psi);
-
+static void fb_panscreen(PSD psd, int, int);
SCREENDEVICE scrdev = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
fb_open,
fb_close,
gen_getscreeninfo,
@@ -64,8 +64,10 @@ SCREENDEVICE scrdev = {
gen_allocatememgc,
fb_mapmemgc,
gen_freememgc,
+ fb_panscreen,
NULL, /* StretchBlit subdriver*/
fb_setportrait /* SetPortrait*/
+
};
/* static variables*/
@@ -144,9 +146,25 @@ fb_open(PSD psd)
psd->xres = psd->xvirtres = fb_var.xres_virtual;
psd->yres = psd->yvirtres = fb_var.yres_virtual;
#else
- psd->xres = psd->xvirtres = fb_var.xres;
- psd->yres = psd->yvirtres = fb_var.yres;
+ /* The entire xvirtres is available for us to draw on */
+
+ psd->xres = psd->xvirtres = fb_var.xres_virtual;
+ psd->yres = psd->yvirtres = fb_var.yres_virtual;
+
+ /* But we want to know how much of the screen is visible so we can
+ know when to pan */
+
+ psd->xvisible = fb_var.xres;
+ psd->yvisible = fb_var.yres;
+
+ printf("FB: total (%d,%d) visible (%d,%d)\n",
+ psd->xvirtres, psd->yvirtres, psd->xvisible, psd->yvisible);
+
#endif
+ /* Offset into the screen for panning purposes */
+
+ psd->xoffset = 0;
+ psd->yoffset = 0;
/* set planes from fb type*/
if (type == FB_TYPE_VGA_PLANES)
@@ -472,6 +490,9 @@ gen_getscreeninfo(PSD psd,PMWSCREENINFO
{
psi->rows = psd->yvirtres;
psi->cols = psd->xvirtres;
+ psi->viscols = psd->xvisible;
+ psi->visrows = psd->yvisible;
+
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
@@ -529,3 +550,21 @@ gen_getscreeninfo(PSD psd,PMWSCREENINFO
psi->ydpcm = 19; /* assumes screen height of 18 cm*/
}
}
+
+static void
+fb_panscreen(PSD psd, int xoffset, int yoffset) {
+ struct fb_var_screeninfo fb_var;
+
+ if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) == -1)
+ return;
+
+ /* Don't bother doing the operation if we don't have to */
+
+ //if (fb_var.xoffset == xoffset && fb_var.yoffset == yoffset)
+ // return;
+
+ fb_var.xoffset = xoffset;
+ fb_var.yoffset = yoffset;
+
+ ioctl(fb, FBIOPAN_DISPLAY, &fb_var);
+}
Index: microwin/src/drivers/scr_fbsd.c
===================================================================
--- microwin.orig/src/drivers/scr_fbsd.c
+++ microwin/src/drivers/scr_fbsd.c
@@ -201,8 +201,8 @@ static PSD FBSD_open(PSD psd)
static void FBSD_getscreeninfo(PSD psd, PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_herc.c
===================================================================
--- microwin.orig/src/drivers/scr_herc.c
+++ microwin/src/drivers/scr_herc.c
@@ -144,8 +144,8 @@ HERC_close(PSD psd)
static void
HERC_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_prsm.c
===================================================================
--- microwin.orig/src/drivers/scr_prsm.c
+++ microwin/src/drivers/scr_prsm.c
@@ -126,8 +126,8 @@ VB_close(PSD psd)
static void
VB_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ pis->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_rtems.c
===================================================================
--- microwin.orig/src/drivers/scr_rtems.c
+++ microwin/src/drivers/scr_rtems.c
@@ -311,8 +311,8 @@ ioctl_setpalette(int start, int len, sho
static void
gen_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_svga.c
===================================================================
--- microwin.orig/src/drivers/scr_svga.c
+++ microwin/src/drivers/scr_svga.c
@@ -109,8 +109,8 @@ SVGA_close(PSD psd)
static void
SVGA_getscreeninfo(PSD psd,PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/drivers/scr_x11.c
===================================================================
--- microwin.orig/src/drivers/scr_x11.c
+++ microwin/src/drivers/scr_x11.c
@@ -841,8 +841,8 @@ X11_close(PSD psd)
static void
X11_getscreeninfo(PSD psd, PMWSCREENINFO psi)
{
- psi->rows = psd->yvirtres;
- psi->cols = psd->xvirtres;
+ psi->visrows = psi->rows = psd->yvirtres;
+ psi->viscols = psi->cols = psd->xvirtres;
psi->planes = psd->planes;
psi->bpp = psd->bpp;
psi->ncolors = psd->ncolors;
Index: microwin/src/engine/devmouse.c
===================================================================
--- microwin.orig/src/engine/devmouse.c
+++ microwin/src/engine/devmouse.c
@@ -183,6 +183,8 @@ GdSetAccelMouse(int newthresh, int newsc
void
GdMoveMouse(MWCOORD newx, MWCOORD newy)
{
+ int xo = scrdev.xoffset, yo = scrdev.yoffset;
+
if (!(mousedev.flags & MOUSE_RAW)) {
if (newx < minx)
newx = minx;
@@ -197,6 +199,30 @@ GdMoveMouse(MWCOORD newx, MWCOORD newy)
if (newx == xpos && newy == ypos)
return;
+#ifdef NOTUSED
+ /* Pan the display if possible - we want to do this smoothly */
+
+ if (newx < scrdev.xoffset)
+ xo = newx - 5;
+ else if (newx > scrdev.xoffset + scrdev.xvisible)
+ xo = (newx + 5) - scrdev.xvisible;
+
+ if (newy < scrdev.yoffset)
+ yo = newy - 5;
+ else if (newy > scrdev.yoffset + scrdev.yvisible)
+ yo = (newy + 5) - scrdev.yvisible;
+
+ if (xo < 0) xo = 0;
+ if (xo > scrdev.xres) xo = scrdev.xres - scrdev.xvisible;
+
+ if (yo < 0) yo = 0;
+ if (yo > scrdev.yres) yo = scrdev.yres - scrdev.yvisible;
+
+ /* Move the screen accordingly */
+ if (xo != scrdev.xoffset || yo != scrdev.yoffset)
+ GdPanScreen(&scrdev, xo, yo);
+#endif
+
changed = TRUE;
xpos = newx;
Index: microwin/src/engine/devopen.c
===================================================================
--- microwin.orig/src/engine/devopen.c
+++ microwin/src/engine/devopen.c
@@ -408,6 +408,41 @@ GdGetColorRGB(PSD psd, MWPIXELVAL pixel)
}
}
+void
+GdPanScreen(PSD psd, int xoffset, int yoffset) {
+
+ if (!psd->PanScreen) return;
+
+ if ((psd->xvisible != psd->xvirtres)) {
+
+ /* Bound it */
+
+ if (xoffset < 0) xoffset = 0;
+ if (xoffset + psd->xvisible > psd->xvirtres)
+ xoffset = psd->xvirtres - psd->xvisible;
+ }
+ else
+ xoffset = 0;
+
+ if ((psd->yvisible != psd->yvirtres)) {
+
+ /* Bound it */
+
+ if (yoffset < 0) yoffset = 0;
+ if (yoffset + psd->yvisible > psd->yvirtres)
+ yoffset = psd->yvirtres - psd->yvisible;
+ }
+ else
+ yoffset = 0;
+
+ if (xoffset != psd->xoffset || yoffset != psd->yoffset) {
+ psd->yoffset = yoffset;
+ psd->xoffset = xoffset;
+
+ psd->PanScreen(psd, psd->xoffset, psd->yoffset);
+ }
+}
+
#if !VXWORKS
#if defined(HAVE_FILEIO)
#include <unistd.h>
@@ -637,3 +672,5 @@ GdCaptureScreen(char *path)
return 0;
}
#endif /* !VXWORKS*/
+
+
Index: microwin/src/include/device.h
===================================================================
--- microwin.orig/src/include/device.h
+++ microwin/src/include/device.h
@@ -338,6 +338,10 @@ typedef struct _mwscreendevice {
MWCOORD yres; /* Y screen res (real) */
MWCOORD xvirtres; /* X drawing res (will be flipped in portrait mode) */
MWCOORD yvirtres; /* Y drawing res (will be flipped in portrait mode) */
+ int xvisible; /* Actual x real estate that is visible */
+ int yvisible; /* Ditto */
+ int xoffset; /* X offset for panning */
+ int yoffset; /* Y offset for panning */
int planes; /* # planes*/
int bpp; /* # bpp*/
int linelen; /* line length in bytes for bpp 1,2,4,8*/
@@ -374,6 +378,7 @@ typedef struct _mwscreendevice {
MWBOOL (*MapMemGC)(PSD mempsd,MWCOORD w,MWCOORD h,int planes,int bpp,
int linelen,int size,void *addr);
void (*FreeMemGC)(PSD mempsd);
+ void (*PanScreen)(PSD, int, int);
void (*StretchBlit)(PSD destpsd,MWCOORD destx,MWCOORD desty,
MWCOORD destw,MWCOORD desth,PSD srcpsd,MWCOORD srcx,
MWCOORD srcy,MWCOORD srcw,MWCOORD srch,long op);
@@ -794,6 +799,8 @@ void drawbitmap(PSD psd, MWCOORD x, MWCO
const MWIMAGEBITS *imagebits);
void drawpoint(PSD psd, MWCOORD x, MWCOORD y);
void drawrow(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y);
+void GdPanScreen(PSD psd, int, int);
+
extern SCREENDEVICE scrdev;
Index: microwin/src/include/mwtypes.h
===================================================================
--- microwin.orig/src/include/mwtypes.h
+++ microwin/src/include/mwtypes.h
@@ -314,6 +314,8 @@ typedef unsigned int MWKEYMOD;
typedef struct {
MWCOORD rows; /* number of rows on screen */
MWCOORD cols; /* number of columns on screen */
+ MWCOORD visrows; /* number of visible rows */
+ MWCOORD viscols; /* number of visible columns */
int xdpcm; /* dots/centimeter in x direction */
int ydpcm; /* dots/centimeter in y direction */
int planes; /* hw # planes*/
Index: microwin/src/include/nano-X.h
===================================================================
--- microwin.orig/src/include/nano-X.h
+++ microwin/src/include/nano-X.h
@@ -559,6 +559,12 @@ typedef union {
typedef void (*GR_FNCALLBACKEVENT)(GR_EVENT *);
+typedef struct {
+ GR_WINDOW_ID buf[2];
+ int active;
+ int size;
+} GR_DOUBLE_BUFFER;
+
/* GR_BITMAP macros*/
/* size of GR_BITMAP image in words*/
#define GR_BITMAP_SIZE(width, height) MWIMAGE_SIZE(width, height)
@@ -925,6 +931,7 @@ void GrSetTransform(GR_TRANSF
int GrCalcTransform(GR_CAL_DATA *, GR_TRANSFORM *);
int GrLoadTransformData(char *filename, GR_TRANSFORM *);
int GrSaveTransformData(GR_TRANSFORM *, char *filename);
+void GrPanDisplay(int, int);
/* nxutil.c - utility routines*/
GR_WINDOW_ID GrNewWindowEx(GR_WM_PROPS props, GR_CHAR *title,
@@ -944,6 +951,12 @@ GR_BITMAP * GrNewBitmapFromPixmap(GR_WIN
GR_REGION_ID GrNewRegionFromPixmap(GR_WINDOW_ID src, MWCOORD x, MWCOORD y,
GR_SIZE width, GR_SIZE height);
+/* nxdblbuf.c */
+
+GR_DOUBLE_BUFFER *GrInitDoubleBuffer(void);
+void GrCloseDoubleBuffer(GR_DOUBLE_BUFFER *);
+void GrFlipBuffers(GR_DOUBLE_BUFFER *);
+
/* direct client-side framebuffer mapping routines*/
unsigned char * GrOpenClientFramebuffer(void);
void GrCloseClientFramebuffer(void);
Index: microwin/src/nanox/Makefile
===================================================================
--- microwin.orig/src/nanox/Makefile
+++ microwin/src/nanox/Makefile
@@ -38,7 +38,8 @@ NANOXFILES := \
OBJS := \
$(MW_DIR_OBJ)/nanox/nxdraw.o \
$(MW_DIR_OBJ)/nanox/nxutil.o \
- $(MW_DIR_OBJ)/nanox/nxtransform.o
+ $(MW_DIR_OBJ)/nanox/nxtransform.o \
+ $(MW_DIR_OBJ)/nanox/nxdblbuf.o
ifeq ($(LINK_APP_INTO_SERVER), Y)
OBJS += $(NANOXFILES)
Index: microwin/src/nanox/client.c
===================================================================
--- microwin.orig/src/nanox/client.c
+++ microwin/src/nanox/client.c
@@ -4761,5 +4761,19 @@ GrCopyFont(GR_FONT_ID fontid, GR_COORD h
}
#endif /*HAVE_FREETYPE_2_SUPPORT*/
+/* Used to pan the display for those devices that have such support */
+void
+GrPanDisplay(int xoffset, int yoffset) {
+
+ nxPanDisplayReq *req;
+
+ LOCK(&nxGlobalLock);
+
+ req = AllocReq(PanDisplay);
+ req->xoffset = xoffset;
+ req->yoffset = yoffset;
+
+ UNLOCK(&nxGlobalLock);
+}
Index: microwin/src/nanox/nxdblbuf.c
===================================================================
--- /dev/null
+++ microwin/src/nanox/nxdblbuf.c
@@ -0,0 +1,49 @@
+#include "nano-X.h"
+#include "device.h"
+
+/* Initalize two windows that act as double buffers */
+
+GR_DOUBLE_BUFFER *GrInitDoubleBuffer(void) {
+
+ GR_SCREEN_INFO si;
+ GR_DOUBLE_BUFFER *s = 0;
+
+ GrGetScreenInfo(&si);
+
+ if (si.rows < si.visrows * 2) return 0;
+
+ s = malloc(sizeof(GR_DOUBLE_BUFFER));
+ if (!s) return 0;
+
+ printf("VISROWS=%d\n", si.visrows);
+
+ s->buf[0] = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, si.cols,
+ si.visrows, 0, 0, 0);
+
+ s->buf[1] = GrNewWindow(GR_ROOT_WINDOW_ID, 0, si.visrows,
+ si.cols, si.visrows, 0, 0, 0);
+
+ s->active = 0;
+ s->size = si.visrows;
+
+ return s;
+}
+
+void GrCloseDoubleBuffer(GR_DOUBLE_BUFFER *buf) {
+ GrDestroyWindow(buf->buf[0]);
+ GrDestroyWindow(buf->buf[1]);
+
+ free(buf);
+}
+
+/* Flip the screen betwee nteh two buffers */
+
+void GrFlipBuffers(GR_DOUBLE_BUFFER *buf) {
+
+ if (!buf) return;
+
+ buf->active = !buf->active;
+ GrPanDisplay(0, buf->size * buf->active);
+}
+
+
Index: microwin/src/nanox/nxproto.h
===================================================================
--- microwin.orig/src/nanox/nxproto.h
+++ microwin/src/nanox/nxproto.h
@@ -1366,4 +1366,13 @@ typedef struct {
INT16 height;
} nxCopyFontReq;
-#define GrTotalNumCalls 125
+#define GrNumPanDisplay 125
+typedef struct {
+ BYTE8 reqType;
+ BYTE8 hilength;
+ UINT16 length;
+ INT16 xoffset;
+ INT16 yoffset;
+} nxPanDisplayReq;
+
+#define GrTotalNumCalls 126
Index: microwin/src/nanox/srvfunc.c
===================================================================
--- microwin.orig/src/nanox/srvfunc.c
+++ microwin/src/nanox/srvfunc.c
@@ -4314,3 +4314,15 @@ GrUngrabKey(GR_WINDOW_ID id, GR_KEY key)
SERVER_UNLOCK();
}
+
+/**
+ * Pan the display
+ *
+ * @param xoffset New xoffset of the display
+ * @param yoffset New yoffset of the display
+ */
+
+void
+GrPanDisplay(int xoffset, int yoffset) {
+ GdPanScreen(rootwp->psd, xoffset, yoffset);
+}
Index: microwin/src/nanox/srvmain.c
===================================================================
--- microwin.orig/src/nanox/srvmain.c
+++ microwin/src/nanox/srvmain.c
@@ -1169,7 +1169,15 @@ GsInitialize(void)
* Tell the mouse driver some things.
*/
curbuttons = 0;
- GdRestrictMouse(0, 0, psd->xvirtres - 1, psd->yvirtres - 1);
+
+ /* If panning is indicated, we now allow the mouse the full range
+ of motion */
+
+ if (psd->PanScreen)
+ GdRestrictMouse(0, 0, psd->xres - 1, psd->yres - 1);
+ else
+ GdRestrictMouse(0, 0, psd->xvirtres - 1, psd->yvirtres - 1);
+
GdMoveMouse(psd->xvirtres / 2, psd->yvirtres / 2);
/* Force root window screen paint*/
Index: microwin/src/nanox/srvnet.c
===================================================================
--- microwin.orig/src/nanox/srvnet.c
+++ microwin/src/nanox/srvnet.c
@@ -1593,6 +1593,11 @@ GrCopyFontWrapper(void *r)
#endif /*HAVE_FREETYPE_2_SUPPORT*/
}
+static void
+GrPanDisplayWrapper(void *r) {
+ nxPanDisplayReq *req = r;
+ GrPanDisplay(req->xoffset, req->yoffset);
+}
void GrShmCmdsFlushWrapper(void *r);
@@ -1729,6 +1734,7 @@ static const struct GrFunction GrFunctio
/* 122 */ {GrSetTransformWrapper, "GrSetTransform" },
/* 123 */ {GrCreateFontFromBufferWrapper, "GrCreateFontFromBuffer"},
/* 124 */ {GrCopyFontWrapper, "GrCopyFont"},
+ /* 125 */ {GrPanDisplayWrapper, "GrPanDisplay" }
};
void