Sophie

Sophie

distrib > Mandriva > 2009.1 > x86_64 > by-pkgid > 56c615211d295fb99ff45dd87fd8e366 > files > 212

lib64allegro-devel-4.2.2-4mdv2009.1.x86_64.rpm

<!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> &mdash; Direct access bank switching line selection for reading.
<li><a href="#bmp_unwrite_line">bmp_unwrite_line</a> &mdash; Direct access bank switching line release.
<li><a href="#bmp_write_line">bmp_write_line</a> &mdash; 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-&gt;<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-&gt;<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-&gt;<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-&gt;<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-&gt;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="alleg046.html#exflame" title="How to write directly to video memory improving performance.">exflame</a>,
<a class="eref" href="alleg046.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="alleg046.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="alleg046.html#exflame" title="How to write directly to video memory improving performance.">exflame</a>,
<a class="eref" href="alleg046.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&lt;&lt;(x&amp;3))|2);
      bmp_select(bmp);
      bmp_write8((unsigned long)bmp-&gt;<a href="alleg013.html#line" class="autotype" title="Draws a line onto the bitmap.">line</a>[y]+(x&gt;&gt;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 &lt;sys/nearptr.h&gt;

   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>-&gt;seg, &amp;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>-&gt;<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>