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 (<&#151; 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)
页面执行时间:407.330毫秒