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