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