Merge branch 'vbo-0.2'
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_context.c
1 /**************************************************************************
2
3 Copyright 2006 Stephane Marchesin
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 on the rights to use, copy, modify, merge, publish, distribute, sub
10 license, and/or sell copies of the Software, and to permit persons to whom
11 the Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice (including the next
14 paragraph) shall be included in all copies or substantial portions of the
15 Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 USE 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
62 int NOUVEAU_DEBUG = 0;
63 #endif
64
65 static 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
77 const struct dri_extension common_extensions[] =
78 {
79 { NULL, 0 }
80 };
81
82 const struct dri_extension nv10_extensions[] =
83 {
84 { NULL, 0 }
85 };
86
87 const struct dri_extension nv20_extensions[] =
88 {
89 { NULL, 0 }
90 };
91
92 const struct dri_extension nv30_extensions[] =
93 {
94 { "GL_ARB_fragment_program", NULL },
95 { NULL, 0 }
96 };
97
98 const 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
108 const struct dri_extension nv50_extensions[] =
109 {
110 { NULL, 0 }
111 };
112
113 /* Create the device specific context.
114 */
115 GLboolean 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_AGP_PHYSICAL,
145 &nmesa->agp_phys))
146 return GL_FALSE;
147 if (!nouveauFifoInit(nmesa))
148 return GL_FALSE;
149 nouveauObjectInit(nmesa);
150
151
152 /* Init default driver functions then plug in our nouveau-specific functions
153 * (the texture functions are especially important)
154 */
155 _mesa_init_driver_functions( &functions );
156 nouveauDriverInitFunctions( &functions );
157 nouveauTexInitFunctions( &functions );
158
159 /* Allocate the Mesa context */
160 if (sharedContextPrivate)
161 shareCtx = ((nouveauContextPtr) sharedContextPrivate)->glCtx;
162 else
163 shareCtx = NULL;
164 nmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
165 &functions, (void *) nmesa);
166 if (!nmesa->glCtx) {
167 FREE(nmesa);
168 return GL_FALSE;
169 }
170 driContextPriv->driverPrivate = nmesa;
171 ctx = nmesa->glCtx;
172
173 /* Parse configuration files */
174 driParseConfigFiles (&nmesa->optionCache, &screen->optionCache,
175 screen->driScreen->myNum, "nouveau");
176
177 nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA +
178 screen->sarea_priv_offset);
179
180 /* Enable any supported extensions */
181 driInitExtensions(ctx, common_extensions, GL_TRUE);
182 if (nmesa->screen->card->type >= NV_10)
183 driInitExtensions(ctx, nv10_extensions, GL_FALSE);
184 if (nmesa->screen->card->type >= NV_20)
185 driInitExtensions(ctx, nv20_extensions, GL_FALSE);
186 if (nmesa->screen->card->type >= NV_30)
187 driInitExtensions(ctx, nv30_extensions, GL_FALSE);
188 if (nmesa->screen->card->type >= NV_40)
189 driInitExtensions(ctx, nv40_extensions, GL_FALSE);
190 if (nmesa->screen->card->type >= NV_50)
191 driInitExtensions(ctx, nv50_extensions, GL_FALSE);
192
193 nmesa->current_primitive = -1;
194
195 nouveauShaderInitFuncs(ctx);
196 /* Install Mesa's fixed-function texenv shader support */
197 if (nmesa->screen->card->type >= NV_40)
198 ctx->_MaintainTexEnvProgram = GL_TRUE;
199
200 /* Initialize the swrast */
201 _swrast_CreateContext( ctx );
202 _vbo_CreateContext( ctx );
203 _tnl_CreateContext( ctx );
204 _swsetup_CreateContext( ctx );
205
206 _math_matrix_ctr(&nmesa->viewport);
207
208 nouveauDDInitStateFuncs( ctx );
209 nouveauSpanInitFunctions( ctx );
210 nouveauDDInitState( nmesa );
211 switch(nmesa->screen->card->type)
212 {
213 case NV_03:
214 //nv03TriInitFunctions( ctx );
215 break;
216 case NV_04:
217 case NV_05:
218 nv04TriInitFunctions( ctx );
219 break;
220 case NV_10:
221 case NV_20:
222 case NV_30:
223 case NV_40:
224 case NV_44:
225 case NV_50:
226 default:
227 nv10TriInitFunctions( ctx );
228 break;
229 }
230
231 nouveauInitBufferObjects(ctx);
232 if (!nouveauSyncInitFuncs(ctx))
233 return GL_FALSE;
234 nouveauQueryInitFuncs(ctx);
235 nmesa->hw_func.InitCard(nmesa);
236 nouveauInitState(ctx);
237
238 driContextPriv->driverPrivate = (void *)nmesa;
239
240 NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ),
241 debug_control );
242
243 if (driQueryOptionb(&nmesa->optionCache, "no_rast")) {
244 fprintf(stderr, "disabling 3D acceleration\n");
245 FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1);
246 }
247
248 return GL_TRUE;
249 }
250
251 /* Destroy the device specific context. */
252 void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv )
253 {
254 nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
255
256 assert(nmesa);
257 if ( nmesa ) {
258 /* free the option cache */
259 driDestroyOptionCache (&nmesa->optionCache);
260
261 FREE( nmesa );
262 }
263
264 }
265
266
267 /* Force the context `c' to be the current context and associate with it
268 * buffer `b'.
269 */
270 GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
271 __DRIdrawablePrivate *driDrawPriv,
272 __DRIdrawablePrivate *driReadPriv )
273 {
274 if ( driContextPriv ) {
275 nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
276 struct gl_framebuffer *draw_fb =
277 (struct gl_framebuffer*)driDrawPriv->driverPrivate;
278 struct gl_framebuffer *read_fb =
279 (struct gl_framebuffer*)driReadPriv->driverPrivate;
280
281 driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq );
282 nmesa->driDrawable = driDrawPriv;
283
284 _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
285 driDrawPriv->w, driDrawPriv->h);
286 if (draw_fb != read_fb) {
287 _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
288 driReadPriv->w,
289 driReadPriv->h);
290 }
291 _mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
292
293 nouveau_build_framebuffer(nmesa->glCtx,
294 driDrawPriv->driverPrivate);
295 } else {
296 _mesa_make_current( NULL, NULL, NULL );
297 }
298
299 return GL_TRUE;
300 }
301
302
303 /* Force the context `c' to be unbound from its buffer.
304 */
305 GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
306 {
307 return GL_TRUE;
308 }
309
310 static void nouveauDoSwapBuffers(nouveauContextPtr nmesa,
311 __DRIdrawablePrivate *dPriv)
312 {
313 struct gl_framebuffer *fb;
314 nouveau_renderbuffer *src, *dst;
315 drm_clip_rect_t *box;
316 int nbox, i;
317
318 fb = (struct gl_framebuffer *)dPriv->driverPrivate;
319 dst = (nouveau_renderbuffer*)
320 fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
321 src = (nouveau_renderbuffer*)
322 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
323
324 #ifdef ALLOW_MULTI_SUBCHANNEL
325 LOCK_HARDWARE(nmesa);
326 nbox = dPriv->numClipRects;
327 box = dPriv->pClipRects;
328
329 if (nbox) {
330 BEGIN_RING_SIZE(NvSubCtxSurf2D,
331 NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
332 if (src->mesa._ActualFormat == GL_RGBA8)
333 OUT_RING (6); /* X8R8G8B8 */
334 else
335 OUT_RING (4); /* R5G6B5 */
336 OUT_RING ((dst->pitch << 16) | src->pitch);
337 OUT_RING (src->offset);
338 OUT_RING (dst->offset);
339 }
340
341 for (i=0; i<nbox; i++, box++) {
342 BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3);
343 OUT_RING (((box->y1 - dPriv->y) << 16) |
344 (box->x1 - dPriv->x));
345 OUT_RING ((box->y1 << 16) | box->x1);
346 OUT_RING (((box->y2 - box->y1) << 16) |
347 (box->x2 - box->x1));
348 }
349
350 UNLOCK_HARDWARE(nmesa);
351 #endif
352 }
353
354 void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
355 {
356 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
357 nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
358
359 if (nmesa->glCtx->Visual.doubleBufferMode) {
360 _mesa_notifySwapBuffers(nmesa->glCtx);
361 nouveauDoSwapBuffers(nmesa, dPriv);
362 }
363
364 }
365 }
366
367 void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
368 int x, int y, int w, int h)
369 {
370 }
371