1. Faster pixel() in SVGA
- Posted by Pete Eberlein <xseal at HARBORSIDE.COM> Aug 18, 1997
- 759 views
- Last edited Aug 19, 1997
The following code demonstrates how to write to SVGA video memory. It does not perform any clipping at screen edges. The procedure svga_info must be called with the graphic mode number before calling pixel or display_image. Performance is optimized when pixel writes are done in small vertical increments. ---- code begins ---- include machine.e sequence regs, dummy integer bank_start, bytes_per_line, bank_granularity bank_start = 0 regs = repeat(0, 10) regs[REG_AX] = #4F05 regs[REG_BX] = #0000 global procedure pixel(object data, sequence p) integer offset, len if atom(data) then len = 1 else len = length(data) end if offset = p[2] * bytes_per_line + p[1] if offset < bank_start or offset + len > bank_start + 65536 then regs[REG_DX] = floor(offset / bank_granularity) dummy = dos_interrupt(#10, regs) bank_start = regs[REG_DX] * bank_granularity end if poke(#A0000 + offset - bank_start, data) end procedure global procedure display_image(sequence p, sequence data) for y = 1 to length(data) do pixel(data[y], p) p[2] = p[2] + 1 end for end procedure global procedure svga_setup(integer mode) atom data sequence regs data = allocate_low(256) regs = repeat(0,10) regs[REG_AX] = #4F01 regs[REG_CX] = mode regs[REG_ES] = floor(data / 16) regs[REG_DI] = and_bits(data, 15) regs = dos_interrupt(#10, regs) bank_granularity = (peek(data + 4) + 256 * peek(data + 5)) * 1024 bytes_per_line = peek(data + #10) + 256 * peek(data + #11) free_low(data) end procedure -- demo stuff include graphics.e atom junk junk = graphics_mode(257) svga_setup(257) for a = 0 to 479 do pixel(repeat(a, 160), {a,a}) end for ---- code ends ---- Pete Eberlein <xseal at harborside.com>
2. Re: Faster pixel() in SVGA
- Posted by Lee woo seob <wslee at HHI.CO.KR> Aug 20, 1997
- 770 views
Hi all! I timed Pete's faster SVGA routine (display_image()) with my 486-66 machine. 1) displaying 320*200 image (257 mode): Euphoria: 30 f.p.s Pete's: 40 f.p.s Pete's routine is 33% faster than Euphoria's built-in. 2) displaying 640*480 image (257 mode): Euphoria: 4.5 f.p.s Pete's: 5.0 f.p.s Pete's routine is 11% faster. Pete's is faster, however, Euphoria's built-in do perform screen edge clipping, whereas the Pete's does'nt... and one more, when Pete's routine is used in my computer, a few(2 or 3) pixel-image lines were blackened in the middle of the runs of pixels. Bye! from Lee woo seob
3. Re: Faster pixel() in SVGA
- Posted by Pete Eberlein <xseal at HARBORSIDE.COM> Aug 20, 1997
- 771 views
Lee woo seob wrote: > I timed Pete's faster SVGA routine (display_image()) with my 486-66 machine. Thanks, I hadn't got around to doing that. Notice that random pixels are not a whole lot faster than in Euphoria, but pixels that are drawn closely in descending order are much faster. > Pete's is faster, however, Euphoria's built-in do perform screen edge > clipping, whereas the Pete's does'nt... > and one more, when Pete's routine is used in my computer, a few(2 or 3) > pixel-image lines were blackened in the middle of the runs of pixels. That blackening is unusual. Send me any test programs you write. > Bye! from Lee woo seob BABOR, JIRI wrote: > Pete, every time I try to run your demo on my 486-66 in win95 dos window, it c raps out > with: A fatal exception 0D has occurred at 5453:00004406. Any ideas? Jiri I had this happen to me once. Has anyone else encountered this error? I'm not sure if it's a problem with calling the vesa interrupt or writing directly to video memory. There is absolutely no bounds checking or error handling, so bad data results in very bad output or worse. There is also a way to call the set_window_func directly, instead of calling an interrupt, but I haven't messed around with that yet. It might be a little faster but I doubt it's worth the effort in machine coding. I also discovered that my display_image is practically the same as the one in image.e, so my display_image procedure is unneccessary. If I had taken the time to look, I would have realized that display_image calls the new pixel procedure as long as it's redefined before including image.e. Display_image is already optimized for the new pixel procedure because it draws the image in a top-down fashion. I've also noticed that using some other graphics functions in conjunction with the modified pixel exhibits some peculiar behavior. Text written to the screen and lines often appear in the wrong position as well as some other undesired effects. Apparently the graphics library Euphoria uses expects the bank to always be reset to 0 after each graphics procedure. This is exactly what I was trying to avoid, so that the bank would not have to be selected through an interrupt quite as often. Other enhancements might be a routine that works like Michael Bolins extended mem copy as Ralf suggested. I've added a complimentary get_pixel function and a svga_mode function that should be used in place of graphics_mode so that I still can get the necessary info on the mode. ---- code begins ---- -- svga.e -- faster routines for SVGA pixel manipulation in Euphoria -- by Pete Eberlein <xseal at harborside.com> include machine.e include graphics.e sequence regs, dummy integer bank_start, bytes_per_line, bank_granularity atom win_func_ptr bank_start = 0 regs = repeat(0, 10) regs[REG_AX] = #4F05 regs[REG_BX] = #0000 global procedure pixel(object data, sequence p) integer offset, len if atom(data) then len = 1 else len = length(data) end if offset = p[2] * bytes_per_line + p[1] if offset < bank_start or offset + len > bank_start + 65536 then regs[REG_DX] = floor(offset / bank_granularity) dummy = dos_interrupt(#10, regs) bank_start = regs[REG_DX] * bank_granularity end if poke(#A0000 + offset - bank_start, data) end procedure global function get_pixel(sequence p) integer offset offset = p[2] * bytes_per_line + p[1] if length(p) = 2 then if offset < bank_start or offset > bank_start + 65535 then regs[REG_DX] = floor(offset / bank_granularity) dummy = dos_interrupt(#10, regs) bank_start = regs[REG_DX] * bank_granularity end if return peek(#A0000 + offset - bank_start) elsif length(p) = 3 then if offset < bank_start or offset + p[3] > bank_start + 65536 then regs[REG_DX] = floor(offset / bank_granularity) dummy = dos_interrupt(#10, regs) bank_start = regs[REG_DX] * bank_granularity end if return peek({#A0000 + offset - bank_start, p[3]}) end if end function global function svga_mode(integer mode) atom data sequence regs regs = repeat(0,10) data = allocate_low(256) if data then regs[REG_AX] = #4F01 regs[REG_CX] = mode regs[REG_ES] = floor(data / 16) regs[REG_DI] = and_bits(data, 15) regs = dos_interrupt(#10, regs) bank_granularity = (peek(data + 4) + 256 * peek(data + 5)) * 1024 bytes_per_line = peek(data + #10) + 256 * peek(data + #11) win_func_ptr = bytes_to_int(peek({data+12, 4})) free_low(data) end if return graphics_mode(mode) or (data = 0) or (regs[REG_AX] != #4F) end function ---- code ends ---- Pete Eberlein <xseal at harborside.com>