270 likes | 461 Views
CS 686: Programming SuperVGA Graphics Devices. Introduction: An exercise in working with graphics file formats. Raster Display Technology. The graphics screen is a two-dimensional array of picture elements (‘pixels’).
E N D
CS 686: Programming SuperVGA Graphics Devices Introduction: An exercise in working with graphics file formats
Raster Display Technology The graphics screen is a two-dimensional array of picture elements (‘pixels’) These pixels are redrawn sequentially, left-to-right, by rows from top to bottom Each pixel’s color is an individually programmable mix of red, green, and blue
Special “dual-ported” memory CRT CPU VRAM RAM 16-MB of VRAM 2048-MB of RAM
Graphics programs • What a graphics program must do is put appropriate bit-patterns into the correct locations in the VRAM, such that the CRT will show an array of colored dots which in some way is meaningful to the human eye • So the programmer must understand what the CRT will do with the contents of VRAM
How much VRAM is needed? • This depends on (1) the total number of pixels, and on (2) the number of bits-per-pixel • The total number of pixels is determined by the screen’s width and height (measured in pixels) • Example: when our “screen-resolution” is set to 1280-by-960, we are seeing 1,228,800 pixels • The number of bits-per-pixel (“color depth”) is a programmable parameter (varies from 1 to 32) • Certain types of applications also need to use extra VRAM (for multiple displays, or for “special effects” like computer game animations)
How ‘truecolor’ works 24 16 8 0 longword alpha red green blue R G B pixel The intensity of each color-component within a pixel is an 8-bit value
Intel uses “little-endian” order 0 1 2 3 4 5 6 7 8 9 10 VRAM B G R B G R B G R Video Screen
Some operating system issues • Linux is a “protected-mode” operating system • I/O devices normally are not directly accessible • On Pentiums: Linux uses “virtual memory” • Privileged software must “map” the VRAM • A device-driver module is needed: ‘vram.c’ • We can compile it using: $ mmake vram • Device-node: # mknod /dev/vram c 99 0 • Make it ‘writable’: # chmod a+w /dev/vram
VGA ROM-BIOS • Our graphics hardware manufacturer has supplied accompanying code (‘firmware’) that ‘programs’ VGA device components to operate in various ‘standard’ modes • But these firmware routines were not written with Linux in mind: they’re for interfacing with ‘real-mode’ MS-DOS • So special software is needed: ‘int86.cpp’
What is ‘int86.cpp’? • This is ‘boilerplate’ code that we can ‘link’ with all of our Linux graphics applications • It invokes some kernel services provided by our ‘dosio.c’ device-driver which set up a ‘pre-boot execution-environment’ (PXE) allowing Linux to run firmware-routines in ‘virtual-8086’ mode (via the ‘vm86()’ call) • Later we will discuss how it works, but for now we just use it to get on with our demo
In-class demo: ‘pcxphoto.cpp’ • First: several system-setup requirements • Some steps need ‘root’ privileges (or ‘sudo’) • Create device-nodes in ‘/etc/udev/devices’: • ‘/etc/udev/devices/dos’ (read-only) • ‘/etc/udev/devices/vram’ (read/write) • Restart Linux in ‘text mode’ (GRUB boot-menu) • Obtain demo sources from our class website • Compile and install our character-mode Linux device-driver modules: ‘dosio.c’ and ‘vram.c’
Typical ‘program-structure’ Usual steps within a graphics application: • Initialize video system hardware • Display some graphical imagery • Wait for a termination condition • Restore original hardware state
Hardware Initialization • The VGA system has over 300 registers • They must be individually reprogrammed • Eventually we shall study those registers • For now, we just ‘reuse’ vendor routines • Such routines are built into VGA firmware • But invoking them isn’t trivial (since they weren’t designed for a Linux environment)
Obtaining our image-data • Eventually we want to ‘compute’ images • For now, we ‘reuse’ pre-computed data • Data was generated using an HP scanner • It’s stored in a standard graphic file-format • Lots of different graphic file-formats exist • Some are ‘proprietary’ (details are secret) • Other formats are public (search the web)
BitMaP (.bmp) file-format FILE HEADER INFO SECTION Optional color palette IMAGE DATA (usually uncompressed) This is an image-format often used by Microsoft Windows
PiCture eXchange (.pcx) format FILE HEADER (128 bytes) IMAGE DATA (compressed) COLOR PALETTE (768 bytes)
Run-Length Encoding (RLE) • A simple technique for ‘data-compression’ • Well-suited for compressing images, when adjacent pixels often have the same colors • Without compression, a computer graphics image-file (for SuperVGA) would be BIG! • Exact size depends on screen-resolution • Also depends on the display’s color-depth • (Those parameters are programmable)
How RLE-compression works If multiple consecutive bytes are identical: example: 0x29 0x29 0x29 0x29 0x29 (This is called a ‘run’ of five identical bytes) We “compress” five bytes into two bytes: the example compressed: 0xC5 0x29 Byte-pairs are used to describe ‘runs’: Initial byte encodes a ‘repetition-count’ (The following byte is the actual data)
Decompression Algorithm int i = 0; do { read( fd, &dat, 1 ); if ( dat < 0xC0 ) reps = 1; else { reps = (dat & 0x3F); read( fd, &dat, 1 ); } do { image[ i++ ] = dat; } while ( --reps ); } while ( i < npixels );
Standard I/O Library • We call standard functions from the C/C++ runtime library to perform i/o operations on a device-file (e.g., vram): open(), read(), write(), lseek(), mmap() • The most useful operation is ‘mmap()’ • It lets us ‘map’ a portion of VRAM into the address-space of our graphics application • So we can ‘draw’ directly onto the screen!
Where shall VRAM go? • We decide to use graphics mode 0x0121 • It’s a ‘truecolor’ mode: 32 bits-per-pixel • It uses a screen-resolution of 640x480 • Size of VRAM needed: 640*480*4 bytes • So we ‘map’ 2-MB of VRAM to user-space • We can map it to this user address-range: 0xA0000000-0xA0200000
Virtual Memory Layout Linux kernel kernel space (1GB) 0xC0000000 stack VRAM 0xA0000000 user space (3GB) runtime library 0x40000000 code and data 0x08048000
How to compile our demo • The demo program is ‘pcxphoto.cpp’ • It needs to include a header: ‘pcx.h’ • It needs to read a datafile: ‘issxmas.pcx’ • It needs to be linked with ‘int86.cpp’ • It needs to include the header: ‘int86.h’ • Compile it with the GNU C++ compiler: $ g++ pcxphoto.cpp int86.cpp –o pcxphoto
Programming Project #1 • Write an analagous demo-program that will display an image in .bmp file-format • The image-file is named ‘fwright.bmp’ • You will need to utilize a different graphics display mode: 1024-by-768 (mode 0x123) • You will need a different header: ‘bmp.h’ • You will need a different image-algorithm
Exercise: Color-to-Grayscale • Sometimes a color image needs to be converted into a ‘grayscale’ format • Example: print a newspaper photograph (the printing press only uses ‘black’ ink) • How can we ‘transform’ color photos into black-and-white format (shades of gray)? • ‘gray’ colors use a mix of red+green+blue, these components have EQUAL intensity
struct { unsigned char r, g, b; } color; int avg = ( 30*r + 49*g + 11*b )/100; color.r = avg; color.g = avg; color.b = avg; long pixel = 0; pixel |= ( avg << 16 ); // r-component pixel |= ( avg << 8 ); // g-component pixel |= ( avg << 0); // b-component vram[ address ] = pixel; // write to screen Color-conversion Algorithm
In-class exercise • Revise the ‘pcxphoto.cpp’ program so that it will display (1) the ‘color-table’, and then (2) the scanned photograph, as ‘grayscale’ images (i.e., different intensities of gray)