Linux 版 (精华区)
发信人: netiscpu (说不如做), 信区: Linux
标 题: [B] Red Hat Linux Unleashed (55)
发信站: 紫 丁 香 (Sat Jul 25 05:04:16 1998), 转信
Adding Server Support for PEX
_________________________________________________________________
o What Is PEX?
o PEX Server
o Building a Server
# Writing Your Own Driver
o Getting PEX
o Sample PEX Source File
o PEXlib and Motif
# Initializing the Toolkit
# Creating the Window
o Where To Look for More Information
o Summary
_________________________________________________________________
55
Adding Server Support for PEX
This chapter is really two chapters in one. I will discuss two topics
here:
* Building a new server for X.
* To build this new server, we will add PEX support to it. This will
serve as an example of how to add more capabilities to the X
server.
After you read this chapter, you will have an idea of how to draw to
an X drawable, and use Motif and PEX together. This chapter is not a
tutorial on PEX, nor will you become the world's expert on writing
additions to X servers. This chapter will introduce you to techniques
that you can use to add features to the X server. You will also learn
where to look for more information about PEX and X servers.
What Is PEX?
The X Window system is primarily a two-dimensional graphical system.
Due to the lack of standards in the three-dimensional (3-D) area,
there hasn't been an evolution of good 3-D developmental tool
libraries. However, PEX is supposed to alleviate this problem by
providing a consistent set of toolkit calls, which enables a user to
support 3-D software with little effort.
PEX originally stood for PHIGS Extensions to X. PHIGS stands for
Programmer's Hierarchical Interactive Graphics System. PEX has been
adopted by the Common Open Software Environment (COSE) for X11
releases that are later than 2.2.
However, PEX is simply historical at this point, because the last
version of the PEX protocol (Version 6.0) is not designed specifically
for PHIGS at all. PEX is now designed to support 3-D application
programs. PEX is an extension to the Core X Protocol to provide 3-D
graphics support within the X Window environment. Included in the
X11R5 distribution is code for the Sample Implementation of the
extensions to the X Window server, which implements the functionality
defined by the PEX Protocol Extensions.
In order to access the PEX functional extensions to the X server, one
must use an application that generates PEX Protocol. The application
can either generate the Protocol bytestream itself, or use something
called an Application Protocol Interface (API). One such API provided
with the X11R5 distribution is the PHIGS 3D graphics standard. This is
a port of the PHIGS C language binding onto an internal layer, which
generates the PEX Protocol enabling this particular PHIGS
implementation to work within the X Window environment. Other
alternate APIs are available via anonymous FTP from
export.lcs.mit.edu.
When discussing PEX, it is important not to confuse the protocol with
the API. The API is the conceptual model of 3-D graphics that the
application developer sees when developing a client program. The PEX
protocol is generated by the API, and is interpreted by the X server
to perform graphics requests on behalf of the client program.
One API provided with the R5 PEX-SI is a PHIGS/PHIGS-PLUS API. The
PHIGS/PHIGS-PLUS standards are specified in two parts. First, a
functional description explains each operation conceptually, in a
language-independent manner. Second, language bindings are used to
bind the particular PHIGS functions to the semantics of the language.
The PEX-SI comes with an application programmer interface that
conforms to the latest revision of the PHIGS/PHIGS-PLUS C language
binding.
If your version of R5 is patched through patch number 22, you have a
second MIT-supplied API called PEXlib. PEXlib is to the PEX protocol
what Xlib is to the core X protocol. PEXlib provides an interface that
is as close as possible to a one-to-one correspondence between
functions and protocol requests. It is intended to be a systems
programming interface (so, people developing graphics toolkits and
graphics systems will implement their system on top of PEXlib). It is
proposed that the PHIGS API be ported to PEXlib when PEXlib is
finalized. This change would not affect programs written to the
existing PHIGS API.
However, because PEXlib is intimately tied to the protocol, it is
expected that there will be changes between the current PEXlib (which
supports Version 5.0 and 5.1 of the PEX protocol) and the PEXlib that
supports the next major version of the PEX protocol, Version 6.0.
Naturally, every attempt will be made to make the changes to the API
minimal. The nature of the changes from 5.1 to 6.0 are not such that
every primitive will be affected; rather the changes deal with the
sticky problems of subsets, multibuffering, and other issues of global
rendering semantics.
PEX Server
Find out whether you have PEX available on your X server first. By
default, PEX support is not built into the servers you received for
Linux. The xdpyinfo command displays all the extensions supported by a
server.
Output from the PEX command should contain strings of the following
form:
number of extensions: 7
XTestExtension1
SHAPE
MIT-SHM
X3D-PEX (<— This is the line you are looking for)
Multi-buffering
MIT-SUNDRY-NONSTANDARD
If one of the extensions listed is X3D-PEX, your server supports PEX.
If you do not see this line, you must build the server yourself.
Building a Server
To build a server that only includes the drivers you need, use the
LinkKit instead of compiling the complete X system. Using the LinkKit
package is much easier. The LinkKit package can be found in
/usr/X386/lib/Server.
The LinkKit package contains a file called site.def for you to edit.
The site.def file contains the site-specific information for your
system. Edit the site.def file to define which servers you want to
build, and the drivers and font renderers (programs that generate
fonts for display) you want to include.
______________________________________________________________
NOTE: You must run all the commands in this section as root.
______________________________________________________________
Let's examine the site.def file in a bit of detail. See Listing 55.1
for the site.def file that I used to create a PEX server for my
machine.
Listing 55.1. Sample site.def file.
XCOMM $XFree86: mit/server/ddx/x386/LinkKit/site.def.LK,v 2.11
1994/04/10 05:49:56 dawes Exp $
/* Configuration file for Server Link Kit */
#ifdef BeforeVendorCF
/*
* Change these definitions if you need to override the defaults:
*/
/*
* HasGcc: defaults:
* SVR3,4: YES
* Mach, 386bsd: YES
*/
/* #define HasGcc NO */
/*
* HasGcc2: (should also set HasGcc)
* defaults:
* SVR3,4: YES
* Mach: YES
* 386bsd: NO
*/
/* #define HasGcc2 NO */
/*
* If the link kit you are using was built with gcc2, and you are using
* a different compiler:
* 1. Install libgcc.a in a directory searched by your 'ld'
* 2. Set NeedLibGcc to YES
*/
#define NeedLibGcc NO
/*
* Uncomment this if you want to link with the Gnu malloc library
*/
/* #define GnuMalloc YES */
/*
* GnuMallocLib: link-time flags to include the Gnu malloc library.
* this is only used when GnuMalloc is set to YES.
* defaults:
* 386bsd: -lgnumalloc
* others: -lgmalloc
*/
/* #define GnuMallocLib -L/usr/local/gnu -lmalloc */
/*
* Server configuration parameters
*/
#define FontRenderers Speedo Type1
#define X386Vga2Drivers et4000 et3000 pvga1 gvga tvga8900 ncr \
compaq oak generic
#define X386Vga16Drivers et4000 tvga8900 generic
#define X386Vga256Drivers et4000 et3000 pvga1 gvga ati tvga8900 cirrus \
ncr compaq oak
#define X386Hga2Drivers /**/
/* To enable the hga2 driver, replace the above line with the following */
/* #define X386Hga2Drivers hga6845 */
/*
* To include the generic banked monochrome driver in the monochrome server,
* uncomment this with one of the following low level drivers
* hgc1280 [Hyundai HGC-1280 1280x1024]
* sigma [Sigma L-View]
* visa [???]
* apollo [???]
* ...
* (list is subject to grow)
*/
/* #define X386Bdm2Drivers hgc1280 sigma visa apollo */
/* #define XF86S3Drivers mmio_928 s3_generic */
/*
* Set which servers to build. Change the YES to NO for servers you don't
* want to build.
*/
/* The SVGA color server */
#define XF86SVGAServer YES
/* The 16-color VGA server */
#define XF86VGA16Server NO
/* The VGA mono server */
#define XF86MonoServer NO
/* The S3 server */
#define XF86S3Server NO
/* The IBM 8514/A server */
#define XF86I8514Server NO
/* The Mach8 server */
#define XF86Mach8Server NO
/* The Mach32 server */
#define XF86Mach32Server NO
/* Set the default server (ie the one that gets the sym-link to "X") */
/* #define XFree86DefaultServer XF86_S3 */
/*
* If you want PEX (and this link kit was built with PEX support), uncomment
* the following
*/
/* #define BuildPexExt YES */
#define BuildPexExt YES
#endif /* BeforeVendorCF */
#ifdef AfterVendorCF
/* If you are using a different ProjectRoot, set it here */
/*
#ifdef ProjectRoot
#undef ProjectRoot
#endif
#define ProjectRoot /usr/X11R5
*/
#endif /* AfterVendorCF */
Note the following items about this site.def file:
* The HasGcc and HasGcc2 definitions have been commented out for
Linux.
* If the LinkKit was built with gcc-2.x and you are using some other
compiler, you must install libgcc.a and set NeedLibGcc to YES.
For Linux, NeedLibGcc is set to NO.
The servers available to you via LinkKit are shown in Table 55.1. To
create any of these servers, you have to set the value of the
corresponding variable to YES.
Table 55.1. Server types in site.def.
Server Type Variable To Set
256-color server XF86SVGAServer
16-color server XF86VGA16Server
Monochrome server XF86MonoServer
S3 server XF86S3Server
Mach8 server XF86Mach8Server
Mach32 server XF86Mach32Server
IBM 8514/A server XF86I8514Server
In the sample site.def in Listing 55.1, I have set only the 256-color
SVGA server to be built. All other servers will not be built.
______________________________________________________________
NOTE: The PEX extensions you have do not support the Monochrome
server.
______________________________________________________________
The Drivers variables define the video drivers that you want to
include in a server. The order of drivers determines the order in
which the server probes the video card to determine which driver to
use. The generic driver should be the last one included in the
monochrome and 16-color servers because its probe always succeeds.
The generic_s3 driver should be the last one included in the S3
servers for similar reasons.
After you have edited the site.def file, you must create the Makefile.
To build the Makefile, run this command:
# ./mkmf
Then, run make to link the servers that you have configured in the
site.def file. This command takes a while. After this command is done,
run the make install command to install the new servers:
# make install
______________________________________________________________
NOTE: Run make clean to remove the files that were created by this
procedure.
This frees the directory structures of any unnecessary files, which
is important because disk space is at a premium under Linux.
______________________________________________________________
Now start X, run the window manager, and in an xterm use the xdpyinfo
command to see whether the PEX extensions are there. It is possible to
see which drivers are included in the server by running the X server
with the -showconfig flag.
Writing Your Own Driver
If you are including a driver that it not part of the standard
distribution, make a directory in drivers/vga256 (drivers/vga2 if it
is for the monochrome server; drivers/vga16 if it is for the 16-color
server; or drivers/bdm2 if it is for the bdm2 monochrome server's bdm2
screen). Copy either the source or the .o file, and a suitable
Imakefile, into that directory. The name of the directory should be
the same as the name of the driver. If you are adding an additional
font renderer, put the library in ./renderers. Look at the
VGADriver.Doc file for more details.
Getting PEX
You have PEX files on the CD-ROM at the back of this book.
There are several examples of PEX code available on the Internet. One
sample library can be found at the site export.lcs.mit.edu in the
/R5contrib/R5contrib-fixes directory as the file PEX.examples.tar.Z.
______________________________________________________________
NOTE: For Tk and Tcl users, PEXtk is available directly from
export.mit.lcs.edu, and is located in /contrib. The files are
pextk.PS.tar.Z, pextk.README, and pextk.tar.Z. PEXtk uses X as its
windowing system, so the UI is X-based.
______________________________________________________________
Sample PEX Source File
Let's look at an example of a simple PEX program that prints the line
Howdy World. (Hello World is a bit overused.) The following is the
listing for printing this line:
#include "phigs/phigs.h"
#include "X11/Xlib.h"
#include "X11/Xatom.h"
#include "strings.h"
char windowName[] = "PEX in Linux";
char HelloStr[] = "Howdy World";
main()
{
Pconnid_x_drawable connid;
Display *display;
int screen;
Ppoint text_pt;
popen_phigs(NULL,0); /* open a conn. to PHIGS server */
/*
** Set the error file name to NULL
** Set default memory size to zero
*/
connid.display = display = XOpenDisplay( NULL );
screen = DefaultScreen( display );
connid.drawable_id =
XCreateSimpleWindow( display,
RootWindow( display, screen ),
0, 0, 600, 600, 4,
WhitePixel( display, screen ),
BlackPixel( display, screen ) );
XChangeProperty( display, connid.drawable_id, XA_WM_NAME,
XA_STRING, 8, PropModeReplace,
(unsigned char *) windowName , strlen(windowName) );
XMapWindow( display, connid.drawable_id );
popen_ws( 1, &connid, phigs_ws_type_x_drawable );
popen_struct( 1 );
text_pt.x = 0.2;
text_pt.y = 0.5;
pset_char_ht( 0.05 );
ptext( &text_pt, HelloStr, strlen(HelloStr)):
pclose_struct( );
ppost_struct( 1, 1, 1.0 );
printf("Hit return to exit");
getchar();
pclose_ws( 1 );
pclose_phigs( );
}
The first executable line in this file opens a connection to the PEX
server with a call to popen_phigs(NULL,0). The NULL parameter sets the
error filename to nothing, and the 0 sets the default memory size to
0.
The next lines set the display, screen, and window IDs for this
application. The window ID is set to point to the root window for the
application with a call to the XCreateSimpleWindow function. The
display and screen IDs are set to the defaults. Note that you are
using low-level X Window system function calls to create the root
window. This example tells you that it's possible to access all the
low-level X Window functions, in addition to the PEX functions.
The XChangeProperty function call sets the window name to the one
desired. The display and window ID (connid.drawable_id) are set to
that of the root window of the application.
The XMapWindow function maps your display to the current window ID.
The popen_ws() call opens the workspace for the display for you to be
able to draw on. You then set the test position for the Howdy World
string. Then, open a structure for writing with PEX primitives to set
the text_pt structure with the text. It is necessary to call the
pclose_struct() function when done with the drawing area buffer.
Lastly, post the structure to ppost_struct.
Wait until the user gives the keystroke you want, and then end the
application. In this case, you must call two functions before ending
the application. One is a call to pclose_ws( 1 ) for closing the
workspace, and the other is a call to pclose_phigs( ) for shutting
down the PEX server.
PEXlib and Motif
In the previous example, the drawable was used to create the drawing
patterns on a drawing area widget. PEXlib by itself is intended to be
an interface into the lower-level Xlib. PEXlib gives you the
capability to do 3-D mappings, shading, and so on, along with other
geometric transformations.
This section covers the basic act of combining PEXlib with Motif. This
way, you can get a drawable area under Motif and be able to use PEX
functions on it. In addition to this, you still have the Motif
framework to add your own menus to it. The steps to combine Motif and
PEXlib are as follows:
* Initialize an X Window, and get the best visual you can for PEX.
* Initialize PEX with a call to PEXInitialize.
* Create a top-level shell.
* Create a drawing area interface for PEX.
* Map the drawing area to the screen.
* Create a PEX renderer (just like the GC) for this drawing area.
* Draw to your heart's delight.
Initializing the Toolkit
For initializing the toolkit, you must use a long method instead of
XtAppInitialize. This long method enables you to select the best
visual you can get for PEX. The following code segment will suffice:
XtToolkitInitialize();
app_context = XtCreateApplicationContext();
cp_argc = argc;
argv_sz = argc * sizeof(char *);
cp_argv = (char **)XtMalloc(argv_sz);
memcpy(cp_argv, argv, argv_sz); /* copy the pointers */
display = XtOpenDisplay(app_context,
argv[0], argv[0],
"pEX", /* Class Name */
NULL, 0, /* no resource options */
&argc, argv);
if (display == (Display *) NULL)
abort("Unable to open display");
You are making a copy of argc and argv to preserve their values,
because the call to XtOpenDisplay() mangles these original values.
It's necessary to check whether the display pointer is set to a valid
value when you return from XtOpenDisplay() because the display may not
have been opened for a variety of reasons, and you do not want to work
a NULL pointer for the display.
Initialize the PEXlib functions with a call to the function
PEXInitialize(). The syntax for this call is as follows:
#include <X11/PEX5/PEXlib.h>
int PEXInitialize(Display *dp,
PEXExtensionInfo *info_ptr,
int message_length,
char *msg);
The PEXExtensionInfo pointer should point to a structure to which you
want this function to return information about the PEX server. The
message array should be about 80 characters long, and contain the text
for any returned error messages. The function returns 0 if no errors
occurred; otherwise, it returns one of the following values:
* PEXBadExtension if the X server does not support PEX
* PEXBadProtocolVersion if your X server and the PEXlib you are
using are of different versions
* PEXBadLocalAlloc if you are out of memory
* PEXBadFloatConversion if the X server does not support the PEX
floating point
Also, note that I used PEX5 as the location of the include files. When
PEX 6.0 comes along, you may have to change this PEX5 reference to
PEX6 in all the code you have to date. A bummer indeed, but necessary
for an upgrade.
The returned PEXExtensionInfo structure is of the following form:
typedef struct {
unsigned_short major_version;
unsigned_short minor_version;
unsigned long release;
unsigned long subset_info;
char *vendor_name;
int major_opcode;
int first_event;
int first_error;
} PEXExtensionInfo;
The major version is usually 5 or 6, and the minor version either 0 or
1. The vendor name and release are vendor-specific. The subset
information contains information about the features in your PEX
server, and can have the following values:
PEXImmediateMode Enables drawing primitives that are sent
directly to the display.
PEXWorkstationOnly Enables workstation resources.
PEXStructureMode Enables drawing primitives to be stored in a
structure before being sent to the display.
PEXCompleteImplementation Enables all of these functions.
Check this value to see what features your X server supports. If your
server does not have either the complete or Immediate mode graphics
(the Linux server is and should be complete), you should exit the
application with an error message.
Creating the Window
Now create the window with the colormap and the best visual for PEX.
The way to do this is as follows:
XStandardColormap colormap;
Colormap PEX_colormap;
/* open display as before */
screen = DefaultScreen(display);
visual = DefaultVisual(display,screen);
depth = DefaultDepth(display,screen);
status = GetStdColormap(display, screen,
visual, depth,
&colormap);
if (status == True)
PEX_colormap = colormap;
blue = AllocNamedColor(display, PEX_colormap,
"Blue", 0L);
white = AllocNamedColor(display, PEX_colormap,
"White", 0L);
n = 0;
XtSetArg(args[n],XmNvisual, visual); n++;
XtSetArg(args[n],XmNdepth, depth); n++;
XtSetArg(args[n],XmNcolormap, colormap); n++;
XtSetArg(args[n],XmNallowResize, True); n++;
XtSetArg(args[n],XmNmapWhenManaged, False); n++;
XtSetArg(args[n],XmNbackground, blue); n++;
XtSetArg(args[n],XmNforeground, white); n++;
XtSetArg(args[n],XmNargc, cp_argc); n++;
XtSetArg(args[n],XmNargv, cp_argv); n++;
XtSetArg(args[n],XmNheight, 400); n++;
XtSetArg(args[n],XmNwidth, 400); n++;
toplevel = XtAppCreateShell(NULL, "peX",
applicationShellWidgetClass, display, args, n);
mainWindow = XmCreateMainWindow(toplevel, "mainWin", NULL, 0);
drawMe = XmCreateDrawingArea(mainWindow,
"pexdraw", args, n);
______________________________________________________________
NOTE: If you are unfamiliar with programming in Motif or X, please
refer to Chapter 32, "Motif for Programmers."
______________________________________________________________
The application requires the toplevel shell. For this shell, you have
to manually set its visual, screen, display, and colormap. Note that
the resize resource is set to True and mapWhenManaged is set to False.
You have to set these values via the XtArgs args array at creation
time for this to work. The toplevel shell is where you create the main
window to place your Motif widgets. After you have created the main
window with the XmCreateMainWindow function call, you create the
drawing area called drawMe on top of this window.
Next, you add callbacks to the drawing area widget to allow for
redrawing. Add the callbacks to the drawing area for the following
types of events: resize, expose, and input.
The complete code for a very simple application is shown in Listing
55.2.
Listing 55.2. A sample PEX application with Motif.
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>
#include <Xm/MainW.h>
#include <Xm/RowColumn.h>
#include <X11/PEX5/PEXlib.h>
#include <stdio.h>
int bailout(char *str)
{
printf ("\n %s", str);
exit(1);
}
int pex_set_line_color(Display *dpy, PEXRenderer p,
float r, float g, float b)
{
PEXColor pc;
pc.rgb.red = r;
pc.rgb.green = g;
pc.rgb.blue = b;
PEXSetLineColor(dpy, p, PEXOCRender, PEXColorTypeRGB, &pc);
}
void doSamplePEX( Display *dpy, Window win, PEXRenderer ren)
{
PEXCoord coords[10];
PEXBeginRendering(dpy, win, ren);
PEXSetLineWidth(dpy, ren, PEXOCRender, 8.0);
pex_set_line_color(dpy, ren, 0.5, 0.5, 1.0);
coords[0].x = 0.3; coords[0].y = 0.3; coords[0].z = 0.0;
coords[1].x = 0.3; coords[1].y = 0.6; coords[1].z = 0.0;
coords[2].x = 0.6; coords[2].y = 0.6; coords[2].z = 0.0;
coords[3].x = 0.6; coords[3].y = 0.3; coords[3].z = 0.0;
PEXPolyline(dpy, ren, PEXOCRender, 4, coords);
pex_set_line_color(dpy, ren, 1.5, 0.5, 1.5);
coords[0].x = 0.3; coords[0].y = 0.3; coords[0].z = 0.5;
coords[1].x = 0.3; coords[1].y = 0.6; coords[1].z = 0.5;
coords[2].x = 0.6; coords[2].y = 0.6; coords[2].z = 0.5;
coords[3].x = 0.6; coords[3].y = 0.3; coords[3].z = 0.5;
PEXPolyline(dpy, ren, PEXOCRender, 4, coords);
PEXEndRendering(dpy, win, ren);
XFlush(dpy); /* important */
}
void quitBtn( Widget w, void *p, void *pp)
{
exit(0);
}
void drawBtn( Widget w, XmDrawingAreaCallbackStruct *sp,
XtPointer *client_data)
{
Dimension wd, ht;
PEXRenderer *rp;
if (sp == NULL) return;
switch(sp->reason)
{
case XmCR_EXPOSE:
if (sp->event->xexpose.count == 0)
{
rp = (PEXRenderer *)client_data;
doSamplePEX(XtDisplay(w), XtWindow(w), *rp);
}
break;
case XmCR_INPUT:
break;
}
}
int
pexInit(Display *dpy, PEXExtensionInfo **pexparms)
{
int err;
char errorMsg[PEXErrorStringLength+1];
PEXExtensionInfo *pex_info;
err = PEXInitialize(dpy, pexparms,
PEXErrorStringLength, errorMsg);
if (err) return False;
pex_info = (PEXExtensionInfo *)(*pexparms);
if( (pex_info->subset_info & PEXImmediateMode) ||
((pex_info->subset_info & 0xffff) == PEXCompleteImplementation))
{
return True;
}
return False;
}
int main(int argc, char *argv[])
{
Widget parent;
XtAppContext app_context;
int cp_size;
int cp_argc;
int cp_argv;
int status;
int screen;
int depth;
int fore;
int bkg;
int n;
Arg wars[20];
Visual *visual;
Colormap colormap;
XStandardColormap std_cmp;
PEXRendererAttributes pex_attr;
Display *dpy;
PEXExtensionInfo *pexParms;
PEXRenderer ren;
Widget mainw;
Widget filemenu;
Widget menubar;
Widget exitBtn;
Widget drawme;
XtToolkitInitialize();
app_context = XtCreateApplicationContext();
cp_argc = argc;
cp_size = argc * (sizeof(char *));
cp_argv = (char **)XtMalloc(cp_size);
memcpy(cp_argv, argv, cp_size);
dpy = XtOpenDisplay(app_context, NULL, NULL,
"pexSample", NULL, 0, &argc, argv);
if (dpy == (Display *) NULL)
bailout("Cannot open display");
status = pexInit(dpy,&pexParms);
if (status == False) bailout("Cannot use PEX");
screen = DefaultScreen(dpy);
visual = DefaultVisual(dpy, screen);
depth = DefaultDepth(dpy,screen);
status = GetStdColormap(dpy, screen, visual, depth, &std_cmp);
colormap = std_cmp.colormap;
bkg = BlackPixel(dpy,screen);
fore = WhitePixel(dpy,screen);
n = 0;
XtSetArg(wars[n], XmNvisual, visual); n++;
XtSetArg(wars[n], XmNdepth, depth); n++;
XtSetArg(wars[n], XmNcolormap, colormap); n++;
XtSetArg(wars[n], XmNbackground, bkg); n++;
XtSetArg(wars[n], XmNborderColor, fore); n++;
XtSetArg(wars[n], XmNargc, cp_argc); n++;
XtSetArg(wars[n], XmNargv,cp_argv); n++;
XtSetArg(wars[n], XmNallowResize, True); n++;
XtSetArg(wars[n], XmNmappedWhenManaged, False); n++;
XtSetArg(wars[n], XmNwidth, 300); n++;
XtSetArg(wars[n], XmNheight, 300); n++;
parent = XtAppCreateShell(NULL,"pexSample",
applicationShellWidgetClass, dpy, wars, n);
n = 0;
mainw = XmCreateMainWindow(parent, "mainwindow", wars, n);
n = 0;
XtSetArg(wars[n], XmNresizePolicy, XmRESIZE_ANY); n++;
XtSetArg(wars[n], XmNbackground, bkg); n++;
XtSetArg(wars[n], XmNborderColor, fore); n++;
drawme = XmCreateDrawingArea(mainw, "da", wars, n);
XtAddCallback(drawme, XmNexposeCallback,
(XtCallbackProc)drawBtn, (XtPointer) &ren);
XtAddCallback(drawme, XmNinputCallback,
(XtCallbackProc)drawBtn, (XtPointer) &ren);
XtAddCallback(drawme, XmNresizeCallback,
(XtCallbackProc)drawBtn, (XtPointer) &ren);
XtManageChild(drawme);
XtManageChild(mainw);
XtRealizeWidget(parent);
pex_set_color_approx(dpy,XtWindow(drawme), &std_cmp, &pex_attr);
XtMapWidget(parent);
ren = PEXCreateRenderer(XtDisplay(mainw), XtWindow(drawme),
PEXRAColorApproxTable, &pex_attr);
if (ren == 0) {
printf("\n Bad renderer \n"); exit (1);
}
XtAppMainLoop(app_context);
return(0);
}
A few points to note about Listing 55.2 are that the immediate mode
was used for rendering on the screen. PEX-SI provides no support for
double buffering. This is a serious bug because lack of double
buffering hinders performance.
Even worse, the PEX-SI API assumes that the client desires an
XClearArea on the window before each frame is drawn. This causes
unnecessary flickering while the screen is cleared and redrawn on all
primitive drawing calls. What should have been done was to provide an
end-of-render procedure hook, with the default hook installed to do a
clear area function call.
Individual vendors (because of market pressure) have provided their
own solutions to the double buffering problem. (Most PHIGS
workstations do double buffering. If you do immediate mode you get
single buffering along with the PEX-SI's XClearArea call.)
A final word about adding too many features in an X server. The more
you add to the X server, the more memory it chews up in your system.
Unless you absolutely require PEX (or other) support, do not add it to
your X server, especially if RAM is 8MB or less. The PEX support for
Linux added about 420KB on my system, which is not a lot, but it does
start adding up. Also, the overhead of PEX applications tend to make
my 8MB, 486/33 somewhat slow when running PEX demos, which leads me to
believe that PEX on Linux with less than 16MB is not worth the hassle.
If you are serious about PEX on Linux, get a faster machine and put
gobs of memory on it. The performance improved very dramatically on a
486/66 with 32MB of RAM.
Where To Look for More Information
If you would like more information and examples of source code for
PEX, check out these FTP sites:
* export.lcs.mit.edu in /R5contrib/contrib-R5fixes has several tar
files of source code for PHIGS and PEX including a 3-D drawing
program.
* http://www.x.org is a good place to start looking for more
information on X.
Summary
This chapter has been a whirlwind tour of PEX. The topic of PEX could
be a book in itself. In fact, there are several texts available that
go into excruciating detail about PEX. You should have learned the
following information from this chapter:
* How to create a new X server with your specifications. Building
your own server with LinkKit is far easier than trying to
re-create the entire X distribution. There are fewer memory
requirements, and the build takes up less disk space and time to
compile and link.
* How to install the new server. The LinkKit does this for you
automatically and gives you options to clean your directories, and
so on.
* How to check for the extensions in the current server.
* How to interface Motif with PEX.
* The trade-offs of having too many extensions in X server, such as
loss of memory and speed for added functionality.
Where to look for more information about PEX and Linux.
--
Enjoy Linux!
-----It's FREE!-----
※ 修改:.netiscpu 于 Jul 25 06:07:05 修改本文.[FROM: mtlab.hit.edu.cn]
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: fengyun.hit.edu.]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:403.895毫秒