nouveau_context.c revision c04c74bc5da454478fd0dbf3b25dd54190ac0942
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 "context.h"
29#include "simple_list.h"
30#include "imports.h"
31#include "matrix.h"
32#include "swrast/swrast.h"
33#include "swrast_setup/swrast_setup.h"
34#include "array_cache/acache.h"
35#include "framebuffer.h"
36
37#include "tnl/tnl.h"
38#include "tnl/t_pipeline.h"
39#include "tnl/t_vp_build.h"
40
41#include "drivers/common/driverfuncs.h"
42
43#include "nouveau_context.h"
44#include "nouveau_driver.h"
45//#include "nouveau_state.h"
46#include "nouveau_span.h"
47#include "nouveau_object.h"
48#include "nouveau_fifo.h"
49#include "nouveau_tex.h"
50#include "nouveau_msg.h"
51#include "nouveau_reg.h"
52#include "nv10_swtcl.h"
53
54#include "vblank.h"
55#include "utils.h"
56#include "texmem.h"
57#include "xmlpool.h" /* for symbolic values of enum-type options */
58
59#ifndef NOUVEAU_DEBUG
60int NOUVEAU_DEBUG = 0;
61#endif
62
63static const struct dri_debug_control debug_control[] =
64{
65	{ NULL,    0 }
66};
67
68#define need_GL_ARB_vertex_program
69#include "extension_helper.h"
70
71const struct dri_extension common_extensions[] =
72{
73	{ NULL,    0 }
74};
75
76const struct dri_extension nv10_extensions[] =
77{
78	{ NULL,    0 }
79};
80
81const struct dri_extension nv20_extensions[] =
82{
83	{ NULL,    0 }
84};
85
86const struct dri_extension nv30_extensions[] =
87{
88	{ "GL_ARB_fragment_program",	NULL                            },
89	{ NULL,    0 }
90};
91
92const struct dri_extension nv40_extensions[] =
93{
94   /* ARB_vp can be moved to nv20/30 once the shader backend has been
95    * written for those cards.
96    */
97	{ "GL_ARB_vertex_program",	GL_ARB_vertex_program_functions },
98	{ NULL, 0 }
99};
100
101const struct dri_extension nv50_extensions[] =
102{
103	{ NULL,    0 }
104};
105
106/* Create the device specific context.
107 */
108GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
109		__DRIcontextPrivate *driContextPriv,
110		void *sharedContextPrivate )
111{
112	GLcontext *ctx, *shareCtx;
113	__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
114	struct dd_function_table functions;
115	nouveauContextPtr nmesa;
116	nouveauScreenPtr screen;
117
118	/* Allocate the context */
119	nmesa = (nouveauContextPtr) CALLOC( sizeof(*nmesa) );
120	if ( !nmesa )
121		return GL_FALSE;
122
123	nmesa->driContext = driContextPriv;
124	nmesa->driScreen = sPriv;
125	nmesa->driDrawable = NULL;
126	nmesa->hHWContext = driContextPriv->hHWContext;
127	nmesa->driHwLock = &sPriv->pSAREA->lock;
128	nmesa->driFd = sPriv->fd;
129
130	nmesa->screen = (nouveauScreenPtr)(sPriv->private);
131	screen=nmesa->screen;
132
133	/* Create the hardware context */
134	if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_PHYSICAL,
135		 		&nmesa->vram_phys))
136	   return GL_FALSE;
137	if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL,
138		 		&nmesa->agp_phys))
139	   return GL_FALSE;
140	if (!nouveauFifoInit(nmesa))
141	   return GL_FALSE;
142	nouveauObjectInit(nmesa);
143
144
145	/* Init default driver functions then plug in our nouveau-specific functions
146	 * (the texture functions are especially important)
147	 */
148	_mesa_init_driver_functions( &functions );
149	nouveauDriverInitFunctions( &functions );
150	nouveauTexInitFunctions( &functions );
151
152	/* Allocate the Mesa context */
153	if (sharedContextPrivate)
154		shareCtx = ((nouveauContextPtr) sharedContextPrivate)->glCtx;
155	else
156		shareCtx = NULL;
157	nmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
158			&functions, (void *) nmesa);
159	if (!nmesa->glCtx) {
160		FREE(nmesa);
161		return GL_FALSE;
162	}
163	driContextPriv->driverPrivate = nmesa;
164	ctx = nmesa->glCtx;
165
166	/* Parse configuration files */
167	driParseConfigFiles (&nmesa->optionCache, &screen->optionCache,
168			screen->driScreen->myNum, "nouveau");
169
170	nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA +
171			screen->sarea_priv_offset);
172
173	/* Enable any supported extensions */
174	driInitExtensions(ctx, common_extensions, GL_TRUE);
175	if (nmesa->screen->card->type >= NV_10)
176		driInitExtensions(ctx, nv10_extensions, GL_FALSE);
177	if (nmesa->screen->card->type >= NV_20)
178		driInitExtensions(ctx, nv20_extensions, GL_FALSE);
179	if (nmesa->screen->card->type >= NV_30)
180		driInitExtensions(ctx, nv30_extensions, GL_FALSE);
181	if (nmesa->screen->card->type >= NV_40)
182		driInitExtensions(ctx, nv40_extensions, GL_FALSE);
183	if (nmesa->screen->card->type >= NV_50)
184		driInitExtensions(ctx, nv50_extensions, GL_FALSE);
185
186	nmesa->current_primitive = -1;
187
188	nouveauShaderInitFuncs(ctx);
189	/* Install Mesa's fixed-function shader support */
190	if (nmesa->screen->card->type >= NV_40) {
191		ctx->_MaintainTnlProgram    = GL_TRUE;
192		ctx->_MaintainTexEnvProgram = GL_TRUE;
193	}
194
195	/* Initialize the swrast */
196	_swrast_CreateContext( ctx );
197	_ac_CreateContext( ctx );
198	_tnl_CreateContext( ctx );
199	_swsetup_CreateContext( ctx );
200
201	_math_matrix_ctr(&nmesa->viewport);
202
203	nouveauDDInitStateFuncs( ctx );
204	nouveauSpanInitFunctions( ctx );
205	nouveauDDInitState( nmesa );
206	switch(nmesa->screen->card->type)
207	{
208		case NV_03:
209			//nv03TriInitFunctions( ctx );
210			break;
211		case NV_04:
212		case NV_05:
213			//nv04TriInitFunctions( ctx );
214			break;
215		case NV_10:
216		case NV_20:
217		case NV_30:
218		case NV_40:
219		case NV_44:
220		case NV_50:
221		default:
222			nv10TriInitFunctions( ctx );
223			break;
224	}
225
226	nmesa->hw_func.InitCard(nmesa);
227        nouveauInitState(ctx);
228
229	driContextPriv->driverPrivate = (void *)nmesa;
230
231	NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ),
232			debug_control );
233
234	if (driQueryOptionb(&nmesa->optionCache, "no_rast")) {
235		fprintf(stderr, "disabling 3D acceleration\n");
236		FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1);
237	}
238
239	return GL_TRUE;
240}
241
242/* Destroy the device specific context. */
243void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv  )
244{
245	nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
246
247	assert(nmesa);
248	if ( nmesa ) {
249		/* free the option cache */
250		driDestroyOptionCache (&nmesa->optionCache);
251
252		FREE( nmesa );
253	}
254
255}
256
257
258/* Force the context `c' to be the current context and associate with it
259 * buffer `b'.
260 */
261GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
262		__DRIdrawablePrivate *driDrawPriv,
263		__DRIdrawablePrivate *driReadPriv )
264{
265	if ( driContextPriv ) {
266		nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
267		struct gl_framebuffer *draw_fb =
268			(struct gl_framebuffer*)driDrawPriv->driverPrivate;
269		struct gl_framebuffer *read_fb =
270			(struct gl_framebuffer*)driReadPriv->driverPrivate;
271
272		driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq );
273		nmesa->driDrawable = driDrawPriv;
274
275		_mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
276					 driDrawPriv->w, driDrawPriv->h);
277		if (draw_fb != read_fb) {
278			_mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
279						 driReadPriv->w,
280						 driReadPriv->h);
281		}
282		_mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
283
284		nouveau_build_framebuffer(nmesa->glCtx,
285		      			  driDrawPriv->driverPrivate);
286	} else {
287		_mesa_make_current( NULL, NULL, NULL );
288	}
289
290	return GL_TRUE;
291}
292
293
294/* Force the context `c' to be unbound from its buffer.
295 */
296GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
297{
298	return GL_TRUE;
299}
300
301static void nouveauDoSwapBuffers(nouveauContextPtr nmesa,
302				 __DRIdrawablePrivate *dPriv)
303{
304	struct gl_framebuffer *fb;
305	nouveau_renderbuffer *src, *dst;
306
307	fb = (struct gl_framebuffer *)dPriv->driverPrivate;
308	dst = (nouveau_renderbuffer*)
309		fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
310	src = (nouveau_renderbuffer*)
311		fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
312
313#ifdef ALLOW_MULTI_SUBCHANNEL
314	/* Ignore this.. it's a hack to test double-buffering, and not how
315	 * SwapBuffers should look :)
316	 */
317	BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
318	OUT_RING       (6); /* X8R8G8B8 */
319	OUT_RING       ((dst->pitch << 16) | src->pitch);
320	OUT_RING       (src->offset);
321	OUT_RING       (dst->offset);
322
323	BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3);
324	OUT_RING       ((0 << 16) | 0); /* src point */
325	OUT_RING       ((0 << 16) | 0); /* dst point */
326	OUT_RING       ((fb->Height << 16) | fb->Width); /* width/height */
327#endif
328}
329
330void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
331{
332	if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
333		nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
334
335		if (nmesa->glCtx->Visual.doubleBufferMode) {
336			_mesa_notifySwapBuffers(nmesa->glCtx);
337			nouveauDoSwapBuffers(nmesa, dPriv);
338		}
339
340	}
341}
342
343void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
344			  int x, int y, int w, int h)
345{
346}
347
348