Merge branch 'master' of git+ssh://znh@git.freedesktop.org/git/mesa/mesa into 965...
[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 extern const struct dri_extension nv10_extensions[];
57 extern const struct dri_extension nv20_extensions[];
58 extern const struct dri_extension nv30_extensions[];
59 extern const struct dri_extension nv40_extensions[];
60 extern const struct dri_extension nv50_extensions[];
61
62 static 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 screen->card=nouveau_card_lookup(dri_priv->device_id);
75 if (!screen->card) {
76 __driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n",
77 __func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF);
78 FREE(screen);
79 return NULL;
80 }
81
82 /* parse information in __driConfigOptions */
83 driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions);
84
85 screen->fbFormat = dri_priv->bpp / 8;
86 screen->frontOffset = dri_priv->front_offset;
87 screen->frontPitch = dri_priv->front_pitch;
88 screen->backOffset = dri_priv->back_offset;
89 screen->backPitch = dri_priv->back_pitch;
90 screen->depthOffset = dri_priv->depth_offset;
91 screen->depthPitch = dri_priv->depth_pitch;
92
93 screen->driScreen = sPriv;
94 return screen;
95 }
96
97 static void
98 nouveauDestroyScreen(__DRIscreenPrivate *sPriv)
99 {
100 nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private;
101
102 if (!screen) return;
103
104 /* free all option information */
105 driDestroyOptionInfo (&screen->optionCache);
106
107 FREE(screen);
108 sPriv->private = NULL;
109 }
110
111 static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv)
112 {
113 sPriv->private = (void *) nouveauCreateScreen( sPriv );
114 if ( !sPriv->private ) {
115 nouveauDestroyScreen( sPriv );
116 return GL_FALSE;
117 }
118
119 return GL_TRUE;
120 }
121
122 /**
123 * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
124 *
125 * \todo This function (and its interface) will need to be updated to support
126 * pbuffers.
127 */
128 static GLboolean
129 nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv,
130 __DRIdrawablePrivate *driDrawPriv,
131 const __GLcontextModes *mesaVis,
132 GLboolean isPixmap)
133 {
134 nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private;
135 nouveau_renderbuffer *nrb;
136 struct gl_framebuffer *fb;
137 const GLboolean swAccum = mesaVis->accumRedBits > 0;
138 const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
139 GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5;
140
141 if (isPixmap)
142 return GL_FALSE; /* not implemented */
143
144 fb = _mesa_create_framebuffer(mesaVis);
145 if (!fb)
146 return GL_FALSE;
147
148 /* Front buffer */
149 nrb = nouveau_renderbuffer_new(color_format,
150 driScrnPriv->pFB + screen->frontOffset,
151 screen->frontOffset,
152 screen->frontPitch * screen->fbFormat,
153 driDrawPriv);
154 nouveauSpanSetFunctions(nrb, mesaVis);
155 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa);
156
157 if (0 /* unified buffers if we choose to support them.. */) {
158 } else {
159 if (mesaVis->doubleBufferMode) {
160 nrb = nouveau_renderbuffer_new(color_format, NULL,
161 0, 0,
162 NULL);
163 nouveauSpanSetFunctions(nrb, mesaVis);
164 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa);
165 }
166
167 if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
168 nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL,
169 0, 0,
170 NULL);
171 nouveauSpanSetFunctions(nrb, mesaVis);
172 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
173 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa);
174 } else if (mesaVis->depthBits == 24) {
175 nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL,
176 0, 0,
177 NULL);
178 nouveauSpanSetFunctions(nrb, mesaVis);
179 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
180 } else if (mesaVis->depthBits == 16) {
181 nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL,
182 0, 0,
183 NULL);
184 nouveauSpanSetFunctions(nrb, mesaVis);
185 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
186 }
187 }
188
189 _mesa_add_soft_renderbuffers(fb,
190 GL_FALSE, /* color */
191 GL_FALSE, /* depth */
192 swStencil,
193 swAccum,
194 GL_FALSE, /* alpha */
195 GL_FALSE /* aux */);
196
197 driDrawPriv->driverPrivate = (void *) fb;
198 return (driDrawPriv->driverPrivate != NULL);
199 }
200
201
202 static void
203 nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
204 {
205 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
206 }
207
208 static int
209 nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo)
210 {
211 return -1;
212 }
213
214 static const struct __DriverAPIRec nouveauAPI = {
215 .InitDriver = nouveauInitDriver,
216 .DestroyScreen = nouveauDestroyScreen,
217 .CreateContext = nouveauCreateContext,
218 .DestroyContext = nouveauDestroyContext,
219 .CreateBuffer = nouveauCreateBuffer,
220 .DestroyBuffer = nouveauDestroyBuffer,
221 .SwapBuffers = nouveauSwapBuffers,
222 .MakeCurrent = nouveauMakeCurrent,
223 .UnbindContext = nouveauUnbindContext,
224 .GetSwapInfo = nouveauGetSwapInfo,
225 .GetMSC = driGetMSC32,
226 .WaitForMSC = driWaitForMSC32,
227 .WaitForSBC = NULL,
228 .SwapBuffersMSC = NULL,
229 .CopySubBuffer = nouveauCopySubBuffer
230 };
231
232
233 static __GLcontextModes *
234 nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits,
235 unsigned stencil_bits, GLboolean have_back_buffer )
236 {
237 __GLcontextModes * modes;
238 __GLcontextModes * m;
239 unsigned num_modes;
240 unsigned depth_buffer_factor;
241 unsigned back_buffer_factor;
242 int i;
243
244 static const struct {
245 GLenum format;
246 GLenum type;
247 } fb_format_array[] = {
248 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 },
249 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
250 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
251 };
252
253 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
254 * support pageflipping at all.
255 */
256 static const GLenum back_buffer_modes[] = {
257 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
258 };
259
260 u_int8_t depth_bits_array[4] = { 0, 16, 24, 24 };
261 u_int8_t stencil_bits_array[4] = { 0, 0, 0, 8 };
262
263 depth_buffer_factor = 4;
264 back_buffer_factor = (have_back_buffer) ? 3 : 1;
265
266 num_modes = ((pixel_bits==16) ? 1 : 2) *
267 depth_buffer_factor * back_buffer_factor * 4;
268 modes = (*dri_interface->createContextModes)(num_modes,
269 sizeof(__GLcontextModes));
270 m = modes;
271
272 for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
273 if (!driFillInModes(&m, fb_format_array[i].format,
274 fb_format_array[i].type,
275 depth_bits_array,
276 stencil_bits_array,
277 depth_buffer_factor,
278 back_buffer_modes,
279 back_buffer_factor,
280 GLX_TRUE_COLOR)) {
281 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
282 __func__, __LINE__ );
283 return NULL;
284 }
285
286 if (!driFillInModes(&m, fb_format_array[i].format,
287 fb_format_array[i].type,
288 depth_bits_array,
289 stencil_bits_array,
290 depth_buffer_factor,
291 back_buffer_modes,
292 back_buffer_factor,
293 GLX_DIRECT_COLOR)) {
294 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
295 __func__, __LINE__ );
296 return NULL;
297 }
298 }
299
300 return modes;
301 }
302
303
304 /**
305 * This is the bootstrap function for the driver. libGL supplies all of the
306 * requisite information about the system, and the driver initializes itself.
307 * This routine also fills in the linked list pointed to by \c driver_modes
308 * with the \c __GLcontextModes that the driver can support for windows or
309 * pbuffers.
310 *
311 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
312 * failure.
313 */
314 PUBLIC
315 void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
316 const __GLcontextModes * modes,
317 const __DRIversion * ddx_version,
318 const __DRIversion * dri_version,
319 const __DRIversion * drm_version,
320 const __DRIframebuffer * frame_buffer,
321 drmAddress pSAREA, int fd,
322 int internal_api_version,
323 const __DRIinterfaceMethods * interface,
324 __GLcontextModes ** driver_modes)
325
326 {
327 __DRIscreenPrivate *psp;
328 static const __DRIversion ddx_expected = { 1, 2, 0 };
329 static const __DRIversion dri_expected = { 4, 0, 0 };
330 static const __DRIversion drm_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
331 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 9
332 #error nouveau_drm.h version doesn't match expected version
333 #endif
334 dri_interface = interface;
335
336 if (!driCheckDriDdxDrmVersions2("nouveau",
337 dri_version, & dri_expected,
338 ddx_version, & ddx_expected,
339 drm_version, & drm_expected)) {
340 return NULL;
341 }
342
343 // temporary lock step versioning
344 if (drm_expected.patch!=drm_version->patch) {
345 __driUtilMessage("%s: wrong DRM version, expected %d, got %d\n",
346 __func__,
347 drm_expected.patch, drm_version->patch);
348 return NULL;
349 }
350
351 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
352 ddx_version, dri_version, drm_version,
353 frame_buffer, pSAREA, fd,
354 internal_api_version, &nouveauAPI);
355 if ( psp != NULL ) {
356 NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
357
358 *driver_modes = nouveauFillInModes(dri_priv->bpp,
359 (dri_priv->bpp == 16) ? 16 : 24,
360 (dri_priv->bpp == 16) ? 0 : 8,
361 1
362 );
363
364 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
365 * enable the extensions. It just makes sure that all the dispatch offsets for all
366 * the extensions that *might* be enables are known. This is needed because the
367 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
368 * enable the extensions until we have a context pointer.
369 *
370 * Hello chicken. Hello egg. How are you two today?
371 */
372 driInitExtensions( NULL, common_extensions, GL_FALSE );
373 driInitExtensions( NULL, nv10_extensions, GL_FALSE );
374 driInitExtensions( NULL, nv10_extensions, GL_FALSE );
375 driInitExtensions( NULL, nv30_extensions, GL_FALSE );
376 driInitExtensions( NULL, nv40_extensions, GL_FALSE );
377 driInitExtensions( NULL, nv50_extensions, GL_FALSE );
378 }
379
380 return (void *) psp;
381 }
382