1209ff23fSmrg/*
2209ff23fSmrg * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
3209ff23fSmrg *                VA Linux Systems Inc., Fremont, California.
4209ff23fSmrg *
5209ff23fSmrg * All Rights Reserved.
6209ff23fSmrg *
7209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining
8209ff23fSmrg * a copy of this software and associated documentation files (the
9209ff23fSmrg * "Software"), to deal in the Software without restriction, including
10209ff23fSmrg * without limitation on the rights to use, copy, modify, merge,
11209ff23fSmrg * publish, distribute, sublicense, and/or sell copies of the Software,
12209ff23fSmrg * and to permit persons to whom the Software is furnished to do so,
13209ff23fSmrg * subject to the following conditions:
14209ff23fSmrg *
15209ff23fSmrg * The above copyright notice and this permission notice (including the
16209ff23fSmrg * next paragraph) shall be included in all copies or substantial
17209ff23fSmrg * portions of the Software.
18209ff23fSmrg *
19209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20209ff23fSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21209ff23fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22209ff23fSmrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23209ff23fSmrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24209ff23fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26209ff23fSmrg * DEALINGS IN THE SOFTWARE.
27209ff23fSmrg */
28209ff23fSmrg
29209ff23fSmrg#ifdef HAVE_CONFIG_H
30209ff23fSmrg#include "config.h"
31209ff23fSmrg#endif
32209ff23fSmrg
33209ff23fSmrg/*
34209ff23fSmrg * Authors:
35209ff23fSmrg *   Kevin E. Martin <martin@xfree86.org>
36209ff23fSmrg *   Rickard E. Faith <faith@valinux.com>
37209ff23fSmrg *   Alan Hourihane <alanh@fairlite.demon.co.uk>
38209ff23fSmrg *   Michel Dänzer <michel@daenzer.net>
39209ff23fSmrg *
40209ff23fSmrg * Credits:
41209ff23fSmrg *
42209ff23fSmrg *   Thanks to Ani Joshi <ajoshi@shell.unixbox.com> for providing source
43209ff23fSmrg *   code to his Radeon driver.  Portions of this file are based on the
44209ff23fSmrg *   initialization code for that driver.
45209ff23fSmrg *
46209ff23fSmrg * References:
47209ff23fSmrg *
48209ff23fSmrg * !!!! FIXME !!!!
49209ff23fSmrg *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
50209ff23fSmrg *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
51209ff23fSmrg *   1999.
52209ff23fSmrg *
53209ff23fSmrg *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
54209ff23fSmrg *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
55209ff23fSmrg *
56209ff23fSmrg * Notes on unimplemented XAA optimizations:
57209ff23fSmrg *
58209ff23fSmrg *   SetClipping:   This has been removed as XAA expects 16bit registers
59209ff23fSmrg *                  for full clipping.
60209ff23fSmrg *   TwoPointLine:  The Radeon supports this. Not Bresenham.
61209ff23fSmrg *   DashedLine with non-power-of-two pattern length: Apparently, there is
62209ff23fSmrg *                  no way to set the length of the pattern -- it is always
63209ff23fSmrg *                  assumed to be 8 or 32 (or 1024?).
64209ff23fSmrg *   ScreenToScreenColorExpandFill: See p. 4-17 of the Technical Reference
65209ff23fSmrg *                  Manual where it states that monochrome expansion of frame
66209ff23fSmrg *                  buffer data is not supported.
67209ff23fSmrg *   CPUToScreenColorExpandFill, direct: The implementation here uses a hybrid
68209ff23fSmrg *                  direct/indirect method.  If we had more data registers,
69209ff23fSmrg *                  then we could do better.  If XAA supported a trigger write
70209ff23fSmrg *                  address, the code would be simpler.
71209ff23fSmrg *   Color8x8PatternFill: Apparently, an 8x8 color brush cannot take an 8x8
72209ff23fSmrg *                  pattern from frame buffer memory.
73209ff23fSmrg *   ImageWrites:   Same as CPUToScreenColorExpandFill
74209ff23fSmrg *
75209ff23fSmrg */
76209ff23fSmrg
77209ff23fSmrg#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
78209ff23fSmrg#error Cannot define both MMIO and CP acceleration!
79209ff23fSmrg#endif
80209ff23fSmrg
81209ff23fSmrg#if !defined(UNIXCPP) || defined(ANSICPP)
82209ff23fSmrg#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
83209ff23fSmrg#else
84209ff23fSmrg#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix
85209ff23fSmrg#endif
86209ff23fSmrg
87209ff23fSmrg#ifdef ACCEL_MMIO
88209ff23fSmrg#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
89209ff23fSmrg#else
90209ff23fSmrg#ifdef ACCEL_CP
91209ff23fSmrg#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
92209ff23fSmrg#else
93209ff23fSmrg#error No accel type defined!
94209ff23fSmrg#endif
95209ff23fSmrg#endif
96209ff23fSmrg
97209ff23fSmrg#ifdef USE_XAA
98209ff23fSmrg
99209ff23fSmrg/* This callback is required for multiheader cards using XAA */
100209ff23fSmrgstatic void
101209ff23fSmrgFUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn)
102209ff23fSmrg{
103209ff23fSmrg    /*RADEONInfoPtr  info       = RADEONPTR(pScrn);
104209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;*/
105209ff23fSmrg
106209ff23fSmrg#ifdef ACCEL_MMIO
107209ff23fSmrg
108209ff23fSmrg/*    OUTREG(RADEON_DEFAULT_OFFSET, info->dst_pitch_offset);*/
109209ff23fSmrg    /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */
110209ff23fSmrg
111209ff23fSmrg    RADEONWaitForIdleMMIO(pScrn);
112209ff23fSmrg
113209ff23fSmrg#else /* ACCEL_CP */
114209ff23fSmrg
115209ff23fSmrg/*    RADEONWaitForFifo(pScrn, 1);
116209ff23fSmrg    OUTREG(RADEON_DEFAULT_OFFSET, info->frontPitchOffset);*/
117209ff23fSmrg
118209ff23fSmrg    RADEONWaitForIdleMMIO(pScrn);
119209ff23fSmrg
120209ff23fSmrg#if 0
121209ff23fSmrg    /* Not working yet */
122209ff23fSmrg    RADEONMMIO_TO_CP(pScrn, info);
123209ff23fSmrg#endif
124209ff23fSmrg
125209ff23fSmrg    /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */
126209ff23fSmrg#endif
127209ff23fSmrg}
128209ff23fSmrg
129209ff23fSmrg/* Setup for XAA SolidFill */
130209ff23fSmrgstatic void
131209ff23fSmrgFUNC_NAME(RADEONSetupForSolidFill)(ScrnInfoPtr pScrn,
132209ff23fSmrg				   int color,
133209ff23fSmrg				   int rop,
134209ff23fSmrg				   unsigned int planemask)
135209ff23fSmrg{
136209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
137209ff23fSmrg    ACCEL_PREAMBLE();
138209ff23fSmrg
139209ff23fSmrg    /* Save for later clipping */
140b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
141b7e1c893Smrg						  | RADEON_GMC_BRUSH_SOLID_COLOR
142b7e1c893Smrg						  | RADEON_GMC_SRC_DATATYPE_COLOR
143b7e1c893Smrg						  | RADEON_ROP[rop].pattern);
144209ff23fSmrg
145209ff23fSmrg    BEGIN_ACCEL(4);
146209ff23fSmrg
147b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
148209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR,  color);
149209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
150209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_CNTL,            (RADEON_DST_X_LEFT_TO_RIGHT
151209ff23fSmrg					      | RADEON_DST_Y_TOP_TO_BOTTOM));
152209ff23fSmrg
153209ff23fSmrg    FINISH_ACCEL();
154209ff23fSmrg    BEGIN_ACCEL(2);
155209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
156209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
157209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
158209ff23fSmrg    FINISH_ACCEL();
159209ff23fSmrg}
160209ff23fSmrg
161209ff23fSmrg/* Subsequent XAA SolidFillRect
162209ff23fSmrg *
163209ff23fSmrg * Tests: xtest CH06/fllrctngl, xterm
164209ff23fSmrg */
165209ff23fSmrgstatic void
166209ff23fSmrgFUNC_NAME(RADEONSubsequentSolidFillRect)(ScrnInfoPtr pScrn,
167209ff23fSmrg					 int x, int y,
168209ff23fSmrg					 int w, int h)
169209ff23fSmrg{
170209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
171209ff23fSmrg    ACCEL_PREAMBLE();
172209ff23fSmrg
173209ff23fSmrg    BEGIN_ACCEL(3);
174209ff23fSmrg
175b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
176209ff23fSmrg    	((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
177209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,          (y << 16) | x);
178209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h);
179209ff23fSmrg
180209ff23fSmrg    FINISH_ACCEL();
181209ff23fSmrg}
182209ff23fSmrg
183209ff23fSmrg/* Setup for XAA solid lines */
184209ff23fSmrgstatic void
185209ff23fSmrgFUNC_NAME(RADEONSetupForSolidLine)(ScrnInfoPtr pScrn,
186209ff23fSmrg				   int color,
187209ff23fSmrg				   int rop,
188209ff23fSmrg				   unsigned int planemask)
189209ff23fSmrg{
190209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
191209ff23fSmrg    ACCEL_PREAMBLE();
192209ff23fSmrg
193209ff23fSmrg    /* Save for later clipping */
194b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
195b7e1c893Smrg						  | RADEON_GMC_BRUSH_SOLID_COLOR
196b7e1c893Smrg						  | RADEON_GMC_SRC_DATATYPE_COLOR
197b7e1c893Smrg						  | RADEON_ROP[rop].pattern);
198209ff23fSmrg
199209ff23fSmrg    if (info->ChipFamily >= CHIP_FAMILY_RV200) {
200209ff23fSmrg	BEGIN_ACCEL(1);
201209ff23fSmrg	OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT,
202209ff23fSmrg		      0x55 << RADEON_BRES_CNTL_SHIFT);
203209ff23fSmrg	FINISH_ACCEL();
204209ff23fSmrg    }
205209ff23fSmrg
206209ff23fSmrg    BEGIN_ACCEL(3);
207209ff23fSmrg
208b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
209209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR,  color);
210209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
211209ff23fSmrg
212209ff23fSmrg    FINISH_ACCEL();
213209ff23fSmrg    BEGIN_ACCEL(2);
214209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
215209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
216209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
217209ff23fSmrg    FINISH_ACCEL();
218209ff23fSmrg}
219209ff23fSmrg
220209ff23fSmrg/* Subsequent XAA solid horizontal and vertical lines */
221209ff23fSmrgstatic void
222209ff23fSmrgFUNC_NAME(RADEONSubsequentSolidHorVertLine)(ScrnInfoPtr pScrn,
223209ff23fSmrg					    int x, int y,
224209ff23fSmrg					    int len,
225209ff23fSmrg					    int dir)
226209ff23fSmrg{
227209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
228209ff23fSmrg    int            w    = 1;
229209ff23fSmrg    int            h    = 1;
230209ff23fSmrg    ACCEL_PREAMBLE();
231209ff23fSmrg
232209ff23fSmrg    if (dir == DEGREES_0) w = len;
233209ff23fSmrg    else                  h = len;
234209ff23fSmrg
235209ff23fSmrg    BEGIN_ACCEL(4);
236209ff23fSmrg
237209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_CNTL,          (RADEON_DST_X_LEFT_TO_RIGHT
238209ff23fSmrg					    | RADEON_DST_Y_TOP_TO_BOTTOM));
239b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
240209ff23fSmrg    	((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
241209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,          (y << 16) | x);
242209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h);
243209ff23fSmrg
244209ff23fSmrg    FINISH_ACCEL();
245209ff23fSmrg}
246209ff23fSmrg
247209ff23fSmrg/* Subsequent XAA solid TwoPointLine line
248209ff23fSmrg *
249209ff23fSmrg * Tests: xtest CH06/drwln, ico, Mark Vojkovich's linetest program
250209ff23fSmrg *
251209ff23fSmrg * [See http://www.xfree86.org/devel/archives/devel/1999-Jun/0102.shtml for
252209ff23fSmrg * Mark Vojkovich's linetest program, posted 2Jun99 to devel@xfree86.org.]
253209ff23fSmrg */
254209ff23fSmrgstatic void
255209ff23fSmrgFUNC_NAME(RADEONSubsequentSolidTwoPointLine)(ScrnInfoPtr pScrn,
256209ff23fSmrg					     int xa, int ya,
257209ff23fSmrg					     int xb, int yb,
258209ff23fSmrg					     int flags)
259209ff23fSmrg{
260209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
261209ff23fSmrg    ACCEL_PREAMBLE();
262209ff23fSmrg
263209ff23fSmrg    /* TODO: Check bounds -- RADEON only has 14 bits */
264209ff23fSmrg
265209ff23fSmrg    if (!(flags & OMIT_LAST))
266209ff23fSmrg	FUNC_NAME(RADEONSubsequentSolidHorVertLine)(pScrn,
267209ff23fSmrg						    xb, yb, 1,
268209ff23fSmrg						    DEGREES_0);
269209ff23fSmrg
270209ff23fSmrg    BEGIN_ACCEL(3);
271209ff23fSmrg
272b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
273209ff23fSmrg    	((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
274209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa);
275209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_LINE_END,   (yb << 16) | xb);
276209ff23fSmrg
277209ff23fSmrg    FINISH_ACCEL();
278209ff23fSmrg}
279209ff23fSmrg
280209ff23fSmrg/* Setup for XAA dashed lines
281209ff23fSmrg *
282209ff23fSmrg * Tests: xtest CH05/stdshs, XFree86/drwln
283209ff23fSmrg *
284209ff23fSmrg * NOTE: Since we can only accelerate lines with power-of-2 patterns of
285209ff23fSmrg * length <= 32
286209ff23fSmrg */
287209ff23fSmrgstatic void
288209ff23fSmrgFUNC_NAME(RADEONSetupForDashedLine)(ScrnInfoPtr pScrn,
289209ff23fSmrg				    int fg,
290209ff23fSmrg				    int bg,
291209ff23fSmrg				    int rop,
292209ff23fSmrg				    unsigned int planemask,
293209ff23fSmrg				    int length,
294209ff23fSmrg				    unsigned char *pattern)
295209ff23fSmrg{
296209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
297209ff23fSmrg    uint32_t pat  = *(uint32_t *)(pointer)pattern;
298209ff23fSmrg    ACCEL_PREAMBLE();
299209ff23fSmrg
300209ff23fSmrg    /* Save for determining whether or not to draw last pixel */
301b7e1c893Smrg    info->accel_state->dashLen = length;
302b7e1c893Smrg    info->accel_state->dashPattern = pat;
303209ff23fSmrg
304209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
305209ff23fSmrg# define PAT_SHIFT(pat, shift) (pat >> shift)
306209ff23fSmrg#else
307209ff23fSmrg# define PAT_SHIFT(pat, shift) (pat << shift)
308209ff23fSmrg#endif
309209ff23fSmrg
310209ff23fSmrg    switch (length) {
311209ff23fSmrg    case  2: pat |= PAT_SHIFT(pat,  2);  /* fall through */
312209ff23fSmrg    case  4: pat |= PAT_SHIFT(pat,  4);  /* fall through */
313209ff23fSmrg    case  8: pat |= PAT_SHIFT(pat,  8);  /* fall through */
314209ff23fSmrg    case 16: pat |= PAT_SHIFT(pat, 16);
315209ff23fSmrg    }
316209ff23fSmrg
317209ff23fSmrg    /* Save for later clipping */
318b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
319b7e1c893Smrg						  | (bg == -1
320b7e1c893Smrg						     ? RADEON_GMC_BRUSH_32x1_MONO_FG_LA
321b7e1c893Smrg						     : RADEON_GMC_BRUSH_32x1_MONO_FG_BG)
322b7e1c893Smrg						  | RADEON_ROP[rop].pattern
323b7e1c893Smrg						  | RADEON_GMC_BYTE_LSB_TO_MSB);
324b7e1c893Smrg    info->accel_state->dash_fg = fg;
325b7e1c893Smrg    info->accel_state->dash_bg = bg;
326209ff23fSmrg
327209ff23fSmrg    BEGIN_ACCEL((bg == -1) ? 4 : 5);
328209ff23fSmrg
329b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
330209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
331209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR,  fg);
332209ff23fSmrg    if (bg != -1)
333209ff23fSmrg	OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, bg);
334209ff23fSmrg    OUT_ACCEL_REG(RADEON_BRUSH_DATA0,        pat);
335209ff23fSmrg
336209ff23fSmrg    FINISH_ACCEL();
337209ff23fSmrg    BEGIN_ACCEL(2);
338209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
339209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
340209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
341209ff23fSmrg    FINISH_ACCEL();
342209ff23fSmrg}
343209ff23fSmrg
344209ff23fSmrg/* Helper function to draw last point for dashed lines */
345209ff23fSmrgstatic void
346209ff23fSmrgFUNC_NAME(RADEONDashedLastPel)(ScrnInfoPtr pScrn,
347209ff23fSmrg			       int x, int y,
348209ff23fSmrg			       int fg)
349209ff23fSmrg{
350209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
351b7e1c893Smrg    uint32_t dp_gui_master_cntl = info->accel_state->dp_gui_master_cntl_clip;
352209ff23fSmrg    ACCEL_PREAMBLE();
353209ff23fSmrg
354209ff23fSmrg    dp_gui_master_cntl &= ~RADEON_GMC_BRUSH_DATATYPE_MASK;
355209ff23fSmrg    dp_gui_master_cntl |=  RADEON_GMC_BRUSH_SOLID_COLOR;
356209ff23fSmrg
357209ff23fSmrg    dp_gui_master_cntl &= ~RADEON_GMC_SRC_DATATYPE_MASK;
358209ff23fSmrg    dp_gui_master_cntl |=  RADEON_GMC_SRC_DATATYPE_COLOR;
359209ff23fSmrg
360209ff23fSmrg    BEGIN_ACCEL(8);
361209ff23fSmrg
362209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, dp_gui_master_cntl);
363209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_CNTL,            (RADEON_DST_X_LEFT_TO_RIGHT
364209ff23fSmrg					      | RADEON_DST_Y_TOP_TO_BOTTOM));
365b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
366209ff23fSmrg    	((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
367209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR,  fg);
368209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,            (y << 16) | x);
369209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT,   (1 << 16) | 1);
370209ff23fSmrg
371209ff23fSmrg    /* Restore old values */
372b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
373b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR,  info->accel_state->dash_fg);
374209ff23fSmrg
375209ff23fSmrg    FINISH_ACCEL();
376209ff23fSmrg    BEGIN_ACCEL(2);
377209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
378209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
379209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
380209ff23fSmrg    FINISH_ACCEL();
381209ff23fSmrg}
382209ff23fSmrg
383209ff23fSmrg/* Subsequent XAA dashed line */
384209ff23fSmrgstatic void
385209ff23fSmrgFUNC_NAME(RADEONSubsequentDashedTwoPointLine)(ScrnInfoPtr pScrn,
386209ff23fSmrg					      int xa, int ya,
387209ff23fSmrg					      int xb, int yb,
388209ff23fSmrg					      int flags,
389209ff23fSmrg					      int phase)
390209ff23fSmrg{
391209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
392209ff23fSmrg    ACCEL_PREAMBLE();
393209ff23fSmrg
394209ff23fSmrg    /* TODO: Check bounds -- RADEON only has 14 bits */
395209ff23fSmrg
396209ff23fSmrg    if (!(flags & OMIT_LAST)) {
397209ff23fSmrg	int deltax = abs(xa - xb);
398209ff23fSmrg	int deltay = abs(ya - yb);
399209ff23fSmrg	int shift;
400209ff23fSmrg
401209ff23fSmrg	if (deltax > deltay) shift = deltax;
402209ff23fSmrg	else                 shift = deltay;
403209ff23fSmrg
404209ff23fSmrg	shift += phase;
405b7e1c893Smrg	shift %= info->accel_state->dashLen;
406209ff23fSmrg
407b7e1c893Smrg	if ((info->accel_state->dashPattern >> shift) & 1)
408b7e1c893Smrg	    FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->accel_state->dash_fg);
409b7e1c893Smrg	else if (info->accel_state->dash_bg != -1)
410b7e1c893Smrg	    FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->accel_state->dash_bg);
411209ff23fSmrg    }
412209ff23fSmrg
413209ff23fSmrg    BEGIN_ACCEL(4);
414209ff23fSmrg
415b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
416209ff23fSmrg    	((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
417209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_LINE_START,   (ya << 16) | xa);
418209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT, phase);
419209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_LINE_END,     (yb << 16) | xb);
420209ff23fSmrg
421209ff23fSmrg    FINISH_ACCEL();
422209ff23fSmrg}
423209ff23fSmrg
424209ff23fSmrg/* Set up for transparency
425209ff23fSmrg *
426209ff23fSmrg * Mmmm, Seems as though the transparency compare is opposite to r128.
427209ff23fSmrg * It should only draw when source != trans_color, this is the opposite
428209ff23fSmrg * of that.
429209ff23fSmrg */
430209ff23fSmrgstatic void
431209ff23fSmrgFUNC_NAME(RADEONSetTransparency)(ScrnInfoPtr pScrn,
432209ff23fSmrg				 int trans_color)
433209ff23fSmrg{
434209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
435209ff23fSmrg
436b7e1c893Smrg    if ((trans_color != -1) || (info->accel_state->XAAForceTransBlit == TRUE)) {
437209ff23fSmrg	ACCEL_PREAMBLE();
438209ff23fSmrg
439209ff23fSmrg	BEGIN_ACCEL(3);
440209ff23fSmrg
441209ff23fSmrg	OUT_ACCEL_REG(RADEON_CLR_CMP_CLR_SRC, trans_color);
442209ff23fSmrg	OUT_ACCEL_REG(RADEON_CLR_CMP_MASK,    RADEON_CLR_CMP_MSK);
443209ff23fSmrg	OUT_ACCEL_REG(RADEON_CLR_CMP_CNTL,    (RADEON_SRC_CMP_EQ_COLOR
444209ff23fSmrg					       | RADEON_CLR_CMP_SRC_SOURCE));
445209ff23fSmrg
446209ff23fSmrg	FINISH_ACCEL();
447209ff23fSmrg    }
448209ff23fSmrg}
449209ff23fSmrg
450209ff23fSmrg/* Setup for XAA screen-to-screen copy
451209ff23fSmrg *
452209ff23fSmrg * Tests: xtest CH06/fllrctngl (also tests transparency)
453209ff23fSmrg */
454209ff23fSmrgstatic void
455209ff23fSmrgFUNC_NAME(RADEONSetupForScreenToScreenCopy)(ScrnInfoPtr pScrn,
456209ff23fSmrg					    int xdir, int ydir,
457209ff23fSmrg					    int rop,
458209ff23fSmrg					    unsigned int planemask,
459209ff23fSmrg					    int trans_color)
460209ff23fSmrg{
461209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
462209ff23fSmrg    ACCEL_PREAMBLE();
463209ff23fSmrg
464b7e1c893Smrg    info->accel_state->xdir = xdir;
465b7e1c893Smrg    info->accel_state->ydir = ydir;
466209ff23fSmrg
467209ff23fSmrg    /* Save for later clipping */
468b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
469b7e1c893Smrg						  | RADEON_GMC_BRUSH_NONE
470b7e1c893Smrg						  | RADEON_GMC_SRC_DATATYPE_COLOR
471b7e1c893Smrg						  | RADEON_ROP[rop].rop
472b7e1c893Smrg						  | RADEON_DP_SRC_SOURCE_MEMORY
473b7e1c893Smrg						  | RADEON_GMC_SRC_PITCH_OFFSET_CNTL);
474209ff23fSmrg
475209ff23fSmrg    BEGIN_ACCEL(3);
476209ff23fSmrg
477b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
478209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
479209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_CNTL,
480209ff23fSmrg		  ((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
481209ff23fSmrg		   (ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
482209ff23fSmrg
483209ff23fSmrg    FINISH_ACCEL();
484209ff23fSmrg    BEGIN_ACCEL(2);
485209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
486209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
487209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
488209ff23fSmrg    FINISH_ACCEL();
489209ff23fSmrg
490b7e1c893Smrg    info->accel_state->trans_color = trans_color;
491209ff23fSmrg    FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
492209ff23fSmrg}
493209ff23fSmrg
494209ff23fSmrg/* Subsequent XAA screen-to-screen copy */
495209ff23fSmrgstatic void
496209ff23fSmrgFUNC_NAME(RADEONSubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn,
497209ff23fSmrg					      int xa, int ya,
498209ff23fSmrg					      int xb, int yb,
499209ff23fSmrg					      int w, int h)
500209ff23fSmrg{
501209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
502209ff23fSmrg    ACCEL_PREAMBLE();
503209ff23fSmrg
504b7e1c893Smrg    if (info->accel_state->xdir < 0) xa += w - 1, xb += w - 1;
505b7e1c893Smrg    if (info->accel_state->ydir < 0) ya += h - 1, yb += h - 1;
506209ff23fSmrg
507209ff23fSmrg    BEGIN_ACCEL(5);
508209ff23fSmrg
509b7e1c893Smrg    OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
510209ff23fSmrg    	((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
511b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
512209ff23fSmrg    	((info->tilingEnabled && (yb <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
513209ff23fSmrg    OUT_ACCEL_REG(RADEON_SRC_Y_X,          (ya << 16) | xa);
514209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,          (yb << 16) | xb);
515209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h  << 16) | w);
516209ff23fSmrg
517209ff23fSmrg    FINISH_ACCEL();
518209ff23fSmrg}
519209ff23fSmrg
520209ff23fSmrg/* Setup for XAA mono 8x8 pattern color expansion.  Patterns with
521209ff23fSmrg * transparency use `bg == -1'.  This routine is only used if the XAA
522209ff23fSmrg * pixmap cache is turned on.
523209ff23fSmrg *
524209ff23fSmrg * Tests: xtest XFree86/fllrctngl (no other test will test this routine with
525209ff23fSmrg *                                 both transparency and non-transparency)
526209ff23fSmrg */
527209ff23fSmrgstatic void
528209ff23fSmrgFUNC_NAME(RADEONSetupForMono8x8PatternFill)(ScrnInfoPtr pScrn,
529209ff23fSmrg					    int patternx,
530209ff23fSmrg					    int patterny,
531209ff23fSmrg					    int fg,
532209ff23fSmrg					    int bg,
533209ff23fSmrg					    int rop,
534209ff23fSmrg					    unsigned int planemask)
535209ff23fSmrg{
536209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
537209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
538209ff23fSmrg    unsigned char  pattern[8];
539209ff23fSmrg#endif
540209ff23fSmrg    ACCEL_PREAMBLE();
541209ff23fSmrg
542209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
543209ff23fSmrg    /* Take care of endianness */
544209ff23fSmrg    pattern[0] = (patternx & 0x000000ff);
545209ff23fSmrg    pattern[1] = (patternx & 0x0000ff00) >> 8;
546209ff23fSmrg    pattern[2] = (patternx & 0x00ff0000) >> 16;
547209ff23fSmrg    pattern[3] = (patternx & 0xff000000) >> 24;
548209ff23fSmrg    pattern[4] = (patterny & 0x000000ff);
549209ff23fSmrg    pattern[5] = (patterny & 0x0000ff00) >> 8;
550209ff23fSmrg    pattern[6] = (patterny & 0x00ff0000) >> 16;
551209ff23fSmrg    pattern[7] = (patterny & 0xff000000) >> 24;
552209ff23fSmrg#endif
553209ff23fSmrg
554209ff23fSmrg    /* Save for later clipping */
555b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
556b7e1c893Smrg						  | (bg == -1
557b7e1c893Smrg						     ? RADEON_GMC_BRUSH_8X8_MONO_FG_LA
558b7e1c893Smrg						     : RADEON_GMC_BRUSH_8X8_MONO_FG_BG)
559b7e1c893Smrg						  | RADEON_ROP[rop].pattern
560209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
561b7e1c893Smrg						  | RADEON_GMC_BYTE_MSB_TO_LSB
562209ff23fSmrg#endif
563b7e1c893Smrg						  );
564209ff23fSmrg
565209ff23fSmrg    BEGIN_ACCEL((bg == -1) ? 5 : 6);
566209ff23fSmrg
567b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
568209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
569209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR,  fg);
570209ff23fSmrg    if (bg != -1)
571209ff23fSmrg	OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, bg);
572209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
573209ff23fSmrg    OUT_ACCEL_REG(RADEON_BRUSH_DATA0,        patternx);
574209ff23fSmrg    OUT_ACCEL_REG(RADEON_BRUSH_DATA1,        patterny);
575209ff23fSmrg#else
576209ff23fSmrg    OUT_ACCEL_REG(RADEON_BRUSH_DATA0,        *(uint32_t *)(pointer)&pattern[0]);
577209ff23fSmrg    OUT_ACCEL_REG(RADEON_BRUSH_DATA1,        *(uint32_t *)(pointer)&pattern[4]);
578209ff23fSmrg#endif
579209ff23fSmrg
580209ff23fSmrg    FINISH_ACCEL();
581209ff23fSmrg    BEGIN_ACCEL(2);
582209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
583209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
584209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
585209ff23fSmrg    FINISH_ACCEL();
586209ff23fSmrg}
587209ff23fSmrg
588209ff23fSmrg/* Subsequent XAA 8x8 pattern color expansion.  Because they are used in
589209ff23fSmrg * the setup function, `patternx' and `patterny' are not used here.
590209ff23fSmrg */
591209ff23fSmrgstatic void
592209ff23fSmrgFUNC_NAME(RADEONSubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn,
593209ff23fSmrg						  int patternx,
594209ff23fSmrg						  int patterny,
595209ff23fSmrg						  int x, int y,
596209ff23fSmrg						  int w, int h)
597209ff23fSmrg{
598209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
599209ff23fSmrg    ACCEL_PREAMBLE();
600209ff23fSmrg
601209ff23fSmrg    BEGIN_ACCEL(4);
602209ff23fSmrg
603b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
604209ff23fSmrg    	((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
605209ff23fSmrg    OUT_ACCEL_REG(RADEON_BRUSH_Y_X,        (patterny << 8) | patternx);
606209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,          (y << 16) | x);
607209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
608209ff23fSmrg
609209ff23fSmrg    FINISH_ACCEL();
610209ff23fSmrg}
611209ff23fSmrg
612209ff23fSmrg#if 0
613209ff23fSmrg/* Setup for XAA color 8x8 pattern fill
614209ff23fSmrg *
615209ff23fSmrg * Tests: xtest XFree86/fllrctngl (with Mono8x8PatternFill off)
616209ff23fSmrg */
617209ff23fSmrgstatic void
618209ff23fSmrgFUNC_NAME(RADEONSetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,
619209ff23fSmrg					     int patx, int paty,
620209ff23fSmrg					     int rop,
621209ff23fSmrg					     unsigned int planemask,
622209ff23fSmrg					     int trans_color)
623209ff23fSmrg{
624209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
625209ff23fSmrg    ACCEL_PREAMBLE();
626209ff23fSmrg
627209ff23fSmrg    /* Save for later clipping */
628b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
629b7e1c893Smrg						  | RADEON_GMC_BRUSH_8x8_COLOR
630b7e1c893Smrg						  | RADEON_GMC_SRC_DATATYPE_COLOR
631b7e1c893Smrg						  | RADEON_ROP[rop].pattern
632b7e1c893Smrg						  | RADEON_DP_SRC_SOURCE_MEMORY);
633209ff23fSmrg
634209ff23fSmrg    BEGIN_ACCEL(3);
635209ff23fSmrg
636b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
637209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
638209ff23fSmrg    OUT_ACCEL_REG(RADEON_SRC_Y_X,            (paty << 16) | patx);
639209ff23fSmrg
640209ff23fSmrg    FINISH_ACCEL();
641209ff23fSmrg
642b7e1c893Smrg    info->accel_state->trans_color = trans_color;
643209ff23fSmrg    FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
644209ff23fSmrg}
645209ff23fSmrg
646209ff23fSmrg/* Subsequent XAA 8x8 pattern color expansion */
647209ff23fSmrgstatic void
648209ff23fSmrgFUNC_NAME(RADEONSubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn,
649209ff23fSmrg						   int patx, int paty,
650209ff23fSmrg						   int x, int y,
651209ff23fSmrg						   int w, int h)
652209ff23fSmrg{
653209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
654209ff23fSmrg    ACCEL_PREAMBLE();
655209ff23fSmrg
656209ff23fSmrg    BEGIN_ACCEL(4);
657209ff23fSmrg
658b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
659209ff23fSmrg    	((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
660209ff23fSmrg    OUT_ACCEL_REG(RADEON_BRUSH_Y_X,        (paty << 16) | patx);
661209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,          (y << 16) | x);
662209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
663209ff23fSmrg
664209ff23fSmrg    FINISH_ACCEL();
665209ff23fSmrg}
666209ff23fSmrg#endif
667209ff23fSmrg
668209ff23fSmrg#ifdef ACCEL_CP
669b7e1c893Smrg#define CP_BUFSIZE (info->cp->indirectBuffer->total/4-10)
670209ff23fSmrg
671209ff23fSmrg/* Helper function to write out a HOSTDATA_BLT packet into the indirect
672209ff23fSmrg * buffer and set the XAA scratch buffer address appropriately.
673209ff23fSmrg */
674209ff23fSmrgstatic void
675209ff23fSmrgRADEONCPScanlinePacket(ScrnInfoPtr pScrn, int bufno)
676209ff23fSmrg{
677209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
678b7e1c893Smrg    int           chunk_words = info->accel_state->scanline_hpass * info->accel_state->scanline_words;
679209ff23fSmrg    ACCEL_PREAMBLE();
680209ff23fSmrg
681209ff23fSmrg    if (RADEON_VERBOSE) {
682209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
683209ff23fSmrg		   "CPScanline Packet h=%d hpass=%d chunkwords=%d\n",
684b7e1c893Smrg		   info->accel_state->scanline_h, info->accel_state->scanline_hpass, chunk_words);
685209ff23fSmrg    }
686209ff23fSmrg    BEGIN_RING(chunk_words+10);
687209ff23fSmrg
688209ff23fSmrg    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT,chunk_words+10-2));
689b7e1c893Smrg    OUT_RING(info->accel_state->dp_gui_master_cntl_clip);
690b7e1c893Smrg    OUT_RING(info->accel_state->dst_pitch_offset |
691b7e1c893Smrg    	((info->tilingEnabled && (info->accel_state->scanline_y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
692b7e1c893Smrg    OUT_RING((info->accel_state->scanline_y << 16) |
693b7e1c893Smrg	     (info->accel_state->scanline_x1clip & 0xffff));
694b7e1c893Smrg    OUT_RING(((info->accel_state->scanline_y+info->accel_state->scanline_hpass) << 16) |
695b7e1c893Smrg	     (info->accel_state->scanline_x2clip & 0xffff));
696b7e1c893Smrg    OUT_RING(info->accel_state->scanline_fg);
697b7e1c893Smrg    OUT_RING(info->accel_state->scanline_bg);
698b7e1c893Smrg    OUT_RING((info->accel_state->scanline_y << 16) |
699b7e1c893Smrg	     (info->accel_state->scanline_x & 0xffff));
700b7e1c893Smrg    OUT_RING((info->accel_state->scanline_hpass << 16) |
701b7e1c893Smrg	     (info->accel_state->scanline_w & 0xffff));
702209ff23fSmrg    OUT_RING(chunk_words);
703209ff23fSmrg
704b7e1c893Smrg    info->accel_state->scratch_buffer[bufno] = (unsigned char *)&__head[__count];
705209ff23fSmrg    __count += chunk_words;
706209ff23fSmrg
707209ff23fSmrg    /* The ring can only be advanced after the __head and __count have
708209ff23fSmrg       been adjusted above */
709209ff23fSmrg    FINISH_ACCEL();
710209ff23fSmrg
711b7e1c893Smrg    info->accel_state->scanline_y += info->accel_state->scanline_hpass;
712b7e1c893Smrg    info->accel_state->scanline_h -= info->accel_state->scanline_hpass;
713209ff23fSmrg}
714209ff23fSmrg#endif
715209ff23fSmrg
716209ff23fSmrg/* Setup for XAA indirect CPU-to-screen color expansion (indirect).
717209ff23fSmrg * Because of how the scratch buffer is initialized, this is really a
718209ff23fSmrg * mainstore-to-screen color expansion.  Transparency is supported when
719209ff23fSmrg * `bg == -1'.
720209ff23fSmrg */
721209ff23fSmrgstatic void
722209ff23fSmrgFUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn,
723209ff23fSmrg							    int fg,
724209ff23fSmrg							    int bg,
725209ff23fSmrg							    int rop,
726209ff23fSmrg							    unsigned int
727209ff23fSmrg							    planemask)
728209ff23fSmrg{
729209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
730209ff23fSmrg    ACCEL_PREAMBLE();
731209ff23fSmrg
732b7e1c893Smrg    info->accel_state->scanline_bpp = 0;
733209ff23fSmrg
734209ff23fSmrg    /* Save for later clipping */
735b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
736b7e1c893Smrg						  | RADEON_GMC_DST_CLIPPING
737b7e1c893Smrg						  | RADEON_GMC_BRUSH_NONE
738b7e1c893Smrg						  | (bg == -1
739b7e1c893Smrg						     ? RADEON_GMC_SRC_DATATYPE_MONO_FG_LA
740b7e1c893Smrg						     : RADEON_GMC_SRC_DATATYPE_MONO_FG_BG)
741b7e1c893Smrg						  | RADEON_ROP[rop].rop
742209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
743b7e1c893Smrg						  | RADEON_GMC_BYTE_LSB_TO_MSB
744209ff23fSmrg#else
745b7e1c893Smrg						  | RADEON_GMC_BYTE_MSB_TO_LSB
746209ff23fSmrg#endif
747b7e1c893Smrg						  | RADEON_DP_SRC_SOURCE_HOST_DATA);
748209ff23fSmrg
749209ff23fSmrg#ifdef ACCEL_MMIO
750209ff23fSmrg
751209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
752209ff23fSmrg    BEGIN_ACCEL(4);
753209ff23fSmrg#else
754209ff23fSmrg    BEGIN_ACCEL(5);
755209ff23fSmrg
756209ff23fSmrg    OUT_ACCEL_REG(RADEON_RBBM_GUICNTL,       RADEON_HOST_DATA_SWAP_NONE);
757209ff23fSmrg#endif
758b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
759209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
760209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR,    fg);
761209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR,    bg);
762209ff23fSmrg
763209ff23fSmrg#else /* ACCEL_CP */
764209ff23fSmrg
765b7e1c893Smrg    info->accel_state->scanline_fg = fg;
766b7e1c893Smrg    info->accel_state->scanline_bg = bg;
767209ff23fSmrg
768209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
769209ff23fSmrg    BEGIN_ACCEL(1);
770209ff23fSmrg#else
771209ff23fSmrg    if (info->ChipFamily < CHIP_FAMILY_R300) {
772209ff23fSmrg	BEGIN_ACCEL(2);
773209ff23fSmrg
774209ff23fSmrg	OUT_ACCEL_REG(RADEON_RBBM_GUICNTL,   RADEON_HOST_DATA_SWAP_32BIT);
775209ff23fSmrg    } else
776209ff23fSmrg	BEGIN_ACCEL(1);
777209ff23fSmrg#endif
778209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
779209ff23fSmrg
780209ff23fSmrg#endif
781209ff23fSmrg
782209ff23fSmrg    FINISH_ACCEL();
783209ff23fSmrg}
784209ff23fSmrg
785209ff23fSmrg/* Subsequent XAA indirect CPU-to-screen color expansion.  This is only
786209ff23fSmrg * called once for each rectangle.
787209ff23fSmrg */
788209ff23fSmrgstatic void
789209ff23fSmrgFUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr
790209ff23fSmrg							      pScrn,
791209ff23fSmrg							      int x, int y,
792209ff23fSmrg							      int w, int h,
793209ff23fSmrg							      int skipleft)
794209ff23fSmrg{
795209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
796209ff23fSmrg#ifdef ACCEL_MMIO
797209ff23fSmrg    ACCEL_PREAMBLE();
798209ff23fSmrg
799b7e1c893Smrg    info->accel_state->scanline_h      = h;
800b7e1c893Smrg    info->accel_state->scanline_words  = (w + 31) >> 5;
801209ff23fSmrg
802209ff23fSmrg#ifdef __alpha__
803209ff23fSmrg    /* Always use indirect for Alpha */
804209ff23fSmrg    if (0)
805209ff23fSmrg#else
806b7e1c893Smrg    if ((info->accel_state->scanline_words * h) <= 9)
807209ff23fSmrg#endif
808209ff23fSmrg    {
809209ff23fSmrg	/* Turn on direct for less than 9 dword colour expansion */
810b7e1c893Smrg	info->accel_state->scratch_buffer[0] =
811209ff23fSmrg	    (unsigned char *)(ADDRREG(RADEON_HOST_DATA_LAST)
812b7e1c893Smrg			      - (info->accel_state->scanline_words - 1));
813b7e1c893Smrg	info->accel_state->scanline_direct   = 1;
814209ff23fSmrg    } else {
815209ff23fSmrg	/* Use indirect for anything else */
816b7e1c893Smrg	info->accel_state->scratch_buffer[0] = info->accel_state->scratch_save;
817b7e1c893Smrg	info->accel_state->scanline_direct   = 0;
818209ff23fSmrg    }
819209ff23fSmrg
820b7e1c893Smrg    BEGIN_ACCEL(5 + (info->accel_state->scanline_direct ?
821b7e1c893Smrg		     (info->accel_state->scanline_words * h) : 0));
822209ff23fSmrg
823b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
824209ff23fSmrg    	((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
825209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_TOP_LEFT,      (y << 16)     | ((x+skipleft)
826209ff23fSmrg							    & 0xffff));
827209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT,  ((y+h) << 16) | ((x+w) & 0xffff));
828209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,          (y << 16)     | (x & 0xffff));
829209ff23fSmrg    /* Have to pad the width here and use clipping engine */
830ad43ddacSmrg    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16)     | RADEON_ALIGN(w, 32));
831209ff23fSmrg
832209ff23fSmrg    FINISH_ACCEL();
833209ff23fSmrg
834209ff23fSmrg#else /* ACCEL_CP */
835209ff23fSmrg
836b7e1c893Smrg    info->accel_state->scanline_x      = x;
837b7e1c893Smrg    info->accel_state->scanline_y      = y;
838209ff23fSmrg    /* Have to pad the width here and use clipping engine */
839ad43ddacSmrg    info->accel_state->scanline_w      = RADEON_ALIGN(w, 32);
840b7e1c893Smrg    info->accel_state->scanline_h      = h;
841209ff23fSmrg
842b7e1c893Smrg    info->accel_state->scanline_x1clip = x + skipleft;
843b7e1c893Smrg    info->accel_state->scanline_x2clip = x + w;
844209ff23fSmrg
845b7e1c893Smrg    info->accel_state->scanline_words  = info->accel_state->scanline_w / 32;
846b7e1c893Smrg    info->accel_state->scanline_hpass  = min(h,(CP_BUFSIZE/info->accel_state->scanline_words));
847209ff23fSmrg
848209ff23fSmrg    RADEONCPScanlinePacket(pScrn, 0);
849209ff23fSmrg
850209ff23fSmrg#endif
851209ff23fSmrg}
852209ff23fSmrg
853209ff23fSmrg/* Subsequent XAA indirect CPU-to-screen color expansion and indirect
854209ff23fSmrg * image write.  This is called once for each scanline.
855209ff23fSmrg */
856209ff23fSmrgstatic void
857209ff23fSmrgFUNC_NAME(RADEONSubsequentScanline)(ScrnInfoPtr pScrn,
858209ff23fSmrg				    int bufno)
859209ff23fSmrg{
860209ff23fSmrg    RADEONInfoPtr    info = RADEONPTR(pScrn);
861209ff23fSmrg#ifdef ACCEL_MMIO
862b7e1c893Smrg    uint32_t        *p    = (pointer)info->accel_state->scratch_buffer[bufno];
863209ff23fSmrg    int              i;
864b7e1c893Smrg    int              left = info->accel_state->scanline_words;
865209ff23fSmrg    volatile uint32_t *d;
866209ff23fSmrg    ACCEL_PREAMBLE();
867209ff23fSmrg
868b7e1c893Smrg    if (info->accel_state->scanline_direct) return;
869209ff23fSmrg
870b7e1c893Smrg    --info->accel_state->scanline_h;
871209ff23fSmrg
872209ff23fSmrg    while (left) {
873209ff23fSmrg	write_mem_barrier();
874209ff23fSmrg	if (left <= 8) {
875209ff23fSmrg	  /* Last scanline - finish write to DATA_LAST */
876b7e1c893Smrg	  if (info->accel_state->scanline_h == 0) {
877209ff23fSmrg	    BEGIN_ACCEL(left);
878209ff23fSmrg				/* Unrolling doesn't improve performance */
879209ff23fSmrg	    for (d = ADDRREG(RADEON_HOST_DATA_LAST) - (left - 1); left; --left)
880209ff23fSmrg		*d++ = *p++;
881209ff23fSmrg	    return;
882209ff23fSmrg	  } else {
883209ff23fSmrg	    BEGIN_ACCEL(left);
884209ff23fSmrg				/* Unrolling doesn't improve performance */
885209ff23fSmrg	    for (d = ADDRREG(RADEON_HOST_DATA7) - (left - 1); left; --left)
886209ff23fSmrg		*d++ = *p++;
887209ff23fSmrg	  }
888209ff23fSmrg	} else {
889209ff23fSmrg	    BEGIN_ACCEL(8);
890209ff23fSmrg				/* Unrolling doesn't improve performance */
891209ff23fSmrg	    for (d = ADDRREG(RADEON_HOST_DATA0), i = 0; i < 8; i++)
892209ff23fSmrg		*d++ = *p++;
893209ff23fSmrg	    left -= 8;
894209ff23fSmrg	}
895209ff23fSmrg    }
896209ff23fSmrg
897209ff23fSmrg    FINISH_ACCEL();
898209ff23fSmrg
899209ff23fSmrg#else /* ACCEL_CP */
900209ff23fSmrg
901209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
902209ff23fSmrg    if (info->ChipFamily >= CHIP_FAMILY_R300) {
903b7e1c893Smrg	if (info->accel_state->scanline_bpp == 16) {
904b7e1c893Smrg	    RADEONCopySwap(info->accel_state->scratch_buffer[bufno],
905b7e1c893Smrg			   info->accel_state->scratch_buffer[bufno],
906b7e1c893Smrg			   info->accel_state->scanline_words << 2,
907209ff23fSmrg			   RADEON_HOST_DATA_SWAP_HDW);
908b7e1c893Smrg	} else if (info->accel_state->scanline_bpp < 15) {
909b7e1c893Smrg	    RADEONCopySwap(info->accel_state->scratch_buffer[bufno],
910b7e1c893Smrg			   info->accel_state->scratch_buffer[bufno],
911b7e1c893Smrg			   info->accel_state->scanline_words << 2,
912209ff23fSmrg			   RADEON_HOST_DATA_SWAP_32BIT);
913209ff23fSmrg	}
914209ff23fSmrg    }
915209ff23fSmrg#endif
916209ff23fSmrg
917b7e1c893Smrg    if (--info->accel_state->scanline_hpass) {
918b7e1c893Smrg	info->accel_state->scratch_buffer[bufno] += 4 * info->accel_state->scanline_words;
919b7e1c893Smrg    } else if (info->accel_state->scanline_h) {
920b7e1c893Smrg	info->accel_state->scanline_hpass =
921b7e1c893Smrg	    min(info->accel_state->scanline_h,(CP_BUFSIZE/info->accel_state->scanline_words));
922209ff23fSmrg	RADEONCPScanlinePacket(pScrn, bufno);
923209ff23fSmrg    }
924209ff23fSmrg
925209ff23fSmrg#endif
926209ff23fSmrg}
927209ff23fSmrg
928209ff23fSmrg/* Setup for XAA indirect image write */
929209ff23fSmrgstatic void
930209ff23fSmrgFUNC_NAME(RADEONSetupForScanlineImageWrite)(ScrnInfoPtr pScrn,
931209ff23fSmrg					    int rop,
932209ff23fSmrg					    unsigned int planemask,
933209ff23fSmrg					    int trans_color,
934209ff23fSmrg					    int bpp,
935209ff23fSmrg					    int depth)
936209ff23fSmrg{
937209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
938209ff23fSmrg    ACCEL_PREAMBLE();
939209ff23fSmrg
940b7e1c893Smrg    info->accel_state->scanline_bpp = bpp;
941209ff23fSmrg
942209ff23fSmrg    /* Save for later clipping */
943b7e1c893Smrg    info->accel_state->dp_gui_master_cntl_clip = (info->accel_state->dp_gui_master_cntl
944b7e1c893Smrg						  | RADEON_GMC_DST_CLIPPING
945b7e1c893Smrg						  | RADEON_GMC_BRUSH_NONE
946b7e1c893Smrg						  | RADEON_GMC_SRC_DATATYPE_COLOR
947b7e1c893Smrg						  | RADEON_ROP[rop].rop
948b7e1c893Smrg						  | RADEON_GMC_BYTE_MSB_TO_LSB
949b7e1c893Smrg						  | RADEON_DP_SRC_SOURCE_HOST_DATA);
950209ff23fSmrg
951209ff23fSmrg#ifdef ACCEL_MMIO
952209ff23fSmrg
953209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
954209ff23fSmrg    BEGIN_ACCEL(2);
955209ff23fSmrg#else
956209ff23fSmrg    BEGIN_ACCEL(3);
957209ff23fSmrg
958209ff23fSmrg    if (bpp == 16)
959209ff23fSmrg	OUT_ACCEL_REG(RADEON_RBBM_GUICNTL,   RADEON_HOST_DATA_SWAP_16BIT);
960209ff23fSmrg    else if (bpp == 32)
961209ff23fSmrg	OUT_ACCEL_REG(RADEON_RBBM_GUICNTL,   RADEON_HOST_DATA_SWAP_32BIT);
962209ff23fSmrg    else
963209ff23fSmrg	OUT_ACCEL_REG(RADEON_RBBM_GUICNTL,   RADEON_HOST_DATA_SWAP_NONE);
964209ff23fSmrg#endif
965b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
966209ff23fSmrg
967209ff23fSmrg#else /* ACCEL_CP */
968209ff23fSmrg
969209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
970209ff23fSmrg    BEGIN_ACCEL(1);
971209ff23fSmrg#else
972209ff23fSmrg    if (info->ChipFamily < CHIP_FAMILY_R300) {
973209ff23fSmrg        BEGIN_ACCEL(2);
974209ff23fSmrg
975209ff23fSmrg	if (bpp == 16)
976209ff23fSmrg	    OUT_ACCEL_REG(RADEON_RBBM_GUICNTL,   RADEON_HOST_DATA_SWAP_HDW);
977209ff23fSmrg	else
978209ff23fSmrg	    OUT_ACCEL_REG(RADEON_RBBM_GUICNTL,   RADEON_HOST_DATA_SWAP_NONE);
979209ff23fSmrg    } else
980209ff23fSmrg	BEGIN_ACCEL(1);
981209ff23fSmrg#endif
982209ff23fSmrg#endif
983209ff23fSmrg    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK,      planemask);
984209ff23fSmrg
985209ff23fSmrg    FINISH_ACCEL();
986209ff23fSmrg
987b7e1c893Smrg    info->accel_state->trans_color = trans_color;
988209ff23fSmrg    FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
989209ff23fSmrg}
990209ff23fSmrg
991209ff23fSmrg/* Subsequent XAA indirect image write. This is only called once for
992209ff23fSmrg * each rectangle.
993209ff23fSmrg */
994209ff23fSmrgstatic void
995209ff23fSmrgFUNC_NAME(RADEONSubsequentScanlineImageWriteRect)(ScrnInfoPtr pScrn,
996209ff23fSmrg						  int x, int y,
997209ff23fSmrg						  int w, int h,
998209ff23fSmrg						  int skipleft)
999209ff23fSmrg{
1000209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1001209ff23fSmrg
1002209ff23fSmrg#ifdef ACCEL_MMIO
1003209ff23fSmrg
1004209ff23fSmrg    int            shift = 0; /* 32bpp */
1005209ff23fSmrg    ACCEL_PREAMBLE();
1006209ff23fSmrg
1007209ff23fSmrg    if (pScrn->bitsPerPixel == 8) shift = 3;
1008209ff23fSmrg    else if (pScrn->bitsPerPixel == 16) shift = 1;
1009209ff23fSmrg
1010b7e1c893Smrg    info->accel_state->scanline_h      = h;
1011b7e1c893Smrg    info->accel_state->scanline_words  = (w * info->accel_state->scanline_bpp + 31) >> 5;
1012209ff23fSmrg
1013209ff23fSmrg#ifdef __alpha__
1014209ff23fSmrg    /* Always use indirect for Alpha */
1015209ff23fSmrg    if (0)
1016209ff23fSmrg#else
1017b7e1c893Smrg    if ((info->accel_state->scanline_words * h) <= 9)
1018209ff23fSmrg#endif
1019209ff23fSmrg    {
1020209ff23fSmrg	/* Turn on direct for less than 9 dword colour expansion */
1021b7e1c893Smrg	info->accel_state->scratch_buffer[0]
1022209ff23fSmrg	    = (unsigned char *)(ADDRREG(RADEON_HOST_DATA_LAST)
1023b7e1c893Smrg				- (info->accel_state->scanline_words - 1));
1024b7e1c893Smrg	info->accel_state->scanline_direct = 1;
1025209ff23fSmrg    } else {
1026209ff23fSmrg	/* Use indirect for anything else */
1027b7e1c893Smrg	info->accel_state->scratch_buffer[0] = info->accel_state->scratch_save;
1028b7e1c893Smrg	info->accel_state->scanline_direct = 0;
1029209ff23fSmrg    }
1030209ff23fSmrg
1031b7e1c893Smrg    BEGIN_ACCEL(5 + (info->accel_state->scanline_direct ?
1032b7e1c893Smrg		     (info->accel_state->scanline_words * h) : 0));
1033209ff23fSmrg
1034b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset |
1035209ff23fSmrg    	((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0));
1036209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_TOP_LEFT,      (y << 16)     | ((x+skipleft)
1037209ff23fSmrg							    & 0xffff));
1038209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT,  ((y+h) << 16) | ((x+w) & 0xffff));
1039209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_Y_X,          (y << 16)     | (x & 0xffff));
1040209ff23fSmrg    /* Have to pad the width here and use clipping engine */
1041209ff23fSmrg    OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16)     | ((w + shift) &
1042209ff23fSmrg							    ~shift));
1043209ff23fSmrg
1044209ff23fSmrg    FINISH_ACCEL();
1045209ff23fSmrg
1046209ff23fSmrg#else /* ACCEL_CP */
1047209ff23fSmrg
1048209ff23fSmrg    int  pad = 0; /* 32bpp */
1049209ff23fSmrg
1050209ff23fSmrg    if (pScrn->bitsPerPixel == 8)       pad = 3;
1051209ff23fSmrg    else if (pScrn->bitsPerPixel == 16) pad = 1;
1052209ff23fSmrg
1053b7e1c893Smrg    info->accel_state->scanline_x      = x;
1054b7e1c893Smrg    info->accel_state->scanline_y      = y;
1055209ff23fSmrg    /* Have to pad the width here and use clipping engine */
1056b7e1c893Smrg    info->accel_state->scanline_w      = (w + pad) & ~pad;
1057b7e1c893Smrg    info->accel_state->scanline_h      = h;
1058209ff23fSmrg
1059b7e1c893Smrg    info->accel_state->scanline_x1clip = x + skipleft;
1060b7e1c893Smrg    info->accel_state->scanline_x2clip = x + w;
1061209ff23fSmrg
1062b7e1c893Smrg    info->accel_state->scanline_words  = (w * info->accel_state->scanline_bpp + 31) / 32;
1063b7e1c893Smrg    info->accel_state->scanline_hpass  = min(h,(CP_BUFSIZE/info->accel_state->scanline_words));
1064209ff23fSmrg
1065209ff23fSmrg    RADEONCPScanlinePacket(pScrn, 0);
1066209ff23fSmrg
1067209ff23fSmrg#endif
1068209ff23fSmrg}
1069209ff23fSmrg
1070209ff23fSmrg/* Set up the clipping rectangle */
1071209ff23fSmrgstatic void
1072209ff23fSmrgFUNC_NAME(RADEONSetClippingRectangle)(ScrnInfoPtr pScrn,
1073209ff23fSmrg				      int xa, int ya,
1074209ff23fSmrg				      int xb, int yb)
1075209ff23fSmrg{
1076209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1077209ff23fSmrg    unsigned long  tmp1 = 0;
1078209ff23fSmrg    unsigned long  tmp2 = 0;
1079209ff23fSmrg    ACCEL_PREAMBLE();
1080209ff23fSmrg
1081209ff23fSmrg    if (xa < 0) {
1082209ff23fSmrg	tmp1 = (-xa) & 0x3fff;
1083209ff23fSmrg	tmp1 |= RADEON_SC_SIGN_MASK_LO;
1084209ff23fSmrg    } else {
1085209ff23fSmrg	tmp1 = xa;
1086209ff23fSmrg    }
1087209ff23fSmrg
1088209ff23fSmrg    if (ya < 0) {
1089209ff23fSmrg	tmp1 |= (((-ya) & 0x3fff) << 16);
1090209ff23fSmrg	tmp1 |= RADEON_SC_SIGN_MASK_HI;
1091209ff23fSmrg    } else {
1092209ff23fSmrg	tmp1 |= (ya << 16);
1093209ff23fSmrg    }
1094209ff23fSmrg
1095209ff23fSmrg    xb++; yb++;
1096209ff23fSmrg
1097209ff23fSmrg    if (xb < 0) {
1098209ff23fSmrg	tmp2 = (-xb) & 0x3fff;
1099209ff23fSmrg	tmp2 |= RADEON_SC_SIGN_MASK_LO;
1100209ff23fSmrg    } else {
1101209ff23fSmrg	tmp2 = xb;
1102209ff23fSmrg    }
1103209ff23fSmrg
1104209ff23fSmrg    if (yb < 0) {
1105209ff23fSmrg	tmp2 |= (((-yb) & 0x3fff) << 16);
1106209ff23fSmrg	tmp2 |= RADEON_SC_SIGN_MASK_HI;
1107209ff23fSmrg    } else {
1108209ff23fSmrg	tmp2 |= (yb << 16);
1109209ff23fSmrg    }
1110209ff23fSmrg
1111209ff23fSmrg    BEGIN_ACCEL(3);
1112209ff23fSmrg
1113b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, (info->accel_state->dp_gui_master_cntl_clip
1114209ff23fSmrg					      | RADEON_GMC_DST_CLIPPING));
1115209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_TOP_LEFT,        tmp1);
1116209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT,    tmp2);
1117209ff23fSmrg
1118209ff23fSmrg    FINISH_ACCEL();
1119209ff23fSmrg    BEGIN_ACCEL(2);
1120209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
1121209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
1122209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
1123209ff23fSmrg    FINISH_ACCEL();
1124209ff23fSmrg
1125b7e1c893Smrg    FUNC_NAME(RADEONSetTransparency)(pScrn, info->accel_state->trans_color);
1126209ff23fSmrg}
1127209ff23fSmrg
1128209ff23fSmrg/* Disable the clipping rectangle */
1129209ff23fSmrgstatic void
1130209ff23fSmrgFUNC_NAME(RADEONDisableClipping)(ScrnInfoPtr pScrn)
1131209ff23fSmrg{
1132209ff23fSmrg    RADEONInfoPtr info  = RADEONPTR(pScrn);
1133209ff23fSmrg    ACCEL_PREAMBLE();
1134209ff23fSmrg
1135209ff23fSmrg    BEGIN_ACCEL(3);
1136209ff23fSmrg
1137b7e1c893Smrg    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->accel_state->dp_gui_master_cntl_clip);
1138209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_TOP_LEFT,        0);
1139209ff23fSmrg    OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT,    (RADEON_DEFAULT_SC_RIGHT_MAX |
1140209ff23fSmrg					      RADEON_DEFAULT_SC_BOTTOM_MAX));
1141209ff23fSmrg
1142209ff23fSmrg    FINISH_ACCEL();
1143209ff23fSmrg    BEGIN_ACCEL(2);
1144209ff23fSmrg    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
1145209ff23fSmrg    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
1146209ff23fSmrg                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
1147209ff23fSmrg    FINISH_ACCEL();
1148209ff23fSmrg
1149b7e1c893Smrg    FUNC_NAME(RADEONSetTransparency)(pScrn, info->accel_state->trans_color);
1150209ff23fSmrg}
1151209ff23fSmrg
1152209ff23fSmrgvoid
1153209ff23fSmrgFUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a)
1154209ff23fSmrg{
1155c135ecebSveego    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
1156209ff23fSmrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
1157209ff23fSmrg
1158209ff23fSmrg    a->Flags                            = (PIXMAP_CACHE
1159209ff23fSmrg					   | OFFSCREEN_PIXMAPS
1160209ff23fSmrg					   | LINEAR_FRAMEBUFFER);
1161209ff23fSmrg
1162209ff23fSmrg				/* Sync */
1163209ff23fSmrg    a->Sync                             = FUNC_NAME(RADEONWaitForIdle);
1164209ff23fSmrg
1165209ff23fSmrg				/* Solid Filled Rectangle */
1166209ff23fSmrg    a->PolyFillRectSolidFlags           = 0;
1167209ff23fSmrg    a->SetupForSolidFill
1168209ff23fSmrg	= FUNC_NAME(RADEONSetupForSolidFill);
1169209ff23fSmrg    a->SubsequentSolidFillRect
1170209ff23fSmrg	= FUNC_NAME(RADEONSubsequentSolidFillRect);
1171209ff23fSmrg
1172209ff23fSmrg				/* Screen-to-screen Copy */
1173209ff23fSmrg    a->ScreenToScreenCopyFlags          = 0;
1174209ff23fSmrg    a->SetupForScreenToScreenCopy
1175209ff23fSmrg	= FUNC_NAME(RADEONSetupForScreenToScreenCopy);
1176209ff23fSmrg    a->SubsequentScreenToScreenCopy
1177209ff23fSmrg	= FUNC_NAME(RADEONSubsequentScreenToScreenCopy);
1178209ff23fSmrg
1179209ff23fSmrg				/* Mono 8x8 Pattern Fill (Color Expand) */
1180209ff23fSmrg    a->SetupForMono8x8PatternFill
1181209ff23fSmrg	= FUNC_NAME(RADEONSetupForMono8x8PatternFill);
1182209ff23fSmrg    a->SubsequentMono8x8PatternFillRect
1183209ff23fSmrg	= FUNC_NAME(RADEONSubsequentMono8x8PatternFillRect);
1184209ff23fSmrg    a->Mono8x8PatternFillFlags          = (HARDWARE_PATTERN_PROGRAMMED_BITS
1185209ff23fSmrg					   | HARDWARE_PATTERN_PROGRAMMED_ORIGIN
1186209ff23fSmrg					   | HARDWARE_PATTERN_SCREEN_ORIGIN);
1187209ff23fSmrg
1188209ff23fSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1189209ff23fSmrg    if (info->ChipFamily >= CHIP_FAMILY_RV200)
1190209ff23fSmrg	a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_MSBFIRST;
1191209ff23fSmrg    else
1192209ff23fSmrg	a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_LSBFIRST;
1193209ff23fSmrg#else
1194209ff23fSmrg    a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_LSBFIRST;
1195209ff23fSmrg#endif
1196209ff23fSmrg
1197209ff23fSmrg				/* Indirect CPU-To-Screen Color Expand */
1198209ff23fSmrg
1199209ff23fSmrg    /* RADEON gets upset, when using HOST provided data without a source
1200209ff23fSmrg       rop.  To show run 'xtest's drwarc. */
1201209ff23fSmrg    a->ScanlineCPUToScreenColorExpandFillFlags
1202209ff23fSmrg	= (LEFT_EDGE_CLIPPING
1203209ff23fSmrg	   | ROP_NEEDS_SOURCE
1204209ff23fSmrg	   | LEFT_EDGE_CLIPPING_NEGATIVE_X);
1205209ff23fSmrg    a->NumScanlineColorExpandBuffers    = 1;
1206b7e1c893Smrg    a->ScanlineColorExpandBuffers       = info->accel_state->scratch_buffer;
1207b7e1c893Smrg    if (!info->accel_state->scratch_save)
1208b7e1c893Smrg	info->accel_state->scratch_save
12092f39173dSmrg	    = malloc(((pScrn->virtualX+31)/32*4)
1210209ff23fSmrg		     + (pScrn->virtualX * info->CurrentLayout.pixel_bytes));
1211b7e1c893Smrg    info->accel_state->scratch_buffer[0]             = info->accel_state->scratch_save;
1212209ff23fSmrg    a->SetupForScanlineCPUToScreenColorExpandFill
1213209ff23fSmrg	= FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill);
1214209ff23fSmrg    a->SubsequentScanlineCPUToScreenColorExpandFill
1215209ff23fSmrg	= FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill);
1216209ff23fSmrg    a->SubsequentColorExpandScanline
1217209ff23fSmrg        = FUNC_NAME(RADEONSubsequentScanline);
1218209ff23fSmrg
1219209ff23fSmrg				/* Solid Lines */
1220209ff23fSmrg    a->SetupForSolidLine
1221209ff23fSmrg	= FUNC_NAME(RADEONSetupForSolidLine);
1222209ff23fSmrg    a->SubsequentSolidHorVertLine
1223209ff23fSmrg	= FUNC_NAME(RADEONSubsequentSolidHorVertLine);
1224209ff23fSmrg
1225209ff23fSmrg    if (info->xaaReq.minorversion >= 1) {
1226209ff23fSmrg
1227209ff23fSmrg    /* RADEON only supports 14 bits for lines and clipping and only
1228209ff23fSmrg     * draws lines that are completely on-screen correctly.  This will
1229209ff23fSmrg     * cause display corruption problem in the cases when out-of-range
1230209ff23fSmrg     * commands are issued, like when dimming screen during GNOME logout
1231209ff23fSmrg     * in dual-head setup.  Solid and dashed lines are therefore limited
1232209ff23fSmrg     * to the virtual screen.
1233209ff23fSmrg     */
1234209ff23fSmrg
1235209ff23fSmrg    a->SolidLineFlags = LINE_LIMIT_COORDS;
1236209ff23fSmrg    a->SolidLineLimits.x1 = 0;
1237209ff23fSmrg    a->SolidLineLimits.y1 = 0;
1238209ff23fSmrg    a->SolidLineLimits.x2 = pScrn->virtualX-1;
1239209ff23fSmrg    a->SolidLineLimits.y2 = pScrn->virtualY-1;
1240209ff23fSmrg
1241209ff23fSmrg    /* Call miSetZeroLineBias() to have mi/mfb/fb routines match
1242209ff23fSmrg       hardware accel two point lines */
1243209ff23fSmrg    miSetZeroLineBias(pScreen, (OCTANT5 | OCTANT6 | OCTANT7 | OCTANT8));
1244209ff23fSmrg
1245209ff23fSmrg#ifdef ACCEL_CP
1246209ff23fSmrg    /* RV280s lock up with this using the CP for reasons to be determined.
1247209ff23fSmrg     * See https://bugs.freedesktop.org/show_bug.cgi?id=5986 .
1248209ff23fSmrg     */
1249209ff23fSmrg    if (info->ChipFamily != CHIP_FAMILY_RV280)
1250209ff23fSmrg#endif
1251209ff23fSmrg	a->SubsequentSolidTwoPointLine
1252209ff23fSmrg	    = FUNC_NAME(RADEONSubsequentSolidTwoPointLine);
1253209ff23fSmrg
1254209ff23fSmrg    /* Disabled on RV200 and newer because it does not pass XTest */
1255209ff23fSmrg    if (info->ChipFamily < CHIP_FAMILY_RV200) {
1256209ff23fSmrg	a->SetupForDashedLine
1257209ff23fSmrg	    = FUNC_NAME(RADEONSetupForDashedLine);
1258209ff23fSmrg	a->SubsequentDashedTwoPointLine
1259209ff23fSmrg	    = FUNC_NAME(RADEONSubsequentDashedTwoPointLine);
1260209ff23fSmrg	a->DashPatternMaxLength         = 32;
1261209ff23fSmrg	/* ROP3 doesn't seem to work properly for dashedline with GXinvert */
1262209ff23fSmrg	a->DashedLineFlags              = (LINE_PATTERN_LSBFIRST_LSBJUSTIFIED
1263209ff23fSmrg					   | LINE_PATTERN_POWER_OF_2_ONLY
1264209ff23fSmrg					   | LINE_LIMIT_COORDS
1265209ff23fSmrg					   | ROP_NEEDS_SOURCE);
1266209ff23fSmrg	a->DashedLineLimits.x1 = 0;
1267209ff23fSmrg	a->DashedLineLimits.y1 = 0;
1268209ff23fSmrg	a->DashedLineLimits.x2 = pScrn->virtualX-1;
1269209ff23fSmrg	a->DashedLineLimits.y2 = pScrn->virtualY-1;
1270209ff23fSmrg    }
1271209ff23fSmrg
1272209ff23fSmrg    } else {
1273209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1274209ff23fSmrg		   "libxaa too old, can't accelerate TwoPoint lines\n");
1275209ff23fSmrg    }
1276209ff23fSmrg
1277209ff23fSmrg    /* Clipping, note that without this, all line accelerations will
1278209ff23fSmrg     * not be called
1279209ff23fSmrg     */
1280209ff23fSmrg    a->SetClippingRectangle
1281209ff23fSmrg	= FUNC_NAME(RADEONSetClippingRectangle);
1282209ff23fSmrg    a->DisableClipping
1283209ff23fSmrg	= FUNC_NAME(RADEONDisableClipping);
1284209ff23fSmrg    a->ClippingFlags
1285209ff23fSmrg	= (HARDWARE_CLIP_SOLID_LINE
1286209ff23fSmrg	   | HARDWARE_CLIP_DASHED_LINE
1287209ff23fSmrg	/* | HARDWARE_CLIP_SOLID_FILL -- seems very slow with this on */
1288209ff23fSmrg	   | HARDWARE_CLIP_MONO_8x8_FILL
1289209ff23fSmrg	   | HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY);
1290209ff23fSmrg
1291209ff23fSmrg    if (xf86IsEntityShared(info->pEnt->index)) {
1292209ff23fSmrg	/* If there are more than one devices sharing this entity, we
1293209ff23fSmrg	 * have to assign this call back, otherwise the XAA will be
1294209ff23fSmrg	 * disabled
1295209ff23fSmrg	 */
1296209ff23fSmrg	if (xf86GetNumEntityInstances(info->pEnt->index) > 1)
1297209ff23fSmrg	    a->RestoreAccelState        = FUNC_NAME(RADEONRestoreAccelState);
1298209ff23fSmrg    }
1299209ff23fSmrg
1300209ff23fSmrg				/* ImageWrite */
1301209ff23fSmrg    a->NumScanlineImageWriteBuffers     = 1;
1302b7e1c893Smrg    a->ScanlineImageWriteBuffers        = info->accel_state->scratch_buffer;
1303209ff23fSmrg    a->SetupForScanlineImageWrite
1304209ff23fSmrg	= FUNC_NAME(RADEONSetupForScanlineImageWrite);
1305209ff23fSmrg    a->SubsequentScanlineImageWriteRect
1306209ff23fSmrg	= FUNC_NAME(RADEONSubsequentScanlineImageWriteRect);
1307209ff23fSmrg    a->SubsequentImageWriteScanline     = FUNC_NAME(RADEONSubsequentScanline);
1308209ff23fSmrg    a->ScanlineImageWriteFlags          = (CPU_TRANSFER_PAD_DWORD
1309209ff23fSmrg#ifdef ACCEL_MMIO
1310209ff23fSmrg		/* Performance tests show that we shouldn't use GXcopy
1311209ff23fSmrg		 * for uploads as a memcpy is faster
1312209ff23fSmrg		 */
1313209ff23fSmrg					  | NO_GXCOPY
1314209ff23fSmrg#endif
1315209ff23fSmrg		/* RADEON gets upset, when using HOST provided data
1316209ff23fSmrg		 * without a source rop. To show run 'xtest's ptimg
1317209ff23fSmrg		 */
1318209ff23fSmrg					  | ROP_NEEDS_SOURCE
1319209ff23fSmrg					  | SCANLINE_PAD_DWORD
1320209ff23fSmrg					  | LEFT_EDGE_CLIPPING
1321209ff23fSmrg					  | LEFT_EDGE_CLIPPING_NEGATIVE_X);
1322209ff23fSmrg
1323209ff23fSmrg#if 0
1324209ff23fSmrg				/* Color 8x8 Pattern Fill */
1325209ff23fSmrg    a->SetupForColor8x8PatternFill
1326209ff23fSmrg	= FUNC_NAME(RADEONSetupForColor8x8PatternFill);
1327209ff23fSmrg    a->SubsequentColor8x8PatternFillRect
1328209ff23fSmrg	= FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect);
1329209ff23fSmrg    a->Color8x8PatternFillFlags         = (HARDWARE_PATTERN_PROGRAMMED_ORIGIN
1330209ff23fSmrg					   | HARDWARE_PATTERN_SCREEN_ORIGIN
1331209ff23fSmrg					   | BIT_ORDER_IN_BYTE_LSBFIRST);
1332209ff23fSmrg#endif
1333209ff23fSmrg
1334209ff23fSmrg#ifdef RENDER
1335209ff23fSmrg    if (info->RenderAccel && info->xaaReq.minorversion >= 2) {
1336209ff23fSmrg
1337209ff23fSmrg	a->CPUToScreenAlphaTextureFlags = XAA_RENDER_POWER_OF_2_TILE_ONLY;
1338209ff23fSmrg	a->CPUToScreenAlphaTextureFormats = RADEONTextureFormats;
1339209ff23fSmrg	a->CPUToScreenAlphaTextureDstFormats = RADEONDstFormats;
1340209ff23fSmrg	a->CPUToScreenTextureFlags = XAA_RENDER_POWER_OF_2_TILE_ONLY;
1341209ff23fSmrg	a->CPUToScreenTextureFormats = RADEONTextureFormats;
1342209ff23fSmrg	a->CPUToScreenTextureDstFormats = RADEONDstFormats;
1343209ff23fSmrg
1344209ff23fSmrg	if (IS_R300_VARIANT || IS_AVIVO_VARIANT) {
1345209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "XAA Render acceleration "
1346209ff23fSmrg		       "unsupported on Radeon 9500/9700 and newer. "
1347209ff23fSmrg		       "Please use EXA instead.\n");
1348ad43ddacSmrg	} else if (IS_R200_3D) {
1349209ff23fSmrg	    a->SetupForCPUToScreenAlphaTexture2 =
1350209ff23fSmrg		FUNC_NAME(R200SetupForCPUToScreenAlphaTexture);
1351209ff23fSmrg	    a->SubsequentCPUToScreenAlphaTexture =
1352209ff23fSmrg		FUNC_NAME(R200SubsequentCPUToScreenTexture);
1353209ff23fSmrg
1354209ff23fSmrg	    a->SetupForCPUToScreenTexture2 =
1355209ff23fSmrg		FUNC_NAME(R200SetupForCPUToScreenTexture);
1356209ff23fSmrg	    a->SubsequentCPUToScreenTexture =
1357209ff23fSmrg		FUNC_NAME(R200SubsequentCPUToScreenTexture);
1358209ff23fSmrg	} else {
1359209ff23fSmrg	    a->SetupForCPUToScreenAlphaTexture2 =
1360209ff23fSmrg		FUNC_NAME(R100SetupForCPUToScreenAlphaTexture);
1361209ff23fSmrg	    a->SubsequentCPUToScreenAlphaTexture =
1362209ff23fSmrg		FUNC_NAME(R100SubsequentCPUToScreenTexture);
1363209ff23fSmrg
1364209ff23fSmrg	    a->SetupForCPUToScreenTexture2 =
1365209ff23fSmrg		FUNC_NAME(R100SetupForCPUToScreenTexture);
1366209ff23fSmrg	    a->SubsequentCPUToScreenTexture =
1367209ff23fSmrg		FUNC_NAME(R100SubsequentCPUToScreenTexture);
1368209ff23fSmrg	}
1369209ff23fSmrg    } else if (info->RenderAccel) {
1370209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration currently "
1371209ff23fSmrg		   "requires XAA v1.2 or newer.\n");
1372209ff23fSmrg    }
1373209ff23fSmrg
1374209ff23fSmrg    if (!a->SetupForCPUToScreenAlphaTexture2 && !a->SetupForCPUToScreenTexture2)
1375209ff23fSmrg	info->RenderAccel = FALSE;
1376209ff23fSmrg
1377209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration %s\n",
1378209ff23fSmrg	       info->RenderAccel ? "enabled" : "disabled");
1379209ff23fSmrg#endif /* RENDER */
1380209ff23fSmrg}
1381209ff23fSmrg
1382209ff23fSmrg#endif /* USE_XAA */
1383209ff23fSmrg
1384209ff23fSmrg#undef FUNC_NAME
1385