Merge branch 'master' into crestline
[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 /* 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
90 static void
91 nouveauDestroyScreen(__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
104 static 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 */
121 static GLboolean
122 nouveauCreateBuffer(__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
195 static void
196 nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
197 {
198 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
199 }
200
201 static int
202 nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo)
203 {
204 return -1;
205 }
206
207 static 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
226 static __GLcontextModes *
227 nouveauFillInModes( 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 int i;
236
237 static const struct {
238 GLenum format;
239 GLenum type;
240 } fb_format_array[] = {
241 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 },
242 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
243 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
244 };
245
246 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
247 * support pageflipping at all.
248 */
249 static const GLenum back_buffer_modes[] = {
250 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
251 };
252
253 u_int8_t depth_bits_array[4] = { 0, 16, 24, 24 };
254 u_int8_t stencil_bits_array[4] = { 0, 0, 0, 8 };
255
256 depth_buffer_factor = 4;
257 back_buffer_factor = (have_back_buffer) ? 3 : 1;
258
259 num_modes = ((pixel_bits==16) ? 1 : 2) *
260 depth_buffer_factor * back_buffer_factor * 4;
261 modes = (*dri_interface->createContextModes)(num_modes,
262 sizeof(__GLcontextModes));
263 m = modes;
264
265 for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
266 if (!driFillInModes(&m, fb_format_array[i].format,
267 fb_format_array[i].type,
268 depth_bits_array,
269 stencil_bits_array,
270 depth_buffer_factor,
271 back_buffer_modes,
272 back_buffer_factor,
273 GLX_TRUE_COLOR)) {
274 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
275 __func__, __LINE__ );
276 return NULL;
277 }
278
279 if (!driFillInModes(&m, fb_format_array[i].format,
280 fb_format_array[i].type,
281 depth_bits_array,
282 stencil_bits_array,
283 depth_buffer_factor,
284 back_buffer_modes,
285 back_buffer_factor,
286 GLX_DIRECT_COLOR)) {
287 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
288 __func__, __LINE__ );
289 return NULL;
290 }
291 }
292
293 return modes;
294 }
295
296
297 /**
298 * This is the bootstrap function for the driver. libGL supplies all of the
299 * requisite information about the system, and the driver initializes itself.
300 * This routine also fills in the linked list pointed to by \c driver_modes
301 * with the \c __GLcontextModes that the driver can support for windows or
302 * pbuffers.
303 *
304 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
305 * failure.
306 */
307 PUBLIC
308 void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
309 const __GLcontextModes * modes,
310 const __DRIversion * ddx_version,
311 const __DRIversion * dri_version,
312 const __DRIversion * drm_version,
313 const __DRIframebuffer * frame_buffer,
314 drmAddress pSAREA, int fd,
315 int internal_api_version,
316 const __DRIinterfaceMethods * interface,
317 __GLcontextModes ** driver_modes)
318
319 {
320 __DRIscreenPrivate *psp;
321 static const __DRIversion ddx_expected = { 1, 2, 0 };
322 static const __DRIversion dri_expected = { 4, 0, 0 };
323 static const __DRIversion drm_expected = { 0, 0, 2 };
324
325 dri_interface = interface;
326
327 if (!driCheckDriDdxDrmVersions2("nouveau",
328 dri_version, & dri_expected,
329 ddx_version, & ddx_expected,
330 drm_version, & drm_expected)) {
331 return NULL;
332 }
333
334 // temporary lock step versioning
335 if (drm_expected.patch!=drm_version->patch)
336 return NULL;
337
338 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
339 ddx_version, dri_version, drm_version,
340 frame_buffer, pSAREA, fd,
341 internal_api_version, &nouveauAPI);
342 if ( psp != NULL ) {
343 NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
344
345 *driver_modes = nouveauFillInModes(dri_priv->bpp,
346 (dri_priv->bpp == 16) ? 16 : 24,
347 (dri_priv->bpp == 16) ? 0 : 8,
348 1
349 );
350
351 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
352 * enable the extensions. It just makes sure that all the dispatch offsets for all
353 * the extensions that *might* be enables are known. This is needed because the
354 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
355 * enable the extensions until we have a context pointer.
356 *
357 * Hello chicken. Hello egg. How are you two today?
358 */
359 driInitExtensions( NULL, common_extensions, GL_FALSE );
360 driInitExtensions( NULL, nv10_extensions, GL_FALSE );
361 driInitExtensions( NULL, nv10_extensions, GL_FALSE );
362 driInitExtensions( NULL, nv30_extensions, GL_FALSE );
363 driInitExtensions( NULL, nv40_extensions, GL_FALSE );
364 driInitExtensions( NULL, nv50_extensions, GL_FALSE );
365 }
366
367 return (void *) psp;
368 }
369