As many of you may have noticed, there is no hardware acceleration for OpenGL in BeOS 5. One reason for this is that we were in the middle of a major re-write of OpenGL which would not support hardware acceleration of BGLView. Another reason is that there were a number of bugs in the previous drivers that prevented other parts of the Be API from functioning normally. As a result, we didn't ship a new version of experimental drivers with BeOS 5, knowing that we would be able to provide much better drivers based on the new implementation shortly after BeOS 5 shipped.
The latest changes dramatically improve both performance and stability with hardware acceleration. The triangle throughput and texture upload speeds have been greatly enhanced and multitexture support has been added. Device enumeration now allows the application to properly determine if it is using a full screen device, eliminating the annoying problem of apps taking over the entire screen.
The geometry pipeline has been rewritten to take full advantage of SIMD processors. This results in large performance improvements on SIMD enabled CPUs such as the PIII. We also improved the scalar pipeline that enhances performance on the Celeron and PII line.
There's a new OS-specific interface layer for OpenGL. Previously, a
number of issues limited our ability to provide proper (i.e., good)
hardware support within the constraints of the existing BGLView
API.
To fix these and add a number of new features we created a new API.
BDirectGLWindow
.
Multiple monitors and hardware devices are supported. It's now possible to render to multiple monitors and hardware cards using OpenGL. Monitors other than your primary display are treated as full screen-only devices.
There's a new locking model. A limitation of BGLView
was that each
application had a global GL lock that only allowed one thread to
render at a given time, even if the rendering was to multiple windows.
This limitation has been lifted, allowing apps to better leverage
multiple CPUs.
The primary display gets proper full screen support. This allows
applications to resize the display and change color depth and still be
cleaned up safely should they crash. Previously, applications needed
to use the BScreen
API that was not safe.
One of the biggest changes between the old and new versions is the introduction of a completely new locking model for OpenGL. The purpose of locking in OpenGL is to associate a context with a window. This is necessary because OpenGL is a C-based API with no explicit connection between a function and the rendering context (Window). The old mechanism handled this by requiring an application to grab a global lock for a window. Once the lock was acquired, all calls to the C API would go to the locked window. The major problem with this is that when you have multiple CPUs and Windows, since the lock is global, you effectively force single threading across windows.
The new locking mechanism now locks the drawing to a window to a specific
thread. This is done through three functions in BDirectGLWindow
:
MakeCurrent()
Makes the current thread the drawing thread for the
window. If another thread is already current for the window this
function will block until the previous owner releases it.
ReleaseCurrent()
Release the current thread. This allows other
threads to grab the context.
YieldCurrent()
Release and reacquire the context. This is exactly the
same as calling ReleaseCurrent()
followed
by MakeCurrent()
. The purpose
is to provide a very low cost method to allow others to grab the
context if necessary. If no other process is blocked on the context,
this will just return without the release/acquire overhead.
Holding a lock for too long blocks other OS functionality, as this lock
will block a DirectConnected
call and some other internal OpenGL
functionality. As a result, an application should release the context
before beginning any long non-drawing functions and should call Yield
within your rendering loop.
The second major new feature is device enumeration and multidevice support. Devices are divided into two categories. Primary devices are those managed by the App server. Rendering in a window is supported on these devices. Secondary devices are full screen-only devices. The functions that follow support this mechanism:
void EnumerateDevices( uint32monitor_id
, uint32color
, uint32depth
, uint32stencil
, uint32accum
)
This function provides a list of devices that meet the requirements
specified. The value of monitor_id
is BGL_MONITOR_PRIMARY
, to return
devices that can render to the standard desktop. BGL_MONITOR_OTHER
returns a list of non-desktop monitors. You can also specify a specific
monitor. The other parameters will specify the application's minimum
requirements for buffer depths. The most common parameters to use will be
BGL_NONE
, BGL_ANY
,
BGL_FASTEST
, BGL_HIGH_QUALITY
. You can specify a
specific buffer depth, but in most cases you'll want to use one of the
above.
virtual void DeviceInfo( uint32device_id
, unit32monitor_id
, const char *name
, booldepth
, boolstencil
, boolaccum
)
A call to EnumerateDevices
generates one or more calls to this function
to describe the devices. The application should record the device_id for
devices the application may wish to use. The name will contain a human
readable description of the device. The three booleans indicate whether
the device can support some form of buffer of the specified type.
virtual voidvideoModeInfo
( uint32mode_id
, uint32width
, uint32height
, uint32color
, uint32depth
, uint32stencil
, uint32accum
)
For each call to DeviceInfo
, one or more calls to
VideoModeInfo
will
follow to describe the abilities of the device. If width
is zero the
device is a windowed device. width
and height
that contain a non-zero
value describe a full screen mode. The color
,
depth
, stencil
, and accum
parameters will contain the specific depths of each buffer.
Using the information obtained from the above calls you can initialize
the OpenGL window and context by calling InitializeGL
.
status_tInitializeGL
( uint32device_id
, uint32color
, uint32depth
, uint32stencil
, uint32accum
)
The device_id
is one of the ids returned in
one of the DeviceInfo
calls.
The other buffer information can be any of the four standard defines
(none, any, fastest, high_quality) or the info from VideoModeInfo
. After
the call to InitializeGL
, you are free to call
MakeCurrent
and begin
rendering.
ShutdownGL()
Destroys the OpenGL context and releases any resources it was using.
By default, the OpenGL rendering area consumes the entire window. It's illegal to draw into the area of a window owned by OpenGL using any means other than the GL API. The results of doing so are not defined. The same applies to reading pixels back from the window. The routines described below are provided to reserve a portion of the window for other drawing.
virtualBRect
UpdateGLRect(BRect
window_rect
)
This function should be overloaded if the application desires to restrict
drawing to a portion of the window. It must be DirectConnected
safe,
meaning that it cannot call normal App server routines. The full window
rect is passed in as window_rect
and the function should return the area
that OpenGL will use for its drawing.
void SetGLRect
()
Trigger a call to UpdateGLRect
to set the GL drawing area.
void SetFullScreen( bool full_screen
)
Toggles the window between full screen and windowed modes. Setting a
window to full screen changes the video mode to the nearest supported
full screen resolution to the current window size. Therefore, to set the
video mode to 800x600 you would set the window size to 800x600 and the
call
to change the video mode.
SetFullScreen
( true
)
Note: This function actually resides in DirectWindow
, but the
functionality changes slightly when a GL context is active.
Not long ago, Dominic wrote an article about the kernel debugger Be Engineering Insights: Welcome to Kernel Debugging Land
It's about time to talk about such things again.
BeOS 5 brings a number of changes to kernel debugging. Some of them are quite visible, others are a little more subtle. Let's take a look at what's new:
We've seen a number of bug reports along the lines of "ALT-PrintScreen" freezes BeOS. What's actually happened is that you've entered the kernel debugger. And if you didn't have some type of serial terminal connected to your first serial port (at 19200 bps, 8 data bits, no parity, 1 stop bit, aka 19200N81), you might have been confused by the lack of response. We've listened! Starting with BeOS 5, you'll need to hold down ALT-PrintScreen and then tap the "d" key. This should prevent people who are trying to save a screenshot from being accidentally teleported to the strange and wonderful habitat of the kernel debugger.
Of course, sometimes bad things happen and the kernel crashes. Previously, this would look as if the machine had just stopped. In BeOS 5, the app_server is kind enough to let the kernel know where screen memory lives, so the kernel debugger can display information on-screen when something goes wrong.
By default, if you invoke the debugger or the system crashes, you'll see
your screen partially overwritten with a friendly message from the kernel
debugger that includes processor registers, a stack crawl, some
information about what team and thread were running, etc. Right now this
only happens on x86. If you're a frequent user of the kernel debugger you
may prefer the serial debug version. If you have a line in
/boot/home/config/settings/kernel/drivers/kernel
that looks like
bluescreen false
you won't get the on-screen debugger. The display is actually black text on a white background, even though the option is called "bluescreen".
If you're in the on-screen debugger, input is accepted from the PS2 or AT keyboard. The USB stack is far, far too complex to operate inside the kernel debugger. You can type "set serial" at the prompt to cause input to be taken from the serial port instead.
If things are scrolling off-screen (e.g., the ps command), you may want
to do something like set paginate on
and set pagesize 40
.
In the event of a crash or debugger request, you'll see some information dumped immediately. The following is an example:
kernel debugger: Welcome to Kernel Debugging Land... eax 600cf0b0 ebp fc003a28 cs 0008 | area 00393058 (kb_mouse_seg0) ebx 600d056c esp fc003a08 ss 0010 | addr 600cb000 size 00005000 ecx fffffedf edi fc003a1b ds 0010 | edx 00000060 esi fffffee0 es 0010 | Thread: idle thread 1 eip 600cdee0 flag 00000013 fs 0000 | Team: kernel_team trap ffffffff err 00000000 gs 0000 | Stack Trace follows: 00000000 600cdee0 _end+1f31c fc003a28 001309ca general_io_interrupt_handler+00ca fc003a60 0016dde4 done_user_hook1+0010 fc003cd8 0016a0f9 ---- iframe ---- fc003cd8 0013974e null_thread+000a fc003ce0 0012ecb8 sysinit1_after_stack_switch+019c kdebug>
The kernel debugger provides many commands by default (type help
at the
prompt to see a pretty extensive list). This code and related data takes
up memory that is locked and not paged. In low-memory conditions (perhaps
on some form of appliance...) you might want to avoid using memory for
debugging code in the final shipping environment. Now it's as easy as
removing the modules you don't want.
/system/add-ons/kernel/debugger
contains several modules:
disasm (26k) | the disassembler (provides "dis" command, etc) |
gdb-stub (7k) | allows for remote GDB debugging (experimental) |
i586 (5k) | some x86 specific extensions (machine specific regs, fp regs, single step, and runto support) |
internals (48k) | debugging commands for fsil, devfs, threads, modules, ports, elfloader, cache and vm |
parser (7k) | allows expressions to be entered in the debugger |
symbols (5k + 200k) | loads the kernel symbols and allows
load_driver_symbols() to work, ads
"lkup" |
If you want to write your own debugger module (to add some neat new functionality not previously available), it's pretty easy:
#include <OS.h> #include <module.h> static int do_test(intargc
, char **argv
) { inti
; kprintf("test command: "); for(i
=0;i
<argc
;i
++) kprintf("%s ",argv
[i
]) kprintf("\n"); return 0; } static status_t std_ops(int32op
, ...) { if(op
==B_MODULE_INIT
) { add_debugger_command("test",do_test
); } else { returnB_ERROR
; } } static module_infotest_info
= { "debugger/test/v1", 0, &std_ops
}; module_info *modules
[] = { &test_info
,NULL
};
That's no doubt what many of our would be downloaders will say when they hear about our last minute misadventure. At 4:45 a.m. PST, we lost our Net connection. On the very morning of the release of BeOS 5, users and mirror sites could not get what we promised to deliver this Tuesday, March 28th—access to the free, Personal Edition. The cyber highway isn't the only one that's congested today. Outside our office, El Camino has a familiar Parisian look—traffic is jammed, two drivers just bent some metal, lanes are closed, and people with hard hats and orange vests are milling around an open trench. The rumor is that the proverbial backhoe has struck again. We're sorry to cause frustration and we apologize for the untimely broken connection.
Other than that, it's a great day. We finally released BeOS 5, with many improvements, including an MP3 _encoder, new MIDI kit with microsecond resolution timing, support for 1394, isochronous USB, more drivers, a lower-memory footprint, new file systems support (such as read-only NTFS and CDDA), support for multiple networking cards, Lucent and PC-Tel softmodem, Pentium III optimization... The list is long and available at <http://www.be.com/products/freebeos/beosspecs.html>. Just as important as the free download, we now offer a "partition-free" install. This appears as a large file on your Windows system; when you launch BeOS, the host shuts down and BeOS runs by itself.
A caveat: as a sage here once announced on a sign above his cube, I'm moving to Theory because everything works in Theory. In other words, your experience may vary. The interaction between Windows and the hardware it runs on is nothing if not idiosyncratic. The shutdown process could leave your machine in an unknown state, which means that BeOS may or may not find a state it can reset to the values it needs. The situation is similar on dual-processor systems: Windows 98 automagically disables the second processor on some systems and leaves it in that state when shutting down.
Fortunately, there is an easy remedy: Please make a BeOS boot floppy. This is not an academic recommendation. If BeOS supports your hardware configuration but doesn't boot from Windows, it will boot unencumbered from your BeOS boot floppy.
As the media have already noted, we're also releasing the source code for the Tracker and the Deskbar, with a license that's a little more liberal than most. This allows interested programmers to modify the appearance and behavior of their systems and to gain better insights into the philosophy behind BeOS. Here again, we want to be cautious. We don't want to represent that we're open sourcing BeOS, nor are we implying anything about the future. This said, I'm personally curious to see what the most creative Be developers will do with the source code we're freeing today.
So far, in spite of our connection problems, thanks to one site in Germany, <http://www.computerchannel.de/specials/beos/>, we already had more than 25,000 downloads by mid-morning PST. This is much appreciated and, as I write this, we're doing our best to clear the clogged arteries.