Table of Contents
BE ENGINEERING INSIGHTS: Using the New MALLOC_DEBUG By Scott Bartasbarta@be.com
Like many BeOS developers, I experience daily frustration at
the lack of debugging tools on the BeOS. Unlike most
developers, though, I'm in a position to do more than just
rant (which still occasionally happens), so I've done some
work on This code will be built into BeOS R4, but you can use it now if you download the R3.1 debugging libroot from ftp://ftp.be.com/pub/experimental/tools/libroot_debug.zip. That archive also contains a more detailed description of
If you want a primer on the original
You turn on What's New The best new feature is that If your program trips up Debugging Levels The new Right now, only three levels of debugging are defined: 1, 5,
and 10, leaving room to add future features. Level 1 is
equivalent to the old Level 5 does all the Level 1 checks, and adds an extra step
to do a better job of catching blocks after they're freed:
when you call As an example, let's say there's a bug in your program where you have an instance of a class. You maintain an old pointer to it and write to it after it's been deleted (which is easy to do in heavily threaded applications with poorly managed object lifetimes). Sometimes, the memory the instance used to occupy is free memory, and your error will likely go undetected. Sometimes, though, the memory has been recycled and is now occupied by another instance of the same class, or a different class. An illegal memory write now affects data in a different data structure. An illegal memory read reads data from a different class instance. With no means of detecting errors like these, you'll probably spend a lot of time looking in the wrong place for the problem. However, if the freed block is trashed, placed on a purgatory list, and stays there awhile, it gives your program ample opportunity to try to read from the block (and see trashed data) or write to it. After some time, hopefully after all the dangling pointers have gone away, the block falls off the list, where it is checked to make sure you haven't written to it, and then it is recycled. You can set the size of the purgatory list through the
Normally, You can prevent this by turning the debugging level all the
way up to 10. At the highest level, As you can imagine, this can be a pretty time-consuming
operation; with the period at 1000, the impact on
performance is small, but the latency between an illegal
operation and its detection is fairly large. If you're
having trouble tracking down where a problem happens, you
can crank this value down to something smaller, even all the
way down to 1, which performs a heap consistency check
*every* time, but is excruciatingly slow. When One problem to be aware of is that the new That's all I have time for, because The Man is beckoning me
to crawl back in my cage and fix some bugs, so I can't tell
you about the values
BE ENGINEERING INSIGHTS: Changes in the OpenGL World By Jason Samsrjs@be.com
Ready for another article about 3D on the BeOS? The BeOS Release 4 OpenGL implementation has been heavily modified >from the previous R3.1 version. We've added support for single-buffer rendering, reduced memory usage, and fixed some bugs. Single Buffering Single buffering is perhaps the greatest improvement for R4. OpenGL now uses the BDirectWindow protocol to provide single buffering. It still works with regular BWindows, but at a substantial performance penalty. To provide this functionality, two new member functions have been added to BGLView: BGLView::DirectConnected( direct_buffer_info *info ); BGLView::EnableDirectMode( bool enabled );
void myDirectWindow::DirectConnected( direct_buffer_info *info ) { if( m_glview ) m_glview->DirectConnected( info ); }
Performance Much effort is placed on having an OpenGL implementation that performs well. Two factors limit OpenGL performance. The first is the geometry processing (triangle) rate. This is the rate at which incoming vertex data can be processed and sent to the triangle, line, or point drawing hardware or software. The performance of this portion is generally independent of the size of the primitives sent to OpenGL. It is primarily dependent on the number of these primitives and other factors such as per vertex calculations like lighting or texture coordinate generation. The second factor is the fill rate -- the number of pixels that can be drawn in a given period of time, usually a second. This depends almost entirely on the state of the GL pixel pipeline. For software rendering, disabling most of the pipeline and rendering only flat, shaded triangles generally gives the best performance. Smooth shading, texturing, fogging, depth testing, stenciling, blending, and alpha testing each reduce performance somewhat. Most of the R4 effort has gone into geometry processing optimizations. The processing speed should be greatly increased from R3. The greatest improvement is in the specular lighting code; specular lights should now have much less impact on performance. Another big gain is in quick clipping of primitives that are completely off screen. We utilized some advantages of Intel processors and didn't ignore the drawing code either. We now have a shiny new MMX filler and some PII-specific depth testing code. For those with other processors, don't worry -- OpenGL detects your CPU and uses the right code. Those who've used our prior OpenGL implementations may be wondering why most of the effort went into the geometry portion and not the primitive rendering code that takes most of the processor time. That can be summed up in one word: Hardware While hardware support is not in R4, it's still on schedule for R5. Our implementation of OpenGL now has the hooks to support hardware acceleration. Continued incremental improvements to the software engine will never approach the performance provided by even a $50 3D-video card. All the geometry improvements will become much more visible once hardware acceleration is available. Can you say 200+ fps for GLTeapot? What can you expect once hardware acceleration is available? Some existing OpenGL functions that were good for performance will suddenly become very bad: BGLView::CopyPixelsOut BGLView::CopyPixelsIn These functions will not be the ideal way to move data into
or out of a GLView. A better solution is to use BGLView::EmbeddedView This function will always return NULL starting with R4. All
drawing in a Text in GL One way to draw text in OpenGL is to create the font as a texture and then draw it using standard GL quads. The example below uses GL to draw the letter B. It uses the app_server to create the font and GL to draw it. int ObjectView::round( int in ) { int tempCount = 0; while( in > 7 ) { in >>= 1; tempCount ++; } return in << tempCount; } void ObjectView::makeFontMipmap( int maxSize, char c ) { /* Get a fixed font */ BFont font( be_fixed_font ); int size = maxSize; int level = 0; float fontSize = maxSize; font_height fh; /* Calculate the largest font which will fit */ /* into the specified size */ do { fontSize /= 1.05; font.SetSize( fontSize ); font.GetHeight( &fh ); } while ( fh.leading >= size ); float x = size / 4; /* Round Y to ensure all but the last 3 mipmaps land on */ /* integer values */ float y = round( size - (fh.descent + fh.leading * 0.05) ); /* Reduce the size of the font until its fits the new */ /* location */ do { fontSize /= 1.05; font.SetSize( fontSize ); font.GetHeight( &fh ); } while ( y < fh.ascent ); /* Create each mipmap for the font */ while( size >= 1 ) { font.SetSize( fontSize ); makeFontLevel( size, level, &font, x, y, c ); size /= 2; level ++; x /= 2.0; y /= 2.0; fontSize /= 2; } } void ObjectView::makeFontLevel( int size, int level, BFont *font, float x, float y, char c ) { /* Create a bounding rect for the bitmap */ BRect boundingRect( 0, 0, size-1, size-1 ); GLubyte *bits; /* Create a gray scale bitmap to hold the font */ BBitmap bitmap( boundingRect, B_CMAP8, true, false ); /* Create an embedded view */ BView view( boundingRect, "Font view", B_FOLLOW_NONE, 0); bitmap.Lock(); bitmap.AddChild( &view ); /* Set the background to bright white */ /* Could be done with app server call */ bits = (GLubyte *)bitmap.Bits(); for( int ct=0; ct<size*size; ct++ ) bits[ct] = 255; /* Draw the character into the bitmap at the specified */ /* location */ view.SetFont( font ); view.DrawChar( c, BPoint( x, y ) ); view.Sync(); /* Invert the bitmap to make an intensity map where the */ /* text is intense and the background is not. */ for( int ct=0; ct<size*size; ct++ ) bits[ct] = 255 - bits[ct]; /* Load the intensity map into GL */ glTexImage2D( GL_TEXTURE_2D, level, GL_INTENSITY4, size, size, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmap.Bits() ); /* Clean up */ bitmap.RemoveChild( &view ); bitmap.Unlock(); } void ObjectView::DrawFrame(bool noPause) { if( initCount < 1 ) return; LockGL(); /* Enable texturing */ glEnable( GL_TEXTURE_2D ); /* Set texturing to clamp to prevent repeating the */ /* texture if invalid texture coordinates were given */ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); /* Set filters. This configures for trilinear filtering */ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); /* Colored text is created with GL_MODULATE. */ /* The intensity map determines the brightness and the */ /* vertexes specify the color */ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); /* Make the character texture */ makeFontMipmap( 128, 'B' ); /* Draw the texture */ glBegin( GL_QUADS ); glColor3f( 1.0, 0.0, 0.0 ); glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, 1.0 ); glColor3f( 1.0, 0.5, 0.0 ); glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, 1.0 ); glColor3f( 0.0, 0.0, 1.0 ); glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, -1.0 ); glColor3f( 0.0, 0.5, 1.0 ); glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, -1.0 ); glEnd(); UnlockGL(); }; This could be improved by creating the fonts in advance and binding them to texture objects using glBindTexture. Conclusion Much has already changed in the OpenGL world and much remains to be done. We are now very close to tremendous performance gains through hardware acceleration and BeOS Release 4 has paved the way. Thanks, and let's create those great looking 3D apps.
DEVELOPERS' WORKSHOP: Fal Parsi By Doug Fultonlbj@be.com "Developers' Workshop" is a weekly feature that provides
answers to our developers' questions, or topic requests.
To submit a question, visit
http://www.be.com/developers/suggestion_box.html.
"Now that DR12 (excuse me, R4) is more than a twinkle in
Eddie's eye, can I ask about new features without
cramming my interlocutant down the Bocca de la Verita?"
-- Amfortas,
Monsalvat, Spain
Good of you to write, Mr. Amfortas (where'd you find Shroud
of Turin stationery?). To answer your only question first
(without actually answering it), here you go:
* Between the dum and dee of finding a handler's looper
and locking the fellow, there lies a race. Consider the
mayhem were the handler is removed from the looper between
the two calls. Rare? You bet, but the best bugs are just
so. Solve the problem with BHandler's new LockLooper()
function. In a single call the looper is cornered and
quartered. So, where you now have this (to examplicate the
commonest):
...you will, in R4, type thus:
* Are you jealously interested in the other apps that the
user is sneaking about with when you're not looking? To
get this information, in R3, you had to pester the roster
like a five-year-old in the back seat on his way to
grandma's. Now, roster will pester you: * As * You like * * How many times has mounting a volume evoked that feeling
of presque vu? Turn that "almost" into a certainty by
examining the volume's new " * The That should help. By the way, wasn't Kundry an intern?
It's almost here. We'll soon begin rounds of beta testing
for the upcoming Release 4 of the BeOS. And that seems like
a good opportunity to state our position or intentions on
the topic of release classifications.
First, an explanation of the terms. It used to be that
"alpha" meant something that occasionally worked and
represented what you wanted the product to do. "Beta" meant
"feature complete," including undocumented features --
a.k.a. bugs.
Cynics say that rounds of beta testing are used to
progressively approximate a commercial product, one that the
customer will pay for and not return in bankrupting numbers.
As with any language artifacts, "alpha" and "beta" have lost
some of their categorical meanings as they've evolved. Beta
testing is now an opportunity to add and delete features as
the product moves toward commercial completion. Some
features prove too problematic to fix in reasonable time.
Others that seemed like a good idea might be rejected by
real users. Missing functions in an earlier beta are now
feasible or clamored for.
With the Web, and the Software Valet client in the BeOS, we
have ideal tools for a more fluid beta testing process. I
mentioned "real users" and the clamor for certain features.
In an ideal world, we have a perfect QA organization with
testing programs that probe every tendril in our software
and take it where no human would dare tread. The more
mundane reality is that QA engineers are too sophisticated
and know too much, including unconscious knowledge. As a
result, they, or their programs, don't tread where normal
human beings naturally go. How did you do that, and why? I
don't know, replies the customer, already annoyed.
I know about this. Because of an apparently innate ability
to misuse software and washer-dryers, I'm used to being on
the receiving end of such questions. For example, on a
certain legacy operating system, the number of bytes
remaining on disk is displayed in a window title. I once
"managed" to replace the comma separator in the number with
a J. My hard disk was promptly confiscated. I promise we
won't do this at Be. We might, though, just beg to borrow
your system to make sure we can reproduce a problem we were
unable to create unaided.
Regarding the clamor for features, we're a little nervous.
Hopefully, the BeOS Release 4 will show that we've been
listening to assertive software developers and users. On the
other hand, with a much larger feature set, we're likely to
get even more vigorous feedback -- some of which will feed
the next round of fixes or improvements.
We like this, especially when we don't like it. The pain
means the critics have touched something important that we'd
better attend to.
1997 Be Newsletters | 1995 & 1996 Be Newsletters Copyright ©1998 Be, Inc. Be is a registered trademark, and BeOS, BeBox, BeWare, GeekPort, the Be logo and the BeOS logo are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners. Comments about this site? Please write us at webmaster@be.com. |