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