First import
[xorg_rtime.git] / xorg-server-1.4 / hw / kdrive / ati / ati_draw.c
blobc10fea4712b285edd71030ef73aea4c8a316c570
1 /*
2 * Copyright © 2003 Eric Anholt
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 Eric Anholt not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Eric Anholt makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ERIC ANHOLT 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.
23 #ifdef HAVE_CONFIG_H
24 #include <kdrive-config.h>
25 #endif
26 #include "ati.h"
27 #include "ati_reg.h"
28 #include "ati_dma.h"
29 #include "ati_draw.h"
30 #include "kaa.h"
32 CARD8 ATISolidRop[16] = {
33 /* GXclear */ 0x00, /* 0 */
34 /* GXand */ 0xa0, /* src AND dst */
35 /* GXandReverse */ 0x50, /* src AND NOT dst */
36 /* GXcopy */ 0xf0, /* src */
37 /* GXandInverted*/ 0x0a, /* NOT src AND dst */
38 /* GXnoop */ 0xaa, /* dst */
39 /* GXxor */ 0x5a, /* src XOR dst */
40 /* GXor */ 0xfa, /* src OR dst */
41 /* GXnor */ 0x05, /* NOT src AND NOT dst */
42 /* GXequiv */ 0xa5, /* NOT src XOR dst */
43 /* GXinvert */ 0x55, /* NOT dst */
44 /* GXorReverse */ 0xf5, /* src OR NOT dst */
45 /* GXcopyInverted*/ 0x0f, /* NOT src */
46 /* GXorInverted */ 0xaf, /* NOT src OR dst */
47 /* GXnand */ 0x5f, /* NOT src OR NOT dst */
48 /* GXset */ 0xff, /* 1 */
51 CARD8 ATIBltRop[16] = {
52 /* GXclear */ 0x00, /* 0 */
53 /* GXand */ 0x88, /* src AND dst */
54 /* GXandReverse */ 0x44, /* src AND NOT dst */
55 /* GXcopy */ 0xcc, /* src */
56 /* GXandInverted*/ 0x22, /* NOT src AND dst */
57 /* GXnoop */ 0xaa, /* dst */
58 /* GXxor */ 0x66, /* src XOR dst */
59 /* GXor */ 0xee, /* src OR dst */
60 /* GXnor */ 0x11, /* NOT src AND NOT dst */
61 /* GXequiv */ 0x99, /* NOT src XOR dst */
62 /* GXinvert */ 0x55, /* NOT dst */
63 /* GXorReverse */ 0xdd, /* src OR NOT dst */
64 /* GXcopyInverted*/ 0x33, /* NOT src */
65 /* GXorInverted */ 0xbb, /* NOT src OR dst */
66 /* GXnand */ 0x77, /* NOT src OR NOT dst */
67 /* GXset */ 0xff, /* 1 */
70 int copydx, copydy;
71 ATIScreenInfo *accel_atis;
72 /* If is_24bpp is set, then we are using the accelerator in 8-bit mode due
73 * to it being broken for 24bpp, so coordinates have to be multiplied by 3.
75 Bool is_24bpp;
76 CARD32 settings, color, src_pitch_offset, dst_pitch_offset;
78 int sample_count;
79 float sample_offsets_x[255];
80 float sample_offsets_y[255];
82 #define DRAW_USING_PACKET3 0
84 void
85 ATIDrawSetup(ScreenPtr pScreen)
87 KdScreenPriv(pScreen);
88 ATIScreenInfo(pScreenPriv);
89 ATICardInfo(pScreenPriv);
90 RING_LOCALS;
92 /* XXX: this shouldn't be necessary, but fixes some R128 composite
93 * issues.
95 /*if (!atic->is_radeon) {
96 char *mmio = atic->reg_base;
97 ATIWaitIdle(atis);
98 MMIO_OUT32(mmio, R128_REG_PC_GUI_MODE,
99 R128_PC_BYPASS_EN);
102 BEGIN_DMA(2);
103 OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
104 ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
105 END_DMA();
107 if (!atic->is_radeon) {
108 /* Setup for R128 Composite */
109 BEGIN_DMA(12);
110 OUT_REG(R128_REG_SCALE_3D_CNTL,
111 R128_SCALE_3D_TEXMAP_SHADE |
112 R128_SCALE_PIX_REPLICATE |
113 R128_TEX_CACHE_SPLIT |
114 R128_TEX_MAP_ALPHA_IN_TEXTURE |
115 R128_TEX_CACHE_LINE_SIZE_4QW);
116 OUT_REG(R128_REG_SETUP_CNTL,
117 R128_COLOR_SOLID_COLOR |
118 R128_PRIM_TYPE_TRI |
119 R128_TEXTURE_ST_MULT_W |
120 R128_STARTING_VERTEX_1 |
121 R128_ENDING_VERTEX_3 |
122 R128_SUB_PIX_4BITS);
123 OUT_REG(R128_REG_PM4_VC_FPU_SETUP,
124 R128_FRONT_DIR_CCW |
125 R128_BACKFACE_CULL |
126 R128_FRONTFACE_SOLID |
127 R128_FPU_COLOR_SOLID |
128 R128_FPU_SUB_PIX_4BITS |
129 R128_FPU_MODE_3D |
130 R128_TRAP_BITS_DISABLE |
131 R128_XFACTOR_2 |
132 R128_YFACTOR_2 |
133 R128_FLAT_SHADE_VERTEX_OGL |
134 R128_FPU_ROUND_TRUNCATE |
135 R128_WM_SEL_8DW);
136 OUT_REG(R128_REG_PLANE_3D_MASK_C, 0xffffffff);
137 OUT_REG(R128_REG_CONSTANT_COLOR_C, 0xff000000);
138 OUT_REG(R128_REG_WINDOW_XY_OFFSET, 0x00000000);
139 END_DMA();
140 } else if (!atic->is_r300) {
141 /* Setup for R100/R200 Composite */
142 BEGIN_DMA(8);
143 OUT_REG(RADEON_REG_RE_TOP_LEFT, 0);
144 OUT_REG(RADEON_REG_RE_WIDTH_HEIGHT, 0xffffffff);
145 OUT_REG(RADEON_REG_RB3D_PLANEMASK, 0xffffffff);
146 OUT_REG(RADEON_REG_SE_CNTL,
147 RADEON_FFACE_CULL_CCW |
148 RADEON_FFACE_SOLID |
149 RADEON_VTX_PIX_CENTER_OGL);
150 END_DMA();
152 if (atic->is_r100) {
153 BEGIN_DMA(6);
154 OUT_REG(RADEON_REG_SE_CNTL_STATUS, RADEON_TCL_BYPASS);
155 OUT_REG(RADEON_REG_SE_COORD_FMT,
156 RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
157 RADEON_VTX_ST0_NONPARAMETRIC |
158 RADEON_VTX_ST1_NONPARAMETRIC |
159 RADEON_TEX1_W_ROUTING_USE_W0);
160 OUT_REG(RADEON_REG_RB3D_DSTCACHE_MODE,
161 RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH |
162 RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH);
163 END_DMA();
164 } else {
165 BEGIN_DMA(18);
166 /* XXX: The 0 below should be RADEON_TCL_BYPASS on
167 * RS300s.
169 OUT_REG(R200_REG_SE_VAP_CNTL_STATUS, 0);
170 OUT_REG(R200_REG_PP_CNTL_X, 0);
171 OUT_REG(R200_REG_PP_TXMULTI_CTL_0, 0);
172 OUT_REG(R200_REG_SE_VTX_STATE_CNTL, 0);
173 OUT_REG(R200_REG_RE_CNTL, 0);
174 /* XXX: VTX_ST_DENORMALIZED is illegal for the case of
175 * repeating textures.
177 OUT_REG(R200_REG_SE_VTE_CNTL, R200_VTX_ST_DENORMALIZED);
178 OUT_REG(R200_REG_SE_VAP_CNTL,
179 R200_VAP_FORCE_W_TO_ONE |
180 R200_VAP_VF_MAX_VTX_NUM);
181 OUT_REG(R200_REG_RE_AUX_SCISSOR_CNTL, 0);
182 OUT_REG(RADEON_REG_RB3D_DSTCACHE_MODE,
183 RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH |
184 RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH |
185 R200_RB3D_DC_2D_CACHE_AUTOFREE |
186 R200_RB3D_DC_3D_CACHE_AUTOFREE);
187 END_DMA();
192 static void
193 ATIWaitMarker(ScreenPtr pScreen, int marker)
195 KdScreenPriv(pScreen);
196 ATIScreenInfo(pScreenPriv);
198 ENTER_DRAW(0);
199 ATIWaitIdle(atis);
200 LEAVE_DRAW(0);
203 void
204 RadeonSwitchTo2D(ATIScreenInfo *atis)
206 RING_LOCALS;
208 ENTER_DRAW(0);
209 BEGIN_DMA(4);
210 OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH);
211 OUT_REG(ATI_REG_WAIT_UNTIL,
212 RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
213 END_DMA();
214 LEAVE_DRAW(0);
217 void
218 RadeonSwitchTo3D(ATIScreenInfo *atis)
220 RING_LOCALS;
222 ENTER_DRAW(0);
223 BEGIN_DMA(4);
224 OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH);
225 /* We must wait for 3d to idle, in case source was just written as a dest. */
226 OUT_REG(ATI_REG_WAIT_UNTIL,
227 RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
228 END_DMA();
229 LEAVE_DRAW(0);
232 #if ATI_TRACE_DRAW
233 void
234 ATIEnterDraw (PixmapPtr pPix, char *function)
236 if (pPix != NULL) {
237 KdScreenPriv(pPix->drawable.pScreen);
238 CARD32 offset;
240 offset = ((CARD8 *)pPix->devPrivate.ptr -
241 pScreenPriv->screen->memory_base);
243 ErrorF ("Enter %s 0x%x (%dx%dx%d/%d)\n", function, offset,
244 pPix->drawable.width, pPix->drawable.height, pPix->drawable.depth,
245 pPix->drawable.bitsPerPixel);
246 } else
247 ErrorF ("Enter %s\n", function);
250 void
251 ATILeaveDraw (PixmapPtr pPix, char *function)
253 if (pPix != NULL) {
254 KdScreenPriv(pPix->drawable.pScreen);
255 CARD32 offset;
257 offset = ((CARD8 *)pPix->devPrivate.ptr -
258 pScreenPriv->screen->memory_base);
260 ErrorF ("Leave %s 0x%x\n", function, offset);
261 } else
262 ErrorF ("Leave %s\n", function);
264 #endif
266 /* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
267 * require src and dest datatypes to be equal.
269 static Bool
270 ATIGetDatatypeBpp(int bpp, CARD32 *type)
272 switch (bpp) {
273 case 8:
274 *type = R128_DATATYPE_CI8;
275 return TRUE;
276 case 16:
277 *type = R128_DATATYPE_RGB565;
278 return TRUE;
279 case 24:
280 *type = R128_DATATYPE_CI8;
281 return TRUE;
282 case 32:
283 *type = R128_DATATYPE_ARGB8888;
284 return TRUE;
285 default:
286 ATI_FALLBACK(("Unsupported bpp: %d\n", bpp));
287 return FALSE;
291 Bool
292 ATIGetOffsetPitch(ATIScreenInfo *atis, int bpp, CARD32 *pitch_offset,
293 int offset, int pitch)
295 ATICardInfo *atic = atis->atic;
297 /* On the R128, depending on the bpp the screen can be set up so that it
298 * doesn't meet the pitchAlign requirement but can still be
299 * accelerated, so we check the specific pitch requirement of alignment
300 * to 8 pixels.
302 if (atic->is_radeon) {
303 if (pitch % atis->kaa.pitchAlign != 0)
304 ATI_FALLBACK(("Bad pitch 0x%08x\n", pitch));
305 *pitch_offset = ((pitch >> 6) << 22) | (offset >> 10);
307 } else {
308 if (pitch % bpp != 0)
309 ATI_FALLBACK(("Bad pitch 0x%08x\n", pitch));
310 *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5);
313 if (offset % atis->kaa.offsetAlign != 0)
314 ATI_FALLBACK(("Bad offset 0x%08x\n", offset));
316 return TRUE;
319 Bool
320 ATIGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset)
322 KdScreenPriv(pPix->drawable.pScreen);
323 ATIScreenInfo(pScreenPriv);
324 CARD32 pitch, offset;
325 int bpp;
327 bpp = pPix->drawable.bitsPerPixel;
328 if (bpp == 24)
329 bpp = 8;
331 offset = ((CARD8 *)pPix->devPrivate.ptr -
332 pScreenPriv->screen->memory_base);
333 pitch = pPix->devKind;
335 return ATIGetOffsetPitch(atis, bpp, pitch_offset, offset, pitch);
338 static Bool
339 ATIPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
341 KdScreenPriv(pPix->drawable.pScreen);
342 ATIScreenInfo(pScreenPriv);
343 ATICardInfo(pScreenPriv);
344 CARD32 datatype;
345 RING_LOCALS;
347 is_24bpp = (pPix->drawable.bitsPerPixel == 24);
348 accel_atis = atis;
350 if (is_24bpp) {
351 /* Solid fills in fake-24bpp mode only work if the pixel color
352 * and planemask are all the same byte.
354 if ((fg & 0xffffff) != (((fg & 0xff) << 16) | ((fg >> 8) &
355 0xffff)))
356 ATI_FALLBACK(("Can't do solid color 0x%08x in 24bpp\n",
357 fg));
358 if ((pm & 0xffffff) != (((pm & 0xff) << 16) | ((pm >> 8) &
359 0xffff)))
360 ATI_FALLBACK(("Can't do planemask 0x%08x in 24bpp\n",
361 pm));
364 if (!ATIGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype))
365 return FALSE;
366 if (!ATIGetPixmapOffsetPitch(pPix, &dst_pitch_offset))
367 return FALSE;
369 ENTER_DRAW(pPix);
371 if (atic->is_radeon)
372 RadeonSwitchTo2D(atis);
374 settings =
375 ATI_GMC_DST_PITCH_OFFSET_CNTL |
376 ATI_GMC_BRUSH_SOLID_COLOR |
377 (datatype << 8) |
378 ATI_GMC_SRC_DATATYPE_COLOR |
379 (ATISolidRop[alu] << 16) |
380 ATI_GMC_CLR_CMP_CNTL_DIS |
381 R128_GMC_AUX_CLIP_DIS;
382 color = fg;
384 #if DRAW_USING_PACKET3
385 BEGIN_DMA(6);
386 OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
387 ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
388 OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
389 OUT_REG(ATI_REG_DP_CNTL, ATI_DST_X_LEFT_TO_RIGHT |
390 ATI_DST_Y_TOP_TO_BOTTOM);
391 END_DMA();
392 #else
393 BEGIN_DMA(12);
394 OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
395 ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
396 OUT_REG(ATI_REG_DST_PITCH_OFFSET, dst_pitch_offset);
397 OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL, settings);
398 OUT_REG(ATI_REG_DP_BRUSH_FRGD_CLR, fg);
399 OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
400 OUT_REG(ATI_REG_DP_CNTL, ATI_DST_X_LEFT_TO_RIGHT |
401 ATI_DST_Y_TOP_TO_BOTTOM);
402 END_DMA();
403 #endif
405 LEAVE_DRAW(pPix);
406 return TRUE;
409 static void
410 ATISolid(int x1, int y1, int x2, int y2)
412 ENTER_DRAW(0);
413 ATIScreenInfo *atis = accel_atis;
414 RING_LOCALS;
416 if (is_24bpp) {
417 x1 *= 3;
418 x2 *= 3;
420 #if DRAW_USING_PACKET3
421 BEGIN_DMA(6);
422 OUT_RING(DMA_PACKET3(ATI_CCE_PACKET3_PAINT_MULTI, 5));
423 OUT_RING(settings);
424 OUT_RING(dst_pitch_offset);
425 OUT_RING(color);
426 OUT_RING((x1 << 16) | y1);
427 OUT_RING(((x2 - x1) << 16) | (y2 - y1));
428 END_DMA();
429 #else
430 BEGIN_DMA(3);
431 OUT_RING(DMA_PACKET0(ATI_REG_DST_Y_X, 2));
432 OUT_RING_REG(ATI_REG_DST_Y_X, (y1 << 16) | x1);
433 OUT_RING_REG(ATI_REG_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1));
434 END_DMA();
435 #endif
436 LEAVE_DRAW(0);
439 static void
440 ATIDoneSolid(void)
442 ENTER_DRAW(0);
443 LEAVE_DRAW(0);
446 static Bool
447 ATIPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, Pixel pm)
449 KdScreenPriv(pDst->drawable.pScreen);
450 ATIScreenInfo(pScreenPriv);
451 ATICardInfo(pScreenPriv);
452 CARD32 datatype;
453 RING_LOCALS;
455 copydx = dx;
456 copydy = dy;
457 is_24bpp = pDst->drawable.bitsPerPixel == 24;
458 accel_atis = atis;
460 if (is_24bpp && ((pm & 0xffffff) != (((pm & 0xff) << 16) | ((pm >> 8) &
461 0xffff))))
462 ATI_FALLBACK(("Can't do planemask 0x%08x in 24bpp\n", pm));
464 if (!ATIGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype))
465 return FALSE;
466 if (!ATIGetPixmapOffsetPitch(pSrc, &src_pitch_offset))
467 return FALSE;
468 if (!ATIGetPixmapOffsetPitch(pDst, &dst_pitch_offset))
469 return FALSE;
471 ENTER_DRAW (pDst);
472 if (atic->is_radeon)
473 RadeonSwitchTo2D(atis);
475 settings =
476 ATI_GMC_SRC_PITCH_OFFSET_CNTL |
477 ATI_GMC_DST_PITCH_OFFSET_CNTL |
478 ATI_GMC_BRUSH_NONE |
479 (datatype << 8) |
480 ATI_GMC_SRC_DATATYPE_COLOR |
481 (ATIBltRop[alu] << 16) |
482 ATI_DP_SRC_SOURCE_MEMORY |
483 ATI_GMC_CLR_CMP_CNTL_DIS |
484 R128_GMC_AUX_CLIP_DIS;
486 #if DRAW_USING_PACKET3
487 BEGIN_DMA(6);
488 OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
489 ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
490 OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
491 OUT_REG(ATI_REG_DP_CNTL,
492 (dx >= 0 ? ATI_DST_X_LEFT_TO_RIGHT : 0) |
493 (dy >= 0 ? ATI_DST_Y_TOP_TO_BOTTOM : 0));
494 END_DMA();
496 #else
497 BEGIN_DMA(12);
498 OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
499 ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
500 OUT_REG(ATI_REG_SRC_PITCH_OFFSET, src_pitch_offset);
501 OUT_REG(ATI_REG_DST_PITCH_OFFSET, dst_pitch_offset);
502 OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL, settings);
503 OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
504 OUT_REG(ATI_REG_DP_CNTL,
505 (dx >= 0 ? ATI_DST_X_LEFT_TO_RIGHT : 0) |
506 (dy >= 0 ? ATI_DST_Y_TOP_TO_BOTTOM : 0));
507 END_DMA();
508 #endif
509 LEAVE_DRAW(pDst);
511 return TRUE;
514 static void
515 ATICopy(int srcX, int srcY, int dstX, int dstY, int w, int h)
517 ATIScreenInfo *atis = accel_atis;
518 RING_LOCALS;
520 if (is_24bpp) {
521 srcX *= 3;
522 dstX *= 3;
523 w *= 3;
526 #if !DRAW_USING_PACKET3
527 if (copydx < 0) {
528 srcX += w - 1;
529 dstX += w - 1;
532 if (copydy < 0) {
533 srcY += h - 1;
534 dstY += h - 1;
536 #endif
538 #if DRAW_USING_PACKET3
539 BEGIN_DMA(7);
540 OUT_RING(DMA_PACKET3(ATI_CCE_PACKET3_BITBLT_MULTI, 6));
541 OUT_RING(settings);
542 OUT_RING(src_pitch_offset);
543 OUT_RING(dst_pitch_offset);
544 OUT_RING((srcX << 16) | srcY);
545 OUT_RING((dstX << 16) | dstY);
546 OUT_RING((w << 16) | h);
547 END_DMA();
548 #else
549 BEGIN_DMA(4);
550 OUT_RING(DMA_PACKET0(ATI_REG_SRC_Y_X, 3));
551 OUT_RING_REG(ATI_REG_SRC_Y_X, (srcY << 16) | srcX);
552 OUT_RING_REG(ATI_REG_DST_Y_X, (dstY << 16) | dstX);
553 OUT_RING_REG(ATI_REG_DST_HEIGHT_WIDTH, (h << 16) | w);
554 END_DMA();
555 #endif
558 static void
559 ATIDoneCopy(void)
563 static Bool
564 ATIUploadToScreen(PixmapPtr pDst, char *src, int src_pitch)
566 ScreenPtr pScreen = pDst->drawable.pScreen;
567 KdScreenPriv(pScreen);
568 ATIScreenInfo(pScreenPriv);
569 ATICardInfo(pScreenPriv);
570 int width, height, bpp, i, dwords;
571 int dst_pitch, dst_offset;
572 CARD32 dst_pitch_offset, datatype;
573 Bool success;
574 RING_LOCALS;
576 ENTER_DRAW (pDst);
578 LEAVE_DRAW (pDst);
579 /* XXX: Hostdata uploads aren't working yet. */
580 return FALSE;
582 dst_offset = ((CARD8 *)pDst->devPrivate.ptr -
583 pScreenPriv->screen->memory_base);
584 dst_pitch = pDst->devKind;
585 width = pDst->drawable.width;
586 height = pDst->drawable.height;
587 bpp = pDst->drawable.bitsPerPixel;
589 success = ATIGetDatatypeBpp(bpp, &datatype);
591 if (bpp == 24) {
592 is_24bpp = TRUE;
593 bpp = 8;
594 } else
595 is_24bpp = FALSE;
597 if (!ATIGetOffsetPitch(atis, bpp, &dst_pitch_offset, dst_offset,
598 dst_pitch))
599 return FALSE;
601 if (src_pitch != (width * bpp / 8))
602 return FALSE;
604 /* No PACKET3 packets when in PIO mode. */
605 if (atis->using_pio)
606 return FALSE;
608 dwords = (width * height * (bpp / 8) + 3) / 4;
610 /* Flush pixel cache so nothing being written to the destination
611 * previously gets mixed up with the hostdata blit.
613 if (atic->is_radeon) {
614 BEGIN_DMA(4);
615 OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH);
616 OUT_REG(ATI_REG_WAIT_UNTIL,
617 RADEON_WAIT_2D_IDLECLEAN |
618 RADEON_WAIT_3D_IDLECLEAN |
619 RADEON_WAIT_HOST_IDLECLEAN);
620 END_DMA();
621 } else {
622 BEGIN_DMA(2);
623 OUT_REG(R128_REG_PC_GUI_CTLSTAT,
624 R128_PC_FLUSH_GUI | R128_PC_RI_GUI);
625 END_DMA();
628 BEGIN_DMA(8);
629 OUT_RING(DMA_PACKET3(ATI_CCE_PACKET3_HOSTDATA_BLT, 7 + dwords));
630 OUT_RING(ATI_GMC_DST_PITCH_OFFSET_CNTL |
631 ATI_GMC_BRUSH_NONE |
632 (datatype << 8) |
633 ATI_GMC_SRC_DATATYPE_COLOR |
634 (ATISolidRop[GXcopy] << 16) |
635 ATI_DP_SRC_SOURCE_HOST_DATA |
636 ATI_GMC_CLR_CMP_CNTL_DIS |
637 R128_GMC_AUX_CLIP_DIS |
638 ATI_GMC_WR_MSK_DIS);
639 OUT_RING(dst_pitch_offset);
640 OUT_RING(0xffffffff);
641 OUT_RING(0xffffffff);
642 OUT_RING((0 << 16) | 0);
643 OUT_RING((height << 16) | width);
644 OUT_RING(dwords);
645 END_DMA();
647 for (i = 0; i < dwords; i++) {
648 BEGIN_DMA(1);
649 OUT_RING(((CARD32 *)src)[i]);
650 END_DMA();
653 if (atic->is_radeon) {
654 BEGIN_DMA(4);
655 OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT,
656 RADEON_RB3D_DC_FLUSH_ALL);
657 OUT_REG(ATI_REG_WAIT_UNTIL,
658 RADEON_WAIT_2D_IDLECLEAN |
659 RADEON_WAIT_HOST_IDLECLEAN);
660 END_DMA();
661 } else {
662 BEGIN_DMA(2);
663 OUT_REG(R128_REG_PC_GUI_CTLSTAT, R128_PC_FLUSH_GUI);
664 END_DMA();
667 kaaMarkSync(pScreen);
669 ErrorF("hostdata upload %d,%d %dbpp\n", width, height, bpp);
671 return TRUE;
675 static Bool
676 ATIUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst)
678 KdScreenPriv(pSrc->drawable.pScreen);
679 ATICardInfo(pScreenPriv);
680 ATIScreenInfo(pScreenPriv);
681 int dst_pitch, src_pitch, w, i, size, bytes;
682 unsigned char *dst, *src;
683 RING_LOCALS;
685 ENTER_DRAW(pSrc);
686 /* Align width to log 2, useful for R128 composite. This should be a
687 * KAA flag we check for (and supported in kaa.c in general) since many
688 * older bits of hardware are going to want POT pitches.
690 w = pSrc->drawable.width;
691 if (atis->kaa.flags & KAA_OFFSCREEN_ALIGN_POT)
692 w = 1 << (ATILog2(w - 1) + 1);
693 dst_pitch = (w * pSrc->drawable.bitsPerPixel / 8 +
694 atis->kaa.pitchAlign - 1) & ~(atis->kaa.pitchAlign - 1);
696 size = dst_pitch * pSrc->drawable.height;
697 if (size > atis->scratch_area->size)
698 ATI_FALLBACK(("Pixmap too large for scratch (%d,%d)\n",
699 pSrc->drawable.width, pSrc->drawable.height));
701 atis->scratch_next = (atis->scratch_next + atis->kaa.offsetAlign - 1) &
702 ~(atis->kaa.offsetAlign - 1);
703 if (atis->scratch_next + size > atis->scratch_area->offset +
704 atis->scratch_area->size) {
705 /* Only sync when we've used all of the scratch area. */
706 kaaWaitSync(pSrc->drawable.pScreen);
707 atis->scratch_next = atis->scratch_area->offset;
709 memcpy(pDst, pSrc, sizeof(*pDst));
710 pDst->devKind = dst_pitch;
711 pDst->devPrivate.ptr = pScreenPriv->screen->memory_base +
712 atis->scratch_next;
713 atis->scratch_next += size;
715 src = pSrc->devPrivate.ptr;
716 src_pitch = pSrc->devKind;
717 dst = pDst->devPrivate.ptr;
718 bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
720 i = pSrc->drawable.height;
721 while (i--) {
722 memcpy(dst, src, bytes);
723 dst += dst_pitch;
724 src += src_pitch;
727 /* Flush the pixel cache */
728 if (atic->is_radeon) {
729 BEGIN_DMA(4);
730 OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT,
731 RADEON_RB3D_DC_FLUSH_ALL);
732 OUT_REG(ATI_REG_WAIT_UNTIL, RADEON_WAIT_HOST_IDLECLEAN);
733 END_DMA();
734 } else {
735 BEGIN_DMA(2);
736 OUT_REG(R128_REG_PC_GUI_CTLSTAT, R128_PC_FLUSH_ALL);
737 END_DMA();
740 LEAVE_DRAW(pSrc);
741 return TRUE;
744 static void
745 ATIBlockHandler(pointer blockData, OSTimePtr timeout, pointer readmask)
747 ScreenPtr pScreen = (ScreenPtr) blockData;
748 KdScreenPriv(pScreen);
749 ATIScreenInfo(pScreenPriv);
751 /* When the server is going to sleep, make sure that all DMA data has
752 * been flushed.
754 if (atis->indirectBuffer)
755 ATIFlushIndirect(atis, 1);
758 static void
759 ATIWakeupHandler(pointer blockData, int result, pointer readmask)
763 Bool
764 ATIDrawInit(ScreenPtr pScreen)
766 KdScreenPriv(pScreen);
767 ATIScreenInfo(pScreenPriv);
768 ATICardInfo(pScreenPriv);
770 ErrorF("Screen: %d/%d depth/bpp\n", pScreenPriv->screen->fb[0].depth,
771 pScreenPriv->screen->fb[0].bitsPerPixel);
773 RegisterBlockAndWakeupHandlers(ATIBlockHandler, ATIWakeupHandler,
774 pScreen);
776 #ifdef USE_DRI
777 atis->using_dri = ATIDRIScreenInit(pScreen);
778 #endif /* USE_DRI */
780 memset(&atis->kaa, 0, sizeof(KaaScreenInfoRec));
781 atis->kaa.waitMarker = ATIWaitMarker;
782 atis->kaa.PrepareSolid = ATIPrepareSolid;
783 atis->kaa.Solid = ATISolid;
784 atis->kaa.DoneSolid = ATIDoneSolid;
785 atis->kaa.PrepareCopy = ATIPrepareCopy;
786 atis->kaa.Copy = ATICopy;
787 atis->kaa.DoneCopy = ATIDoneCopy;
788 /* Other acceleration will be hooked in in DrawEnable depending on
789 * what type of DMA gets initialized.
792 atis->kaa.flags = KAA_OFFSCREEN_PIXMAPS;
793 if (atic->is_radeon) {
794 atis->kaa.offsetAlign = 1024;
795 atis->kaa.pitchAlign = 64;
796 } else {
797 /* Rage 128 compositing wants power-of-two pitches. */
798 atis->kaa.flags |= KAA_OFFSCREEN_ALIGN_POT;
799 atis->kaa.offsetAlign = 32;
800 /* Pitch alignment is in sets of 8 pixels, and we need to cover
801 * 32bpp, so 32 bytes.
803 atis->kaa.pitchAlign = 32;
806 kaaInitTrapOffsets(8, sample_offsets_x, sample_offsets_y, 0.0, 0.0);
807 sample_count = (1 << 8) - 1;
809 if (!kaaDrawInit(pScreen, &atis->kaa))
810 return FALSE;
812 return TRUE;
815 static void
816 ATIScratchSave(ScreenPtr pScreen, KdOffscreenArea *area)
818 KdScreenPriv(pScreen);
819 ATIScreenInfo(pScreenPriv);
821 atis->scratch_area = NULL;
824 void
825 ATIDrawEnable(ScreenPtr pScreen)
827 KdScreenPriv(pScreen);
828 ATIScreenInfo(pScreenPriv);
829 ATICardInfo(pScreenPriv);
831 ATIDMASetup(pScreen);
832 ATIDrawSetup(pScreen);
834 atis->scratch_area = NULL;
835 atis->kaa.PrepareBlend = NULL;
836 atis->kaa.Blend = NULL;
837 atis->kaa.DoneBlend = NULL;
838 atis->kaa.CheckComposite = NULL;
839 atis->kaa.PrepareComposite = NULL;
840 atis->kaa.Composite = NULL;
841 atis->kaa.DoneComposite = NULL;
842 atis->kaa.UploadToScreen = NULL;
843 atis->kaa.UploadToScratch = NULL;
845 /* We can't dispatch 3d commands in PIO mode. */
846 if (!atis->using_pio) {
847 if (!atic->is_radeon) {
848 atis->kaa.CheckComposite = R128CheckComposite;
849 atis->kaa.PrepareComposite = R128PrepareComposite;
850 atis->kaa.Composite = R128Composite;
851 atis->kaa.DoneComposite = R128DoneComposite;
852 } else if (atic->is_r100) {
853 atis->kaa.CheckComposite = R100CheckComposite;
854 atis->kaa.PrepareComposite = R100PrepareComposite;
855 atis->kaa.Composite = RadeonComposite;
856 atis->kaa.DoneComposite = RadeonDoneComposite;
857 } else if (atic->is_r200) {
858 atis->kaa.CheckComposite = R200CheckComposite;
859 atis->kaa.PrepareComposite = R200PrepareComposite;
860 atis->kaa.Composite = RadeonComposite;
861 atis->kaa.DoneComposite = RadeonDoneComposite;
864 #ifdef USE_DRI
865 if (atis->using_dri) {
866 if (!atic->is_radeon) {
867 /*atis->kaa.PrepareTrapezoids = R128PrepareTrapezoids;
868 atis->kaa.Trapezoids = R128Trapezoids;
869 atis->kaa.DoneTrapezoids = R128DoneTrapezoids;*/
870 } else if (atic->is_r100 || atic->is_r200) {
871 atis->kaa.PrepareTrapezoids = RadeonPrepareTrapezoids;
872 atis->kaa.Trapezoids = RadeonTrapezoids;
873 atis->kaa.DoneTrapezoids = RadeonDoneTrapezoids;
876 #endif /* USE_DRI */
878 atis->kaa.UploadToScreen = ATIUploadToScreen;
880 /* Reserve a scratch area. It'll be used for storing glyph data during
881 * Composite operations, because glyphs aren't in real pixmaps and thus
882 * can't be migrated.
884 atis->scratch_area = KdOffscreenAlloc(pScreen, 131072,
885 atis->kaa.offsetAlign, TRUE, ATIScratchSave, atis);
886 if (atis->scratch_area != NULL) {
887 atis->scratch_next = atis->scratch_area->offset;
888 atis->kaa.UploadToScratch = ATIUploadToScratch;
891 kaaMarkSync(pScreen);
894 void
895 ATIDrawDisable(ScreenPtr pScreen)
897 kaaWaitSync(pScreen);
898 ATIDMATeardown(pScreen);
901 void
902 ATIDrawFini(ScreenPtr pScreen)
904 #ifdef USE_DRI
905 KdScreenPriv(pScreen);
906 ATIScreenInfo(pScreenPriv);
907 if (atis->using_dri) {
908 ATIDRICloseScreen(pScreen);
909 atis->using_dri = FALSE;
911 #endif /* USE_DRI */
913 RemoveBlockAndWakeupHandlers(ATIBlockHandler, ATIWakeupHandler,
914 pScreen);
916 kaaDrawFini(pScreen);