/* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */ /* grlib.c Main module */ #include #include #include #include "inlstring.h" /* include inline string operations */ #include "vgagl.h" #include "def.h" #include "driver.h" /* Global variables */ #ifdef DLL_CONTEXT_SHADOW /* The current context variable is shadowed in a read-only variable for */ /* external use. */ GraphicsContext __currentcontext; /* Internal current context. */ GraphicsContext currentcontext; /* Copy for external use. */ #else GraphicsContext currentcontext; #endif void (*__svgalib_nonaccel_fillbox)(int, int, int, int, int); static int screenoffset = 0; /* Used by copy(box)toscreen. */ /* Framebuffer function pointers */ static framebufferfunctions ff8 = { __svgalib_driver8_setpixel, __svgalib_driver8_getpixel, __svgalib_driver8_hline, __svgalib_driver8_fillbox, __svgalib_driver8_putbox, __svgalib_driver8_getbox, __svgalib_driver8_putboxmask, __svgalib_driver8_putboxpart, __svgalib_driver8_getboxpart, __svgalib_driver8_copybox }; static framebufferfunctions ff16 = { __svgalib_driver16_setpixel, __svgalib_driver16_getpixel, __svgalib_driver16_hline, __svgalib_driver16_fillbox, __svgalib_driver16_putbox, __svgalib_driver16_getbox, __svgalib_driver16_putboxmask, __svgalib_driver16_putboxpart, __svgalib_driver16_getboxpart, __svgalib_driver16_copybox }; static framebufferfunctions ff24 = { __svgalib_driver24_setpixel, __svgalib_driver24_getpixel, __svgalib_driver24_hline, __svgalib_driver24_fillbox, __svgalib_driver24_putbox, __svgalib_driver24_getbox, __svgalib_driver24_putboxmask, __svgalib_driver24_putboxpart, __svgalib_driver24_getboxpart, __svgalib_driver24_copybox }; static framebufferfunctions ff32 = { __svgalib_driver32_setpixel, __svgalib_driver32_getpixel, __svgalib_driver32_hline, __svgalib_driver32_fillbox, __svgalib_driver32_putbox, __svgalib_driver32_getbox, __svgalib_driver32_putboxmask, __svgalib_driver32_putboxpart, __svgalib_driver32_getboxpart, __svgalib_driver32_copybox }; static framebufferfunctions ff8paged = { __svgalib_driver8p_setpixel, __svgalib_driver8p_getpixel, __svgalib_driver8p_hline, __svgalib_driver8p_fillbox, __svgalib_driver8p_putbox, __svgalib_driver8p_getbox, __svgalib_driver8p_putboxmask, __svgalib_driver8p_putboxpart, __svgalib_driver8p_getboxpart, __svgalib_driver8p_copybox }; static framebufferfunctions ff16paged = { __svgalib_driver16p_setpixel, __svgalib_driver16p_getpixel, __svgalib_driver16p_hline, __svgalib_driver16p_fillbox, __svgalib_driver16p_putbox, __svgalib_driver16p_getbox, __svgalib_driver16p_putboxmask, __svgalib_driver16p_putboxpart, __svgalib_driver16p_getboxpart, __svgalib_driver16p_copybox }; static framebufferfunctions ff24paged = { __svgalib_driver24p_setpixel, __svgalib_driver24p_getpixel, __svgalib_driver24p_hline, __svgalib_driver24p_fillbox, __svgalib_driver24p_putbox, __svgalib_driver24p_getbox, __svgalib_driver24p_putboxmask, __svgalib_driver24p_putboxpart, __svgalib_driver24p_getboxpart, __svgalib_driver24p_copybox }; static framebufferfunctions ff32paged = { __svgalib_driver32p_setpixel, __svgalib_driver32p_getpixel, __svgalib_driver32p_hline, __svgalib_driver32p_fillbox, __svgalib_driver32p_putbox, __svgalib_driver32p_getbox, __svgalib_driver32p_putboxmask, __svgalib_driver32p_putboxpart, __svgalib_driver32p_getboxpart, __svgalib_driver32p_copybox }; static framebufferfunctions ffplanar256 = { (void *) __svgalib_driverplanar256_nothing, (void *) __svgalib_driverplanar256_nothing, (void *) __svgalib_driverplanar256_nothing, (void *) __svgalib_driverplanar256_nothing, __svgalib_driverplanar256_putbox, (void *) __svgalib_driverplanar256_nothing, (void *) __svgalib_driverplanar256_nothing, (void *) __svgalib_driverplanar256_nothing, (void *) __svgalib_driverplanar256_nothing, (void *) __svgalib_driverplanar256_nothing, }; #if 0 /* Not yet used */ static framebufferfunctions ffplanar16 = { (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, (void *) __svgalib_driverplanar16_nothing, }; #endif /* Initialization and graphics contexts */ #define SCREENSIZE(gc) ((gc).bytewidth * (gc).height) static int colorbits(int c) { switch (c) { default: case 256: return 8; case 32768: return 15; case 65536: return 16; case 256 * 65536: return 24; } } int gl_setcontextvga(int m) { framebufferfunctions *ff; vga_modeinfo *modeinfo; int accelfuncs; if (!vga_hasmode(m)) return -1; modeinfo = vga_getmodeinfo(m); /* Set graphics context */ WIDTH = modeinfo->width; HEIGHT = modeinfo->height; BYTESPERPIXEL = modeinfo->bytesperpixel; COLORS = modeinfo->colors; BITSPERPIXEL = colorbits(COLORS); BYTEWIDTH = modeinfo->linewidth; VBUF = vga_getgraphmem(); MODEFLAGS = 0; __clip = 0; ff = &(__currentcontext.ff); if (modeinfo->flags & IS_MODEX) { /* Pretend it's a regular (linear) context. */ BYTESPERPIXEL = 1; BYTEWIDTH *= 4; MODETYPE = CONTEXT_MODEX; if (BYTEWIDTH * HEIGHT * 2 <= 256 * 1024) MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; if (BYTEWIDTH * HEIGHT * 3 <= 256 * 1024) MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; __currentcontext.ff = ffplanar256; } else if (modeinfo->colors == 16) { /* Pretend it's a regular one byte per pixel context. */ BYTESPERPIXEL = 1; BYTEWIDTH *= 8; MODETYPE = CONTEXT_PLANAR16; if (BYTEWIDTH * HEIGHT <= 256 * 1024) MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; if (BYTEWIDTH * HEIGHT * 3 / 2 <= 256 * 1024) MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; } else if ((m == G320x200x256 && modeinfo->maxpixels <= 65536) || (modeinfo->flags & IS_LINEAR) #if 1 /* svgalib doesn't VT-switch correctly with linear addressing. */ || ((modeinfo->flags & CAPABLE_LINEAR) /* Creepy. Try linear addressing only if the mode is set. */ && vga_getcurrentmode() == m && (vga_setlinearaddressing() != -1)) #endif ) { /* No banking. */ /* Get get the fb address in case we set linear addressing. */ VBUF = vga_getgraphmem(); MODETYPE = CONTEXT_LINEAR; if (modeinfo->maxpixels >= WIDTH * HEIGHT * 2) MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; if (modeinfo->maxpixels >= WIDTH * HEIGHT * 3) MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; switch (BYTESPERPIXEL) { case 1: __currentcontext.ff = ff8; break; case 2: __currentcontext.ff = ff16; break; case 3: __currentcontext.ff = ff24; break; case 4: __currentcontext.ff = ff32; break; } if (modeinfo->flags & RGB_MISORDERED) MODEFLAGS |= MODEFLAG_32BPP_SHIFT8; } else { /* Banked mode. */ MODETYPE = CONTEXT_PAGED; if (modeinfo->maxpixels >= WIDTH * HEIGHT * 2) MODEFLAGS |= MODEFLAG_PAGEFLIPPING_CAPABLE; if (modeinfo->maxpixels >= WIDTH * HEIGHT * 3) MODEFLAGS |= MODEFLAG_TRIPLEBUFFERING_CAPABLE; if ((modeinfo->startaddressrange & 0x1ffff) == 0x10000) { /* This hack is required for 320x200x256 page flipping */ /* on Trident, which doesn't work with bank boundary */ /* within the second page. */ MODEFLAGS |= MODEFLAG_FLIPPAGE_BANKALIGNED; } switch (BYTESPERPIXEL) { case 1: __currentcontext.ff = ff8paged; break; case 2: __currentcontext.ff = ff16paged; break; case 3: __currentcontext.ff = ff24paged; break; case 4: __currentcontext.ff = ff32paged; break; } if (modeinfo->flags & RGB_MISORDERED) MODEFLAGS |= MODEFLAG_32BPP_SHIFT8; } if (vga_getcurrentmode() == m) { accelfuncs = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL); __svgalib_nonaccel_fillbox = __currentcontext.ff.driver_fillbox_func; if (accelfuncs & ACCELFLAG_FILLBOX) __currentcontext.ff.driver_fillbox_func = __svgalib_driver8a_fillbox; if (accelfuncs & ACCELFLAG_SCREENCOPY) __currentcontext.ff.driver_copybox_func = __svgalib_driver8a_copybox; } #ifdef DLL_CONTEXT_SHADOW currentcontext = __currentcontext; #endif return 0; } int gl_setcontextvgavirtual(int m) { vga_modeinfo *modeinfo; if (!vga_hasmode(m)) return -1; modeinfo = vga_getmodeinfo(m); /* Set graphics context */ WIDTH = modeinfo->width; HEIGHT = modeinfo->height; if (modeinfo->flags & IS_MODEX) { /* Use a regular virtual screen for planar 256 color modes. */ BYTESPERPIXEL = 1; BYTEWIDTH = modeinfo->linewidth * 4; } else if (modeinfo->colors == 16) { /* Use a regular one byte per pixel virtual screen for */ /* planar 16 color modes. */ BYTESPERPIXEL = 1; BYTEWIDTH = modeinfo->linewidth * 8; } else { BYTESPERPIXEL = modeinfo->bytesperpixel; BYTEWIDTH = modeinfo->linewidth; } COLORS = modeinfo->colors; BITSPERPIXEL = colorbits(COLORS); VBUF = malloc(SCREENSIZE(__currentcontext)); MODETYPE = CONTEXT_VIRTUAL; MODEFLAGS = 0; __clip = 0; switch (BYTESPERPIXEL) { case 1: __currentcontext.ff = ff8; break; case 2: __currentcontext.ff = ff16; break; case 3: __currentcontext.ff = ff24; break; case 4: __currentcontext.ff = ff32; break; } #ifdef DLL_CONTEXT_SHADOW currentcontext = __currentcontext; #endif return 0; } void gl_setcontextvirtual(int w, int h, int bpp, int bitspp, void *v) { WIDTH = w; HEIGHT = h; BYTESPERPIXEL = bpp; BITSPERPIXEL = bitspp; COLORS = 1 << bitspp; BYTEWIDTH = WIDTH * BYTESPERPIXEL; VBUF = v; MODETYPE = CONTEXT_VIRTUAL; MODEFLAGS = 0; switch (BYTESPERPIXEL) { case 1: __currentcontext.ff = ff8; break; case 2: __currentcontext.ff = ff16; break; case 3: __currentcontext.ff = ff24; break; case 4: __currentcontext.ff = ff32; break; } __clip = 0; #ifdef DLL_CONTEXT_SHADOW currentcontext = __currentcontext; #endif } GraphicsContext * gl_allocatecontext() { return malloc(sizeof(GraphicsContext)); } void gl_setcontext(GraphicsContext * gc) { __currentcontext = *gc; #ifdef DLL_CONTEXT_SHADOW currentcontext = *gc; #endif } void gl_getcontext(GraphicsContext * gc) { *gc = __currentcontext; } void gl_freecontext(GraphicsContext * gc) { if (gc->modetype == CONTEXT_VIRTUAL) free(gc->vbuf); } void gl_setcontextwidth(int w) { __currentcontext.width = currentcontext.width = w; __currentcontext.bytewidth = currentcontext.bytewidth = w * BYTESPERPIXEL; } void gl_setcontextheight(int h) { __currentcontext.height = currentcontext.height = h; } /* Clipping */ void gl_setclippingwindow(int x1, int y1, int x2, int y2) { __clip = 1; __clipx1 = x1; __clipy1 = y1; __clipx2 = x2; __clipy2 = y2; } void gl_enableclipping() { __clip = 1; __clipx1 = 0; __clipy1 = 0; __clipx2 = WIDTH - 1; __clipy2 = HEIGHT - 1; } void gl_disableclipping() { __clip = 0; } /* Primitive functions */ void gl_setpixel(int x, int y, int c) { if (__clip && outside(x, y)) return; setpixel(x, y, c); } int gl_getpixel(int x, int y) { if (__clip && outside(x, y)) return -1; return getpixel(x, y); } void gl_hline(int x1, int y, int x2, int c) { if (__clip) { if (y_outside(y)) return; clipxleft(x1); clipxright(x2); } if (x1 > x2) return; hline(x1, y, x2, c); } #define ADJUSTBITMAPBOX() \ nw = w; nh = h; nx = x; ny = y; \ if (nx + nw < __clipx1 || nx > __clipx2) \ return; \ if (ny + nh < __clipy1 || ny > __clipy2) \ return; \ if (nx < __clipx1) { /* left adjust */ \ nw += nx - __clipx1; \ nx = __clipx1; \ } \ if (ny < __clipy1) { /* top adjust */ \ nh += ny - __clipy1; \ ny = __clipy1; \ } \ if (nx + nw > __clipx2) /* right adjust */ \ nw = __clipx2 - nx + 1; \ if (ny + nh > __clipy2) /* bottom adjust */ \ nh = __clipy2 - ny + 1; \ void gl_fillbox(int x, int y, int w, int h, int c) { if (__clip) { if (x + w < __clipx1 || x > __clipx2) return; if (y + h < __clipy1 || y > __clipy2) return; if (x < __clipx1) { w -= __clipx1 - x; x = __clipx1; } if (y < __clipy1) { h -= __clipy1 - y; y = __clipy1; } if (x + w > __clipx2 + 1) w = __clipx2 - x + 1; if (y + h > __clipy2 + 1) h = __clipy2 - y + 1; } if (w <= 0 || h <= 0) return; fillbox(x, y, w, h, c); } void gl_putboxpart(int x, int y, int w, int h, int ow, int oh, void *b, int ox, int oy) { putboxpart(x, y, w, h, ow, oh, b, ox, oy); } void gl_putbox(int x, int y, int w, int h, void *b) { uchar *bp = b; if (w <= 0 || h <= 0) return; if (__clip) { int nx, ny, nw, nh; ADJUSTBITMAPBOX(); if (nw <= 0 || nh <= 0) return; if (nw != w || nh != h) { putboxpart(nx, ny, nw, nh, w, h, bp, nx - x, ny - y); return; } } putbox(x, y, w, h, bp, w); } static void emulate_putboxmask(int x, int y, int w, int h, void *b) { void *box; GraphicsContext gc; box = alloca(w * h * BYTESPERPIXEL); gl_getbox(x, y, w, h, box); /* does clipping */ gl_getcontext(&gc); /* save context */ /* create context that is only the box */ gl_setcontextvirtual(w, h, BYTESPERPIXEL, BITSPERPIXEL, box); gl_putboxmask(0, 0, w, h, b); gl_setcontext(&gc); /* restore context */ gl_putbox(x, y, w, h, box); } void gl_putboxmask(int x, int y, int w, int h, void *b) { if (w <= 0 || h <= 0) return; if (__clip) { if (x + w < __clipx1 || x > __clipx2) return; if (y + h < __clipy1 || y > __clipy2) return; if (x < __clipx1 || y < __clipy1 || x + w > __clipx2 + 1 || y + h > __clipy2 + 1) { /* clipping is not directly implemented */ emulate_putboxmask(x, y, w, h, b); return; } } if (MODETYPE == CONTEXT_PAGED) /* paged primitive is not implemented */ emulate_putboxmask(x, y, w, h, b); else putboxmask(x, y, w, h, b); } void gl_getbox(int x, int y, int w, int h, void *b) { if (__clip) { int nx, ny, nw, nh; ADJUSTBITMAPBOX(); if (nw <= 0 || nh <= 0) return; if (nw != w || nh != h) { getboxpart(nx, ny, nw, nh, w, h, b, nx - x, ny - y); return; } } getbox(x, y, w, h, b, w); } void gl_copybox(int x1, int y1, int w, int h, int x2, int y2) { /* Doesn't handle clipping. */ if (MODETYPE == CONTEXT_PAGED) { /* Paged primitive is not implemented. */ void *box; box = alloca(w * h * BYTESPERPIXEL); getbox(x1, y1, w, h, box, w); putbox(x2, y2, w, h, box, w); return; } copybox(x1, y1, w, h, x2, y2); } /* Miscellaneous functions */ void gl_clearscreen(int c) { gl_fillbox(0, 0, WIDTH, HEIGHT, c); } int gl_rgbcolor(int r, int g, int b) { unsigned v; switch (BITSPERPIXEL) { case 8: /* assumes RGB palette at index 0-255 */ /* bits 0-2 = blue (3 bits) */ /* 3-5 = green (3 bits) */ /* 6-7 = red (2 bits) */ return (r & 0xc0) + ((g & 0xe0) >> 2) + (b >> 5); case 24: case 32: v = (r << 16) + (g << 8) + b; if (MODEFLAGS & MODEFLAG_32BPP_SHIFT8) return v << 8; return v; case 15: return ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + (b >> 3); case 16: return ((r & 0xf8) << 8) + ((g & 0xfc) << 3) + (b >> 3); case 4: /* Now this is real fun. Map to standard EGA palette. */ v = 0; if (b >= 64) v += 1; if (g >= 64) v += 2; if (r >= 64) v += 4; if (b >= 192 || g >= 192 || r >= 192) v += 8; return v; } return -1; } void gl_setpixelrgb(int x, int y, int r, int g, int b) { /* Color components range from 0 to 255 */ if (__clip && outside(x, y)) return; setpixel(x, y, gl_rgbcolor(r, g, b)); } void gl_getpixelrgb(int x, int y, int *r, int *g, int *b) { unsigned c; if (__clip && outside(x, y)) { *r = *g = *b = -1; return; } c = getpixel(x, y); switch (BITSPERPIXEL) { case 8: *b = (c & (1 + 2 + 4)) << 5; /* bits 0-2 */ *g = (c & (8 + 16 + 32)) << 2; /* bits 3-5 */ *r = (c & (64 + 128)); /* bits 6-7 */ break; case 32: if (MODEFLAGS & MODEFLAG_32BPP_SHIFT8) { *b = (c & 0xff00) >> 8; *g = (c & 0xff0000) >> 16; *r = c >> 24; break; } case 24: *b = c & 0xff; *g = (c & 0xff00) >> 8; *r = c >> 16; break; case 15: *b = (c & (1 + 2 + 4 + 8 + 16)) << 3; *g = (c & (32 + 64 + 128 + 256 + 512)) >> 2; *r = (c & (1024 + 2048 + 4096 + 8192 + 16384)) >> 7; break; case 16: *b = (c & (1 + 2 + 4 + 8 + 16)) << 3; *g = (c & (32 + 64 + 128 + 256 + 512 + 1024)) >> 3; *r = (c & (2048 + 4096 + 8192 + 16384 + 32768)) >> 8; break; case 4: *b = (c & 1) * ((c & 8) ? 255 : 128); *g = (c & 2) * ((c & 8) ? 255 : 128); *r = (c & 4) * ((c & 8) ? 255 : 128); break; } } void gl_setdisplaystart(int x, int y) { vga_setdisplaystart(y * BYTEWIDTH + x * BYTESPERPIXEL); } /* Screen copying */ void gl_setscreenoffset(int o) { screenoffset = o; } int gl_enablepageflipping(GraphicsContext * gc) { if (gc->modeflags & MODEFLAG_PAGEFLIPPING_CAPABLE) { gc->modeflags |= MODEFLAG_PAGEFLIPPING_ENABLED; } if (gc->modeflags & MODEFLAG_TRIPLEBUFFERING_CAPABLE) { gc->modeflags &= ~(MODEFLAG_PAGEFLIPPING_ENABLED); gc->modeflags |= MODEFLAG_TRIPLEBUFFERING_ENABLED; } gc->flippage = 0; if (gc->modeflags & MODEFLAG_TRIPLEBUFFERING_ENABLED) return 3; if (gc->modeflags & MODEFLAG_PAGEFLIPPING_ENABLED) return 2; return 0; } void gl_copyscreen(GraphicsContext * gc) { int size; void *svp, *dvp; if (gc->modeflags & MODEFLAG_PAGEFLIPPING_ENABLED) gc->flippage ^= 1; if (gc->modeflags & MODEFLAG_TRIPLEBUFFERING_ENABLED) gc->flippage = (gc->flippage + 1) % 3; if (gc->modeflags & (MODEFLAG_PAGEFLIPPING_ENABLED | MODEFLAG_TRIPLEBUFFERING_ENABLED)) { /* Calculate screen offset in bytes. */ screenoffset = gc->bytewidth * HEIGHT * gc->flippage; if (gc->modeflags & MODEFLAG_FLIPPAGE_BANKALIGNED) screenoffset = ((screenoffset + 0xffff) & ~0xffff); } if (gc->modetype == CONTEXT_MODEX) { vga_copytoplanar256(VBUF, BYTEWIDTH, screenoffset / 4, gc->bytewidth / 4, WIDTH, HEIGHT); goto end; } if (gc->modetype == CONTEXT_PLANAR16) { if (WIDTH == 1024 && HEIGHT >= 512 && ((screenoffset / 8) & 0xffff) == 0) { /* Kludge to allow 1024x768x16 with page flipping. */ int page; page = (screenoffset / 8) >> 16; vga_setpage(page); vga_copytoplanar16(VBUF, BYTEWIDTH, 0, gc->bytewidth / 8, WIDTH, 512); vga_setpage(page + 1); vga_copytoplanar16(VBUF + WIDTH * 512, BYTEWIDTH, 0, gc->bytewidth / 8, WIDTH, HEIGHT - 512); return; } if (WIDTH * HEIGHT >= 512 * 1024) /* We don't handle banking. */ return; vga_copytoplanar16(VBUF, BYTEWIDTH, screenoffset / 8, gc->bytewidth / 8, WIDTH, HEIGHT); goto end; } if (BYTESPERPIXEL == 4 && gc->bytesperpixel == 3) { /* Special case. */ int soffset, doffset; if (BYTEWIDTH / 4 != gc->bytewidth / 3) { /* Even more special case for physical truecolor */ /* modes that have extra scanline padding. */ /* This has the effect of slowing down */ /* '3d' in some truecolor modes on ATI mach32. */ gl_copyboxtocontext(0, 0, WIDTH, HEIGHT, gc, 0, 0); goto end; } soffset = 0; doffset = screenoffset; size = WIDTH * HEIGHT; while (soffset / 4 < size) { int schunk, dchunk; int count; schunk = __svgalib_driver_setread(&__currentcontext, soffset, &svp); dchunk = __svgalib_driver_setwrite(gc, doffset, &dvp); if (dchunk == 1) { /* One byte left in segment. */ int pix; pix = *(unsigned *) svp; /* 32-bit pixel */ *(unsigned char *) dvp = pix; dchunk = __svgalib_driver_setwrite(gc, doffset + 1, &dvp); *(unsigned short *) dvp = pix >> 8; count = 1; /* 1 pixel handled. */ } else if (dchunk == 2) { /* Two bytes left. */ int pix; pix = *(unsigned *) svp; /* 32-bit pixel */ *(unsigned short *) dvp = pix; dchunk = __svgalib_driver_setwrite(gc, doffset + 2, &dvp); *(unsigned char *) dvp = pix >> 16; count = 1; /* 1 pixel handled. */ } else { count = min(min(schunk / 4, dchunk / 3), size - (soffset / 4)); __svgalib_memcpy4to3(dvp, svp, count); } soffset += count * 4; doffset += count * 3; } goto end; } if (BYTESPERPIXEL == 4 && gc->bytesperpixel == 4 && (gc->modeflags & MODEFLAG_32BPP_SHIFT8)) { int soffset = 0; int doffset = screenoffset; size = SCREENSIZE(__currentcontext); while (soffset < size) { int schunk, dchunk; int count; schunk = __svgalib_driver_setread(&__currentcontext, soffset, &svp); dchunk = __svgalib_driver_setwrite(gc, doffset, &dvp); count = min(min(schunk, dchunk), (size - soffset)); __svgalib_memcpy32shift8(dvp, svp, count / 4); soffset += count; doffset += count; } } else { int soffset = 0; int doffset = screenoffset; size = SCREENSIZE(__currentcontext); while (soffset < size) { int schunk, dchunk; int count; schunk = __svgalib_driver_setread(&__currentcontext, soffset, &svp); dchunk = __svgalib_driver_setwrite(gc, doffset, &dvp); count = min(min(schunk, dchunk), (size - soffset)); __memcpy(dvp, svp, count); soffset += count; doffset += count; } } end: if (gc->modeflags & (MODEFLAG_PAGEFLIPPING_ENABLED | MODEFLAG_TRIPLEBUFFERING_ENABLED)) { GraphicsContext save; /* setdisplaystart will use BYTEWIDTH of the virtual screen, */ /* which is what we want since vga_setdisplaystart is */ /* defined in terms of pixel offset (except for hicolor */ /* modes, which are defined in terms of bytes). */ gl_getcontext(&save); gl_setcontext(gc); if (gc->modeflags & MODEFLAG_FLIPPAGE_BANKALIGNED) vga_setdisplaystart(screenoffset); else gl_setdisplaystart(0, gc->height * gc->flippage); gl_setcontext(&save); /* For page flipping, it might be appropriate to add a */ /* waitverticalretrace here. */ } screenoffset = 0; } void gl_copyboxtocontext(int x1, int y1, int w, int h, GraphicsContext * gc, int x2, int y2) { /* This is now reasonably efficient if clipping is not enabled. */ void *buf; GraphicsContext save; gl_getcontext(&save); if ((MODETYPE == CONTEXT_LINEAR || MODETYPE == CONTEXT_VIRTUAL) && (BYTESPERPIXEL == gc->bytesperpixel) && !__clip && !gc->clip) { #ifdef DLL_CONTEXT_SHADOW __currentcontext = *gc; #else gl_setcontext(gc); #endif /* * Note: Using save.bytewidth / BYTESPERPIXEL is probably not an optimal hack here. * it would be better to transfer save.bytewidth to putbox as it is what is really * used there. However, putbox is used all over interpreting the last entry as a * pixel count, so we keep it this way to avoid problems if some other place not * updated by accident. */ putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, save.vbuf + y1 * save.bytewidth + x1 * BYTESPERPIXEL, save.bytewidth / BYTESPERPIXEL); goto end; } buf = alloca(w * h * BYTESPERPIXEL); gl_getbox(x1, y1, w, h, buf); #ifdef DLL_CONTEXT_SHADOW __currentcontext = *gc; #else gl_setcontext(gc); #endif if (save.bytesperpixel == 4 && gc->bytesperpixel == 3) { /* Special case conversion from 32-bit virtual screen to */ /* 24-bit truecolor framebuffer. */ if (gc->modetype == CONTEXT_PAGED || gc->clip) { /* For paged modes or clipping, use another buffer. */ void *buf2; buf2 = alloca(w * h * 3); __svgalib_memcpy4to3(buf2, buf, w * h); gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, buf2); } else /* No clipping, linear. */ __svgalib_driver24_putbox32(x2, y2, w, h, buf, w); } else /* Contexts assumed to have same pixel size. */ gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, buf); end: #ifdef DLL_CONTEXT_SHADOW __currentcontext = save; #else gl_setcontext(&save); #endif } void gl_copyboxfromcontext(GraphicsContext * gc, int x1, int y1, int w, int h, int x2, int y2) { void *buf; GraphicsContext save; if ((gc->modetype == CONTEXT_LINEAR || gc->modetype == CONTEXT_VIRTUAL) && (BYTESPERPIXEL == gc->bytesperpixel) && !__clip && !gc->clip) { /* * see above on gc->bytewidth / BYTESPERPIXEL. */ putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, gc->vbuf + y1 * gc->bytewidth + x1 * BYTESPERPIXEL, gc->bytewidth / BYTESPERPIXEL); return; } gl_getcontext(&save); #ifdef DLL_CONTEXT_SHADOW __currentcontext = *gc; #else gl_setcontext(gc); #endif buf = alloca(w * h * BYTESPERPIXEL); gl_getbox(x1, y1, w, h, buf); #ifdef DLL_CONTEXT_SHADOW __currentcontext = save; #else gl_setcontext(&save); #endif if (gc->bytesperpixel == 4 && save.bytesperpixel == 3) { /* Special case conversion from 32-bit virtual screen to */ /* 24-bit truecolor framebuffer. */ if (save.modetype == CONTEXT_PAGED || save.clip) { /* For paged modes or clipping, use another buffer. */ void *buf2; buf2 = alloca(w * h * 3); __svgalib_memcpy4to3(buf2, buf, w * h); gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, buf2); } else /* No clipping, linear. */ __svgalib_driver24_putbox32(x2, y2, w, h, buf, w); } else /* Contexts assumed to have same pixel size. */ gl_putbox(x2, y2 + screenoffset / BYTEWIDTH, w, h, buf); }