i965: always call dri_emit_reloc when creating clip unit state
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_screen.c
index 51f9fb148760268366041f2df9a9b3763973ae61..533b4b1e6e15335dde34b986fa7631f3f4a0d4ae 100644 (file)
@@ -53,6 +53,11 @@ DRI_CONF_END;
 static const GLuint __driNConfigOptions = 1;
 
 extern const struct dri_extension common_extensions[];
+extern const struct dri_extension nv10_extensions[];
+extern const struct dri_extension nv20_extensions[];
+extern const struct dri_extension nv30_extensions[];
+extern const struct dri_extension nv40_extensions[];
+extern const struct dri_extension nv50_extensions[];
 
 static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv)
 {
@@ -66,6 +71,14 @@ static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv)
                return NULL;
        }
        
+       screen->card=nouveau_card_lookup(dri_priv->device_id);
+       if (!screen->card) {
+               __driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n",
+                       __func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF);
+               FREE(screen);
+               return NULL;
+       }
+
        /* parse information in __driConfigOptions */
        driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions);
 
@@ -77,7 +90,6 @@ static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv)
        screen->depthOffset = dri_priv->depth_offset;
        screen->depthPitch  = dri_priv->depth_pitch;
 
-       screen->card=nouveau_card_lookup(dri_priv->device_id);
        screen->driScreen = sPriv;
        return screen;
 }
@@ -120,93 +132,60 @@ nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv,
                     GLboolean isPixmap)
 {
        nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private;
-
-       if (isPixmap) {
+       nouveau_renderbuffer_t *nrb;
+       struct gl_framebuffer *fb;
+       const GLboolean swAccum = mesaVis->accumRedBits > 0;
+       const GLboolean swStencil = (mesaVis->stencilBits > 0 &&
+                                    mesaVis->depthBits != 24);
+       GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5;
+
+       if (isPixmap)
                return GL_FALSE; /* not implemented */
-       }
-       else {
-               const GLboolean swDepth = GL_FALSE;
-               const GLboolean swAlpha = GL_FALSE;
-               const GLboolean swAccum = mesaVis->accumRedBits > 0;
-               const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
-               struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
-
-               /* front color renderbuffer */
-               {
-                       driRenderbuffer *frontRb
-                               = driNewRenderbuffer(GL_RGBA,
-                                                    driScrnPriv->pFB + screen->frontOffset,
-                                                    screen->fbFormat,
-                                                    screen->frontOffset, screen->frontPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(frontRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
-               }
-
-               /* back color renderbuffer */
-               if (mesaVis->doubleBufferMode) {
-                       driRenderbuffer *backRb
-                               = driNewRenderbuffer(GL_RGBA,
-                                                    driScrnPriv->pFB + screen->backOffset,
-                                                    screen->fbFormat,
-                                                    screen->backOffset, screen->backPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(backRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
-               }
 
-               /* depth renderbuffer */
-               if (mesaVis->depthBits == 16) {
-                       driRenderbuffer *depthRb
-                               = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
-                                                    driScrnPriv->pFB + screen->depthOffset,
-                                                    screen->fbFormat,
-                                                    screen->depthOffset, screen->depthPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(depthRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
-               }
-               else if (mesaVis->depthBits == 24) {
-                       driRenderbuffer *depthRb
-                               = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
-                                                    driScrnPriv->pFB + screen->depthOffset,
-                                                    screen->fbFormat,
-                                                    screen->depthOffset, screen->depthPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(depthRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
-               }
+       fb = _mesa_create_framebuffer(mesaVis);
+       if (!fb)
+               return GL_FALSE;
 
-               /* stencil renderbuffer */
-               if (mesaVis->stencilBits > 0 && !swStencil) {
-                       driRenderbuffer *stencilRb
-                               = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
-                                                    driScrnPriv->pFB + screen->depthOffset,
-                                                    screen->fbFormat,
-                                                    screen->depthOffset, screen->depthPitch,
-                                                    driDrawPriv);
-                       nouveauSpanSetFunctions(stencilRb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
-               }
+       /* Front buffer */
+       nrb = nouveau_renderbuffer_new(color_format);
+       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa);
 
-               _mesa_add_soft_renderbuffers(fb,
-                                            GL_FALSE, /* color */
-                                            swDepth,
-                                            swStencil,
-                                            swAccum,
-                                            swAlpha,
-                                            GL_FALSE /* aux */);
-               driDrawPriv->driverPrivate = (void *) fb;
+       if (mesaVis->doubleBufferMode) {
+               nrb = nouveau_renderbuffer_new(color_format);
+               _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa);
+       }
 
-               return (driDrawPriv->driverPrivate != NULL);
+       if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
+               nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+               _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa);
+       } else
+       if (mesaVis->depthBits == 24) {
+               nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
+       } else
+       if (mesaVis->depthBits == 16) {
+               nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
        }
+
+       _mesa_add_soft_renderbuffers(fb,
+                                    GL_FALSE, /* color */
+                                    GL_FALSE, /* depth */
+                                    swStencil,
+                                    swAccum,
+                                    GL_FALSE, /* alpha */
+                                    GL_FALSE  /* aux */);
+
+       driDrawPriv->driverPrivate = (void *) fb;
+       return (driDrawPriv->driverPrivate != NULL);
 }
 
 
 static void
 nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
 {
-       _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+       _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
 }
 
 static int
@@ -216,7 +195,6 @@ nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo)
 }
 
 static const struct __DriverAPIRec nouveauAPI = {
-       .InitDriver      = nouveauInitDriver,
        .DestroyScreen   = nouveauDestroyScreen,
        .CreateContext   = nouveauCreateContext,
        .DestroyContext  = nouveauDestroyContext,
@@ -227,6 +205,7 @@ static const struct __DriverAPIRec nouveauAPI = {
        .UnbindContext   = nouveauUnbindContext,
        .GetSwapInfo     = nouveauGetSwapInfo,
        .GetMSC          = driGetMSC32,
+       .GetDrawableMSC  = driDrawableGetMSC32,
        .WaitForMSC      = driWaitForMSC32,
        .WaitForSBC      = NULL,
        .SwapBuffersMSC  = NULL,
@@ -243,8 +222,16 @@ nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits,
        unsigned num_modes;
        unsigned depth_buffer_factor;
        unsigned back_buffer_factor;
-       GLenum fb_format;
-       GLenum fb_type;
+       int i;
+
+       static const struct {
+               GLenum format;
+               GLenum type;
+       } fb_format_array[] = {
+               { GL_RGB , GL_UNSIGNED_SHORT_5_6_5     },
+               { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
+               { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
+       };
 
        /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
         * support pageflipping at all.
@@ -253,58 +240,43 @@ nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits,
                GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
        };
 
-       u_int8_t depth_bits_array[3];
-       u_int8_t stencil_bits_array[3];
-
-       depth_bits_array[0] = 0;
-       depth_bits_array[1] = depth_bits;
-       depth_bits_array[2] = depth_bits;
+       u_int8_t depth_bits_array[4]   = { 0, 16, 24, 24 };
+       u_int8_t stencil_bits_array[4] = { 0,  0,  0,  8 };
 
-       /* Just like with the accumulation buffer, always provide some modes
-        * with a stencil buffer.  It will be a sw fallback, but some apps won't
-        * care about that.
-        */
-       stencil_bits_array[0] = 0;
-       stencil_bits_array[1] = 0;
-       stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
-
-       depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
+       depth_buffer_factor = 4;
        back_buffer_factor  = (have_back_buffer) ? 3 : 1;
 
-       num_modes = depth_buffer_factor * back_buffer_factor * 4;
-
-       if ( pixel_bits == 16 ) {
-               fb_format = GL_RGB;
-               fb_type = GL_UNSIGNED_SHORT_5_6_5;
-       } else {
-               fb_format = GL_BGRA;
-               fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
-       }
-
-       modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
+       num_modes = ((pixel_bits==16) ? 1 : 2) *
+               depth_buffer_factor * back_buffer_factor * 4;
+       modes = (*dri_interface->createContextModes)(num_modes,
+                                                    sizeof(__GLcontextModes));
        m = modes;
-       if (!driFillInModes(&m, fb_format, fb_type,
-                           depth_bits_array, stencil_bits_array, depth_buffer_factor,
-                           back_buffer_modes, back_buffer_factor,
-                           GLX_TRUE_COLOR)) {
+
+       for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
+               if (!driFillInModes(&m, fb_format_array[i].format,
+                                       fb_format_array[i].type,
+                                       depth_bits_array,
+                                       stencil_bits_array,
+                                       depth_buffer_factor,
+                                       back_buffer_modes,
+                                       back_buffer_factor,
+                                       GLX_TRUE_COLOR)) {
                fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
                                __func__, __LINE__ );
                return NULL;
-       }
-       if (!driFillInModes(&m, fb_format, fb_type,
-                           depth_bits_array, stencil_bits_array, depth_buffer_factor,
-                           back_buffer_modes, back_buffer_factor,
-                           GLX_DIRECT_COLOR)) {
+               }
+
+               if (!driFillInModes(&m, fb_format_array[i].format,
+                                       fb_format_array[i].type,
+                                       depth_bits_array,
+                                       stencil_bits_array,
+                                       depth_buffer_factor,
+                                       back_buffer_modes,
+                                       back_buffer_factor,
+                                       GLX_DIRECT_COLOR)) {
                fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
                                __func__, __LINE__ );
                return NULL;
-       }
-
-       /* Mark the visual as slow if there are "fake" stencil bits.
-        */
-       for ( m = modes ; m != NULL ; m = m->next ) {
-               if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
-                       m->visualRating = GLX_SLOW_CONFIG;
                }
        }
 
@@ -313,69 +285,62 @@ nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits,
 
 
 /**
- * This is the bootstrap function for the driver.  libGL supplies all of the
- * requisite information about the system, and the driver initializes itself.
- * This routine also fills in the linked list pointed to by \c driver_modes
- * with the \c __GLcontextModes that the driver can support for windows or
- * pbuffers.
+ * This is the driver specific part of the createNewScreen entry point.
  * 
- * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on 
- *         failure.
+ * \todo maybe fold this into intelInitDriver
+ *
+ * \return the __GLcontextModes supported by this driver
  */
-PUBLIC
-void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
-                                    const __GLcontextModes * modes,
-                                    const __DRIversion * ddx_version,
-                                    const __DRIversion * dri_version,
-                                    const __DRIversion * drm_version,
-                                    const __DRIframebuffer * frame_buffer,
-                                    drmAddress pSAREA, int fd, 
-                                    int internal_api_version,
-                                    const __DRIinterfaceMethods * interface,
-                                    __GLcontextModes ** driver_modes)
-                            
+__GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp)
 {
-       __DRIscreenPrivate *psp;
        static const __DRIversion ddx_expected = { 1, 2, 0 };
        static const __DRIversion dri_expected = { 4, 0, 0 };
-       static const __DRIversion drm_expected = { 0, 0, 1 };
+       static const __DRIversion drm_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
+       NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
 
-       dri_interface = interface;
+#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 10
+#error nouveau_drm.h version doesn't match expected version
+#endif
 
        if (!driCheckDriDdxDrmVersions2("nouveau",
-                                       dri_version, & dri_expected,
-                                       ddx_version, & ddx_expected,
-                                       drm_version, & drm_expected)) {
+                                       &psp->dri_version, & dri_expected,
+                                       &psp->ddx_version, & ddx_expected,
+                                       &psp->drm_version, & drm_expected))
                return NULL;
-       }
 
        // temporary lock step versioning
-       if (drm_expected.patch!=drm_version->patch)
+       if (drm_expected.patch != psp->drm_version.patch) {
+               __driUtilMessage("%s: wrong DRM version, expected %d, got %d\n",
+                                __func__,
+                                drm_expected.patch, psp->drm_version.patch);
                return NULL;
-
-       psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
-                                      ddx_version, dri_version, drm_version,
-                                      frame_buffer, pSAREA, fd,
-                                      internal_api_version, &nouveauAPI);
-       if ( psp != NULL ) {
-               NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
-
-               *driver_modes = nouveauFillInModes(dri_priv->bpp,
-                                                  (dri_priv->bpp == 16) ? 16 : 24,
-                                                  (dri_priv->bpp == 16) ? 0  : 8,
-                                                  (dri_priv->back_offset != dri_priv->depth_offset));
-
-               /* Calling driInitExtensions here, with a NULL context pointer, does not actually
-                * enable the extensions.  It just makes sure that all the dispatch offsets for all
-                * the extensions that *might* be enables are known.  This is needed because the
-                * dispatch offsets need to be known when _mesa_context_create is called, but we can't
-                * enable the extensions until we have a context pointer.
-                * 
-                * Hello chicken.  Hello egg.  How are you two today?
-                */
-               driInitExtensions( NULL, common_extensions, GL_FALSE );
        }
 
-       return (void *) psp;
+       psp->DriverAPI = nouveauAPI;
+
+       /* Calling driInitExtensions here, with a NULL context
+        * pointer, does not actually enable the extensions.  It just
+        * makes sure that all the dispatch offsets for all the
+        * extensions that *might* be enables are known.  This is
+        * needed because the dispatch offsets need to be known when
+        * _mesa_context_create is called, but we can't enable the
+        * extensions until we have a context pointer.
+        * 
+        * Hello chicken.  Hello egg.  How are you two today?
+        */
+       driInitExtensions( NULL, common_extensions, GL_FALSE );
+       driInitExtensions( NULL,   nv10_extensions, GL_FALSE );
+       driInitExtensions( NULL,   nv10_extensions, GL_FALSE );
+       driInitExtensions( NULL,   nv30_extensions, GL_FALSE );
+       driInitExtensions( NULL,   nv40_extensions, GL_FALSE );
+       driInitExtensions( NULL,   nv50_extensions, GL_FALSE );
+
+       if (!nouveauInitDriver(psp))
+               return NULL;
+
+       return nouveauFillInModes(dri_priv->bpp,
+                                 (dri_priv->bpp == 16) ? 16 : 24,
+                                 (dri_priv->bpp == 16) ? 0  : 8,
+                                 1);
 }