Merge branch 'master' of git+ssh://znh@git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / drivers / dri / mga / mgapixel.c
1 /*
2 * Copyright 2000 Compaq Computer Inc. and VA Linux Systems, Inc.
3 * 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 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * 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 * VA LINUX SYSTEMS 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
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file mgapixel.c
27 * Implement framebuffer pixel operations for MGA.
28 *
29 * \todo
30 * Someday the accelerated \c glReadPixels and \c glDrawPixels paths need to
31 * be resurrected. They are currently ifdef'ed out because they don't seem
32 * to work and they only get activated some very rare circumstances.
33 *
34 * \author Keith Whitwell <keith@tungstengraphics.com>
35 * \author Gareth Hughes <gareth@valinux.com>
36 */
37 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgapixel.c,v 1.9 2002/11/05 17:46:08 tsi Exp $ */
38
39 #include "mtypes.h"
40 #include "macros.h"
41 #include "mgadd.h"
42 #include "mgacontext.h"
43 #include "mgaioctl.h"
44 #include "mgapixel.h"
45 #include "mgastate.h"
46
47 #include "swrast/swrast.h"
48 #include "imports.h"
49
50 #if 0
51 #define IS_AGP_MEM( mmesa, p ) \
52 ((unsigned long)mmesa->mgaScreen->buffers.map <= ((unsigned long)p) && \
53 (unsigned long)mmesa->mgaScreen->buffers.map + \
54 (unsigned long)mmesa->mgaScreen->buffers.size > ((unsigned long)p))
55 #define AGP_OFFSET( mmesa, p ) \
56 (((unsigned long)p) - (unsigned long)mmesa->mgaScreen->buffers.map)
57
58
59 #if defined(MESA_packed_depth_stencil)
60 static GLboolean
61 check_depth_stencil_24_8( const GLcontext *ctx, GLenum type,
62 const struct gl_pixelstore_attrib *packing,
63 const void *pixels, GLint sz,
64 GLint pitch )
65 {
66 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
67
68 return ( type == GL_UNSIGNED_INT_24_8_MESA &&
69 ctx->Visual->DepthBits == 24 &&
70 ctx->Visual->StencilBits == 8 &&
71 mmesa->mgaScreen->cpp == 4 &&
72 mmesa->hw_stencil &&
73 !ctx->Pixel.IndexShift &&
74 !ctx->Pixel.IndexOffset &&
75 !ctx->Pixel.MapStencilFlag &&
76 ctx->Pixel.DepthBias == 0.0 &&
77 ctx->Pixel.DepthScale == 1.0 &&
78 !packing->SwapBytes &&
79 pitch % 32 == 0 &&
80 pitch < 4096 );
81 }
82 #endif
83
84
85 static GLboolean
86 check_depth( const GLcontext *ctx, GLenum type,
87 const struct gl_pixelstore_attrib *packing,
88 const void *pixels, GLint sz, GLint pitch )
89 {
90 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
91
92 if ( IS_AGP_MEM( mmesa, pixels ) &&
93 !( ( type == GL_UNSIGNED_INT && mmesa->mgaScreen->cpp == 4 ) ||
94 ( type == GL_UNSIGNED_SHORT && mmesa->mgaScreen->cpp == 2 ) ) )
95 return GL_FALSE;
96
97 return ( ctx->Pixel.DepthBias == 0.0 &&
98 ctx->Pixel.DepthScale == 1.0 &&
99 !packing->SwapBytes &&
100 pitch % 32 == 0 &&
101 pitch < 4096 );
102 }
103
104
105 static GLboolean
106 check_color( const GLcontext *ctx, GLenum type, GLenum format,
107 const struct gl_pixelstore_attrib *packing,
108 const void *pixels, GLint sz, GLint pitch )
109 {
110 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
111 GLuint cpp = mmesa->mgaScreen->cpp;
112
113 /* Can't do conversions on agp reads/draws.
114 */
115 if ( IS_AGP_MEM( mmesa, pixels ) &&
116 !( pitch % 32 == 0 && pitch < 4096 &&
117 ( ( type == GL_UNSIGNED_BYTE &&
118 cpp == 4 && format == GL_BGRA ) ||
119 ( type == GL_UNSIGNED_INT_8_8_8_8 &&
120 cpp == 4 && format == GL_BGRA ) ||
121 ( type == GL_UNSIGNED_SHORT_5_6_5_REV &&
122 cpp == 2 && format == GL_RGB ) ) ) )
123 return GL_FALSE;
124
125 return (!ctx->_ImageTransferState &&
126 !packing->SwapBytes &&
127 !packing->LsbFirst);
128 }
129
130 static GLboolean
131 check_color_per_fragment_ops( const GLcontext *ctx )
132 {
133 return (!( ctx->Color.AlphaEnabled ||
134 ctx->Depth.Test ||
135 ctx->Fog.Enabled ||
136 ctx->Scissor.Enabled ||
137 ctx->Stencil.Enabled ||
138 !ctx->Color.ColorMask[0] ||
139 !ctx->Color.ColorMask[1] ||
140 !ctx->Color.ColorMask[2] ||
141 !ctx->Color.ColorMask[3] ||
142 ctx->Color.ColorLogicOpEnabled ||
143 ctx->Texture._EnabledUnits
144 ) &&
145 ctx->Current.RasterPosValid &&
146 ctx->Pixel.ZoomX == 1.0F &&
147 (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F));
148 }
149
150 static GLboolean
151 check_depth_per_fragment_ops( const GLcontext *ctx )
152 {
153 return ( ctx->Current.RasterPosValid &&
154 ctx->Color.ColorMask[RCOMP] == 0 &&
155 ctx->Color.ColorMask[BCOMP] == 0 &&
156 ctx->Color.ColorMask[GCOMP] == 0 &&
157 ctx->Color.ColorMask[ACOMP] == 0 &&
158 ctx->Pixel.ZoomX == 1.0F &&
159 ( ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F ) );
160 }
161
162 /* In addition to the requirements for depth:
163 */
164 #if defined(MESA_packed_depth_stencil)
165 static GLboolean
166 check_stencil_per_fragment_ops( const GLcontext *ctx )
167 {
168 return ( !ctx->Pixel.IndexShift &&
169 !ctx->Pixel.IndexOffset );
170 }
171 #endif
172
173
174 static GLboolean
175 clip_pixelrect( const GLcontext *ctx,
176 const GLframebuffer *buffer,
177 GLint *x, GLint *y,
178 GLsizei *width, GLsizei *height,
179 GLint *skipPixels, GLint *skipRows,
180 GLint *size )
181 {
182 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
183
184 *width = MIN2(*width, MAX_WIDTH); /* redundant? */
185
186 /* left clipping */
187 if (*x < buffer->_Xmin) {
188 *skipPixels += (buffer->_Xmin - *x);
189 *width -= (buffer->_Xmin - *x);
190 *x = buffer->_Xmin;
191 }
192
193 /* right clipping */
194 if (*x + *width > buffer->_Xmax)
195 *width -= (*x + *width - buffer->_Xmax - 1);
196
197 if (*width <= 0)
198 return GL_FALSE;
199
200 /* bottom clipping */
201 if (*y < buffer->_Ymin) {
202 *skipRows += (buffer->_Ymin - *y);
203 *height -= (buffer->_Ymin - *y);
204 *y = buffer->_Ymin;
205 }
206
207 /* top clipping */
208 if (*y + *height > buffer->_Ymax)
209 *height -= (*y + *height - buffer->_Ymax - 1);
210
211 if (*height <= 0)
212 return GL_FALSE;
213
214 *size = ((*y + *height - 1) * mmesa->mgaScreen->frontPitch +
215 (*x + *width - 1) * mmesa->mgaScreen->cpp);
216
217 return GL_TRUE;
218 }
219
220 static GLboolean
221 mgaTryReadPixels( GLcontext *ctx,
222 GLint x, GLint y, GLsizei width, GLsizei height,
223 GLenum format, GLenum type,
224 const struct gl_pixelstore_attrib *pack,
225 GLvoid *pixels )
226 {
227 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
228 GLint size, skipPixels, skipRows;
229 GLint pitch = pack->RowLength ? pack->RowLength : width;
230 GLboolean ok;
231
232 GLuint planemask;
233 GLuint source;
234 #if 0
235 drmMGABlit blit;
236 GLuint dest;
237 GLint source_pitch, dest_pitch;
238 GLint delta_sx, delta_sy;
239 GLint delta_dx, delta_dy;
240 GLint blit_height, ydir;
241 #endif
242
243 if (!clip_pixelrect(ctx, ctx->ReadBuffer,
244 &x, &y, &width, &height,
245 &skipPixels, &skipRows, &size)) {
246 return GL_TRUE;
247 }
248
249 /* Only accelerate reading to agp buffers.
250 */
251 if ( !IS_AGP_MEM(mmesa, (char *)pixels) ||
252 !IS_AGP_MEM(mmesa, (char *)pixels + size) )
253 return GL_FALSE;
254
255 switch (format) {
256 #if defined(MESA_packed_depth_stencil)
257 case GL_DEPTH_STENCIL_MESA:
258 ok = check_depth_stencil_24_8(ctx, type, pack, pixels, size, pitch);
259 planemask = ~0;
260 source = mmesa->mgaScreen->depthOffset;
261 break;
262 #endif
263
264 case GL_DEPTH_COMPONENT:
265 ok = check_depth(ctx, type, pack, pixels, size, pitch);
266
267 /* Can't accelerate at this depth -- planemask does the wrong
268 * thing; it doesn't clear the low order bits in the
269 * destination, instead it leaves them untouched.
270 *
271 * Could get the acclerator to solid fill the destination with
272 * zeros first... Or get the cpu to do it...
273 */
274 if (ctx->Visual.depthBits == 24)
275 return GL_FALSE;
276
277 planemask = ~0;
278 source = mmesa->mgaScreen->depthOffset;
279 break;
280
281 case GL_RGB:
282 case GL_BGRA:
283 ok = check_color(ctx, type, format, pack, pixels, size, pitch);
284 planemask = ~0;
285 source = (mmesa->draw_buffer == MGA_FRONT ?
286 mmesa->mgaScreen->frontOffset :
287 mmesa->mgaScreen->backOffset);
288 break;
289
290 default:
291 return GL_FALSE;
292 }
293
294 if (!ok) {
295 return GL_FALSE;
296 }
297
298
299 LOCK_HARDWARE( mmesa );
300
301 #if 0
302 {
303 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
304 int nbox, retcode, i;
305
306 UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
307
308 if (mmesa->dirty_cliprects & MGA_FRONT)
309 mgaUpdateRects( mmesa, MGA_FRONT );
310
311 nbox = dPriv->numClipRects;
312
313 y = dPriv->h - y - height;
314 x += mmesa->drawX;
315 y += mmesa->drawY;
316
317 dest = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels)) |
318 DO_dstmap_sys | DO_dstacc_agp);
319 source_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp;
320 dest_pitch = pitch;
321 delta_sx = 0;
322 delta_sy = 0;
323 delta_dx = -x;
324 delta_dy = -y;
325 blit_height = 2*y + height;
326 ydir = -1;
327
328 if (0) fprintf(stderr, "XX doing readpixel blit src_pitch %d dst_pitch %d\n",
329 source_pitch, dest_pitch);
330
331
332
333 for (i = 0 ; i < nbox ; )
334 {
335 int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
336 drm_clip_rect_t *box = dPriv->pClipRects;
337 drm_clip_rect_t *b = mmesa->sarea->boxes;
338 int n = 0;
339
340 for ( ; i < nr ; i++) {
341 GLint bx = box[i].x1;
342 GLint by = box[i].y1;
343 GLint bw = box[i].x2 - bx;
344 GLint bh = box[i].y2 - by;
345
346 if (bx < x) bw -= x - bx, bx = x;
347 if (by < y) bh -= y - by, by = y;
348 if (bx + bw > x + width) bw = x + width - bx;
349 if (by + bh > y + height) bh = y + height - by;
350 if (bw <= 0) continue;
351 if (bh <= 0) continue;
352
353 b->x1 = bx;
354 b->y1 = by;
355 b->x2 = bx + bw;
356 b->y2 = by + bh;
357 b++;
358 n++;
359 }
360
361 mmesa->sarea->nbox = n;
362
363 if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT,
364 &blit, sizeof(drmMGABlit)))) {
365 fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode);
366 UNLOCK_HARDWARE( mmesa );
367 exit(1);
368 }
369 }
370
371 UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
372 }
373 #endif
374
375 UNLOCK_HARDWARE( mmesa );
376
377 return GL_TRUE;
378 }
379
380 static void
381 mgaDDReadPixels( GLcontext *ctx,
382 GLint x, GLint y, GLsizei width, GLsizei height,
383 GLenum format, GLenum type,
384 const struct gl_pixelstore_attrib *pack,
385 GLvoid *pixels )
386 {
387 if (!mgaTryReadPixels( ctx, x, y, width, height, format, type, pack, pixels))
388 _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels);
389 }
390
391
392
393
394 static void do_draw_pix( GLcontext *ctx,
395 GLint x, GLint y, GLsizei width, GLsizei height,
396 GLint pitch,
397 const void *pixels,
398 GLuint dest, GLuint planemask)
399 {
400 #if 0
401 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
402 drmMGABlit blit;
403 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
404 drm_clip_rect_t pbox = dPriv->pClipRects;
405 int nbox = dPriv->numClipRects;
406 int retcode, i;
407
408 y = dPriv->h - y - height;
409 x += mmesa->drawX;
410 y += mmesa->drawY;
411
412 blit.dest = dest;
413 blit.planemask = planemask;
414 blit.source = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels))
415 | SO_srcmap_sys | SO_srcacc_agp);
416 blit.dest_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp;
417 blit.source_pitch = pitch;
418 blit.delta_sx = -x;
419 blit.delta_sy = -y;
420 blit.delta_dx = 0;
421 blit.delta_dy = 0;
422 if (ctx->Pixel.ZoomY == -1) {
423 blit.height = height;
424 blit.ydir = 1;
425 } else {
426 blit.height = height;
427 blit.ydir = -1;
428 }
429
430 if (0) fprintf(stderr,
431 "doing drawpixel blit src_pitch %d dst_pitch %d\n",
432 blit.source_pitch, blit.dest_pitch);
433
434 for (i = 0 ; i < nbox ; )
435 {
436 int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
437 drm_clip_rect_t *box = mmesa->pClipRects;
438 drm_clip_rect_t *b = mmesa->sarea->boxes;
439 int n = 0;
440
441 for ( ; i < nr ; i++) {
442 GLint bx = box[i].x1;
443 GLint by = box[i].y1;
444 GLint bw = box[i].x2 - bx;
445 GLint bh = box[i].y2 - by;
446
447 if (bx < x) bw -= x - bx, bx = x;
448 if (by < y) bh -= y - by, by = y;
449 if (bx + bw > x + width) bw = x + width - bx;
450 if (by + bh > y + height) bh = y + height - by;
451 if (bw <= 0) continue;
452 if (bh <= 0) continue;
453
454 b->x1 = bx;
455 b->y1 = by;
456 b->x2 = bx + bw;
457 b->y2 = by + bh;
458 b++;
459 n++;
460 }
461
462 mmesa->sarea->nbox = n;
463
464 if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT,
465 &blit, sizeof(drmMGABlit)))) {
466 fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode);
467 UNLOCK_HARDWARE( mmesa );
468 exit(1);
469 }
470 }
471 #endif
472 }
473
474
475
476
477 static GLboolean
478 mgaTryDrawPixels( GLcontext *ctx,
479 GLint x, GLint y, GLsizei width, GLsizei height,
480 GLenum format, GLenum type,
481 const struct gl_pixelstore_attrib *unpack,
482 const GLvoid *pixels )
483 {
484 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
485 GLint size, skipPixels, skipRows;
486 GLint pitch = unpack->RowLength ? unpack->RowLength : width;
487 GLuint dest, planemask;
488 GLuint cpp = mmesa->mgaScreen->cpp;
489
490 if (!clip_pixelrect(ctx, ctx->DrawBuffer,
491 &x, &y, &width, &height,
492 &skipPixels, &skipRows, &size)) {
493 return GL_TRUE;
494 }
495
496
497 switch (format) {
498 #if defined(MESA_packed_depth_stencil)
499 case GL_DEPTH_STENCIL_MESA:
500 dest = mmesa->mgaScreen->depthOffset;
501 planemask = ~0;
502 if (!check_depth_stencil_24_8(ctx, type, unpack, pixels, size, pitch) ||
503 !check_depth_per_fragment_ops(ctx) ||
504 !check_stencil_per_fragment_ops(ctx))
505 return GL_FALSE;
506 break;
507 #endif
508
509 case GL_DEPTH_COMPONENT:
510 dest = mmesa->mgaScreen->depthOffset;
511
512 if (ctx->Visual.depthBits == 24)
513 planemask = ~0xff;
514 else
515 planemask = ~0;
516
517 if (!check_depth(ctx, type, unpack, pixels, size, pitch) ||
518 !check_depth_per_fragment_ops(ctx))
519 return GL_FALSE;
520 break;
521
522 case GL_RGB:
523 case GL_BGRA:
524 dest = (mmesa->draw_buffer == MGA_FRONT ?
525 mmesa->mgaScreen->frontOffset :
526 mmesa->mgaScreen->backOffset);
527
528 planemask = mgaPackColor(cpp,
529 ctx->Color.ColorMask[RCOMP],
530 ctx->Color.ColorMask[GCOMP],
531 ctx->Color.ColorMask[BCOMP],
532 ctx->Color.ColorMask[ACOMP]);
533
534 if (cpp == 2)
535 planemask |= planemask << 16;
536
537 if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
538 return GL_FALSE;
539 }
540 if (!check_color_per_fragment_ops(ctx)) {
541 return GL_FALSE;
542 }
543 break;
544
545 default:
546 return GL_FALSE;
547 }
548
549 LOCK_HARDWARE_QUIESCENT( mmesa );
550
551 if (mmesa->dirty_cliprects & MGA_FRONT)
552 mgaUpdateRects( mmesa, MGA_FRONT );
553
554 if ( IS_AGP_MEM(mmesa, (char *)pixels) &&
555 IS_AGP_MEM(mmesa, (char *)pixels + size) )
556 {
557 do_draw_pix( ctx, x, y, width, height, pitch, pixels,
558 dest, planemask );
559 UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
560 }
561 else
562 {
563 /* Pixels is in regular memory -- get dma buffers and perform
564 * upload through them.
565 */
566 /* drmBufPtr buf = mgaGetBufferLocked(mmesa); */
567 GLuint bufferpitch = (width*cpp+31)&~31;
568
569 char *address = 0; /* mmesa->mgaScreen->agp.map; */
570
571 do {
572 /* GLuint rows = MIN2( height, MGA_DMA_BUF_SZ / bufferpitch ); */
573 GLuint rows = height;
574
575
576 if (0) fprintf(stderr, "trying to upload %d rows (pitch %d)\n",
577 rows, bufferpitch);
578
579 /* The texture conversion code is so slow that there is only
580 * negligble speedup when the buffers/images don't exactly
581 * match:
582 */
583 #if 0
584 if (cpp == 2) {
585 if (!_mesa_convert_texsubimage2d( MESA_FORMAT_RGB565,
586 0, 0, width, rows,
587 bufferpitch, format, type,
588 unpack, pixels, address )) {
589 /* mgaReleaseBufLocked( mmesa, buf ); */
590 UNLOCK_HARDWARE(mmesa);
591 return GL_FALSE;
592 }
593 } else {
594 if (!_mesa_convert_texsubimage2d( MESA_FORMAT_ARGB8888,
595 0, 0, width, rows,
596 bufferpitch, format, type,
597 unpack, pixels, address )) {
598 /* mgaReleaseBufLocked( mmesa, buf ); */
599 UNLOCK_HARDWARE(mmesa);
600 return GL_FALSE;
601 }
602 }
603 #else
604 MEMCPY( address, pixels, rows*bufferpitch );
605 #endif
606
607 do_draw_pix( ctx, x, y, width, rows,
608 bufferpitch/cpp, address, dest, planemask );
609
610 /* Fix me -- use multiple buffers to avoid flush.
611 */
612 UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
613
614 pixels = (void *)((char *) pixels + rows * pitch);
615 height -= rows;
616 y += rows;
617 } while (height);
618
619 /* mgaReleaseBufLocked( mmesa, buf ); */
620 }
621
622 UNLOCK_HARDWARE( mmesa );
623 mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
624
625 return GL_TRUE;
626 }
627
628 static void
629 mgaDDDrawPixels( GLcontext *ctx,
630 GLint x, GLint y, GLsizei width, GLsizei height,
631 GLenum format, GLenum type,
632 const struct gl_pixelstore_attrib *unpack,
633 const GLvoid *pixels )
634 {
635 if (!mgaTryDrawPixels( ctx, x, y, width, height, format, type,
636 unpack, pixels ))
637 _swrast_DrawPixels( ctx, x, y, width, height, format, type,
638 unpack, pixels );
639 }
640 #endif
641
642
643 /* Stub functions - not a real allocator, always returns pointer to
644 * the same block of agp space which isn't used for anything else at
645 * present.
646 */
647 void mgaDDInitPixelFuncs( GLcontext *ctx )
648 {
649 #if 0
650 /* evidently, these functions don't always work */
651 if (getenv("MGA_BLIT_PIXELS")) {
652 ctx->Driver.ReadPixels = mgaDDReadPixels; /* requires agp dest */
653 ctx->Driver.DrawPixels = mgaDDDrawPixels; /* works with agp/normal mem */
654 }
655 #endif
656 }