diff options
author | Ben Skeggs <[email protected]> | 2006-11-12 08:38:44 +0000 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2006-11-12 08:38:44 +0000 |
commit | 2af374716f351421b978050b113e93abae0e2dc8 (patch) | |
tree | 080cb508e981ac9db66794132dffb8954124e805 /src/mesa/drivers/dri/nouveau/nouveau_screen.c | |
parent | b8e05366e192ab4ebaf69dc8a4a18da4e65cbf80 (diff) |
Some more nouveau_screen.c setup, not sure how correct it is yet though..
Diffstat (limited to 'src/mesa/drivers/dri/nouveau/nouveau_screen.c')
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_screen.c | 309 |
1 files changed, 308 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c index d1beafe40ef..75da6324474 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c @@ -24,9 +24,23 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" +#include "framebuffer.h" +#include "renderbuffer.h" + #include "nouveau_context.h" #include "nouveau_screen.h" #include "nouveau_object.h" +#include "nouveau_span.h" + +#include "utils.h" +#include "context.h" +#include "vblank.h" +#include "drirenderbuffer.h" + +#include "GL/internal/dri_interface.h" #include "xmlpool.h" @@ -38,6 +52,8 @@ DRI_CONF_BEGIN DRI_CONF_END; static const GLuint __driNConfigOptions = 1; +extern const struct dri_extension common_extensions[]; + static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv) { nouveauScreenPtr screen; @@ -49,12 +65,35 @@ static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv) __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__); return NULL; } - /* parse information in __driConfigOptions */ driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions); + screen->fbFormat = dri_priv->bpp / 8; + screen->frontOffset = dri_priv->front_offset; + screen->frontPitch = dri_priv->front_pitch; + screen->backOffset = dri_priv->back_offset; + screen->backPitch = dri_priv->back_pitch; + 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; +} + +static void +nouveauDestroyScreen(__DRIscreenPrivate *sPriv) +{ + nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private; + + if (!screen) return; + + /* free all option information */ + driDestroyOptionInfo (&screen->optionCache); + + FREE(screen); + sPriv->private = NULL; } static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv) @@ -68,3 +107,271 @@ static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv) return GL_TRUE; } +/** + * Create the Mesa framebuffer and renderbuffers for a given window/drawable. + * + * \todo This function (and its interface) will need to be updated to support + * pbuffers. + */ +static GLboolean +nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap) +{ + nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private; + + 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); + } + + /* 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); + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + swDepth, + swStencil, + swAccum, + swAlpha, + GL_FALSE /* aux */); + driDrawPriv->driverPrivate = (void *) fb; + + return (driDrawPriv->driverPrivate != NULL); + } +} + + +static void +nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); +} + +static int +nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo) +{ + return -1; +} + +static const struct __DriverAPIRec nouveauAPI = { + .InitDriver = nouveauInitDriver, + .DestroyScreen = nouveauDestroyScreen, + .CreateContext = nouveauCreateContext, + .DestroyContext = nouveauDestroyContext, + .CreateBuffer = nouveauCreateBuffer, + .DestroyBuffer = nouveauDestroyBuffer, + .SwapBuffers = nouveauSwapBuffers, + .MakeCurrent = nouveauMakeCurrent, + .UnbindContext = nouveauUnbindContext, + .GetSwapInfo = nouveauGetSwapInfo, + .GetMSC = driGetMSC32, + .WaitForMSC = driWaitForMSC32, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL, + .CopySubBuffer = nouveauCopySubBuffer +}; + + +static __GLcontextModes * +nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't + * support pageflipping at all. + */ + static const GLenum back_buffer_modes[] = { + 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; + + /* 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; + 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 ) ); + 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)) { + 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)) { + 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; + } + } + + return modes; +} + + +/** + * 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. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +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) + +{ + __DRIscreenPrivate *psp; + static const __DRIversion ddx_expected = { 1, 2, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 0, 0 }; + + dri_interface = interface; + + if (!driCheckDriDdxDrmVersions2("nouveau", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected)) { + 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; +} + |