nouveau_screen.c revision 254ce75ac300d8d20ba4e2fce81c4459c692d2b1
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	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 */
307PUBLIC
308void * __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
370