Make GL_ARB_draw_buffers mandatory
[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 "vbo/vbo.h"
34
35 #include "tnl/tnl.h"
36 #include "tnl/t_pipeline.h"
37
38 #include "main/context.h"
39 #include "main/simple_list.h"
40 #include "main/matrix.h"
41 #include "main/extensions.h"
42 #include "main/framebuffer.h"
43 #include "main/renderbuffer.h"
44 #if defined(USE_X86_ASM)
45 #include "x86/common_x86_asm.h"
46 #endif
47 #include "main/simple_list.h"
48 #include "main/mm.h"
49 #include "drirenderbuffer.h"
50
51 #include "drivers/common/driverfuncs.h"
52 #include "dri_util.h"
53 #include "utils.h"
54
55 static const struct tnl_pipeline_stage *trident_pipeline[] = {
56 &_tnl_vertex_transform_stage,
57 &_tnl_normal_transform_stage,
58 &_tnl_lighting_stage,
59 &_tnl_texgen_stage,
60 &_tnl_texture_transform_stage,
61 &_tnl_render_stage,
62 0,
63 };
64
65
66 static GLboolean
67 tridentCreateContext( const __GLcontextModes *glVisual,
68 __DRIcontextPrivate *driContextPriv,
69 void *sharedContextPrivate)
70 {
71 GLcontext *ctx, *shareCtx;
72 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
73 tridentContextPtr tmesa;
74 tridentScreenPtr tridentscrn;
75 struct dd_function_table functions;
76 #if 0
77 drm_trident_sarea_t *saPriv=(drm_trident_sarea_t *)(((char*)sPriv->pSAREA)+
78 sizeof(XF86DRISAREARec));
79 #endif
80
81 tmesa = (tridentContextPtr) CALLOC( sizeof(*tmesa) );
82 if ( !tmesa ) return GL_FALSE;
83
84 /* Allocate the Mesa context */
85 if (sharedContextPrivate)
86 shareCtx = ((tridentContextPtr) sharedContextPrivate)->glCtx;
87 else
88 shareCtx = NULL;
89
90 _mesa_init_driver_functions(&functions);
91
92 tmesa->glCtx =
93 _mesa_create_context(glVisual, shareCtx, &functions, (void *)tmesa);
94
95 if (!tmesa->glCtx) {
96 FREE(tmesa);
97 return GL_FALSE;
98 }
99
100 tmesa->driContext = driContextPriv;
101 tmesa->driScreen = sPriv;
102 tmesa->driDrawable = NULL; /* Set by XMesaMakeCurrent */
103
104 tmesa->hHWContext = driContextPriv->hHWContext;
105 tmesa->driHwLock = (drmLock *)&sPriv->pSAREA->lock;
106 tmesa->driFd = sPriv->fd;
107 #if 0
108 tmesa->sarea = saPriv;
109 #endif
110
111 tridentscrn = tmesa->tridentScreen = (tridentScreenPtr)(sPriv->private);
112
113 ctx = tmesa->glCtx;
114
115 ctx->Const.MaxTextureLevels = 13; /* 4K by 4K? Is that right? */
116 ctx->Const.MaxTextureUnits = 1; /* Permedia 3 */
117
118 ctx->Const.MinLineWidth = 0.0;
119 ctx->Const.MaxLineWidth = 255.0;
120
121 ctx->Const.MinLineWidthAA = 0.0;
122 ctx->Const.MaxLineWidthAA = 65536.0;
123
124 ctx->Const.MinPointSize = 0.0;
125 ctx->Const.MaxPointSize = 255.0;
126
127 ctx->Const.MinPointSizeAA = 0.5; /* 4x4 quality mode */
128 ctx->Const.MaxPointSizeAA = 16.0;
129 ctx->Const.PointSizeGranularity = 0.25;
130
131 ctx->Const.MaxDrawBuffers = 1;
132
133 #if 0
134 tmesa->texHeap = mmInit( 0, tmesa->tridentScreen->textureSize );
135
136 make_empty_list(&tmesa->TexObjList);
137 make_empty_list(&tmesa->SwappedOut);
138
139 tmesa->CurrentTexObj[0] = 0;
140 tmesa->CurrentTexObj[1] = 0; /* Permedia 3, second texture */
141
142 tmesa->RenderIndex = ~0;
143 #endif
144
145 /* Initialize the software rasterizer and helper modules.
146 */
147 _swrast_CreateContext( ctx );
148 _vbo_CreateContext( ctx );
149 _tnl_CreateContext( ctx );
150 _swsetup_CreateContext( ctx );
151
152 /* Install the customized pipeline:
153 */
154 _tnl_destroy_pipeline( ctx );
155 _tnl_install_pipeline( ctx, trident_pipeline );
156
157 /* Configure swrast to match hardware characteristics:
158 */
159 _swrast_allow_pixel_fog( ctx, GL_FALSE );
160 _swrast_allow_vertex_fog( ctx, GL_TRUE );
161
162 tridentInitVB( ctx );
163 tridentDDInitExtensions( ctx );
164 tridentDDInitDriverFuncs( ctx );
165 tridentDDInitStateFuncs( ctx );
166 #if 0
167 tridentDDInitSpanFuncs( ctx );
168 tridentDDInitTextureFuncs( ctx );
169 #endif
170 tridentDDInitTriFuncs( ctx );
171 tridentDDInitState( tmesa );
172
173 driContextPriv->driverPrivate = (void *)tmesa;
174
175 UNLOCK_HARDWARE(tmesa);
176
177 return GL_TRUE;
178 }
179
180 static void
181 tridentDestroyContext(__DRIcontextPrivate *driContextPriv)
182 {
183 tridentContextPtr tmesa = (tridentContextPtr)driContextPriv->driverPrivate;
184
185 if (tmesa) {
186 _swsetup_DestroyContext( tmesa->glCtx );
187 _tnl_DestroyContext( tmesa->glCtx );
188 _vbo_DestroyContext( tmesa->glCtx );
189 _swrast_DestroyContext( tmesa->glCtx );
190
191 /* free the Mesa context */
192 tmesa->glCtx->DriverCtx = NULL;
193 _mesa_destroy_context(tmesa->glCtx);
194
195 _mesa_free(tmesa);
196 driContextPriv->driverPrivate = NULL;
197 }
198 }
199
200
201 static GLboolean
202 tridentCreateBuffer( __DRIscreenPrivate *driScrnPriv,
203 __DRIdrawablePrivate *driDrawPriv,
204 const __GLcontextModes *mesaVis,
205 GLboolean isPixmap )
206 {
207 tridentScreenPtr screen = (tridentScreenPtr) driScrnPriv->private;
208
209 if (isPixmap) {
210 return GL_FALSE; /* not implemented */
211 }
212 else {
213 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
214
215 {
216 driRenderbuffer *frontRb
217 = driNewRenderbuffer(GL_RGBA, NULL, screen->cpp,
218 screen->frontOffset, screen->frontPitch,
219 driDrawPriv);
220 /*
221 tridentSetSpanFunctions(frontRb, mesaVis);
222 */
223 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
224 }
225
226 if (mesaVis->doubleBufferMode) {
227 driRenderbuffer *backRb
228 = driNewRenderbuffer(GL_RGBA, NULL, screen->cpp,
229 screen->backOffset, screen->backPitch,
230 driDrawPriv);
231 /*
232 tridentSetSpanFunctions(backRb, mesaVis);
233 */
234 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
235 }
236
237 if (mesaVis->depthBits == 16) {
238 driRenderbuffer *depthRb
239 = driNewRenderbuffer(GL_DEPTH_COMPONENT16, NULL, screen->cpp,
240 screen->depthOffset, screen->depthPitch,
241 driDrawPriv);
242 /*
243 tridentSetSpanFunctions(depthRb, mesaVis);
244 */
245 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
246 }
247 else if (mesaVis->depthBits == 24) {
248 driRenderbuffer *depthRb
249 = driNewRenderbuffer(GL_DEPTH_COMPONENT24, NULL, screen->cpp,
250 screen->depthOffset, screen->depthPitch,
251 driDrawPriv);
252 /*
253 tridentSetSpanFunctions(depthRb, mesaVis);
254 */
255 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
256 }
257
258 /* no h/w stencil?
259 if (mesaVis->stencilBits > 0 && !swStencil) {
260 driRenderbuffer *stencilRb
261 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT);
262 tridentSetSpanFunctions(stencilRb, mesaVis);
263 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
264 }
265 */
266
267 _mesa_add_soft_renderbuffers(fb,
268 GL_FALSE, /* color */
269 GL_FALSE, /* depth */
270 mesaVis->stencilBits > 0,
271 mesaVis->accumRedBits > 0,
272 GL_FALSE, /* alpha */
273 GL_FALSE /* aux */);
274 driDrawPriv->driverPrivate = (void *) fb;
275
276 return (driDrawPriv->driverPrivate != NULL);
277 }
278 }
279
280
281 static void
282 tridentDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
283 {
284 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
285 }
286
287 static void
288 tridentSwapBuffers(__DRIdrawablePrivate *drawablePrivate)
289 {
290 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
291
292 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
293 tridentContextPtr tmesa;
294 GLcontext *ctx;
295 tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate;
296 ctx = tmesa->glCtx;
297 if (ctx->Visual.doubleBufferMode) {
298 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
299 tridentCopyBuffer( dPriv );
300 }
301 }
302 else {
303 /* XXX this shouldn't be an error but we can't handle it for now */
304 _mesa_problem(NULL, "tridentSwapBuffers: drawable has no context!\n");
305 }
306 }
307
308 static GLboolean
309 tridentMakeCurrent(__DRIcontextPrivate *driContextPriv,
310 __DRIdrawablePrivate *driDrawPriv,
311 __DRIdrawablePrivate *driReadPriv)
312 {
313 if (driContextPriv) {
314 GET_CURRENT_CONTEXT(ctx);
315 tridentContextPtr oldCtx = ctx ? TRIDENT_CONTEXT(ctx) : NULL;
316 tridentContextPtr newCtx = (tridentContextPtr) driContextPriv->driverPrivate;
317
318 if ( newCtx != oldCtx ) {
319 newCtx->dirty = ~0;
320 }
321
322 if (newCtx->driDrawable != driDrawPriv) {
323 newCtx->driDrawable = driDrawPriv;
324 #if 0
325 tridentUpdateWindow ( newCtx->glCtx );
326 tridentUpdateViewportOffset( newCtx->glCtx );
327 #endif
328 }
329
330 newCtx->drawOffset = newCtx->tridentScreen->backOffset;
331 newCtx->drawPitch = newCtx->tridentScreen->backPitch;
332
333 _mesa_make_current( newCtx->glCtx,
334 (GLframebuffer *) driDrawPriv->driverPrivate,
335 (GLframebuffer *) driReadPriv->driverPrivate );
336
337 if (!newCtx->glCtx->Viewport.Width) {
338 _mesa_set_viewport(newCtx->glCtx, 0, 0,
339 driDrawPriv->w, driDrawPriv->h);
340 }
341 } else {
342 _mesa_make_current( NULL, NULL, NULL );
343 }
344 return GL_TRUE;
345 }
346
347
348 static GLboolean
349 tridentUnbindContext( __DRIcontextPrivate *driContextPriv )
350 {
351 return GL_TRUE;
352 }
353
354
355 static tridentScreenPtr
356 tridentCreateScreen( __DRIscreenPrivate *sPriv )
357 {
358 TRIDENTDRIPtr tDRIPriv = (TRIDENTDRIPtr)sPriv->pDevPriv;
359 tridentScreenPtr tridentScreen;
360
361 if (sPriv->devPrivSize != sizeof(TRIDENTDRIRec)) {
362 fprintf(stderr,"\nERROR! sizeof(TRIDENTDRIRec) does not match passed size from device driver\n");
363 return GL_FALSE;
364 }
365
366 /* Allocate the private area */
367 tridentScreen = (tridentScreenPtr) CALLOC( sizeof(*tridentScreen) );
368 if ( !tridentScreen ) return NULL;
369
370 tridentScreen->driScreen = sPriv;
371
372 tridentScreen->frontOffset = tDRIPriv->frontOffset;
373 tridentScreen->backOffset = tDRIPriv->backOffset;
374 tridentScreen->depthOffset = tDRIPriv->depthOffset;
375 tridentScreen->frontPitch = tDRIPriv->frontPitch;
376 tridentScreen->backPitch = tDRIPriv->backPitch;
377 tridentScreen->depthPitch = tDRIPriv->depthPitch;
378 tridentScreen->width = tDRIPriv->width;
379 tridentScreen->height = tDRIPriv->height;
380
381 printf("%d %d\n",tridentScreen->width,tridentScreen->height);
382 printf("%d %d\n",tridentScreen->frontPitch,tridentScreen->backPitch);
383 printf("offset 0x%x 0x%x\n",tridentScreen->backOffset,tridentScreen->depthOffset);
384
385 tridentScreen->mmio.handle = tDRIPriv->regs;
386 tridentScreen->mmio.size = 0x20000;
387
388 if (drmMap(sPriv->fd,
389 tridentScreen->mmio.handle, tridentScreen->mmio.size,
390 (drmAddressPtr)&tridentScreen->mmio.map)) {
391 FREE(tridentScreen);
392 return GL_FALSE;
393 }
394 printf("MAPPED at %p\n", tridentScreen->mmio.map);
395
396 return tridentScreen;
397 }
398
399 /* Destroy the device specific screen private data struct.
400 */
401 static void
402 tridentDestroyScreen( __DRIscreenPrivate *sPriv )
403 {
404 tridentScreenPtr tridentScreen = (tridentScreenPtr)sPriv->private;
405
406 FREE(tridentScreen);
407 }
408
409 static GLboolean
410 tridentInitDriver(__DRIscreenPrivate *sPriv)
411 {
412 sPriv->private = (void *) tridentCreateScreen( sPriv );
413
414 if (!sPriv->private) {
415 tridentDestroyScreen( sPriv );
416 return GL_FALSE;
417 }
418
419 return GL_TRUE;
420 }
421
422 /**
423 * This is the driver specific part of the createNewScreen entry point.
424 *
425 * \todo maybe fold this into intelInitDriver
426 *
427 * \return the __GLcontextModes supported by this driver
428 */
429 const __DRIconfig **tridentInitScreen(__DRIscreenPrivate *psp)
430 {
431 static const __DRIversion ddx_expected = { 4, 0, 0 };
432 static const __DRIversion dri_expected = { 3, 1, 0 };
433 static const __DRIversion drm_expected = { 1, 0, 0 };
434
435 if ( ! driCheckDriDdxDrmVersions2( "Trident",
436 &psp->dri_version, & dri_expected,
437 &psp->ddx_version, & ddx_expected,
438 &psp->drm_version, & drm_expected ) )
439 return NULL;
440
441 if (!tridentInitDriver(psp))
442 return NULL;
443
444 /* Wait... what? This driver doesn't report any modes... */
445 #if 0
446 TRIDENTDRIPtr dri_priv = (TRIDENTDRIPtr) psp->pDevPriv;
447 *driver_modes = tridentFillInModes( dri_priv->bytesPerPixel * 8,
448 GL_TRUE );
449 #endif
450
451 return NULL;
452 }
453
454 const struct __DriverAPIRec driDriverAPI = {
455 tridentInitScreen,
456 tridentDestroyScreen,
457 tridentCreateContext,
458 tridentDestroyContext,
459 tridentCreateBuffer,
460 tridentDestroyBuffer,
461 tridentSwapBuffers,
462 tridentMakeCurrent,
463 tridentUnbindContext,
464 };