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