intel_screen.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00028 #include "utils.h"
00029 #include "vblank.h"
00030 #include "xmlpool.h"
00031 
00032 #include "intel_context.h"
00033 #include "intel_screen.h"
00034 #include "intel_batchbuffer.h"
00035 #include "intel_swapbuffers.h"
00036 
00037 #include "i830_dri.h"
00038 #include "ws_dri_bufpool.h"
00039 
00040 #include "pipe/p_context.h"
00041 #include "pipe/p_screen.h"
00042 #include "pipe/p_inlines.h"
00043 #include "state_tracker/st_public.h"
00044 #include "state_tracker/st_cb_fbo.h"
00045 
00046 static void
00047 intelCreateSurface(struct intel_screen *intelScreen, struct pipe_winsys *winsys, unsigned handle);
00048 
00049 static void
00050 intelCreateSurface(struct intel_screen *intelScreen, struct pipe_winsys *winsys, unsigned handle)
00051 {
00052    struct pipe_screen *screen = intelScreen->base.screen;
00053    struct pipe_texture *texture;
00054    struct pipe_texture templat;
00055    struct pipe_surface *surface;
00056    struct pipe_buffer *buffer;
00057    unsigned pitch;
00058 
00059    assert(intelScreen->front.cpp == 4);
00060 
00061    buffer = intel_be_buffer_from_handle(&intelScreen->base,
00062                                         "front", handle);
00063 
00064    if (!buffer)
00065       return;
00066 
00067    intelScreen->front.buffer = dri_bo(buffer);
00068 
00069    memset(&templat, 0, sizeof(templat));
00070    templat.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
00071    templat.target = PIPE_TEXTURE_2D;
00072    templat.last_level = 0;
00073    templat.depth[0] = 1;
00074    templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
00075    templat.width[0] = intelScreen->front.width;
00076    templat.height[0] = intelScreen->front.height;
00077    pf_get_block(templat.format, &templat.block);
00078    pitch = intelScreen->front.pitch;
00079 
00080    texture = screen->texture_blanket(screen,
00081                                      &templat,
00082                                      &pitch,
00083                                      buffer);
00084 
00085    /* Unref the buffer we don't need it anyways */
00086    pipe_buffer_reference(screen, &buffer, NULL);
00087 
00088    surface = screen->get_tex_surface(screen,
00089                                      texture,
00090                                      0,
00091                                      0,
00092                                      0,
00093                                      PIPE_BUFFER_USAGE_GPU_WRITE);
00094 
00095    intelScreen->front.texture = texture;
00096    intelScreen->front.surface = surface;
00097 }
00098 
00099 PUBLIC const char __driConfigOptions[] =
00100    DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
00101    DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
00102    DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
00103    DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
00104 //   DRI_CONF_FORCE_S3TC_ENABLE(false)
00105    DRI_CONF_ALLOW_LARGE_TEXTURES(1)
00106    DRI_CONF_SECTION_END DRI_CONF_END;
00107 
00108 const uint __driNConfigOptions = 3;
00109 
00110 #ifdef USE_NEW_INTERFACE
00111 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
00112 #endif /*USE_NEW_INTERFACE */
00113 
00114 extern const struct dri_extension card_extensions[];
00115 
00116 
00117 
00118 
00119 static void
00120 intelPrintDRIInfo(struct intel_screen * intelScreen,
00121                   __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
00122 {
00123    fprintf(stderr, "*** Front size:   0x%x  offset: 0x%x  pitch: %d\n",
00124            intelScreen->front.size, intelScreen->front.offset,
00125            intelScreen->front.pitch);
00126    fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
00127 }
00128 
00129 
00130 #if 0
00131 static void
00132 intelPrintSAREA(const drmI830Sarea * sarea)
00133 {
00134    fprintf(stderr, "SAREA: sarea width %d  height %d\n", sarea->width,
00135            sarea->height);
00136    fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
00137    fprintf(stderr,
00138            "SAREA: front offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
00139            sarea->front_offset, sarea->front_size,
00140            (unsigned) sarea->front_handle);
00141    fprintf(stderr,
00142            "SAREA: back  offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
00143            sarea->back_offset, sarea->back_size,
00144            (unsigned) sarea->back_handle);
00145    fprintf(stderr, "SAREA: depth offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
00146            sarea->depth_offset, sarea->depth_size,
00147            (unsigned) sarea->depth_handle);
00148    fprintf(stderr, "SAREA: tex   offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
00149            sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
00150    fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
00151    fprintf(stderr,
00152            "SAREA: rotated offset: 0x%08x  size: 0x%x\n",
00153            sarea->rotated_offset, sarea->rotated_size);
00154    fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch);
00155 }
00156 #endif
00157 
00158 
00163 void
00164 intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
00165 {
00166    struct intel_screen *intelScreen = intel_screen(sPriv);
00167 
00168    if (intelScreen->front.map) {
00169       drmUnmap(intelScreen->front.map, intelScreen->front.size);
00170       intelScreen->front.map = NULL;
00171    }
00172 
00173    if (intelScreen->front.buffer)
00174       driDeleteBuffers(1, &intelScreen->front.buffer);
00175 
00176    intelScreen->front.width = sarea->width;
00177    intelScreen->front.height = sarea->height;
00178    intelScreen->front.offset = sarea->front_offset;
00179    intelScreen->front.pitch = sarea->pitch * intelScreen->front.cpp;
00180    intelScreen->front.size = sarea->front_size;
00181    intelScreen->front.handle = sarea->front_handle;
00182 
00183    assert( sarea->front_size >=
00184            intelScreen->front.pitch * intelScreen->front.height );
00185 
00186 #if 0 /* JB not important */
00187    if (!sarea->front_handle)
00188       return;
00189 
00190    if (drmMap(sPriv->fd,
00191               sarea->front_handle,
00192               intelScreen->front.size,
00193               (drmAddress *) & intelScreen->front.map) != 0) {
00194       fprintf(stderr, "drmMap(frontbuffer) failed!\n");
00195       return;
00196    }
00197 #endif
00198 
00199 #if 0 /* JB */
00200    if (intelScreen->staticPool) {
00201       driGenBuffers(intelScreen->staticPool, "static region", 1,
00202                     &intelScreen->front.buffer, 64,
00203                     DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
00204                     DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
00205 
00206       driBOSetStatic(intelScreen->front.buffer,
00207                      intelScreen->front.offset,
00208                      intelScreen->front.pitch * intelScreen->front.height,
00209                      intelScreen->front.map, 0);
00210    }
00211 #else
00212    if (intelScreen->base.staticPool) {
00213       if (intelScreen->front.buffer) {
00214          driBOUnReference(intelScreen->front.buffer);
00215          pipe_surface_reference(&intelScreen->front.surface, NULL);
00216          pipe_texture_reference(&intelScreen->front.texture, NULL);
00217       }
00218       intelCreateSurface(intelScreen, &intelScreen->base.base, sarea->front_bo_handle);
00219    }
00220 #endif
00221 }
00222 
00223 
00224 boolean
00225 intelCreatePools(__DRIscreenPrivate * sPriv)
00226 {
00227    //unsigned batchPoolSize = 1024*1024;
00228    struct intel_screen *intelScreen = intel_screen(sPriv);
00229 
00230    if (intelScreen->havePools)
00231       return GL_TRUE;
00232 
00233    intelScreen->havePools = GL_TRUE;
00234 
00235    intelUpdateScreenRotation(sPriv, intelScreen->sarea);
00236 
00237    return GL_TRUE;
00238 }
00239 
00240 static const char *
00241 intel_get_name( struct pipe_winsys *winsys )
00242 {
00243    return "Intel/DRI/ttm";
00244 }
00245 
00246 /*
00247  * The state tracker (should!) keep track of whether the fake
00248  * frontbuffer has been touched by any rendering since the last time
00249  * we copied its contents to the real frontbuffer.  Our task is easy:
00250  */
00251 static void
00252 intel_flush_frontbuffer( struct pipe_winsys *winsys,
00253                          struct pipe_surface *surf,
00254                          void *context_private)
00255 {
00256    struct intel_context *intel = (struct intel_context *) context_private;
00257    __DRIdrawablePrivate *dPriv = intel->driDrawable;
00258 
00259    intelDisplaySurface(dPriv, surf, NULL);
00260 }
00261 
00262 static boolean
00263 intelInitDriver(__DRIscreenPrivate * sPriv)
00264 {
00265    struct intel_screen *intelScreen;
00266    I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
00267 
00268    PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
00269       (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->
00270                                       getProcAddress("glxEnableExtension"));
00271    void *const psc = sPriv->psc->screenConfigs;
00272 
00273    if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
00274       fprintf(stderr,
00275               "\nERROR!  sizeof(I830DRIRec) does not match passed size from device driver\n");
00276       return GL_FALSE;
00277    }
00278 
00279    /* Allocate the private area */
00280    intelScreen = CALLOC_STRUCT(intel_screen);
00281    if (!intelScreen)
00282       return GL_FALSE;
00283 
00284    /* parse information in __driConfigOptions */
00285    driParseOptionInfo(&intelScreen->optionCache,
00286                       __driConfigOptions, __driNConfigOptions);
00287 
00288    sPriv->private = (void *) intelScreen;
00289 
00290    intelScreen->sarea = (drmI830Sarea *) (((GLubyte *) sPriv->pSAREA) +
00291                                           gDRIPriv->sarea_priv_offset);
00292    intelScreen->deviceID = gDRIPriv->deviceID;
00293    intelScreen->front.cpp = gDRIPriv->cpp;
00294    intelScreen->drmMinor = sPriv->drmMinor;
00295 
00296    assert(gDRIPriv->bitsPerPixel == 16 ||
00297           gDRIPriv->bitsPerPixel == 32);
00298 
00299    intelUpdateScreenRotation(sPriv, intelScreen->sarea);
00300 
00301    if (0)
00302       intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
00303 
00304    if (glx_enable_extension != NULL) {
00305       (*glx_enable_extension) (psc, "GLX_SGI_swap_control");
00306       (*glx_enable_extension) (psc, "GLX_SGI_video_sync");
00307       (*glx_enable_extension) (psc, "GLX_MESA_swap_control");
00308       (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage");
00309       (*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
00310    }
00311 
00312    intelScreen->base.base.flush_frontbuffer = intel_flush_frontbuffer;
00313    intelScreen->base.base.get_name = intel_get_name;
00314    intel_be_init_device(&intelScreen->base, sPriv->fd, intelScreen->deviceID);
00315 
00316    return GL_TRUE;
00317 }
00318 
00319 
00320 static void
00321 intelDestroyScreen(__DRIscreenPrivate * sPriv)
00322 {
00323    struct intel_screen *intelScreen = intel_screen(sPriv);
00324 
00325    intel_be_destroy_device(&intelScreen->base);
00326    /*  intelUnmapScreenRegions(intelScreen); */
00327 
00328    FREE(intelScreen);
00329    sPriv->private = NULL;
00330 }
00331 
00332 
00336 static boolean
00337 intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
00338                   __DRIdrawablePrivate * driDrawPriv,
00339                   const __GLcontextModes * visual, boolean isPixmap)
00340 {
00341    if (isPixmap) {
00342       return GL_FALSE;          /* not implemented */
00343    }
00344    else {
00345       enum pipe_format colorFormat, depthFormat, stencilFormat;
00346       struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer);
00347 
00348       if (!intelfb)
00349          return GL_FALSE;
00350 
00351       if (visual->redBits == 5)
00352          colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
00353       else
00354          colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
00355 
00356       if (visual->depthBits == 16)
00357          depthFormat = PIPE_FORMAT_Z16_UNORM;
00358       else if (visual->depthBits == 24)
00359          depthFormat = PIPE_FORMAT_S8Z24_UNORM;
00360       else
00361          depthFormat = PIPE_FORMAT_NONE;
00362 
00363       if (visual->stencilBits == 8)
00364          stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
00365       else
00366          stencilFormat = PIPE_FORMAT_NONE;
00367 
00368       intelfb->stfb = st_create_framebuffer(visual,
00369                                             colorFormat,
00370                                             depthFormat,
00371                                             stencilFormat,
00372                                             driDrawPriv->w,
00373                                             driDrawPriv->h,
00374                                             (void*) intelfb);
00375       if (!intelfb->stfb) {
00376          free(intelfb);
00377          return GL_FALSE;
00378       }
00379 
00380       driDrawPriv->driverPrivate = (void *) intelfb;
00381       return GL_TRUE;
00382    }
00383 }
00384 
00385 static void
00386 intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
00387 {
00388    struct intel_framebuffer *intelfb = intel_framebuffer(driDrawPriv);
00389    assert(intelfb->stfb);
00390    st_unreference_framebuffer(&intelfb->stfb);
00391    free(intelfb);
00392 }
00393 
00394 
00398 static int
00399 intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
00400 {
00401    if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
00402        || (sInfo == NULL)) {
00403       return -1;
00404    }
00405 
00406    return 0;
00407 }
00408 
00409 
00410 static void
00411 intelSetTexOffset(__DRIcontext *pDRICtx, int texname,
00412                   unsigned long long offset, int depth, uint pitch)
00413 {
00414    abort();
00415 #if 0
00416    struct intel_context *intel = (struct intel_context*)
00417       ((__DRIcontextPrivate*)pDRICtx->private)->driverPrivate;
00418    struct gl_texture_object *tObj = _mesa_lookup_texture(&intel->ctx, texname);
00419    struct st_texture_object *stObj = st_texture_object(tObj);
00420 
00421    if (!stObj)
00422       return;
00423 
00424    if (stObj->pt)
00425       st->pipe->texture_release(intel->st->pipe, &stObj->pt);
00426 
00427    stObj->imageOverride = GL_TRUE;
00428    stObj->depthOverride = depth;
00429    stObj->pitchOverride = pitch;
00430 
00431    if (offset)
00432       stObj->textureOffset = offset;
00433 #endif
00434 }
00435 
00436 
00437 static const struct __DriverAPIRec intelAPI = {
00438    .InitDriver = intelInitDriver,
00439    .DestroyScreen = intelDestroyScreen,
00440    .CreateContext = intelCreateContext,
00441    .DestroyContext = intelDestroyContext,
00442    .CreateBuffer = intelCreateBuffer,
00443    .DestroyBuffer = intelDestroyBuffer,
00444    .SwapBuffers = intelSwapBuffers,
00445    .MakeCurrent = intelMakeCurrent,
00446    .UnbindContext = intelUnbindContext,
00447    .GetSwapInfo = intelGetSwapInfo,
00448    .GetMSC = driGetMSC32,
00449    .WaitForMSC = driWaitForMSC32,
00450    .WaitForSBC = NULL,
00451    .SwapBuffersMSC = NULL,
00452    .CopySubBuffer = intelCopySubBuffer,
00453    .setTexOffset = intelSetTexOffset,
00454 };
00455 
00456 
00457 static __GLcontextModes *
00458 intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
00459                  unsigned stencil_bits, boolean have_back_buffer)
00460 {
00461    __GLcontextModes *modes;
00462    __GLcontextModes *m;
00463    unsigned num_modes;
00464    unsigned depth_buffer_factor;
00465    unsigned back_buffer_factor;
00466    GLenum fb_format;
00467    GLenum fb_type;
00468 
00469    /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
00470     * support pageflipping at all.
00471     */
00472    static const GLenum back_buffer_modes[] = {
00473       GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
00474    };
00475 
00476    uint8_t depth_bits_array[3];
00477    uint8_t stencil_bits_array[3];
00478    uint8_t msaa_samples_array[1];
00479 
00480 
00481    depth_bits_array[0] = 0;
00482    depth_bits_array[1] = depth_bits;
00483    depth_bits_array[2] = depth_bits;
00484    msaa_samples_array[0] = 0;
00485 
00486    /* Just like with the accumulation buffer, always provide some modes
00487     * with a stencil buffer.  It will be a sw fallback, but some apps won't
00488     * care about that.
00489     */
00490    stencil_bits_array[0] = 0;
00491    stencil_bits_array[1] = 0;
00492    if (depth_bits == 24)
00493       stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
00494 
00495    stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
00496 
00497    depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
00498    back_buffer_factor = (have_back_buffer) ? 3 : 1;
00499 
00500    num_modes = depth_buffer_factor * back_buffer_factor * 4;
00501 
00502    if (pixel_bits == 16) {
00503       fb_format = GL_RGB;
00504       fb_type = GL_UNSIGNED_SHORT_5_6_5;
00505    }
00506    else {
00507       fb_format = GL_BGRA;
00508       fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
00509    }
00510 
00511    modes =
00512       (*dri_interface->createContextModes) (num_modes,
00513                                             sizeof(__GLcontextModes));
00514    m = modes;
00515    if (!driFillInModes(&m, fb_format, fb_type,
00516                        depth_bits_array, stencil_bits_array,
00517                        depth_buffer_factor, back_buffer_modes,
00518                        back_buffer_factor, msaa_samples_array, 1, GLX_TRUE_COLOR)) {
00519       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
00520               __LINE__);
00521       return NULL;
00522    }
00523    if (!driFillInModes(&m, fb_format, fb_type,
00524                        depth_bits_array, stencil_bits_array,
00525                        depth_buffer_factor, back_buffer_modes,
00526                        back_buffer_factor, msaa_samples_array, 1, GLX_DIRECT_COLOR)) {
00527       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
00528               __LINE__);
00529       return NULL;
00530    }
00531 
00532    /* Mark the visual as slow if there are "fake" stencil bits.
00533     */
00534    for (m = modes; m != NULL; m = m->next) {
00535       if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
00536          m->visualRating = GLX_SLOW_CONFIG;
00537       }
00538    }
00539 
00540    return modes;
00541 }
00542 
00543 
00554 PUBLIC void *
00555 __driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
00556                               __DRIscreen * psc,
00557                               const __GLcontextModes * modes,
00558                               const __DRIversion * ddx_version,
00559                               const __DRIversion * dri_version,
00560                               const __DRIversion * drm_version,
00561                               const __DRIframebuffer * frame_buffer,
00562                               drmAddress pSAREA, int fd,
00563                               int internal_api_version,
00564                               const __DRIinterfaceMethods * interface,
00565                               __GLcontextModes ** driver_modes)
00566 {
00567    __DRIscreenPrivate *psp;
00568    static const __DRIversion ddx_expected = { 1, 7, 0 };
00569    static const __DRIversion dri_expected = { 4, 0, 0 };
00570    static const __DRIversion drm_expected = { 1, 7, 0 };
00571 
00572    dri_interface = interface;
00573 
00574    if (!driCheckDriDdxDrmVersions2("i915",
00575                                    dri_version, &dri_expected,
00576                                    ddx_version, &ddx_expected,
00577                                    drm_version, &drm_expected)) {
00578       return NULL;
00579    }
00580 
00581    psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
00582                                   ddx_version, dri_version, drm_version,
00583                                   frame_buffer, pSAREA, fd,
00584                                   internal_api_version, &intelAPI);
00585 
00586    if (psp != NULL) {
00587       I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
00588       *driver_modes = intelFillInModes(dri_priv->cpp * 8,
00589                                        (dri_priv->cpp == 2) ? 16 : 24,
00590                                        (dri_priv->cpp == 2) ? 0 : 8, 1);
00591 
00592       /* Calling driInitExtensions here, with a NULL context pointer,
00593        * does not actually enable the extensions.  It just makes sure
00594        * that all the dispatch offsets for all the extensions that
00595        * *might* be enables are known.  This is needed because the
00596        * dispatch offsets need to be known when _mesa_context_create
00597        * is called, but we can't enable the extensions until we have a
00598        * context pointer.
00599        *
00600        * Hello chicken.  Hello egg.  How are you two today?
00601        */
00602       driInitExtensions(NULL, card_extensions, GL_FALSE);
00603    }
00604 
00605    return (void *) psp;
00606 }
00607 

Generated on Tue Sep 29 06:25:17 2009 for Gallium3D by  doxygen 1.5.4