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