Major rip-up of internal function insertion interface. The old
[mesa.git] / src / mesa / drivers / dri / trident / trident_context.c
1 /*
2 * Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
23 *
24 * Trident CyberBladeXP driver.
25 *
26 */
27 #include "trident_dri.h"
28 #include "trident_context.h"
29 #include "trident_lock.h"
30
31 #include "swrast/swrast.h"
32 #include "swrast_setup/swrast_setup.h"
33 #include "array_cache/acache.h"
34
35 #include "tnl/tnl.h"
36 #include "tnl/t_pipeline.h"
37
38 #include "context.h"
39 #include "simple_list.h"
40 #include "matrix.h"
41 #include "extensions.h"
42 #include "framebuffer.h"
43 #include "renderbuffer.h"
44 #if defined(USE_X86_ASM)
45 #include "x86/common_x86_asm.h"
46 #endif
47 #include "simple_list.h"
48 #include "mm.h"
49 #include "drirenderbuffer.h"
50
51 #include "drivers/common/driverfuncs.h"
52 #include "dri_util.h"
53
54 static const struct tnl_pipeline_stage *trident_pipeline[] = {
55 &_tnl_vertex_transform_stage,
56 &_tnl_normal_transform_stage,
57 &_tnl_lighting_stage,
58 &_tnl_texgen_stage,
59 &_tnl_texture_transform_stage,
60 &_tnl_render_stage,
61 0,
62 };
63
64
65 GLboolean tridentCreateContext( const __GLcontextModes *glVisual,
66 __DRIcontextPrivate *driContextPriv,
67 void *sharedContextPrivate)
68 {
69 GLcontext *ctx, *shareCtx;
70 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
71 tridentContextPtr tmesa;
72 tridentScreenPtr tridentscrn;
73 struct dd_function_table functions;
74 #if 0
75 drm_trident_sarea_t *saPriv=(drm_trident_sarea_t *)(((char*)sPriv->pSAREA)+
76 sizeof(XF86DRISAREARec));
77 #endif
78
79 tmesa = (tridentContextPtr) CALLOC( sizeof(*tmesa) );
80 if ( !tmesa ) return GL_FALSE;
81
82 /* Allocate the Mesa context */
83 if (sharedContextPrivate)
84 shareCtx = ((tridentContextPtr) sharedContextPrivate)->glCtx;
85 else
86 shareCtx = NULL;
87
88 _mesa_init_driver_functions(&functions);
89
90 tmesa->glCtx =
91 _mesa_create_context(glVisual, shareCtx, &functions, (void *)tmesa);
92
93 if (!tmesa->glCtx) {
94 FREE(tmesa);
95 return GL_FALSE;
96 }
97
98 tmesa->driContext = driContextPriv;
99 tmesa->driScreen = sPriv;
100 tmesa->driDrawable = NULL; /* Set by XMesaMakeCurrent */
101
102 tmesa->hHWContext = driContextPriv->hHWContext;
103 tmesa->driHwLock = (drmLock *)&sPriv->pSAREA->lock;
104 tmesa->driFd = sPriv->fd;
105 #if 0
106 tmesa->sarea = saPriv;
107 #endif
108
109 tridentscrn = tmesa->tridentScreen = (tridentScreenPtr)(sPriv->private);
110
111 ctx = tmesa->glCtx;
112
113 ctx->Const.MaxTextureLevels = 13; /* 4K by 4K? Is that right? */
114 ctx->Const.MaxTextureUnits = 1; /* Permedia 3 */
115
116 ctx->Const.MinLineWidth = 0.0;
117 ctx->Const.MaxLineWidth = 255.0;
118
119 ctx->Const.MinLineWidthAA = 0.0;
120 ctx->Const.MaxLineWidthAA = 65536.0;
121
122 ctx->Const.MinPointSize = 0.0;
123 ctx->Const.MaxPointSize = 255.0;
124
125 ctx->Const.MinPointSizeAA = 0.5; /* 4x4 quality mode */
126 ctx->Const.MaxPointSizeAA = 16.0;
127 ctx->Const.PointSizeGranularity = 0.25;
128
129 #if 0
130 tmesa->texHeap = mmInit( 0, tmesa->tridentScreen->textureSize );
131
132 make_empty_list(&tmesa->TexObjList);
133 make_empty_list(&tmesa->SwappedOut);
134
135 tmesa->CurrentTexObj[0] = 0;
136 tmesa->CurrentTexObj[1] = 0; /* Permedia 3, second texture */
137
138 tmesa->RenderIndex = ~0;
139 #endif
140
141 /* Initialize the software rasterizer and helper modules.
142 */
143 _swrast_CreateContext( ctx );
144 _ac_CreateContext( ctx );
145 _tnl_CreateContext( ctx );
146 _swsetup_CreateContext( ctx );
147
148 /* Install the customized pipeline:
149 */
150 _tnl_destroy_pipeline( ctx );
151 _tnl_install_pipeline( ctx, trident_pipeline );
152
153 /* Configure swrast to match hardware characteristics:
154 */
155 _swrast_allow_pixel_fog( ctx, GL_FALSE );
156 _swrast_allow_vertex_fog( ctx, GL_TRUE );
157
158 tridentInitVB( ctx );
159 tridentDDInitExtensions( ctx );
160 tridentDDInitDriverFuncs( ctx );
161 tridentDDInitStateFuncs( ctx );
162 #if 0
163 tridentDDInitSpanFuncs( ctx );
164 tridentDDInitTextureFuncs( ctx );
165 #endif
166 tridentDDInitTriFuncs( ctx );
167 tridentDDInitState( tmesa );
168
169 driContextPriv->driverPrivate = (void *)tmesa;
170
171 UNLOCK_HARDWARE(tmesa);
172
173 return GL_TRUE;
174 }
175
176 static void
177 tridentDestroyContext(__DRIcontextPrivate *driContextPriv)
178 {
179 tridentContextPtr tmesa = (tridentContextPtr)driContextPriv->driverPrivate;
180
181 if (tmesa) {
182 _swsetup_DestroyContext( tmesa->glCtx );
183 _tnl_DestroyContext( tmesa->glCtx );
184 _ac_DestroyContext( tmesa->glCtx );
185 _swrast_DestroyContext( tmesa->glCtx );
186
187 /* free the Mesa context */
188 tmesa->glCtx->DriverCtx = NULL;
189 _mesa_destroy_context(tmesa->glCtx);
190
191 _mesa_free(tmesa);
192 driContextPriv->driverPrivate = NULL;
193 }
194 }
195
196
197 static GLboolean
198 tridentCreateBuffer( __DRIscreenPrivate *driScrnPriv,
199 __DRIdrawablePrivate *driDrawPriv,
200 const __GLcontextModes *mesaVis,
201 GLboolean isPixmap )
202 {
203 tridentScreenPtr screen = (tridentScreenPtr) driScrnPriv->private;
204
205 if (isPixmap) {
206 return GL_FALSE; /* not implemented */
207 }
208 else {
209 #if 0
210 driDrawPriv->driverPrivate = (void *)
211 _mesa_create_framebuffer(mesaVis,
212 GL_FALSE, /* software depth buffer? */
213 mesaVis->stencilBits > 0,
214 mesaVis->accumRedBits > 0,
215 mesaVis->alphaBits > 0
216 );
217 #else
218 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
219
220 {
221 driRenderbuffer *frontRb
222 = driNewRenderbuffer(GL_RGBA, screen->cpp,
223 screen->frontOffset, screen->frontPitch);
224 /*
225 tridentSetSpanFunctions(frontRb, mesaVis);
226 */
227 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
228 }
229
230 if (mesaVis->doubleBufferMode) {
231 driRenderbuffer *backRb
232 = driNewRenderbuffer(GL_RGBA, screen->cpp,
233 screen->backOffset, screen->backPitch);
234 /*
235 tridentSetSpanFunctions(backRb, mesaVis);
236 */
237 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
238 }
239
240 if (mesaVis->depthBits == 16) {
241 driRenderbuffer *depthRb
242 = driNewRenderbuffer(GL_DEPTH_COMPONENT16, screen->cpp,
243 screen->depthOffset, screen->depthPitch);
244 /*
245 tridentSetSpanFunctions(depthRb, mesaVis);
246 */
247 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
248 }
249 else if (mesaVis->depthBits == 24) {
250 driRenderbuffer *depthRb
251 = driNewRenderbuffer(GL_DEPTH_COMPONENT24, screen->cpp,
252 screen->depthOffset, screen->depthPitch);
253 /*
254 tridentSetSpanFunctions(depthRb, mesaVis);
255 */
256 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
257 }
258
259 /* no h/w stencil?
260 if (mesaVis->stencilBits > 0 && !swStencil) {
261 driRenderbuffer *stencilRb
262 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT);
263 tridentSetSpanFunctions(stencilRb, mesaVis);
264 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
265 }
266 */
267
268 _mesa_add_soft_renderbuffers(fb,
269 GL_FALSE, /* color */
270 GL_FALSE, /* depth */
271 mesaVis->stencilBits > 0,
272 mesaVis->accumRedBits > 0,
273 GL_FALSE, /* alpha */
274 GL_FALSE /* aux */);
275 driDrawPriv->driverPrivate = (void *) fb;
276 #endif
277 return (driDrawPriv->driverPrivate != NULL);
278 }
279 }
280
281
282 static void
283 tridentDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
284 {
285 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
286 }
287
288 static void
289 tridentSwapBuffers(__DRIdrawablePrivate *drawablePrivate)
290 {
291 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
292
293 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
294 tridentContextPtr tmesa;
295 GLcontext *ctx;
296 tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate;
297 ctx = tmesa->glCtx;
298 if (ctx->Visual.doubleBufferMode) {
299 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
300 tridentCopyBuffer( dPriv );
301 }
302 }
303 else {
304 /* XXX this shouldn't be an error but we can't handle it for now */
305 _mesa_problem(NULL, "tridentSwapBuffers: drawable has no context!\n");
306 }
307 }
308
309 static GLboolean
310 tridentMakeCurrent(__DRIcontextPrivate *driContextPriv,
311 __DRIdrawablePrivate *driDrawPriv,
312 __DRIdrawablePrivate *driReadPriv)
313 {
314 if (driContextPriv) {
315 GET_CURRENT_CONTEXT(ctx);
316 tridentContextPtr oldCtx = ctx ? TRIDENT_CONTEXT(ctx) : NULL;
317 tridentContextPtr newCtx = (tridentContextPtr) driContextPriv->driverPrivate;
318
319 if ( newCtx != oldCtx ) {
320 newCtx->dirty = ~0;
321 }
322
323 if (newCtx->driDrawable != driDrawPriv) {
324 newCtx->driDrawable = driDrawPriv;
325 #if 0
326 tridentUpdateWindow ( newCtx->glCtx );
327 tridentUpdateViewportOffset( newCtx->glCtx );
328 #endif
329 }
330
331 newCtx->drawOffset = newCtx->tridentScreen->backOffset;
332 newCtx->drawPitch = newCtx->tridentScreen->backPitch;
333
334 _mesa_make_current( newCtx->glCtx,
335 (GLframebuffer *) driDrawPriv->driverPrivate,
336 (GLframebuffer *) driReadPriv->driverPrivate );
337
338 if (!newCtx->glCtx->Viewport.Width) {
339 _mesa_set_viewport(newCtx->glCtx, 0, 0,
340 driDrawPriv->w, driDrawPriv->h);
341 }
342 } else {
343 _mesa_make_current( NULL, NULL, NULL );
344 }
345 return GL_TRUE;
346 }
347
348
349 static GLboolean
350 tridentUnbindContext( __DRIcontextPrivate *driContextPriv )
351 {
352 return GL_TRUE;
353 }
354
355
356 tridentScreenPtr tridentCreateScreen( __DRIscreenPrivate *sPriv )
357 {
358 TRIDENTDRIPtr tDRIPriv = (TRIDENTDRIPtr)sPriv->pDevPriv;
359 tridentScreenPtr tridentScreen;
360
361
362 /* Allocate the private area */
363 tridentScreen = (tridentScreenPtr) CALLOC( sizeof(*tridentScreen) );
364 if ( !tridentScreen ) return NULL;
365
366 tridentScreen->driScreen = sPriv;
367
368 tridentScreen->frontOffset = tDRIPriv->frontOffset;
369 tridentScreen->backOffset = tDRIPriv->backOffset;
370 tridentScreen->depthOffset = tDRIPriv->depthOffset;
371 tridentScreen->frontPitch = tDRIPriv->frontPitch;
372 tridentScreen->backPitch = tDRIPriv->backPitch;
373 tridentScreen->depthPitch = tDRIPriv->depthPitch;
374 tridentScreen->width = tDRIPriv->width;
375 tridentScreen->height = tDRIPriv->height;
376
377 printf("%d %d\n",tridentScreen->width,tridentScreen->height);
378 printf("%d %d\n",tridentScreen->frontPitch,tridentScreen->backPitch);
379 printf("offset 0x%x 0x%x\n",tridentScreen->backOffset,tridentScreen->depthOffset);
380
381 tridentScreen->mmio.handle = tDRIPriv->regs;
382 tridentScreen->mmio.size = 0x20000;
383
384 if (drmMap(sPriv->fd,
385 tridentScreen->mmio.handle, tridentScreen->mmio.size,
386 (drmAddressPtr)&tridentScreen->mmio.map)) {
387 FREE(tridentScreen);
388 return GL_FALSE;
389 }
390 printf("MAPPED at %p\n", tridentScreen->mmio.map);
391
392 return tridentScreen;
393 }
394
395 /* Destroy the device specific screen private data struct.
396 */
397 void tridentDestroyScreen( __DRIscreenPrivate *sPriv )
398 {
399 tridentScreenPtr tridentScreen = (tridentScreenPtr)sPriv->private;
400
401 FREE(tridentScreen);
402 }
403 static GLboolean
404 tridentInitDriver(__DRIscreenPrivate *sPriv)
405 {
406 sPriv->private = (void *) tridentCreateScreen( sPriv );
407
408 if (!sPriv->private) {
409 tridentDestroyScreen( sPriv );
410 return GL_FALSE;
411 }
412
413 return GL_TRUE;
414 }
415
416 static struct __DriverAPIRec tridentAPI = {
417 tridentInitDriver,
418 tridentDestroyScreen,
419 tridentCreateContext,
420 tridentDestroyContext,
421 tridentCreateBuffer,
422 tridentDestroyBuffer,
423 tridentSwapBuffers,
424 tridentMakeCurrent,
425 tridentUnbindContext,
426 };
427
428
429 PUBLIC void *__driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn,
430 __DRIscreen *psc,
431 const __GLcontextModes * modes,
432 const __DRIversion * ddx_version,
433 const __DRIversion * dri_version,
434 const __DRIversion * drm_version,
435 const __DRIframebuffer * frame_buffer,
436 drmAddress pSAREA, int fd,
437 int internal_api_version,
438 const __DRIinterfaceMethods * interface,
439 __GLcontextModes ** driver_modes )
440 {
441 __DRIscreenPrivate *psp;
442 static const __DRIversion ddx_expected = { 4, 0, 0 };
443 static const __DRIversion dri_expected = { 3, 1, 0 };
444 static const __DRIversion drm_expected = { 1, 0, 0 };
445
446 dri_interface = interface;
447
448 if ( ! driCheckDriDdxDrmVersions2( "Trident",
449 dri_version, & dri_expected,
450 ddx_version, & ddx_expected,
451 drm_version, & drm_expected ) ) {
452 return NULL;
453 }
454
455 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
456 ddx_version, dri_version, drm_version,
457 frame_buffer, pSAREA, fd,
458 internal_api_version, &tridentAPI);
459
460 if ( psp != NULL ) {
461 #if 0
462 TRIDENTDRIPtr dri_priv = (TRIDENTDRIPtr) psp->pDevPriv;
463 *driver_modes = tridentFillInModes( dri_priv->bytesPerPixel * 8,
464 GL_TRUE );
465 #endif
466 }
467 return (void *) psp;
468 }