nouveau_context.c revision 601a6b872c33bfe3cb4ea03a5a8ba5ebe92dedaf
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_04:
220		case NV_05:
221			nv04TriInitFunctions( ctx );
222			break;
223		case NV_10:
224		case NV_11:
225		case NV_17:
226		case NV_20:
227		case NV_30:
228		case NV_40:
229		case NV_44:
230		case NV_50:
231		default:
232			nv10TriInitFunctions( ctx );
233			break;
234	}
235
236	nouveauInitBufferObjects(ctx);
237	if (!nouveauSyncInitFuncs(ctx))
238	   return GL_FALSE;
239	nouveauQueryInitFuncs(ctx);
240	nmesa->hw_func.InitCard(nmesa);
241        nouveauInitState(ctx);
242
243	driContextPriv->driverPrivate = (void *)nmesa;
244
245	NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ),
246			debug_control );
247
248	if (driQueryOptionb(&nmesa->optionCache, "no_rast")) {
249		fprintf(stderr, "disabling 3D acceleration\n");
250		FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1);
251	}
252
253	return GL_TRUE;
254}
255
256/* Destroy the device specific context. */
257void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv  )
258{
259	nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
260
261	assert(nmesa);
262	if ( nmesa ) {
263		/* free the option cache */
264		driDestroyOptionCache (&nmesa->optionCache);
265
266		FREE( nmesa );
267	}
268
269}
270
271
272/* Force the context `c' to be the current context and associate with it
273 * buffer `b'.
274 */
275GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
276		__DRIdrawablePrivate *driDrawPriv,
277		__DRIdrawablePrivate *driReadPriv )
278{
279	if ( driContextPriv ) {
280		nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
281		struct gl_framebuffer *draw_fb =
282			(struct gl_framebuffer*)driDrawPriv->driverPrivate;
283		struct gl_framebuffer *read_fb =
284			(struct gl_framebuffer*)driReadPriv->driverPrivate;
285
286		if (driDrawPriv->swap_interval == (unsigned)-1) {
287			driDrawPriv->vblFlags =
288				driGetDefaultVBlankFlags(&nmesa->optionCache);
289
290			driDrawableInitVBlank(driDrawPriv);
291		}
292
293		nmesa->driDrawable = driDrawPriv;
294
295		_mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
296					 driDrawPriv->w, driDrawPriv->h);
297		if (draw_fb != read_fb) {
298			_mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
299						 driReadPriv->w,
300						 driReadPriv->h);
301		}
302		_mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
303
304		nouveau_build_framebuffer(nmesa->glCtx,
305		      			  driDrawPriv->driverPrivate);
306	} else {
307		_mesa_make_current( NULL, NULL, NULL );
308	}
309
310	return GL_TRUE;
311}
312
313
314/* Force the context `c' to be unbound from its buffer.
315 */
316GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
317{
318	return GL_TRUE;
319}
320
321void
322nouveauDoSwapBuffers(nouveauContextPtr nmesa, __DRIdrawablePrivate *dPriv)
323{
324	struct gl_framebuffer *fb;
325	nouveauScreenPtr screen = dPriv->driScreenPriv->private;
326	nouveau_renderbuffer_t *src;
327	drm_clip_rect_t *box;
328	int nbox, i;
329
330	fb = (struct gl_framebuffer *)dPriv->driverPrivate;
331	if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
332		src = (nouveau_renderbuffer_t *)
333			fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
334	} else {
335		src = (nouveau_renderbuffer_t *)
336			fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
337	}
338
339	LOCK_HARDWARE(nmesa);
340	nbox = dPriv->numClipRects;
341	box  = dPriv->pClipRects;
342
343	if (nbox) {
344		BEGIN_RING_SIZE(NvSubCtxSurf2D,
345				NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
346		if (src->mesa._ActualFormat == GL_RGBA8)
347			OUT_RING       (6); /* X8R8G8B8 */
348		else
349			OUT_RING       (4); /* R5G6B5 */
350		OUT_RING(((screen->frontPitch * screen->fbFormat) << 16) |
351			  src->pitch);
352		OUT_RING(src->offset);
353		OUT_RING(screen->frontOffset);
354	}
355
356	for (i=0; i<nbox; i++, box++) {
357		BEGIN_RING_SIZE(NvSubImageBlit, NV_IMAGE_BLIT_POINT_IN, 3);
358		OUT_RING       (((box->y1 - dPriv->y) << 16) |
359				(box->x1 - dPriv->x));
360		OUT_RING       ((box->y1 << 16) | box->x1);
361		OUT_RING       (((box->y2 - box->y1) << 16) |
362				(box->x2 - box->x1));
363	}
364	FIRE_RING();
365
366	UNLOCK_HARDWARE(nmesa);
367}
368
369void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
370{
371	if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
372		nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
373
374		if (nmesa->glCtx->Visual.doubleBufferMode) {
375			_mesa_notifySwapBuffers(nmesa->glCtx);
376			nouveauDoSwapBuffers(nmesa, dPriv);
377		}
378
379	}
380}
381
382void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
383			  int x, int y, int w, int h)
384{
385}
386
387void nouveauClearBuffer(GLcontext *ctx, nouveau_renderbuffer_t *buffer,
388	int fill, int mask)
389{
390	nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
391	int dimensions;
392
393	if (!buffer) {
394		return;
395	}
396
397	/* FIXME: only support 32 bits atm */
398
399	/* Surface that we will work on */
400	nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D);
401
402	BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
403	OUT_RING(0x0b); /* Y32 color format */
404	OUT_RING((buffer->pitch<<16)|buffer->pitch);
405	OUT_RING(buffer->offset);
406	OUT_RING(buffer->offset);
407
408	/* Now clear a rectangle */
409	dimensions = ((buffer->mesa.Height)<<16) | (buffer->mesa.Width);
410
411	nouveauObjectOnSubchannel(nmesa, NvSubGdiRectText, NvGdiRectText);
412
413	BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
414	OUT_RING(3);	/* SRCCOPY */
415
416	BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL1_TL, 5);
417	OUT_RING(0);	/* top left */
418	OUT_RING(dimensions);	/* bottom right */
419	OUT_RING(fill);
420	OUT_RING(0);	/* top left */
421	OUT_RING(dimensions);	/* bottom right */
422}
423