radeon_textured_videofuncs.c revision 209ff23f
1/*
2 * Copyright 2008 Alex Deucher
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 *
24 * Based on radeon_exa_render.c and kdrive ati_video.c by Eric Anholt, et al.
25 *
26 */
27
28#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
29#error Cannot define both MMIO and CP acceleration!
30#endif
31
32#if !defined(UNIXCPP) || defined(ANSICPP)
33#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
34#else
35#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix
36#endif
37
38#ifdef ACCEL_MMIO
39#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
40#else
41#ifdef ACCEL_CP
42#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
43#else
44#error No accel type defined!
45#endif
46#endif
47
48#define VTX_DWORD_COUNT 4
49
50#ifdef ACCEL_CP
51
52#define VTX_OUT(_dstX, _dstY, _srcX, _srcY)	\
53do {								\
54    OUT_VIDEO_RING_F(_dstX);						\
55    OUT_VIDEO_RING_F(_dstY);						\
56    OUT_VIDEO_RING_F(_srcX);						\
57    OUT_VIDEO_RING_F(_srcY);						\
58} while (0)
59
60#else /* ACCEL_CP */
61
62#define VTX_OUT(_dstX, _dstY, _srcX, _srcY)	\
63do {								\
64    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _dstX);		\
65    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _dstY);		\
66    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _srcX);		\
67    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _srcY);		\
68} while (0)
69
70#endif /* !ACCEL_CP */
71
72static void
73FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
74{
75    RADEONInfoPtr info = RADEONPTR(pScrn);
76    PixmapPtr pPixmap = pPriv->pPixmap;
77    uint32_t txformat;
78    uint32_t txfilter, txformat0, txformat1, txoffset, txpitch;
79    uint32_t dst_offset, dst_pitch, dst_format;
80    uint32_t txenable, colorpitch;
81    uint32_t blendcntl;
82    int dstxoff, dstyoff, pixel_shift;
83    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
84    int nBox = REGION_NUM_RECTS(&pPriv->clip);
85    VIDEO_PREAMBLE();
86
87    pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
88
89#ifdef USE_EXA
90    if (info->useEXA) {
91	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
92	dst_pitch = exaGetPixmapPitch(pPixmap);
93    } else
94#endif
95	{
96	    dst_offset = (pPixmap->devPrivate.ptr - info->FB) +
97		info->fbLocation + pScrn->fbOffset;
98	    dst_pitch = pPixmap->devKind;
99	}
100
101#ifdef COMPOSITE
102    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
103    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
104#else
105    dstxoff = 0;
106    dstyoff = 0;
107#endif
108
109    if (!info->XInited3D)
110	RADEONInit3DEngine(pScrn);
111
112    /* we can probably improve this */
113    BEGIN_VIDEO(2);
114    if (IS_R300_3D || IS_R500_3D)
115	OUT_VIDEO_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D);
116    else
117	OUT_VIDEO_REG(RADEON_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH);
118    /* We must wait for 3d to idle, in case source was just written as a dest. */
119    OUT_VIDEO_REG(RADEON_WAIT_UNTIL,
120		  RADEON_WAIT_HOST_IDLECLEAN |
121		  RADEON_WAIT_2D_IDLECLEAN |
122		  RADEON_WAIT_3D_IDLECLEAN |
123		  RADEON_WAIT_DMA_GUI_IDLE);
124    FINISH_VIDEO();
125
126    if (IS_R300_3D || IS_R500_3D) {
127	uint32_t output_fmt;
128
129	switch (pPixmap->drawable.bitsPerPixel) {
130	case 16:
131	    if (pPixmap->drawable.depth == 15)
132		dst_format = R300_COLORFORMAT_ARGB1555;
133	    else
134		dst_format = R300_COLORFORMAT_RGB565;
135	    break;
136	case 32:
137	    dst_format = R300_COLORFORMAT_ARGB8888;
138	    break;
139	default:
140	    return;
141	}
142
143	output_fmt = (R300_OUT_FMT_C4_8 |
144		      R300_OUT_FMT_C0_SEL_BLUE |
145		      R300_OUT_FMT_C1_SEL_GREEN |
146		      R300_OUT_FMT_C2_SEL_RED |
147		      R300_OUT_FMT_C3_SEL_ALPHA);
148
149	colorpitch = dst_pitch >> pixel_shift;
150	colorpitch |= dst_format;
151
152	if (RADEONTilingEnabled(pScrn, pPixmap))
153	    colorpitch |= R300_COLORTILE;
154
155	if (pPriv->id == FOURCC_UYVY)
156	    txformat1 = R300_TX_FORMAT_YVYU422;
157	else
158	    txformat1 = R300_TX_FORMAT_VYUY422;
159
160	txformat1 |= R300_TX_FORMAT_YUV_TO_RGB_CLAMP;
161
162	txformat0 = ((((pPriv->w - 1) & 0x7ff) << R300_TXWIDTH_SHIFT) |
163		     (((pPriv->h - 1) & 0x7ff) << R300_TXHEIGHT_SHIFT));
164
165	txformat0 |= R300_TXPITCH_EN;
166
167	info->texW[0] = pPriv->w;
168	info->texH[0] = pPriv->h;
169
170	txfilter = (R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_LAST) |
171		    R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_LAST) |
172		    R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR);
173
174	/* pitch is in pixels */
175	txpitch = pPriv->src_pitch / 2;
176	txpitch -= 1;
177
178	if (IS_R500_3D && ((pPriv->w - 1) & 0x800))
179	    txpitch |= R500_TXWIDTH_11;
180
181	if (IS_R500_3D && ((pPriv->h - 1) & 0x800))
182	    txpitch |= R500_TXHEIGHT_11;
183
184	txoffset = pPriv->src_offset;
185
186	BEGIN_VIDEO(6);
187	OUT_VIDEO_REG(R300_TX_FILTER0_0, txfilter);
188	OUT_VIDEO_REG(R300_TX_FILTER1_0, 0);
189	OUT_VIDEO_REG(R300_TX_FORMAT0_0, txformat0);
190	OUT_VIDEO_REG(R300_TX_FORMAT1_0, txformat1);
191	OUT_VIDEO_REG(R300_TX_FORMAT2_0, txpitch);
192	OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset);
193	FINISH_VIDEO();
194
195	txenable = R300_TEX_0_ENABLE;
196
197	/* setup the VAP */
198	if (info->has_tcl)
199	    BEGIN_VIDEO(6);
200	else
201	    BEGIN_VIDEO(4);
202
203	/* These registers define the number, type, and location of data submitted
204	 * to the PVS unit of GA input (when PVS is disabled)
205	 * DST_VEC_LOC is the slot in the PVS input vector memory when PVS/TCL is
206	 * enabled.  This memory provides the imputs to the vertex shader program
207	 * and ordering is not important.  When PVS/TCL is disabled, this field maps
208	 * directly to the GA input memory and the order is signifigant.  In
209	 * PVS_BYPASS mode the order is as follows:
210	 * Position
211	 * Point Size
212	 * Color 0-3
213	 * Textures 0-7
214	 * Fog
215	 */
216	OUT_VIDEO_REG(R300_VAP_PROG_STREAM_CNTL_0,
217		      ((R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
218		       (0 << R300_SKIP_DWORDS_0_SHIFT) |
219		       (0 << R300_DST_VEC_LOC_0_SHIFT) |
220		       R300_SIGNED_0 |
221		       (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_1_SHIFT) |
222		       (0 << R300_SKIP_DWORDS_1_SHIFT) |
223		       (6 << R300_DST_VEC_LOC_1_SHIFT) |
224		       R300_LAST_VEC_1 |
225		       R300_SIGNED_1));
226
227	/* load the vertex shader
228	 * We pre-load vertex programs in RADEONInit3DEngine():
229	 * - exa no mask
230	 * - exa mask
231	 * - Xv
232	 * Here we select the offset of the vertex program we want to use
233	 */
234	if (info->has_tcl) {
235	    OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_0,
236			  ((5 << R300_PVS_FIRST_INST_SHIFT) |
237			   (6 << R300_PVS_XYZW_VALID_INST_SHIFT) |
238			   (6 << R300_PVS_LAST_INST_SHIFT)));
239	    OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_1,
240			  (6 << R300_PVS_LAST_VTX_SRC_INST_SHIFT));
241	}
242
243	/* Position and one set of 2 texture coordinates */
244	OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_0, R300_VTX_POS_PRESENT);
245	OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_1, (2 << R300_TEX_0_COMP_CNT_SHIFT));
246	OUT_VIDEO_REG(R300_US_OUT_FMT_0, output_fmt);
247	FINISH_VIDEO();
248
249	/* setup pixel shader */
250	if (IS_R300_3D) {
251	    BEGIN_VIDEO(8);
252	    /* 2 components: 2 for tex0 */
253	    OUT_VIDEO_REG(R300_RS_COUNT,
254			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
255			   R300_RS_COUNT_HIRES_EN));
256	    /* R300_INST_COUNT_RS - highest RS instruction used */
257	    OUT_VIDEO_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
258
259	    OUT_VIDEO_REG(R300_US_CODE_OFFSET,
260			  (R300_ALU_CODE_OFFSET(0) |
261			   R300_ALU_CODE_SIZE(1) |
262			   R300_TEX_CODE_OFFSET(0) |
263			   R300_TEX_CODE_SIZE(1)));
264
265	    OUT_VIDEO_REG(R300_US_CODE_ADDR_3,
266			  (R300_ALU_START(0) |
267			   R300_ALU_SIZE(0) |
268			   R300_TEX_START(0) |
269			   R300_TEX_SIZE(0) |
270			   R300_RGBA_OUT));
271
272	    /* tex inst is preloaded in RADEONInit3DEngine() */
273
274	    /* ALU inst */
275	    /* RGB */
276	    OUT_VIDEO_REG(R300_US_ALU_RGB_ADDR_0,
277			  (R300_ALU_RGB_ADDR0(0) |
278			   R300_ALU_RGB_ADDR1(0) |
279			   R300_ALU_RGB_ADDR2(0) |
280			   R300_ALU_RGB_ADDRD(0) |
281			   R300_ALU_RGB_OMASK((R300_ALU_RGB_MASK_R |
282					       R300_ALU_RGB_MASK_G |
283					       R300_ALU_RGB_MASK_B)) |
284			   R300_ALU_RGB_TARGET_A));
285	    OUT_VIDEO_REG(R300_US_ALU_RGB_INST_0,
286			  (R300_ALU_RGB_SEL_A(R300_ALU_RGB_SRC0_RGB) |
287			   R300_ALU_RGB_MOD_A(R300_ALU_RGB_MOD_NOP) |
288			   R300_ALU_RGB_SEL_B(R300_ALU_RGB_1_0) |
289			   R300_ALU_RGB_MOD_B(R300_ALU_RGB_MOD_NOP) |
290			   R300_ALU_RGB_SEL_C(R300_ALU_RGB_0_0) |
291			   R300_ALU_RGB_MOD_C(R300_ALU_RGB_MOD_NOP) |
292			   R300_ALU_RGB_OP(R300_ALU_RGB_OP_MAD) |
293			   R300_ALU_RGB_OMOD(R300_ALU_RGB_OMOD_NONE) |
294			   R300_ALU_RGB_CLAMP));
295	    /* Alpha */
296	    OUT_VIDEO_REG(R300_US_ALU_ALPHA_ADDR_0,
297			  (R300_ALU_ALPHA_ADDR0(0) |
298			   R300_ALU_ALPHA_ADDR1(0) |
299			   R300_ALU_ALPHA_ADDR2(0) |
300			   R300_ALU_ALPHA_ADDRD(0) |
301			   R300_ALU_ALPHA_OMASK(R300_ALU_ALPHA_MASK_A) |
302			   R300_ALU_ALPHA_TARGET_A |
303			   R300_ALU_ALPHA_OMASK_W(R300_ALU_ALPHA_MASK_NONE)));
304	    OUT_VIDEO_REG(R300_US_ALU_ALPHA_INST_0,
305			  (R300_ALU_ALPHA_SEL_A(R300_ALU_ALPHA_SRC0_A) |
306			   R300_ALU_ALPHA_MOD_A(R300_ALU_ALPHA_MOD_NOP) |
307			   R300_ALU_ALPHA_SEL_B(R300_ALU_ALPHA_1_0) |
308			   R300_ALU_ALPHA_MOD_B(R300_ALU_ALPHA_MOD_NOP) |
309			   R300_ALU_ALPHA_SEL_C(R300_ALU_ALPHA_0_0) |
310			   R300_ALU_ALPHA_MOD_C(R300_ALU_ALPHA_MOD_NOP) |
311			   R300_ALU_ALPHA_OP(R300_ALU_ALPHA_OP_MAD) |
312			   R300_ALU_ALPHA_OMOD(R300_ALU_ALPHA_OMOD_NONE) |
313			   R300_ALU_ALPHA_CLAMP));
314	    FINISH_VIDEO();
315	} else {
316	    BEGIN_VIDEO(18);
317	    /* 2 components: 2 for tex0 */
318	    OUT_VIDEO_REG(R300_RS_COUNT,
319			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
320			   R300_RS_COUNT_HIRES_EN));
321
322	    /* R300_INST_COUNT_RS - highest RS instruction used */
323	    OUT_VIDEO_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
324
325	    OUT_VIDEO_REG(R500_US_CODE_ADDR, (R500_US_CODE_START_ADDR(0) |
326					      R500_US_CODE_END_ADDR(1)));
327	    OUT_VIDEO_REG(R500_US_CODE_RANGE, (R500_US_CODE_RANGE_ADDR(0) |
328					       R500_US_CODE_RANGE_SIZE(1)));
329	    OUT_VIDEO_REG(R500_US_CODE_OFFSET, 0);
330	    OUT_VIDEO_REG(R500_GA_US_VECTOR_INDEX, 0);
331
332	    /* tex inst */
333	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
334						   R500_INST_TEX_SEM_WAIT |
335						   R500_INST_RGB_WMASK_R |
336						   R500_INST_RGB_WMASK_G |
337						   R500_INST_RGB_WMASK_B |
338						   R500_INST_ALPHA_WMASK |
339						   R500_INST_RGB_CLAMP |
340						   R500_INST_ALPHA_CLAMP));
341
342	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(0) |
343						   R500_TEX_INST_LD |
344						   R500_TEX_SEM_ACQUIRE |
345						   R500_TEX_IGNORE_UNCOVERED));
346
347	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(0) |
348						   R500_TEX_SRC_S_SWIZ_R |
349						   R500_TEX_SRC_T_SWIZ_G |
350						   R500_TEX_DST_ADDR(0) |
351						   R500_TEX_DST_R_SWIZ_R |
352						   R500_TEX_DST_G_SWIZ_G |
353						   R500_TEX_DST_B_SWIZ_B |
354						   R500_TEX_DST_A_SWIZ_A));
355	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_DX_ADDR(0) |
356						   R500_DX_S_SWIZ_R |
357						   R500_DX_T_SWIZ_R |
358						   R500_DX_R_SWIZ_R |
359						   R500_DX_Q_SWIZ_R |
360						   R500_DY_ADDR(0) |
361						   R500_DY_S_SWIZ_R |
362						   R500_DY_T_SWIZ_R |
363						   R500_DY_R_SWIZ_R |
364						   R500_DY_Q_SWIZ_R));
365	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
366	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
367
368	    /* ALU inst */
369	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_OUT |
370						   R500_INST_TEX_SEM_WAIT |
371						   R500_INST_LAST |
372						   R500_INST_RGB_OMASK_R |
373						   R500_INST_RGB_OMASK_G |
374						   R500_INST_RGB_OMASK_B |
375						   R500_INST_ALPHA_OMASK |
376						   R500_INST_RGB_CLAMP |
377						   R500_INST_ALPHA_CLAMP));
378
379	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
380						   R500_RGB_ADDR1(0) |
381						   R500_RGB_ADDR1_CONST |
382						   R500_RGB_ADDR2(0) |
383						   R500_RGB_ADDR2_CONST));
384	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
385						   R500_ALPHA_ADDR1(0) |
386						   R500_ALPHA_ADDR1_CONST |
387						   R500_ALPHA_ADDR2(0) |
388						   R500_ALPHA_ADDR2_CONST));
389
390	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC0 |
391						   R500_ALU_RGB_R_SWIZ_A_R |
392						   R500_ALU_RGB_G_SWIZ_A_G |
393						   R500_ALU_RGB_B_SWIZ_A_B |
394						   R500_ALU_RGB_SEL_B_SRC0 |
395						   R500_ALU_RGB_R_SWIZ_B_1 |
396						   R500_ALU_RGB_B_SWIZ_B_1 |
397						   R500_ALU_RGB_G_SWIZ_B_1));
398
399	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_OP_MAD |
400						   R500_ALPHA_SWIZ_A_A |
401						   R500_ALPHA_SWIZ_B_1));
402
403	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_OP_MAD |
404						   R500_ALU_RGBA_R_SWIZ_0 |
405						   R500_ALU_RGBA_G_SWIZ_0 |
406						   R500_ALU_RGBA_B_SWIZ_0 |
407						   R500_ALU_RGBA_A_SWIZ_0));
408	    FINISH_VIDEO();
409	}
410
411	BEGIN_VIDEO(5);
412	OUT_VIDEO_REG(R300_TX_INVALTAGS, 0);
413	OUT_VIDEO_REG(R300_TX_ENABLE, txenable);
414
415	OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset);
416	OUT_VIDEO_REG(R300_RB3D_COLORPITCH0, colorpitch);
417
418	blendcntl = RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO;
419	/* no need to enable blending */
420	OUT_VIDEO_REG(R300_RB3D_BLENDCNTL, blendcntl);
421	FINISH_VIDEO();
422
423	BEGIN_VIDEO(1);
424	OUT_VIDEO_REG(R300_VAP_VTX_SIZE, VTX_DWORD_COUNT);
425	FINISH_VIDEO();
426
427    } else {
428
429	/* Same for R100/R200 */
430	switch (pPixmap->drawable.bitsPerPixel) {
431	case 16:
432	    if (pPixmap->drawable.depth == 15)
433		dst_format = RADEON_COLOR_FORMAT_ARGB1555;
434	    else
435		dst_format = RADEON_COLOR_FORMAT_RGB565;
436	    break;
437	case 32:
438	    dst_format = RADEON_COLOR_FORMAT_ARGB8888;
439	    break;
440	default:
441	    return;
442	}
443
444	if (pPriv->id == FOURCC_UYVY)
445	    txformat = RADEON_TXFORMAT_YVYU422;
446	else
447	    txformat = RADEON_TXFORMAT_VYUY422;
448
449	txformat |= RADEON_TXFORMAT_NON_POWER2;
450
451	colorpitch = dst_pitch >> pixel_shift;
452
453	if (RADEONTilingEnabled(pScrn, pPixmap))
454	    colorpitch |= RADEON_COLOR_TILE_ENABLE;
455
456	BEGIN_VIDEO(5);
457
458	OUT_VIDEO_REG(RADEON_PP_CNTL,
459		    RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
460	OUT_VIDEO_REG(RADEON_RB3D_CNTL,
461		    dst_format | RADEON_ALPHA_BLEND_ENABLE);
462	OUT_VIDEO_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
463
464	OUT_VIDEO_REG(RADEON_RB3D_COLORPITCH, colorpitch);
465
466	OUT_VIDEO_REG(RADEON_RB3D_BLENDCNTL,
467		    RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
468
469	FINISH_VIDEO();
470
471
472	if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
473	    (info->ChipFamily == CHIP_FAMILY_RV280) ||
474	    (info->ChipFamily == CHIP_FAMILY_RS300) ||
475	    (info->ChipFamily == CHIP_FAMILY_R200)) {
476
477	    info->texW[0] = pPriv->w;
478	    info->texH[0] = pPriv->h;
479
480	    BEGIN_VIDEO(12);
481
482	    OUT_VIDEO_REG(R200_SE_VTX_FMT_0, R200_VTX_XY);
483	    OUT_VIDEO_REG(R200_SE_VTX_FMT_1,
484			(2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
485
486	    OUT_VIDEO_REG(R200_PP_TXFILTER_0,
487			R200_MAG_FILTER_LINEAR |
488			R200_MIN_FILTER_LINEAR |
489			R200_YUV_TO_RGB);
490	    OUT_VIDEO_REG(R200_PP_TXFORMAT_0, txformat);
491	    OUT_VIDEO_REG(R200_PP_TXFORMAT_X_0, 0);
492	    OUT_VIDEO_REG(R200_PP_TXSIZE_0,
493			(pPriv->w - 1) |
494			((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
495	    OUT_VIDEO_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
496
497	    OUT_VIDEO_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
498
499	    OUT_VIDEO_REG(R200_PP_TXCBLEND_0,
500			R200_TXC_ARG_A_ZERO |
501			R200_TXC_ARG_B_ZERO |
502			R200_TXC_ARG_C_R0_COLOR |
503			R200_TXC_OP_MADD);
504	    OUT_VIDEO_REG(R200_PP_TXCBLEND2_0,
505			R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
506	    OUT_VIDEO_REG(R200_PP_TXABLEND_0,
507			R200_TXA_ARG_A_ZERO |
508			R200_TXA_ARG_B_ZERO |
509			R200_TXA_ARG_C_R0_ALPHA |
510			R200_TXA_OP_MADD);
511	    OUT_VIDEO_REG(R200_PP_TXABLEND2_0,
512			R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
513	    FINISH_VIDEO();
514	} else {
515
516	    info->texW[0] = 1;
517	    info->texH[0] = 1;
518
519	    BEGIN_VIDEO(8);
520
521	    OUT_VIDEO_REG(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY |
522			RADEON_SE_VTX_FMT_ST0);
523
524	    OUT_VIDEO_REG(RADEON_PP_TXFILTER_0, RADEON_MAG_FILTER_LINEAR |
525			RADEON_MIN_FILTER_LINEAR |
526			RADEON_YUV_TO_RGB);
527	    OUT_VIDEO_REG(RADEON_PP_TXFORMAT_0, txformat);
528	    OUT_VIDEO_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset);
529	    OUT_VIDEO_REG(RADEON_PP_TXCBLEND_0,
530			RADEON_COLOR_ARG_A_ZERO |
531			RADEON_COLOR_ARG_B_ZERO |
532			RADEON_COLOR_ARG_C_T0_COLOR |
533			RADEON_BLEND_CTL_ADD |
534			RADEON_CLAMP_TX);
535	    OUT_VIDEO_REG(RADEON_PP_TXABLEND_0,
536			RADEON_ALPHA_ARG_A_ZERO |
537			RADEON_ALPHA_ARG_B_ZERO |
538			RADEON_ALPHA_ARG_C_T0_ALPHA |
539			RADEON_BLEND_CTL_ADD |
540			RADEON_CLAMP_TX);
541
542	    OUT_VIDEO_REG(RADEON_PP_TEX_SIZE_0,
543			(pPriv->w - 1) |
544			((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
545	    OUT_VIDEO_REG(RADEON_PP_TEX_PITCH_0,
546			pPriv->src_pitch - 32);
547	    FINISH_VIDEO();
548	}
549    }
550
551    while (nBox--) {
552	int srcX, srcY, srcw, srch;
553	int dstX, dstY, dstw, dsth;
554	xPointFixed srcTopLeft, srcTopRight, srcBottomLeft, srcBottomRight;
555	dstX = pBox->x1 + dstxoff;
556	dstY = pBox->y1 + dstyoff;
557	dstw = pBox->x2 - pBox->x1;
558	dsth = pBox->y2 - pBox->y1;
559
560	srcX = ((pBox->x1 - pPriv->drw_x) *
561		pPriv->src_w) / pPriv->dst_w;
562	srcY = ((pBox->y1 - pPriv->drw_y) *
563		pPriv->src_h) / pPriv->dst_h;
564
565	srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
566	srch = (pPriv->src_h * dsth) / pPriv->dst_h;
567
568	srcTopLeft.x     = IntToxFixed(srcX);
569	srcTopLeft.y     = IntToxFixed(srcY);
570	srcTopRight.x    = IntToxFixed(srcX + srcw);
571	srcTopRight.y    = IntToxFixed(srcY);
572	srcBottomLeft.x  = IntToxFixed(srcX);
573	srcBottomLeft.y  = IntToxFixed(srcY + srch);
574	srcBottomRight.x = IntToxFixed(srcX + srcw);
575	srcBottomRight.y = IntToxFixed(srcY + srch);
576
577
578#if 0
579	ErrorF("dst: %d, %d, %d, %d\n", dstX, dstY, dstw, dsth);
580	ErrorF("src: %d, %d, %d, %d\n", srcX, srcY, srcw, srch);
581#endif
582
583#ifdef ACCEL_CP
584	if (info->ChipFamily < CHIP_FAMILY_R200) {
585	    BEGIN_RING(4 * VTX_DWORD_COUNT + 3);
586	    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
587				4 * VTX_DWORD_COUNT + 1));
588	    OUT_RING(RADEON_CP_VC_FRMT_XY |
589		     RADEON_CP_VC_FRMT_ST0);
590	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
591		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
592		     RADEON_CP_VC_CNTL_MAOS_ENABLE |
593		     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
594		     (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
595	} else {
596	    if (IS_R300_3D || IS_R500_3D)
597		BEGIN_RING(4 * VTX_DWORD_COUNT + 4);
598	    else
599		BEGIN_RING(4 * VTX_DWORD_COUNT + 2);
600	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
601				4 * VTX_DWORD_COUNT));
602	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
603		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
604		     (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
605	}
606#else /* ACCEL_CP */
607	if (IS_R300_3D || IS_R500_3D)
608	    BEGIN_VIDEO(2 + VTX_DWORD_COUNT * 4);
609	else
610	    BEGIN_VIDEO(1 + VTX_DWORD_COUNT * 4);
611
612	if (info->ChipFamily < CHIP_FAMILY_R200) {
613	    OUT_VIDEO_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_FAN |
614					      RADEON_VF_PRIM_WALK_DATA |
615					      RADEON_VF_RADEON_MODE |
616					      4 << RADEON_VF_NUM_VERTICES_SHIFT));
617	} else {
618	    OUT_VIDEO_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
619					      RADEON_VF_PRIM_WALK_DATA |
620					      4 << RADEON_VF_NUM_VERTICES_SHIFT));
621	}
622#endif
623
624	VTX_OUT((float)dstX,                                      (float)dstY,
625		xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0]);
626	VTX_OUT((float)dstX,                                      (float)(dstY + dsth),
627		xFixedToFloat(srcBottomLeft.x) / info->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->texH[0]);
628	VTX_OUT((float)(dstX + dstw),                                (float)(dstY + dsth),
629		xFixedToFloat(srcBottomRight.x) / info->texW[0],  xFixedToFloat(srcBottomRight.y) / info->texH[0]);
630	VTX_OUT((float)(dstX + dstw),                                (float)dstY,
631		xFixedToFloat(srcTopRight.x) / info->texW[0],     xFixedToFloat(srcTopRight.y) / info->texH[0]);
632
633	if (IS_R300_3D || IS_R500_3D)
634	    /* flushing is pipelined, free/finish is not */
635	    OUT_VIDEO_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D);
636
637#ifdef ACCEL_CP
638	ADVANCE_RING();
639#else
640	FINISH_VIDEO();
641#endif /* !ACCEL_CP */
642
643	pBox++;
644    }
645
646    if (IS_R300_3D || IS_R500_3D) {
647	BEGIN_VIDEO(2);
648	OUT_VIDEO_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH_ALL);
649    } else
650	BEGIN_VIDEO(1);
651    OUT_VIDEO_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
652    FINISH_VIDEO();
653
654    DamageDamageRegion(pPriv->pDraw, &pPriv->clip);
655}
656
657#undef VTX_OUT
658#undef FUNC_NAME
659