/usr/share/doc/allegro4-doc/html/alleg022.html is in allegro4-doc 2:4.4.2-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>
Allegro Manual: Direct access to video memory
</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="stylesheet" title="Default" type="text/css" href="allegro.css"></head><body bgcolor=white text=black link="#0000ee" alink="#ff0000" vlink="#551a8b">
<h1><a name="Direct access to video memory">Direct access to video memory</a></h1>
<ul>
<li><a href="#bmp_read_line">bmp_read_line</a> — Direct access bank switching line selection for reading.
<li><a href="#bmp_unwrite_line">bmp_unwrite_line</a> — Direct access bank switching line release.
<li><a href="#bmp_write_line">bmp_write_line</a> — Direct access bank switching line selection for writing.
</ul>
<p>
Read chapter "Structures and types defined by Allegro" for an internal
description of the BITMAP structure. There are several ways to get direct
access to the image memory of a bitmap, varying in complexity depending on
what sort of bitmap you are using.
<p>
The simplest approach will only work with memory bitmaps (obtained from
create_bitmap(), grabber datafiles, and image files) and sub-bitmaps of
memory bitmaps. This uses a table of char pointers, called <tt>`line'</tt>, which is
a part of the bitmap structure and contains pointers to the start of each
line of the image. For example, a simple memory bitmap putpixel function is:
<blockquote class="code"><pre>
void memory_putpixel(<a href="alleg001.html#BITMAP" class="autotype" title="Stores the contents of a bitmap.">BITMAP</a> *bmp, int x, int y, int color)
{
bmp-><a href="alleg013.html#line" class="autotype" title="Draws a line onto the bitmap.">line</a>[y][x] = color;
}
</pre></blockquote>
For truecolor modes you need to cast the line pointer to the appropriate
type, for example:
<blockquote class="code"><pre>
void memory_putpixel_15_or_16_bpp(<a href="alleg001.html#BITMAP" class="autotype" title="Stores the contents of a bitmap.">BITMAP</a> *bmp, int x, int y, int color)
{
((short *)bmp-><a href="alleg013.html#line" class="autotype" title="Draws a line onto the bitmap.">line</a>[y])[x] = color;
}
void memory_putpixel_32(<a href="alleg001.html#BITMAP" class="autotype" title="Stores the contents of a bitmap.">BITMAP</a> *bmp, int x, int y, int color)
{
((long *)bmp-><a href="alleg013.html#line" class="autotype" title="Draws a line onto the bitmap.">line</a>[y])[x] = color;
}
</pre></blockquote>
If you want to write to the screen as well as to memory bitmaps, you need to
use some helper macros, because the video memory may not be part of your
normal address space. This simple routine will work for any linear screen,
eg. a VESA linear framebuffers:
<blockquote class="code"><pre>
void linear_screen_putpixel(<a href="alleg001.html#BITMAP" class="autotype" title="Stores the contents of a bitmap.">BITMAP</a> *bmp, int x, int y, int color)
{
bmp_select(bmp);
bmp_write8((unsigned long)bmp-><a href="alleg013.html#line" class="autotype" title="Draws a line onto the bitmap.">line</a>[y]+x, color);
}
</pre></blockquote>
For truecolor modes you should replace the bmp_write8() with bmp_write16(),
bmp_write24(), or bmp_write32(), and multiply the x offset by the number of
bytes per pixel. There are of course similar functions to read a pixel value
from a bitmap, namely bmp_read8(), bmp_read16(), bmp_read24() and
bmp_read32().
<p>
This still won't work in banked SVGA modes, however, or on platforms like
Windows that do special processing inside the bank switching functions. For
more flexible access to bitmap memory, you need to call the following
routines. They are implemented as inline assembler routines, so they are not
as inefficient as they might seem. If the bitmap doesn't require bank
switching (ie. it is a memory bitmap, mode 13h screen, etc), these functions
just return bmp->line[line].
<p><br>
<div class="al-api"><b>unsigned long <a name="bmp_write_line">bmp_write_line</a>(<a class="autotype" href="alleg001.html#BITMAP" title="Stores the contents of a bitmap.">BITMAP</a> *bmp, int line);</b></div><br>
Selects the line of a bitmap that you are going to draw onto.
<p><b>Return value:</b>
Returns the address of the selected line for writing.
<blockquote class="eref"><em><b>Examples using this:</b></em>
<a class="eref" href="alleg045.html#exflame" title="How to write directly to video memory improving performance.">exflame</a>,
<a class="eref" href="alleg045.html#exlights" title="One way to do colored lighting effects in a hicolor video mode.">exlights</a>.</blockquote>
<div class="al-api"><b>unsigned long <a name="bmp_read_line">bmp_read_line</a>(<a class="autotype" href="alleg001.html#BITMAP" title="Stores the contents of a bitmap.">BITMAP</a> *bmp, int line);</b></div><br>
Selects the line of a bitmap that you are going to read from.
<p><b>Return value:</b>
Returns the address of the selected line for reading.
<blockquote class="eref"><em><b>Examples using this:</b></em>
<a class="eref" href="alleg045.html#exflame" title="How to write directly to video memory improving performance.">exflame</a>.</blockquote>
<div class="al-api"><b>void <a name="bmp_unwrite_line">bmp_unwrite_line</a>(<a class="autotype" href="alleg001.html#BITMAP" title="Stores the contents of a bitmap.">BITMAP</a> *bmp);</b></div><br>
Releases the bitmap memory after you are finished with it. You only need
to call this once at the end of a drawing operation, even if you have
called bmp_write_line() or bmp_read_line() several times before it.
<blockquote class="eref"><em><b>Examples using this:</b></em>
<a class="eref" href="alleg045.html#exflame" title="How to write directly to video memory improving performance.">exflame</a>,
<a class="eref" href="alleg045.html#exlights" title="One way to do colored lighting effects in a hicolor video mode.">exlights</a>.</blockquote>
<br><center><h2><a name="More on banked direct memory access">More on banked direct memory access</a></h2></center><p>
<p>
Although SVGA bitmaps are banked, Allegro provides linear access to the
memory within each scanline, so you only need to pass a y coordinate to
these functions. Various x positions can be obtained by simply adding the x
coordinate to the returned address. The return value is an unsigned long
rather than a char pointer because the bitmap memory may not be in your data
segment, and you need to access it with far pointers. For example, a
putpixel using the bank switching functions is:
<blockquote class="code"><pre>
void banked_putpixel(<a href="alleg001.html#BITMAP" class="autotype" title="Stores the contents of a bitmap.">BITMAP</a> *bmp, int x, int y, int color)
{
unsigned long address = <a href="#bmp_write_line" class="autotype" title="Direct access bank switching line selection for writing.">bmp_write_line</a>(bmp, y);
bmp_select(bmp);
bmp_write8(address+x, color);
<a href="#bmp_unwrite_line" class="autotype" title="Direct access bank switching line release.">bmp_unwrite_line</a>(bmp);
}
</pre></blockquote>
You will notice that Allegro provides separate functions for setting the
read and write banks. It is important that you distinguish between these,
because on some graphics cards the banks can be set individually, and on
others the video memory is read and written at different addresses. Life is
never quite as simple as we might wish it to be, though (this is true even
when we _aren't_ talking about graphics coding :-) and so of course some
cards only provide a single bank. On these the read and write bank functions
will behave identically, so you shouldn't assume that you can read from one
part of video memory and write to another at the same time. You can call
bmp_read_line(), and read whatever you like from that line, and then call
bmp_write_line() with the same or a different line number, and write
whatever you like to this second line, but you mustn't call bmp_read_line()
and bmp_write_line() together and expect to be able to read one line and
write the other simultaneously. It would be nice if this was possible, but
if you do it, your code won't work on single banked SVGA cards.
<p>
And then there's mode-X. If you've never done any mode-X graphics coding,
you probably won't understand this, but for those of you who want to know
how Allegro sets up the mode-X screen bitmaps, here goes...
<p>
The line pointers are still present, and they contain planar addresses, ie.
the actual location at which you access the first pixel in the line. These
addresses are guaranteed to be quad aligned, so you can just set the write
plane, divide your x coordinate by four, and add it to the line pointer. For
example, a mode-X putpixel is:
<blockquote class="code"><pre>
void modex_putpixel(<a href="alleg001.html#BITMAP" class="autotype" title="Stores the contents of a bitmap.">BITMAP</a> *b, int x, int y, int color)
{
outportw(0x3C4, (0x100<<(x&3))|2);
bmp_select(bmp);
bmp_write8((unsigned long)bmp-><a href="alleg013.html#line" class="autotype" title="Draws a line onto the bitmap.">line</a>[y]+(x>>2), color);
}</pre></blockquote>
<p>
Oh yeah: the DJGPP nearptr hack. Personally I don't like this very much
because it disables memory protection and isn't portable to other platforms,
but a lot of people swear by it because it can give you direct access to the
screen memory via a normal C pointer. Warning: this method will only work
with the DJGPP library, when using VGA 13h or a linear framebuffer modes!
<p>
In your setup code:
<blockquote class="code"><pre>
#include <sys/nearptr.h>
unsigned char *screenmemory;
unsigned long screen_base_addr;
__djgpp_nearptr_enable();
__dpmi_get_segment_base_address(<a href="alleg009.html#screen" class="autotype" title="Global pointer to the screen hardware video memory.">screen</a>->seg, &screen_base_addr);
screenmemory = (unsigned char *)(screen_base_addr +
<a href="alleg009.html#screen" class="autotype" title="Global pointer to the screen hardware video memory.">screen</a>-><a href="alleg013.html#line" class="autotype" title="Draws a line onto the bitmap.">line</a>[0] -
__djgpp_base_address);
</pre></blockquote>
Then:
<blockquote class="code"><pre>
void nearptr_putpixel(int x, int y, int color)
{
screenmemory[x + y*<a href="alleg009.html#VIRTUAL_W" class="autotype" title="Global define to obtain the virtual size of the screen.">VIRTUAL_W</a>] = color;
}
</pre></blockquote>
<p><br>
<hr><div class="al-back-to-contents"><a href="allegro.html">Back to contents</a></div>
</body>
</html>
|