d92da8f4963c3fe4381f487264cb2f0a4e5d5c71
[mesa.git] / src / mesa / drivers / dri / unichrome / via_context.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file via_context.c
27 *
28 * \author John Sheng (presumably of either VIA Technologies or S3 Graphics)
29 * \author Others at VIA Technologies?
30 * \author Others at S3 Graphics?
31 */
32
33 #include "glheader.h"
34 #include "context.h"
35 #include "matrix.h"
36 #include "state.h"
37 #include "simple_list.h"
38 #include "extensions.h"
39 #include "framebuffer.h"
40 #include "renderbuffer.h"
41
42 #include "swrast/swrast.h"
43 #include "swrast_setup/swrast_setup.h"
44 #include "tnl/tnl.h"
45 #include "array_cache/acache.h"
46
47 #include "tnl/t_pipeline.h"
48
49 #include "drivers/common/driverfuncs.h"
50
51 #include "via_screen.h"
52 #include "via_dri.h"
53
54 #include "via_state.h"
55 #include "via_tex.h"
56 #include "via_span.h"
57 #include "via_tris.h"
58 #include "via_ioctl.h"
59 #include "via_fb.h"
60
61 #include <stdio.h>
62 #include "macros.h"
63 #include "drirenderbuffer.h"
64
65 #define need_GL_ARB_multisample
66 #define need_GL_ARB_point_parameters
67 #define need_GL_EXT_fog_coord
68 #define need_GL_EXT_secondary_color
69 #include "extension_helper.h"
70
71 #define DRIVER_DATE "20060710"
72
73 #include "vblank.h"
74 #include "utils.h"
75
76 GLuint VIA_DEBUG = 0;
77
78 /**
79 * Return various strings for \c glGetString.
80 *
81 * \sa glGetString
82 */
83 static const GLubyte *viaGetString(GLcontext *ctx, GLenum name)
84 {
85 static char buffer[128];
86 unsigned offset;
87
88
89 switch (name) {
90 case GL_VENDOR:
91 return (GLubyte *)"VIA Technology";
92
93 case GL_RENDERER: {
94 static const char * const chipset_names[] = {
95 "UniChrome",
96 "CastleRock (CLE266)",
97 "UniChrome (KM400)",
98 "UniChrome (K8M800)",
99 "UniChrome (PM8x0/CN400)",
100 };
101 struct via_context *vmesa = VIA_CONTEXT(ctx);
102 unsigned id = vmesa->viaScreen->deviceID;
103
104 offset = driGetRendererString( buffer,
105 chipset_names[(id > VIA_PM800) ? 0 : id],
106 DRIVER_DATE, 0 );
107 return (GLubyte *)buffer;
108 }
109
110 default:
111 return NULL;
112 }
113 }
114
115
116 /**
117 * Calculate a width that satisfies the hardware's alignment requirements.
118 * On the Unichrome hardware, each scanline must be aligned to a multiple of
119 * 16 pixels.
120 *
121 * \param width Minimum buffer width, in pixels.
122 *
123 * \returns A pixel width that meets the alignment requirements.
124 */
125 static __inline__ unsigned
126 buffer_align( unsigned width )
127 {
128 return (width + 0x0f) & ~0x0f;
129 }
130
131
132 static void
133 viaDeleteRenderbuffer(struct gl_renderbuffer *rb)
134 {
135 /* Don't free() since we're contained in via_context struct. */
136 }
137
138 static GLboolean
139 viaRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb,
140 GLenum internalFormat, GLuint width, GLuint height)
141 {
142 rb->Width = width;
143 rb->Height = height;
144 rb->InternalFormat = internalFormat;
145 return GL_TRUE;
146 }
147
148
149 static void
150 viaInitRenderbuffer(struct gl_renderbuffer *rb, GLenum format)
151 {
152 const GLuint name = 0;
153
154 _mesa_init_renderbuffer(rb, name);
155
156 /* Make sure we're using a null-valued GetPointer routine */
157 assert(rb->GetPointer(NULL, rb, 0, 0) == NULL);
158
159 rb->InternalFormat = format;
160
161 if (format == GL_RGBA) {
162 /* Color */
163 rb->_BaseFormat = GL_RGBA;
164 rb->DataType = GL_UNSIGNED_BYTE;
165 }
166 else if (format == GL_DEPTH_COMPONENT16) {
167 /* Depth */
168 rb->_BaseFormat = GL_DEPTH_COMPONENT;
169 /* we always Get/Put 32-bit Z values */
170 rb->DataType = GL_UNSIGNED_INT;
171 }
172 else if (format == GL_DEPTH_COMPONENT24) {
173 /* Depth */
174 rb->_BaseFormat = GL_DEPTH_COMPONENT;
175 /* we always Get/Put 32-bit Z values */
176 rb->DataType = GL_UNSIGNED_INT;
177 }
178 else {
179 /* Stencil */
180 ASSERT(format == GL_STENCIL_INDEX8_EXT);
181 rb->_BaseFormat = GL_STENCIL_INDEX;
182 rb->DataType = GL_UNSIGNED_BYTE;
183 }
184
185 rb->Delete = viaDeleteRenderbuffer;
186 rb->AllocStorage = viaRenderbufferStorage;
187 }
188
189
190 /**
191 * Calculate the framebuffer parameters for all buffers (front, back, depth,
192 * and stencil) associated with the specified context.
193 *
194 * \warning
195 * This function also calls \c AllocateBuffer to actually allocate the
196 * buffers.
197 *
198 * \sa AllocateBuffer
199 */
200 static GLboolean
201 calculate_buffer_parameters( struct via_context *vmesa,
202 struct gl_framebuffer *fb )
203 {
204 const unsigned shift = vmesa->viaScreen->bitsPerPixel / 16;
205 const unsigned extra = 32;
206 unsigned w;
207 unsigned h;
208
209 /* Normally, the renderbuffer would be added to the framebuffer just once
210 * when the framebuffer was created. The VIA driver is a bit funny
211 * though in that the front/back/depth renderbuffers are in the per-context
212 * state!
213 * That should be fixed someday.
214 */
215
216 if (!vmesa->front.Base.InternalFormat) {
217 /* do one-time init for the renderbuffers */
218 viaInitRenderbuffer(&vmesa->front.Base, GL_RGBA);
219 viaSetSpanFunctions(&vmesa->front, &fb->Visual);
220 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &vmesa->front.Base);
221
222 if (fb->Visual.doubleBufferMode) {
223 viaInitRenderbuffer(&vmesa->back.Base, GL_RGBA);
224 viaSetSpanFunctions(&vmesa->back, &fb->Visual);
225 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &vmesa->back.Base);
226 }
227
228 if (vmesa->glCtx->Visual.depthBits > 0) {
229 viaInitRenderbuffer(&vmesa->depth.Base,
230 (vmesa->glCtx->Visual.depthBits == 16
231 ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24));
232 viaSetSpanFunctions(&vmesa->depth, &fb->Visual);
233 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &vmesa->depth.Base);
234 }
235
236 if (vmesa->glCtx->Visual.stencilBits > 0) {
237 viaInitRenderbuffer(&vmesa->stencil.Base, GL_STENCIL_INDEX8_EXT);
238 viaSetSpanFunctions(&vmesa->stencil, &fb->Visual);
239 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &vmesa->stencil.Base);
240 }
241 }
242
243 assert(vmesa->front.Base.InternalFormat);
244 assert(vmesa->front.Base.AllocStorage);
245 if (fb->Visual.doubleBufferMode) {
246 assert(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
247 assert(vmesa->front.Base.AllocStorage);
248 }
249 if (fb->Visual.depthBits) {
250 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
251 assert(vmesa->depth.Base.AllocStorage);
252 }
253
254
255 /* Allocate front-buffer */
256 if (vmesa->drawType == GLX_PBUFFER_BIT) {
257 w = vmesa->driDrawable->w;
258 h = vmesa->driDrawable->h;
259
260 vmesa->front.bpp = vmesa->viaScreen->bitsPerPixel;
261 vmesa->front.pitch = buffer_align( w ) << shift; /* bytes, not pixels */
262 vmesa->front.size = vmesa->front.pitch * h;
263
264 if (vmesa->front.map)
265 via_free_draw_buffer(vmesa, &vmesa->front);
266 if (!via_alloc_draw_buffer(vmesa, &vmesa->front))
267 return GL_FALSE;
268
269 } else {
270 w = vmesa->viaScreen->width;
271 h = vmesa->viaScreen->height;
272
273 vmesa->front.bpp = vmesa->viaScreen->bitsPerPixel;
274 vmesa->front.pitch = buffer_align( w ) << shift; /* bytes, not pixels */
275 vmesa->front.size = vmesa->front.pitch * h;
276 if (getenv("ALTERNATE_SCREEN"))
277 vmesa->front.offset = vmesa->front.size;
278 else
279 vmesa->front.offset = 0;
280 vmesa->front.map = (char *) vmesa->driScreen->pFB;
281 }
282
283
284 /* Allocate back-buffer */
285 if (vmesa->hasBack) {
286 vmesa->back.bpp = vmesa->viaScreen->bitsPerPixel;
287 vmesa->back.pitch = (buffer_align( vmesa->driDrawable->w ) << shift);
288 vmesa->back.pitch += extra;
289 vmesa->back.pitch = MIN2(vmesa->back.pitch, vmesa->front.pitch);
290 vmesa->back.size = vmesa->back.pitch * vmesa->driDrawable->h;
291 if (vmesa->back.map)
292 via_free_draw_buffer(vmesa, &vmesa->back);
293 if (!via_alloc_draw_buffer(vmesa, &vmesa->back))
294 return GL_FALSE;
295 }
296 else {
297 if (vmesa->back.map)
298 via_free_draw_buffer(vmesa, &vmesa->back);
299 (void) memset( &vmesa->back, 0, sizeof( vmesa->back ) );
300 }
301
302
303 /* Allocate depth-buffer */
304 if ( vmesa->hasStencil || vmesa->hasDepth ) {
305 vmesa->depth.bpp = vmesa->depthBits;
306 if (vmesa->depth.bpp == 24)
307 vmesa->depth.bpp = 32;
308
309 vmesa->depth.pitch = (buffer_align( vmesa->driDrawable->w ) *
310 (vmesa->depth.bpp/8)) + extra;
311 vmesa->depth.size = vmesa->depth.pitch * vmesa->driDrawable->h;
312
313 if (vmesa->depth.map)
314 via_free_draw_buffer(vmesa, &vmesa->depth);
315 if (!via_alloc_draw_buffer(vmesa, &vmesa->depth)) {
316 return GL_FALSE;
317 }
318 }
319 else {
320 if (vmesa->depth.map)
321 via_free_draw_buffer(vmesa, &vmesa->depth);
322 (void) memset( & vmesa->depth, 0, sizeof( vmesa->depth ) );
323 }
324
325 /* stencil buffer is same as depth buffer */
326 vmesa->stencil.handle = vmesa->depth.handle;
327 vmesa->stencil.size = vmesa->depth.size;
328 vmesa->stencil.offset = vmesa->depth.offset;
329 vmesa->stencil.index = vmesa->depth.index;
330 vmesa->stencil.pitch = vmesa->depth.pitch;
331 vmesa->stencil.bpp = vmesa->depth.bpp;
332 vmesa->stencil.map = vmesa->depth.map;
333 vmesa->stencil.orig = vmesa->depth.orig;
334 vmesa->stencil.origMap = vmesa->depth.origMap;
335
336 if( vmesa->viaScreen->width == vmesa->driDrawable->w &&
337 vmesa->viaScreen->height == vmesa->driDrawable->h ) {
338 vmesa->doPageFlip = vmesa->allowPageFlip;
339 if (vmesa->hasBack) {
340 assert(vmesa->back.pitch == vmesa->front.pitch);
341 }
342 }
343 else
344 vmesa->doPageFlip = GL_FALSE;
345
346 return GL_TRUE;
347 }
348
349
350 void viaReAllocateBuffers(GLcontext *ctx, GLframebuffer *drawbuffer,
351 GLuint width, GLuint height)
352 {
353 struct via_context *vmesa = VIA_CONTEXT(ctx);
354
355 calculate_buffer_parameters( vmesa, drawbuffer );
356
357 _mesa_resize_framebuffer(ctx, drawbuffer, width, height);
358 }
359
360 static void viaBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
361 {
362 GET_CURRENT_CONTEXT(ctx);
363 struct via_context *vmesa = VIA_CONTEXT(ctx);
364 *width = vmesa->driDrawable->w;
365 *height = vmesa->driDrawable->h;
366 }
367
368 /* Extension strings exported by the Unichrome driver.
369 */
370 const struct dri_extension card_extensions[] =
371 {
372 { "GL_ARB_multisample", GL_ARB_multisample_functions },
373 { "GL_ARB_multitexture", NULL },
374 { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
375 { "GL_ARB_texture_env_add", NULL },
376 { "GL_ARB_texture_env_combine", NULL },
377 /* { "GL_ARB_texture_env_dot3", NULL }, */
378 { "GL_ARB_texture_mirrored_repeat", NULL },
379 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
380 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
381 { "GL_EXT_stencil_wrap", NULL },
382 { "GL_EXT_texture_env_combine", NULL },
383 /* { "GL_EXT_texture_env_dot3", NULL }, */
384 { "GL_EXT_texture_lod_bias", NULL },
385 { "GL_NV_blend_square", NULL },
386 { NULL, NULL }
387 };
388
389 extern const struct tnl_pipeline_stage _via_fastrender_stage;
390 extern const struct tnl_pipeline_stage _via_render_stage;
391
392 static const struct tnl_pipeline_stage *via_pipeline[] = {
393 &_tnl_vertex_transform_stage,
394 &_tnl_normal_transform_stage,
395 &_tnl_lighting_stage,
396 &_tnl_fog_coordinate_stage,
397 &_tnl_texgen_stage,
398 &_tnl_texture_transform_stage,
399 /* REMOVE: point attenuation stage */
400 #if 1
401 &_via_fastrender_stage, /* ADD: unclipped rastersetup-to-dma */
402 #endif
403 &_tnl_render_stage,
404 0,
405 };
406
407
408 static const struct dri_debug_control debug_control[] =
409 {
410 { "fall", DEBUG_FALLBACKS },
411 { "tex", DEBUG_TEXTURE },
412 { "ioctl", DEBUG_IOCTL },
413 { "prim", DEBUG_PRIMS },
414 { "vert", DEBUG_VERTS },
415 { "state", DEBUG_STATE },
416 { "verb", DEBUG_VERBOSE },
417 { "dri", DEBUG_DRI },
418 { "dma", DEBUG_DMA },
419 { "san", DEBUG_SANITY },
420 { "sync", DEBUG_SYNC },
421 { "sleep", DEBUG_SLEEP },
422 { "pix", DEBUG_PIXEL },
423 { "2d", DEBUG_2D },
424 { NULL, 0 }
425 };
426
427
428 static GLboolean
429 AllocateDmaBuffer(struct via_context *vmesa)
430 {
431 if (vmesa->dma)
432 via_free_dma_buffer(vmesa);
433
434 if (!via_alloc_dma_buffer(vmesa))
435 return GL_FALSE;
436
437 vmesa->dmaLow = 0;
438 vmesa->dmaCliprectAddr = ~0;
439 return GL_TRUE;
440 }
441
442 static void
443 FreeBuffer(struct via_context *vmesa)
444 {
445 if (vmesa->front.map && vmesa->drawType == GLX_PBUFFER_BIT)
446 via_free_draw_buffer(vmesa, &vmesa->front);
447
448 if (vmesa->back.map)
449 via_free_draw_buffer(vmesa, &vmesa->back);
450
451 if (vmesa->depth.map)
452 via_free_draw_buffer(vmesa, &vmesa->depth);
453
454 if (vmesa->breadcrumb.map)
455 via_free_draw_buffer(vmesa, &vmesa->breadcrumb);
456
457 if (vmesa->dma)
458 via_free_dma_buffer(vmesa);
459 }
460
461
462 GLboolean
463 viaCreateContext(const __GLcontextModes *visual,
464 __DRIcontextPrivate *driContextPriv,
465 void *sharedContextPrivate)
466 {
467 GLcontext *ctx, *shareCtx;
468 struct via_context *vmesa;
469 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
470 viaScreenPrivate *viaScreen = (viaScreenPrivate *)sPriv->private;
471 drm_via_sarea_t *saPriv = (drm_via_sarea_t *)
472 (((GLubyte *)sPriv->pSAREA) + viaScreen->sareaPrivOffset);
473 struct dd_function_table functions;
474
475 /* Allocate via context */
476 vmesa = (struct via_context *) CALLOC_STRUCT(via_context);
477 if (!vmesa) {
478 return GL_FALSE;
479 }
480
481 /* Parse configuration files.
482 */
483 driParseConfigFiles (&vmesa->optionCache, &viaScreen->optionCache,
484 sPriv->myNum, "via");
485
486 /* pick back buffer */
487 vmesa->hasBack = visual->doubleBufferMode;
488
489 switch(visual->depthBits) {
490 case 0:
491 vmesa->hasDepth = GL_FALSE;
492 vmesa->depthBits = 0;
493 vmesa->depth_max = 1.0;
494 break;
495 case 16:
496 vmesa->hasDepth = GL_TRUE;
497 vmesa->depthBits = visual->depthBits;
498 vmesa->have_hw_stencil = GL_FALSE;
499 vmesa->depth_max = (GLfloat)0xffff;
500 vmesa->depth_clear_mask = 0xf << 28;
501 vmesa->ClearDepth = 0xffff;
502 vmesa->polygon_offset_scale = 1.0 / vmesa->depth_max;
503 break;
504 case 24:
505 vmesa->hasDepth = GL_TRUE;
506 vmesa->depthBits = visual->depthBits;
507 vmesa->depth_max = (GLfloat) 0xffffff;
508 vmesa->depth_clear_mask = 0xe << 28;
509 vmesa->ClearDepth = 0xffffff00;
510
511 assert(visual->haveStencilBuffer);
512 assert(visual->stencilBits == 8);
513
514 vmesa->have_hw_stencil = GL_TRUE;
515 vmesa->stencilBits = visual->stencilBits;
516 vmesa->stencil_clear_mask = 0x1 << 28;
517 vmesa->polygon_offset_scale = 2.0 / vmesa->depth_max;
518 break;
519 case 32:
520 vmesa->hasDepth = GL_TRUE;
521 vmesa->depthBits = visual->depthBits;
522 assert(!visual->haveStencilBuffer);
523 vmesa->have_hw_stencil = GL_FALSE;
524 vmesa->depth_max = (GLfloat)0xffffffff;
525 vmesa->depth_clear_mask = 0xf << 28;
526 vmesa->ClearDepth = 0xffffffff;
527 vmesa->polygon_offset_scale = 2.0 / vmesa->depth_max;
528 break;
529 default:
530 assert(0);
531 break;
532 }
533
534 make_empty_list(&vmesa->freed_tex_buffers);
535 make_empty_list(&vmesa->tex_image_list[VIA_MEM_VIDEO]);
536 make_empty_list(&vmesa->tex_image_list[VIA_MEM_AGP]);
537 make_empty_list(&vmesa->tex_image_list[VIA_MEM_SYSTEM]);
538
539 _mesa_init_driver_functions(&functions);
540 viaInitTextureFuncs(&functions);
541
542 /* Allocate the Mesa context */
543 if (sharedContextPrivate)
544 shareCtx = ((struct via_context *) sharedContextPrivate)->glCtx;
545 else
546 shareCtx = NULL;
547
548 vmesa->glCtx = _mesa_create_context(visual, shareCtx, &functions,
549 (void*) vmesa);
550
551 vmesa->shareCtx = shareCtx;
552
553 if (!vmesa->glCtx) {
554 FREE(vmesa);
555 return GL_FALSE;
556 }
557 driContextPriv->driverPrivate = vmesa;
558
559 ctx = vmesa->glCtx;
560
561 ctx->Const.MaxTextureLevels = 11;
562 ctx->Const.MaxTextureUnits = 2;
563 ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
564 ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
565
566 ctx->Const.MinLineWidth = 1.0;
567 ctx->Const.MinLineWidthAA = 1.0;
568 ctx->Const.MaxLineWidth = 1.0;
569 ctx->Const.MaxLineWidthAA = 1.0;
570 ctx->Const.LineWidthGranularity = 1.0;
571
572 ctx->Const.MinPointSize = 1.0;
573 ctx->Const.MinPointSizeAA = 1.0;
574 ctx->Const.MaxPointSize = 1.0;
575 ctx->Const.MaxPointSizeAA = 1.0;
576 ctx->Const.PointSizeGranularity = 1.0;
577
578 ctx->Driver.GetBufferSize = viaBufferSize;
579 /* ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; *//* FIXME ?? */
580 ctx->Driver.GetString = viaGetString;
581
582 ctx->DriverCtx = (void *)vmesa;
583 vmesa->glCtx = ctx;
584
585 /* Initialize the software rasterizer and helper modules.
586 */
587 _swrast_CreateContext(ctx);
588 _ac_CreateContext(ctx);
589 _tnl_CreateContext(ctx);
590 _swsetup_CreateContext(ctx);
591
592 /* Install the customized pipeline:
593 */
594 _tnl_destroy_pipeline(ctx);
595 _tnl_install_pipeline(ctx, via_pipeline);
596
597 /* Configure swrast and T&L to match hardware characteristics:
598 */
599 _swrast_allow_pixel_fog(ctx, GL_FALSE);
600 _swrast_allow_vertex_fog(ctx, GL_TRUE);
601 _tnl_allow_pixel_fog(ctx, GL_FALSE);
602 _tnl_allow_vertex_fog(ctx, GL_TRUE);
603
604 /* vmesa->display = dpy; */
605 vmesa->display = sPriv->display;
606
607 vmesa->hHWContext = driContextPriv->hHWContext;
608 vmesa->driFd = sPriv->fd;
609 vmesa->driHwLock = &sPriv->pSAREA->lock;
610
611 vmesa->viaScreen = viaScreen;
612 vmesa->driScreen = sPriv;
613 vmesa->sarea = saPriv;
614
615 vmesa->renderIndex = ~0;
616 vmesa->setupIndex = ~0;
617 vmesa->hwPrimitive = GL_POLYGON+1;
618
619 /* KW: Hardwire this. Was previously set bogusly in
620 * viaCreateBuffer. Needs work before PBUFFER can be used:
621 */
622 vmesa->drawType = GLX_WINDOW_BIT;
623
624
625 _math_matrix_ctr(&vmesa->ViewportMatrix);
626
627 /* Do this early, before VIA_FLUSH_DMA can be called:
628 */
629 if (!AllocateDmaBuffer(vmesa)) {
630 fprintf(stderr ,"AllocateDmaBuffer fail\n");
631 FreeBuffer(vmesa);
632 FREE(vmesa);
633 return GL_FALSE;
634 }
635
636 /* Allocate a small piece of fb memory for synchronization:
637 */
638 vmesa->breadcrumb.bpp = 32;
639 vmesa->breadcrumb.pitch = buffer_align( 64 ) << 2;
640 vmesa->breadcrumb.size = vmesa->breadcrumb.pitch;
641
642 if (!via_alloc_draw_buffer(vmesa, &vmesa->breadcrumb)) {
643 fprintf(stderr ,"AllocateDmaBuffer fail\n");
644 FreeBuffer(vmesa);
645 FREE(vmesa);
646 return GL_FALSE;
647 }
648
649 driInitExtensions( ctx, card_extensions, GL_TRUE );
650 viaInitStateFuncs(ctx);
651 viaInitTriFuncs(ctx);
652 viaInitSpanFuncs(ctx);
653 viaInitIoctlFuncs(ctx);
654 viaInitState(ctx);
655
656 if (getenv("VIA_DEBUG"))
657 VIA_DEBUG = driParseDebugString( getenv( "VIA_DEBUG" ),
658 debug_control );
659
660 if (getenv("VIA_NO_RAST"))
661 FALLBACK(vmesa, VIA_FALLBACK_USER_DISABLE, 1);
662
663 /* I don't understand why this isn't working:
664 */
665 vmesa->vblank_flags =
666 vmesa->viaScreen->irqEnabled ?
667 driGetDefaultVBlankFlags(&vmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
668
669 /* Hack this up in its place:
670 */
671 vmesa->vblank_flags = (getenv("VIA_VSYNC") ?
672 VBLANK_FLAG_SYNC : VBLANK_FLAG_NO_IRQ);
673
674 if (getenv("VIA_PAGEFLIP"))
675 vmesa->allowPageFlip = 1;
676
677 (*dri_interface->getUST)( &vmesa->swap_ust );
678
679
680 vmesa->regMMIOBase = (GLuint *)((unsigned long)viaScreen->reg);
681 vmesa->pnGEMode = (GLuint *)((unsigned long)viaScreen->reg + 0x4);
682 vmesa->regEngineStatus = (GLuint *)((unsigned long)viaScreen->reg + 0x400);
683 vmesa->regTranSet = (GLuint *)((unsigned long)viaScreen->reg + 0x43C);
684 vmesa->regTranSpace = (GLuint *)((unsigned long)viaScreen->reg + 0x440);
685 vmesa->agpBase = viaScreen->agpBase;
686
687
688 return GL_TRUE;
689 }
690
691 void
692 viaDestroyContext(__DRIcontextPrivate *driContextPriv)
693 {
694 GET_CURRENT_CONTEXT(ctx);
695 struct via_context *vmesa =
696 (struct via_context *)driContextPriv->driverPrivate;
697 struct via_context *current = ctx ? VIA_CONTEXT(ctx) : NULL;
698 assert(vmesa); /* should never be null */
699
700 /* check if we're deleting the currently bound context */
701 if (vmesa == current) {
702 VIA_FLUSH_DMA(vmesa);
703 _mesa_make_current(NULL, NULL, NULL);
704 }
705
706 if (vmesa) {
707 viaWaitIdle(vmesa, GL_FALSE);
708 if (vmesa->doPageFlip) {
709 LOCK_HARDWARE(vmesa);
710 if (vmesa->pfCurrentOffset != 0) {
711 fprintf(stderr, "%s - reset pf\n", __FUNCTION__);
712 viaResetPageFlippingLocked(vmesa);
713 }
714 UNLOCK_HARDWARE(vmesa);
715 }
716
717 _swsetup_DestroyContext(vmesa->glCtx);
718 _tnl_DestroyContext(vmesa->glCtx);
719 _ac_DestroyContext(vmesa->glCtx);
720 _swrast_DestroyContext(vmesa->glCtx);
721 /* free the Mesa context */
722 _mesa_destroy_context(vmesa->glCtx);
723 /* release our data */
724 FreeBuffer(vmesa);
725
726 assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_AGP]));
727 assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_VIDEO]));
728 assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_SYSTEM]));
729 assert (is_empty_list(&vmesa->freed_tex_buffers));
730
731 FREE(vmesa);
732 }
733 }
734
735
736 void viaXMesaWindowMoved(struct via_context *vmesa)
737 {
738 __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
739 GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
740
741 if (!dPriv)
742 return;
743
744 switch (vmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) {
745 case BUFFER_BIT_BACK_LEFT:
746 if (dPriv->numBackClipRects == 0) {
747 vmesa->numClipRects = dPriv->numClipRects;
748 vmesa->pClipRects = dPriv->pClipRects;
749 }
750 else {
751 vmesa->numClipRects = dPriv->numBackClipRects;
752 vmesa->pClipRects = dPriv->pBackClipRects;
753 }
754 break;
755 case BUFFER_BIT_FRONT_LEFT:
756 vmesa->numClipRects = dPriv->numClipRects;
757 vmesa->pClipRects = dPriv->pClipRects;
758 break;
759 default:
760 vmesa->numClipRects = 0;
761 break;
762 }
763
764 if (vmesa->drawW != dPriv->w ||
765 vmesa->drawH != dPriv->h)
766 calculate_buffer_parameters( vmesa, vmesa->glCtx->DrawBuffer );
767
768 vmesa->drawXoff = (GLuint)(((dPriv->x * bytePerPixel) & 0x1f) /
769 bytePerPixel);
770 vmesa->drawX = dPriv->x - vmesa->drawXoff;
771 vmesa->drawY = dPriv->y;
772 vmesa->drawW = dPriv->w;
773 vmesa->drawH = dPriv->h;
774
775 vmesa->front.orig = (vmesa->front.offset +
776 vmesa->drawY * vmesa->front.pitch +
777 vmesa->drawX * bytePerPixel);
778
779 vmesa->front.origMap = (vmesa->front.map +
780 vmesa->drawY * vmesa->front.pitch +
781 vmesa->drawX * bytePerPixel);
782
783 vmesa->back.orig = vmesa->back.offset;
784 vmesa->depth.orig = vmesa->depth.offset;
785 vmesa->back.origMap = vmesa->back.map;
786 vmesa->depth.origMap = vmesa->depth.map;
787
788 viaCalcViewport(vmesa->glCtx);
789 }
790
791 GLboolean
792 viaUnbindContext(__DRIcontextPrivate *driContextPriv)
793 {
794 return GL_TRUE;
795 }
796
797 GLboolean
798 viaMakeCurrent(__DRIcontextPrivate *driContextPriv,
799 __DRIdrawablePrivate *driDrawPriv,
800 __DRIdrawablePrivate *driReadPriv)
801 {
802 if (VIA_DEBUG & DEBUG_DRI) {
803 fprintf(stderr, "driContextPriv = %016lx\n", (unsigned long)driContextPriv);
804 fprintf(stderr, "driDrawPriv = %016lx\n", (unsigned long)driDrawPriv);
805 fprintf(stderr, "driReadPriv = %016lx\n", (unsigned long)driReadPriv);
806 }
807
808 if (driContextPriv) {
809 struct via_context *vmesa =
810 (struct via_context *)driContextPriv->driverPrivate;
811 GLcontext *ctx = vmesa->glCtx;
812 struct gl_framebuffer *drawBuffer, *readBuffer;
813
814 drawBuffer = (GLframebuffer *)driDrawPriv->driverPrivate;
815 readBuffer = (GLframebuffer *)driReadPriv->driverPrivate;
816
817 if ( vmesa->driDrawable != driDrawPriv ) {
818 driDrawableInitVBlank( driDrawPriv, vmesa->vblank_flags,
819 &vmesa->vbl_seq );
820 vmesa->driDrawable = driDrawPriv;
821 if ( ! calculate_buffer_parameters( vmesa, drawBuffer ) ) {
822 return GL_FALSE;
823 }
824 }
825
826 _mesa_make_current(vmesa->glCtx, drawBuffer, readBuffer);
827
828 ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
829
830 viaXMesaWindowMoved(vmesa);
831 ctx->Driver.Scissor(vmesa->glCtx,
832 vmesa->glCtx->Scissor.X,
833 vmesa->glCtx->Scissor.Y,
834 vmesa->glCtx->Scissor.Width,
835 vmesa->glCtx->Scissor.Height);
836 }
837 else {
838 _mesa_make_current(NULL, NULL, NULL);
839 }
840
841 return GL_TRUE;
842 }
843
844 void viaGetLock(struct via_context *vmesa, GLuint flags)
845 {
846 __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
847 __DRIscreenPrivate *sPriv = vmesa->driScreen;
848
849 drmGetLock(vmesa->driFd, vmesa->hHWContext, flags);
850
851 DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
852
853 if (vmesa->sarea->ctxOwner != vmesa->hHWContext) {
854 vmesa->sarea->ctxOwner = vmesa->hHWContext;
855 vmesa->newEmitState = ~0;
856 }
857
858 if (vmesa->lastStamp != dPriv->lastStamp) {
859 viaXMesaWindowMoved(vmesa);
860 driUpdateFramebufferSize(vmesa->glCtx, dPriv);
861 vmesa->newEmitState = ~0;
862 vmesa->lastStamp = dPriv->lastStamp;
863 }
864
865 if (vmesa->doPageFlip &&
866 vmesa->pfCurrentOffset != vmesa->sarea->pfCurrentOffset) {
867 fprintf(stderr, "%s - reset pf\n", __FUNCTION__);
868 viaResetPageFlippingLocked(vmesa);
869 }
870 }
871
872
873 void
874 viaSwapBuffers(__DRIdrawablePrivate *drawablePrivate)
875 {
876 __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *)drawablePrivate;
877
878 if (dPriv &&
879 dPriv->driContextPriv &&
880 dPriv->driContextPriv->driverPrivate) {
881 struct via_context *vmesa =
882 (struct via_context *)dPriv->driContextPriv->driverPrivate;
883 GLcontext *ctx = vmesa->glCtx;
884
885 _mesa_notifySwapBuffers(ctx);
886
887 if (ctx->Visual.doubleBufferMode) {
888 if (vmesa->doPageFlip) {
889 viaPageFlip(dPriv);
890 }
891 else {
892 viaCopyBuffer(dPriv);
893 }
894 }
895 else
896 VIA_FLUSH_DMA(vmesa);
897 }
898 else {
899 _mesa_problem(NULL, "viaSwapBuffers: drawable has no context!\n");
900 }
901 }