nouveau_screen.c revision ae8d8d132600cc544b7295c9554e6531bdbd8094
1/************************************************************************** 2 3Copyright 2006 Stephane Marchesin 4All Rights Reserved. 5 6Permission is hereby granted, free of charge, to any person obtaining a 7copy of this software and associated documentation files (the "Software"), 8to deal in the Software without restriction, including without limitation 9on the rights to use, copy, modify, merge, publish, distribute, sub 10license, and/or sell copies of the Software, and to permit persons to whom 11the Software is furnished to do so, subject to the following conditions: 12 13The above copyright notice and this permission notice (including the next 14paragraph) shall be included in all copies or substantial portions of the 15Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, 21DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25**************************************************************************/ 26 27#include "glheader.h" 28#include "imports.h" 29#include "mtypes.h" 30#include "framebuffer.h" 31#include "renderbuffer.h" 32 33#include "nouveau_context.h" 34#include "nouveau_screen.h" 35#include "nouveau_object.h" 36#include "nouveau_span.h" 37 38#include "utils.h" 39#include "context.h" 40#include "vblank.h" 41#include "drirenderbuffer.h" 42 43#include "GL/internal/dri_interface.h" 44 45#include "xmlpool.h" 46 47PUBLIC const char __driConfigOptions[] = 48DRI_CONF_BEGIN 49 DRI_CONF_SECTION_DEBUG 50 DRI_CONF_NO_RAST(false) 51 DRI_CONF_SECTION_END 52DRI_CONF_END; 53static const GLuint __driNConfigOptions = 1; 54 55extern const struct dri_extension common_extensions[]; 56extern const struct dri_extension nv10_extensions[]; 57extern const struct dri_extension nv20_extensions[]; 58extern const struct dri_extension nv30_extensions[]; 59extern const struct dri_extension nv40_extensions[]; 60extern const struct dri_extension nv50_extensions[]; 61 62static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv) 63{ 64 nouveauScreenPtr screen; 65 NOUVEAUDRIPtr dri_priv=(NOUVEAUDRIPtr)sPriv->pDevPriv; 66 67 /* allocate screen */ 68 screen = (nouveauScreenPtr) CALLOC( sizeof(*screen) ); 69 if ( !screen ) { 70 __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__); 71 return NULL; 72 } 73 74 /* parse information in __driConfigOptions */ 75 driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions); 76 77 screen->fbFormat = dri_priv->bpp / 8; 78 screen->frontOffset = dri_priv->front_offset; 79 screen->frontPitch = dri_priv->front_pitch; 80 screen->backOffset = dri_priv->back_offset; 81 screen->backPitch = dri_priv->back_pitch; 82 screen->depthOffset = dri_priv->depth_offset; 83 screen->depthPitch = dri_priv->depth_pitch; 84 85 screen->card=nouveau_card_lookup(dri_priv->device_id); 86 screen->driScreen = sPriv; 87 return screen; 88} 89 90static void 91nouveauDestroyScreen(__DRIscreenPrivate *sPriv) 92{ 93 nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private; 94 95 if (!screen) return; 96 97 /* free all option information */ 98 driDestroyOptionInfo (&screen->optionCache); 99 100 FREE(screen); 101 sPriv->private = NULL; 102} 103 104static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv) 105{ 106 sPriv->private = (void *) nouveauCreateScreen( sPriv ); 107 if ( !sPriv->private ) { 108 nouveauDestroyScreen( sPriv ); 109 return GL_FALSE; 110 } 111 112 return GL_TRUE; 113} 114 115/** 116 * Create the Mesa framebuffer and renderbuffers for a given window/drawable. 117 * 118 * \todo This function (and its interface) will need to be updated to support 119 * pbuffers. 120 */ 121static GLboolean 122nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv, 123 __DRIdrawablePrivate *driDrawPriv, 124 const __GLcontextModes *mesaVis, 125 GLboolean isPixmap) 126{ 127 nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private; 128 nouveau_renderbuffer *nrb; 129 struct gl_framebuffer *fb; 130 const GLboolean swAccum = mesaVis->accumRedBits > 0; 131 const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24; 132 GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5; 133 134 if (isPixmap) 135 return GL_FALSE; /* not implemented */ 136 137 fb = _mesa_create_framebuffer(mesaVis); 138 if (!fb) 139 return GL_FALSE; 140 141 /* Front buffer */ 142 nrb = nouveau_renderbuffer_new(color_format, 143 driScrnPriv->pFB + screen->frontOffset, 144 screen->frontOffset, 145 screen->frontPitch * screen->fbFormat, 146 driDrawPriv); 147 nouveauSpanSetFunctions(nrb, mesaVis); 148 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa); 149 150 if (0 /* unified buffers if we choose to support them.. */) { 151 } else { 152 if (mesaVis->doubleBufferMode) { 153 nrb = nouveau_renderbuffer_new(color_format, NULL, 154 0, 0, 155 NULL); 156 nouveauSpanSetFunctions(nrb, mesaVis); 157 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa); 158 } 159 160 if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { 161 nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL, 162 0, 0, 163 NULL); 164 nouveauSpanSetFunctions(nrb, mesaVis); 165 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); 166 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa); 167 } else if (mesaVis->depthBits == 24) { 168 nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL, 169 0, 0, 170 NULL); 171 nouveauSpanSetFunctions(nrb, mesaVis); 172 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); 173 } else if (mesaVis->depthBits == 16) { 174 nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL, 175 0, 0, 176 NULL); 177 nouveauSpanSetFunctions(nrb, mesaVis); 178 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); 179 } 180 } 181 182 _mesa_add_soft_renderbuffers(fb, 183 GL_FALSE, /* color */ 184 GL_FALSE, /* depth */ 185 swStencil, 186 swAccum, 187 GL_FALSE, /* alpha */ 188 GL_FALSE /* aux */); 189 190 driDrawPriv->driverPrivate = (void *) fb; 191 return (driDrawPriv->driverPrivate != NULL); 192} 193 194 195static void 196nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) 197{ 198 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); 199} 200 201static int 202nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo) 203{ 204 return -1; 205} 206 207static const struct __DriverAPIRec nouveauAPI = { 208 .InitDriver = nouveauInitDriver, 209 .DestroyScreen = nouveauDestroyScreen, 210 .CreateContext = nouveauCreateContext, 211 .DestroyContext = nouveauDestroyContext, 212 .CreateBuffer = nouveauCreateBuffer, 213 .DestroyBuffer = nouveauDestroyBuffer, 214 .SwapBuffers = nouveauSwapBuffers, 215 .MakeCurrent = nouveauMakeCurrent, 216 .UnbindContext = nouveauUnbindContext, 217 .GetSwapInfo = nouveauGetSwapInfo, 218 .GetMSC = driGetMSC32, 219 .WaitForMSC = driWaitForMSC32, 220 .WaitForSBC = NULL, 221 .SwapBuffersMSC = NULL, 222 .CopySubBuffer = nouveauCopySubBuffer 223}; 224 225 226static __GLcontextModes * 227nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits, 228 unsigned stencil_bits, GLboolean have_back_buffer ) 229{ 230 __GLcontextModes * modes; 231 __GLcontextModes * m; 232 unsigned num_modes; 233 unsigned depth_buffer_factor; 234 unsigned back_buffer_factor; 235 unsigned fb_format_factor; 236 int i; 237 238 static const struct { 239 GLenum format; 240 GLenum type; 241 } fb_format_array[] = { 242 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 }, 243 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, 244 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, 245 }; 246 247 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 248 * support pageflipping at all. 249 */ 250 static const GLenum back_buffer_modes[] = { 251 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 252 }; 253 254 u_int8_t depth_bits_array[4] = { 0, 16, 24, 24 }; 255 u_int8_t stencil_bits_array[4] = { 0, 0, 0, 8 }; 256 257 depth_buffer_factor = 4; 258 back_buffer_factor = (have_back_buffer) ? 3 : 1; 259 260 num_modes = ((pixel_bits==16) ? 1 : 2) * 261 depth_buffer_factor * back_buffer_factor * 4; 262 modes = (*dri_interface->createContextModes)(num_modes, 263 sizeof(__GLcontextModes)); 264 m = modes; 265 266 for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) { 267 if (!driFillInModes(&m, fb_format_array[i].format, 268 fb_format_array[i].type, 269 depth_bits_array, 270 stencil_bits_array, 271 depth_buffer_factor, 272 back_buffer_modes, 273 back_buffer_factor, 274 GLX_TRUE_COLOR)) { 275 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", 276 __func__, __LINE__ ); 277 return NULL; 278 } 279 280 if (!driFillInModes(&m, fb_format_array[i].format, 281 fb_format_array[i].type, 282 depth_bits_array, 283 stencil_bits_array, 284 depth_buffer_factor, 285 back_buffer_modes, 286 back_buffer_factor, 287 GLX_DIRECT_COLOR)) { 288 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", 289 __func__, __LINE__ ); 290 return NULL; 291 } 292 } 293 294 return modes; 295} 296 297 298/** 299 * This is the bootstrap function for the driver. libGL supplies all of the 300 * requisite information about the system, and the driver initializes itself. 301 * This routine also fills in the linked list pointed to by \c driver_modes 302 * with the \c __GLcontextModes that the driver can support for windows or 303 * pbuffers. 304 * 305 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on 306 * failure. 307 */ 308PUBLIC 309void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, 310 const __GLcontextModes * modes, 311 const __DRIversion * ddx_version, 312 const __DRIversion * dri_version, 313 const __DRIversion * drm_version, 314 const __DRIframebuffer * frame_buffer, 315 drmAddress pSAREA, int fd, 316 int internal_api_version, 317 const __DRIinterfaceMethods * interface, 318 __GLcontextModes ** driver_modes) 319 320{ 321 __DRIscreenPrivate *psp; 322 static const __DRIversion ddx_expected = { 1, 2, 0 }; 323 static const __DRIversion dri_expected = { 4, 0, 0 }; 324 static const __DRIversion drm_expected = { 0, 0, 1 }; 325 326 dri_interface = interface; 327 328 if (!driCheckDriDdxDrmVersions2("nouveau", 329 dri_version, & dri_expected, 330 ddx_version, & ddx_expected, 331 drm_version, & drm_expected)) { 332 return NULL; 333 } 334 335 // temporary lock step versioning 336 if (drm_expected.patch!=drm_version->patch) 337 return NULL; 338 339 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, 340 ddx_version, dri_version, drm_version, 341 frame_buffer, pSAREA, fd, 342 internal_api_version, &nouveauAPI); 343 if ( psp != NULL ) { 344 NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv; 345 346 *driver_modes = nouveauFillInModes(dri_priv->bpp, 347 (dri_priv->bpp == 16) ? 16 : 24, 348 (dri_priv->bpp == 16) ? 0 : 8, 349 1 350 ); 351 352 /* Calling driInitExtensions here, with a NULL context pointer, does not actually 353 * enable the extensions. It just makes sure that all the dispatch offsets for all 354 * the extensions that *might* be enables are known. This is needed because the 355 * dispatch offsets need to be known when _mesa_context_create is called, but we can't 356 * enable the extensions until we have a context pointer. 357 * 358 * Hello chicken. Hello egg. How are you two today? 359 */ 360 driInitExtensions( NULL, common_extensions, GL_FALSE ); 361 driInitExtensions( NULL, nv10_extensions, GL_FALSE ); 362 driInitExtensions( NULL, nv10_extensions, GL_FALSE ); 363 driInitExtensions( NULL, nv30_extensions, GL_FALSE ); 364 driInitExtensions( NULL, nv40_extensions, GL_FALSE ); 365 driInitExtensions( NULL, nv50_extensions, GL_FALSE ); 366 } 367 368 return (void *) psp; 369} 370 371