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>