evergreen_textured_videofuncs.c revision b13dfe66
1/*
2 * Copyright 2010 Advanced Micro Devices, Inc.
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 * Author: Alex Deucher <alexander.deucher@amd.com>
24 *
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#ifdef XF86DRM_MODE
32
33#include "xf86.h"
34
35#include "exa.h"
36
37#include "radeon.h"
38#include "radeon_reg.h"
39#include "evergreen_shader.h"
40#include "evergreen_reg.h"
41#include "evergreen_state.h"
42
43#include "radeon_video.h"
44
45#include <X11/extensions/Xv.h>
46#include "fourcc.h"
47
48#include "damage.h"
49
50#include "radeon_exa_shared.h"
51#include "radeon_vbo.h"
52
53/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces
54   note the difference to the parameters used in overlay are due
55   to 10bit vs. float calcs */
56static REF_TRANSFORM trans[2] =
57{
58    {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */
59    {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0}  /* BT.709 */
60};
61
62void
63EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
64{
65    RADEONInfoPtr info = RADEONPTR(pScrn);
66    struct radeon_accel_state *accel_state = info->accel_state;
67    PixmapPtr pPixmap = pPriv->pPixmap;
68    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
69    int nBox = REGION_NUM_RECTS(&pPriv->clip);
70    int dstxoff, dstyoff;
71    struct r600_accel_object src_obj, dst_obj;
72    cb_config_t     cb_conf;
73    tex_resource_t  tex_res;
74    tex_sampler_t   tex_samp;
75    shader_config_t vs_conf, ps_conf;
76    /*
77     * y' = y - .0625
78     * u' = u - .5
79     * v' = v - .5;
80     *
81     * r = 1.1643 * y' + 0.0     * u' + 1.5958  * v'
82     * g = 1.1643 * y' - 0.39173 * u' - 0.81290 * v'
83     * b = 1.1643 * y' + 2.017   * u' + 0.0     * v'
84     *
85     * DP3 might look like the straightforward solution
86     * but we'd need to move the texture yuv values in
87     * the same reg for this to work. Therefore use MADs.
88     * Brightness just adds to the off constant.
89     * Contrast is multiplication of luminance.
90     * Saturation and hue change the u and v coeffs.
91     * Default values (before adjustments - depend on colorspace):
92     * yco = 1.1643
93     * uco = 0, -0.39173, 2.017
94     * vco = 1.5958, -0.8129, 0
95     * off = -0.0625 * yco + -0.5 * uco[r] + -0.5 * vco[r],
96     *       -0.0625 * yco + -0.5 * uco[g] + -0.5 * vco[g],
97     *       -0.0625 * yco + -0.5 * uco[b] + -0.5 * vco[b],
98     *
99     * temp = MAD(yco, yuv.yyyy, off)
100     * temp = MAD(uco, yuv.uuuu, temp)
101     * result = MAD(vco, yuv.vvvv, temp)
102     */
103    /* TODO: calc consts in the shader */
104    const float Loff = -0.0627;
105    const float Coff = -0.502;
106    float uvcosf, uvsinf;
107    float yco;
108    float uco[3], vco[3], off[3];
109    float bright, cont, gamma;
110    int ref = pPriv->transform_index;
111    Bool needgamma = FALSE;
112    float *ps_alu_consts;
113    const_config_t ps_const_conf;
114    float *vs_alu_consts;
115    const_config_t vs_const_conf;
116
117    cont = RTFContrast(pPriv->contrast);
118    bright = RTFBrightness(pPriv->brightness);
119    gamma = (float)pPriv->gamma / 1000.0;
120    uvcosf = RTFSaturation(pPriv->saturation) * cos(RTFHue(pPriv->hue));
121    uvsinf = RTFSaturation(pPriv->saturation) * sin(RTFHue(pPriv->hue));
122    /* overlay video also does pre-gamma contrast/sat adjust, should we? */
123
124    yco = trans[ref].RefLuma * cont;
125    uco[0] = -trans[ref].RefRCr * uvsinf;
126    uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf;
127    uco[2] = trans[ref].RefBCb * uvcosf;
128    vco[0] = trans[ref].RefRCr * uvcosf;
129    vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf;
130    vco[2] = trans[ref].RefBCb * uvsinf;
131    off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright;
132    off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright;
133    off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;
134
135    // XXX
136    gamma = 1.0;
137
138    if (gamma != 1.0) {
139	needgamma = TRUE;
140	/* note: gamma correction is out = in ^ gamma;
141	   gpu can only do LG2/EX2 therefore we transform into
142	   in ^ gamma = 2 ^ (log2(in) * gamma).
143	   Lots of scalar ops, unfortunately (better solution?) -
144	   without gamma that's 3 inst, with gamma it's 10...
145	   could use different gamma factors per channel,
146	   if that's of any use. */
147    }
148
149    CLEAR (cb_conf);
150    CLEAR (tex_res);
151    CLEAR (tex_samp);
152    CLEAR (vs_conf);
153    CLEAR (ps_conf);
154    CLEAR (vs_const_conf);
155    CLEAR (ps_const_conf);
156
157#if defined(XF86DRM_MODE)
158    if (info->cs) {
159	dst_obj.offset = 0;
160	src_obj.offset = 0;
161	dst_obj.bo = radeon_get_pixmap_bo(pPixmap);
162    } else
163#endif
164    {
165	dst_obj.offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
166	src_obj.offset = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
167	dst_obj.bo = src_obj.bo = NULL;
168    }
169    dst_obj.pitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel / 8);
170
171    src_obj.pitch = pPriv->src_pitch;
172    src_obj.width = pPriv->w;
173    src_obj.height = pPriv->h;
174    src_obj.bpp = 16;
175    src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
176    src_obj.bo = pPriv->src_bo[pPriv->currentBuffer];
177
178    dst_obj.width = pPixmap->drawable.width;
179    dst_obj.height = pPixmap->drawable.height;
180    dst_obj.bpp = pPixmap->drawable.bitsPerPixel;
181    dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
182
183    if (!R600SetAccelState(pScrn,
184			   &src_obj,
185			   NULL,
186			   &dst_obj,
187			   accel_state->xv_vs_offset, accel_state->xv_ps_offset,
188			   3, 0xffffffff))
189	return;
190
191#ifdef COMPOSITE
192    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
193    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
194#else
195    dstxoff = 0;
196    dstyoff = 0;
197#endif
198
199    radeon_vbo_check(pScrn, &accel_state->vbo, 16);
200    radeon_vbo_check(pScrn, &accel_state->cbuf, 512);
201    radeon_cp_start(pScrn);
202
203    evergreen_set_default_state(pScrn);
204
205    evergreen_set_generic_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height);
206    evergreen_set_screen_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height);
207    evergreen_set_window_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height);
208
209    /* PS bool constant */
210    switch(pPriv->id) {
211    case FOURCC_YV12:
212    case FOURCC_I420:
213	evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (1 << 0));
214	break;
215    case FOURCC_UYVY:
216    case FOURCC_YUY2:
217    default:
218	evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (0 << 0));
219	break;
220    }
221
222    /* Shader */
223    vs_conf.shader_addr         = accel_state->vs_mc_addr;
224    vs_conf.shader_size         = accel_state->vs_size;
225    vs_conf.num_gprs            = 2;
226    vs_conf.stack_size          = 0;
227    vs_conf.bo                  = accel_state->shaders_bo;
228    evergreen_vs_setup(pScrn, &vs_conf, RADEON_GEM_DOMAIN_VRAM);
229
230    ps_conf.shader_addr         = accel_state->ps_mc_addr;
231    ps_conf.shader_size         = accel_state->ps_size;
232    ps_conf.num_gprs            = 3;
233    ps_conf.stack_size          = 1;
234    ps_conf.clamp_consts        = 0;
235    ps_conf.export_mode         = 2;
236    ps_conf.bo                  = accel_state->shaders_bo;
237    evergreen_ps_setup(pScrn, &ps_conf, RADEON_GEM_DOMAIN_VRAM);
238
239    /* Texture */
240    switch(pPriv->id) {
241    case FOURCC_YV12:
242    case FOURCC_I420:
243	accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h;
244
245	/* Y texture */
246	tex_res.id                  = 0;
247	tex_res.w                   = accel_state->src_obj[0].width;
248	tex_res.h                   = accel_state->src_obj[0].height;
249	tex_res.pitch               = accel_state->src_obj[0].pitch;
250	tex_res.depth               = 0;
251	tex_res.dim                 = SQ_TEX_DIM_2D;
252	tex_res.base                = accel_state->src_obj[0].offset;
253	tex_res.mip_base            = accel_state->src_obj[0].offset;
254	tex_res.size                = accel_state->src_size[0];
255	tex_res.bo                  = accel_state->src_obj[0].bo;
256	tex_res.mip_bo              = accel_state->src_obj[0].bo;
257
258	tex_res.format              = FMT_8;
259	tex_res.dst_sel_x           = SQ_SEL_X; /* Y */
260	tex_res.dst_sel_y           = SQ_SEL_1;
261	tex_res.dst_sel_z           = SQ_SEL_1;
262	tex_res.dst_sel_w           = SQ_SEL_1;
263
264	tex_res.base_level          = 0;
265	tex_res.last_level          = 0;
266	tex_res.perf_modulation     = 0;
267	tex_res.interlaced          = 0;
268	if (accel_state->src_obj[0].tiling_flags == 0)
269	    tex_res.array_mode          = 1;
270	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);
271
272	/* Y sampler */
273	tex_samp.id                 = 0;
274	tex_samp.clamp_x            = SQ_TEX_CLAMP_LAST_TEXEL;
275	tex_samp.clamp_y            = SQ_TEX_CLAMP_LAST_TEXEL;
276	tex_samp.clamp_z            = SQ_TEX_WRAP;
277
278	/* xxx: switch to bicubic */
279	tex_samp.xy_mag_filter      = SQ_TEX_XY_FILTER_BILINEAR;
280	tex_samp.xy_min_filter      = SQ_TEX_XY_FILTER_BILINEAR;
281
282	tex_samp.z_filter           = SQ_TEX_Z_FILTER_NONE;
283	tex_samp.mip_filter         = 0;			/* no mipmap */
284	evergreen_set_tex_sampler(pScrn, &tex_samp);
285
286	/* U or V texture */
287	tex_res.id                  = 1;
288	tex_res.format              = FMT_8;
289	tex_res.w                   = accel_state->src_obj[0].width >> 1;
290	tex_res.h                   = accel_state->src_obj[0].height >> 1;
291	tex_res.pitch               = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, pPriv->hw_align);
292	tex_res.dst_sel_x           = SQ_SEL_X; /* V or U */
293	tex_res.dst_sel_y           = SQ_SEL_1;
294	tex_res.dst_sel_z           = SQ_SEL_1;
295	tex_res.dst_sel_w           = SQ_SEL_1;
296	tex_res.interlaced          = 0;
297
298	tex_res.base                = accel_state->src_obj[0].offset + pPriv->planev_offset;
299	tex_res.mip_base            = accel_state->src_obj[0].offset + pPriv->planev_offset;
300	tex_res.size                = tex_res.pitch * (pPriv->h >> 1);
301	if (accel_state->src_obj[0].tiling_flags == 0)
302	    tex_res.array_mode          = 1;
303	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);
304
305	/* U or V sampler */
306	tex_samp.id                 = 1;
307	evergreen_set_tex_sampler(pScrn, &tex_samp);
308
309	/* U or V texture */
310	tex_res.id                  = 2;
311	tex_res.format              = FMT_8;
312	tex_res.w                   = accel_state->src_obj[0].width >> 1;
313	tex_res.h                   = accel_state->src_obj[0].height >> 1;
314	tex_res.pitch               = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, pPriv->hw_align);
315	tex_res.dst_sel_x           = SQ_SEL_X; /* V or U */
316	tex_res.dst_sel_y           = SQ_SEL_1;
317	tex_res.dst_sel_z           = SQ_SEL_1;
318	tex_res.dst_sel_w           = SQ_SEL_1;
319	tex_res.interlaced          = 0;
320
321	tex_res.base                = accel_state->src_obj[0].offset + pPriv->planeu_offset;
322	tex_res.mip_base            = accel_state->src_obj[0].offset + pPriv->planeu_offset;
323	tex_res.size                = tex_res.pitch * (pPriv->h >> 1);
324	if (accel_state->src_obj[0].tiling_flags == 0)
325	    tex_res.array_mode          = 1;
326	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);
327
328	/* UV sampler */
329	tex_samp.id                 = 2;
330	evergreen_set_tex_sampler(pScrn, &tex_samp);
331	break;
332    case FOURCC_UYVY:
333    case FOURCC_YUY2:
334    default:
335	accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h;
336
337	/* Y texture */
338	tex_res.id                  = 0;
339	tex_res.w                   = accel_state->src_obj[0].width;
340	tex_res.h                   = accel_state->src_obj[0].height;
341	tex_res.pitch               = accel_state->src_obj[0].pitch >> 1;
342	tex_res.depth               = 0;
343	tex_res.dim                 = SQ_TEX_DIM_2D;
344	tex_res.base                = accel_state->src_obj[0].offset;
345	tex_res.mip_base            = accel_state->src_obj[0].offset;
346	tex_res.size                = accel_state->src_size[0];
347	tex_res.bo                  = accel_state->src_obj[0].bo;
348	tex_res.mip_bo              = accel_state->src_obj[0].bo;
349
350	tex_res.format              = FMT_8_8;
351	if (pPriv->id == FOURCC_UYVY)
352	    tex_res.dst_sel_x           = SQ_SEL_Y; /* Y */
353	else
354	    tex_res.dst_sel_x           = SQ_SEL_X; /* Y */
355	tex_res.dst_sel_y           = SQ_SEL_1;
356	tex_res.dst_sel_z           = SQ_SEL_1;
357	tex_res.dst_sel_w           = SQ_SEL_1;
358
359	tex_res.base_level          = 0;
360	tex_res.last_level          = 0;
361	tex_res.perf_modulation     = 0;
362	tex_res.interlaced          = 0;
363	if (accel_state->src_obj[0].tiling_flags == 0)
364	    tex_res.array_mode          = 1;
365	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);
366
367	/* Y sampler */
368	tex_samp.id                 = 0;
369	tex_samp.clamp_x            = SQ_TEX_CLAMP_LAST_TEXEL;
370	tex_samp.clamp_y            = SQ_TEX_CLAMP_LAST_TEXEL;
371	tex_samp.clamp_z            = SQ_TEX_WRAP;
372
373	tex_samp.xy_mag_filter      = SQ_TEX_XY_FILTER_BILINEAR;
374	tex_samp.xy_min_filter      = SQ_TEX_XY_FILTER_BILINEAR;
375
376	tex_samp.z_filter           = SQ_TEX_Z_FILTER_NONE;
377	tex_samp.mip_filter         = 0;			/* no mipmap */
378	evergreen_set_tex_sampler(pScrn, &tex_samp);
379
380	/* UV texture */
381	tex_res.id                  = 1;
382	tex_res.format              = FMT_8_8_8_8;
383	tex_res.w                   = accel_state->src_obj[0].width >> 1;
384	tex_res.h                   = accel_state->src_obj[0].height;
385	tex_res.pitch               = accel_state->src_obj[0].pitch >> 2;
386	if (pPriv->id == FOURCC_UYVY) {
387	    tex_res.dst_sel_x           = SQ_SEL_X; /* V */
388	    tex_res.dst_sel_y           = SQ_SEL_Z; /* U */
389	} else {
390	    tex_res.dst_sel_x           = SQ_SEL_Y; /* V */
391	    tex_res.dst_sel_y           = SQ_SEL_W; /* U */
392	}
393	tex_res.dst_sel_z           = SQ_SEL_1;
394	tex_res.dst_sel_w           = SQ_SEL_1;
395	tex_res.interlaced          = 0;
396
397	tex_res.base                = accel_state->src_obj[0].offset;
398	tex_res.mip_base            = accel_state->src_obj[0].offset;
399	tex_res.size                = accel_state->src_size[0];
400	if (accel_state->src_obj[0].tiling_flags == 0)
401	    tex_res.array_mode          = 1;
402	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);
403
404	/* UV sampler */
405	tex_samp.id                 = 1;
406	evergreen_set_tex_sampler(pScrn, &tex_samp);
407	break;
408    }
409
410    cb_conf.id = 0;
411    cb_conf.w = accel_state->dst_obj.pitch;
412    cb_conf.h = accel_state->dst_obj.height;
413    cb_conf.base = accel_state->dst_obj.offset;
414    cb_conf.bo = accel_state->dst_obj.bo;
415
416    switch (accel_state->dst_obj.bpp) {
417    case 16:
418	if (pPixmap->drawable.depth == 15) {
419	    cb_conf.format = COLOR_1_5_5_5;
420	    cb_conf.comp_swap = 1; /* ARGB */
421	} else {
422	    cb_conf.format = COLOR_5_6_5;
423	    cb_conf.comp_swap = 2; /* RGB */
424	}
425#if X_BYTE_ORDER == X_BIG_ENDIAN
426	cb_conf.endian = ENDIAN_8IN16;
427#endif
428	break;
429    case 32:
430	cb_conf.format = COLOR_8_8_8_8;
431	cb_conf.comp_swap = 1; /* ARGB */
432#if X_BYTE_ORDER == X_BIG_ENDIAN
433	cb_conf.endian = ENDIAN_8IN32;
434#endif
435	break;
436    default:
437	return;
438    }
439
440    cb_conf.source_format = EXPORT_4C_16BPC;
441    cb_conf.blend_clamp = 1;
442    cb_conf.pmask = 0xf;
443    cb_conf.rop = 3;
444    if (accel_state->dst_obj.tiling_flags == 0) {
445	cb_conf.array_mode = 1;
446	cb_conf.non_disp_tiling = 1;
447    }
448    evergreen_set_render_target(pScrn, &cb_conf, accel_state->dst_obj.domain);
449
450    evergreen_set_spi(pScrn, (1 - 1), 1);
451
452    /* PS alu constants */
453    ps_const_conf.size_bytes = 256;
454    ps_const_conf.type = SHADER_TYPE_PS;
455    ps_alu_consts = radeon_vbo_space(pScrn, &accel_state->cbuf, 256);
456    ps_const_conf.bo = accel_state->cbuf.vb_bo;
457    ps_const_conf.const_addr = accel_state->cbuf.vb_mc_addr + accel_state->cbuf.vb_offset;
458
459    ps_alu_consts[0] = off[0];
460    ps_alu_consts[1] = off[1];
461    ps_alu_consts[2] = off[2];
462    ps_alu_consts[3] = yco;
463
464    ps_alu_consts[4] = uco[0];
465    ps_alu_consts[5] = uco[1];
466    ps_alu_consts[6] = uco[2];
467    ps_alu_consts[7] = gamma;
468
469    ps_alu_consts[8] = vco[0];
470    ps_alu_consts[9] = vco[1];
471    ps_alu_consts[10] = vco[2];
472    ps_alu_consts[11] = 0.0;
473
474    radeon_vbo_commit(pScrn, &accel_state->cbuf);
475    evergreen_set_alu_consts(pScrn, &ps_const_conf, RADEON_GEM_DOMAIN_GTT);
476
477    /* VS alu constants */
478    vs_const_conf.size_bytes = 256;
479    vs_const_conf.type = SHADER_TYPE_VS;
480    vs_alu_consts = radeon_vbo_space(pScrn, &accel_state->cbuf, 256);
481    vs_const_conf.bo = accel_state->cbuf.vb_bo;
482    vs_const_conf.const_addr = accel_state->cbuf.vb_mc_addr + accel_state->cbuf.vb_offset;
483
484    vs_alu_consts[0] = 1.0 / pPriv->w;
485    vs_alu_consts[1] = 1.0 / pPriv->h;
486    vs_alu_consts[2] = 0.0;
487    vs_alu_consts[3] = 0.0;
488
489    radeon_vbo_commit(pScrn, &accel_state->cbuf);
490    evergreen_set_alu_consts(pScrn, &vs_const_conf, RADEON_GEM_DOMAIN_GTT);
491
492    if (pPriv->vsync) {
493	xf86CrtcPtr crtc;
494	if (pPriv->desired_crtc)
495	    crtc = pPriv->desired_crtc;
496	else
497	    crtc = radeon_pick_best_crtc(pScrn,
498					 pPriv->drw_x,
499					 pPriv->drw_x + pPriv->dst_w,
500					 pPriv->drw_y,
501					 pPriv->drw_y + pPriv->dst_h);
502	if (crtc)
503	    evergreen_cp_wait_vline_sync(pScrn, pPixmap,
504					 crtc,
505					 pPriv->drw_y - crtc->y,
506					 (pPriv->drw_y - crtc->y) + pPriv->dst_h);
507    }
508
509    while (nBox--) {
510	int srcX, srcY, srcw, srch;
511	int dstX, dstY, dstw, dsth;
512	float *vb;
513
514
515	dstX = pBox->x1 + dstxoff;
516	dstY = pBox->y1 + dstyoff;
517	dstw = pBox->x2 - pBox->x1;
518	dsth = pBox->y2 - pBox->y1;
519
520	srcX = pPriv->src_x;
521	srcX += ((pBox->x1 - pPriv->drw_x) *
522		 pPriv->src_w) / pPriv->dst_w;
523	srcY = pPriv->src_y;
524	srcY += ((pBox->y1 - pPriv->drw_y) *
525		 pPriv->src_h) / pPriv->dst_h;
526
527	srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
528	srch = (pPriv->src_h * dsth) / pPriv->dst_h;
529
530	vb = radeon_vbo_space(pScrn, &accel_state->vbo, 16);
531
532	vb[0] = (float)dstX;
533	vb[1] = (float)dstY;
534	vb[2] = (float)srcX;
535	vb[3] = (float)srcY;
536
537	vb[4] = (float)dstX;
538	vb[5] = (float)(dstY + dsth);
539	vb[6] = (float)srcX;
540	vb[7] = (float)(srcY + srch);
541
542	vb[8] = (float)(dstX + dstw);
543	vb[9] = (float)(dstY + dsth);
544	vb[10] = (float)(srcX + srcw);
545	vb[11] = (float)(srcY + srch);
546
547	radeon_vbo_commit(pScrn, &accel_state->vbo);
548
549	pBox++;
550    }
551
552    evergreen_finish_op(pScrn, 16);
553
554    DamageDamageRegion(pPriv->pDraw, &pPriv->clip);
555}
556
557#endif
558