diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-08-20 16:55:21 -0400 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2010-08-20 16:55:21 -0400 |
commit | 6930d2c981221757b1e11ef194809f085753a611 (patch) | |
tree | bc0315f106229488603ba9ef009581772fb9bdcc /src/evergreen_textured_videofuncs.c | |
parent | bdd41fecdb19c83c6c7b793016b61d38065dcd13 (diff) |
Add initial EXA and Xv support for evergreen
Based on the r6xx/r7xx code updated for evergreen.
Still causes GPU hangs in some cases. We haven't
tracked down why yet. Might be related to constant
buffer persistence.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Diffstat (limited to 'src/evergreen_textured_videofuncs.c')
-rw-r--r-- | src/evergreen_textured_videofuncs.c | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/src/evergreen_textured_videofuncs.c b/src/evergreen_textured_videofuncs.c new file mode 100644 index 00000000..2b8d65e3 --- /dev/null +++ b/src/evergreen_textured_videofuncs.c @@ -0,0 +1,587 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: Alex Deucher <alexander.deucher@amd.com> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" + +#include "exa.h" + +#include "radeon.h" +#include "radeon_reg.h" +#include "evergreen_shader.h" +#include "evergreen_reg.h" +#include "evergreen_state.h" + +#include "radeon_video.h" + +#include <X11/extensions/Xv.h> +#include "fourcc.h" + +#include "damage.h" + +#include "radeon_exa_shared.h" +#include "radeon_vbo.h" + +/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces + note the difference to the parameters used in overlay are due + to 10bit vs. float calcs */ +static REF_TRANSFORM trans[2] = +{ + {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */ + {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0} /* BT.709 */ +}; + +void +EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + PixmapPtr pPixmap = pPriv->pPixmap; + BoxPtr pBox = REGION_RECTS(&pPriv->clip); + int nBox = REGION_NUM_RECTS(&pPriv->clip); + int dstxoff, dstyoff; + struct r600_accel_object src_obj, dst_obj; + cb_config_t cb_conf; + tex_resource_t tex_res; + tex_sampler_t tex_samp; + shader_config_t vs_conf, ps_conf; + /* + * y' = y - .0625 + * u' = u - .5 + * v' = v - .5; + * + * r = 1.1643 * y' + 0.0 * u' + 1.5958 * v' + * g = 1.1643 * y' - 0.39173 * u' - 0.81290 * v' + * b = 1.1643 * y' + 2.017 * u' + 0.0 * v' + * + * DP3 might look like the straightforward solution + * but we'd need to move the texture yuv values in + * the same reg for this to work. Therefore use MADs. + * Brightness just adds to the off constant. + * Contrast is multiplication of luminance. + * Saturation and hue change the u and v coeffs. + * Default values (before adjustments - depend on colorspace): + * yco = 1.1643 + * uco = 0, -0.39173, 2.017 + * vco = 1.5958, -0.8129, 0 + * off = -0.0625 * yco + -0.5 * uco[r] + -0.5 * vco[r], + * -0.0625 * yco + -0.5 * uco[g] + -0.5 * vco[g], + * -0.0625 * yco + -0.5 * uco[b] + -0.5 * vco[b], + * + * temp = MAD(yco, yuv.yyyy, off) + * temp = MAD(uco, yuv.uuuu, temp) + * result = MAD(vco, yuv.vvvv, temp) + */ + /* TODO: calc consts in the shader */ + const float Loff = -0.0627; + const float Coff = -0.502; + float uvcosf, uvsinf; + float yco; + float uco[3], vco[3], off[3]; + float bright, cont, gamma; + int ref = pPriv->transform_index; + Bool needgamma = FALSE; + float *ps_alu_consts; + const_config_t ps_const_conf; + float *vs_alu_consts; + const_config_t vs_const_conf; + int ret; + + cont = RTFContrast(pPriv->contrast); + bright = RTFBrightness(pPriv->brightness); + gamma = (float)pPriv->gamma / 1000.0; + uvcosf = RTFSaturation(pPriv->saturation) * cos(RTFHue(pPriv->hue)); + uvsinf = RTFSaturation(pPriv->saturation) * sin(RTFHue(pPriv->hue)); + /* overlay video also does pre-gamma contrast/sat adjust, should we? */ + + yco = trans[ref].RefLuma * cont; + uco[0] = -trans[ref].RefRCr * uvsinf; + uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf; + uco[2] = trans[ref].RefBCb * uvcosf; + vco[0] = trans[ref].RefRCr * uvcosf; + vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf; + vco[2] = trans[ref].RefBCb * uvsinf; + off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright; + off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright; + off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright; + + // XXX + gamma = 1.0; + + if (gamma != 1.0) { + needgamma = TRUE; + /* note: gamma correction is out = in ^ gamma; + gpu can only do LG2/EX2 therefore we transform into + in ^ gamma = 2 ^ (log2(in) * gamma). + Lots of scalar ops, unfortunately (better solution?) - + without gamma that's 3 inst, with gamma it's 10... + could use different gamma factors per channel, + if that's of any use. */ + } + + CLEAR (cb_conf); + CLEAR (tex_res); + CLEAR (tex_samp); + CLEAR (vs_conf); + CLEAR (ps_conf); + CLEAR (vs_const_conf); + CLEAR (ps_const_conf); + + /* setup the ps consts */ + ps_const_conf.bo = radeon_bo_open(info->bufmgr, 0, 256, 0, + RADEON_GEM_DOMAIN_GTT, 0); + if (ps_const_conf.bo == NULL) { + ErrorF("ps const buffer alloc failed\n"); + return; + } + ret = radeon_bo_map(ps_const_conf.bo, 0); + if (ret) { + ErrorF("ps const buffer map failed\n"); + return; + } + + /* PS alu constants */ + ps_const_conf.size_bytes = 256; + ps_const_conf.const_addr = 0; + ps_const_conf.type = SHADER_TYPE_PS; + ps_alu_consts = (float *)ps_const_conf.bo->ptr; + + ps_alu_consts[0] = off[0]; + ps_alu_consts[1] = off[1]; + ps_alu_consts[2] = off[2]; + ps_alu_consts[3] = yco; + + ps_alu_consts[4] = uco[0]; + ps_alu_consts[5] = uco[1]; + ps_alu_consts[6] = uco[2]; + ps_alu_consts[7] = gamma; + + ps_alu_consts[8] = vco[0]; + ps_alu_consts[9] = vco[1]; + ps_alu_consts[10] = vco[2]; + ps_alu_consts[11] = 0.0; + radeon_bo_unmap(ps_const_conf.bo); + + vs_const_conf.bo = radeon_bo_open(info->bufmgr, 0, 256, 0, + RADEON_GEM_DOMAIN_GTT, 0); + if (vs_const_conf.bo == NULL) { + ErrorF("vs const buffer alloc failed\n"); + return; + } + ret = radeon_bo_map(vs_const_conf.bo, 0); + if (ret) { + ErrorF("vs const buffer map failed\n"); + return; + } + + /* PS alu constants */ + vs_const_conf.size_bytes = 256; + vs_const_conf.const_addr = 0; + vs_const_conf.type = SHADER_TYPE_VS; + vs_alu_consts = (float *)vs_const_conf.bo->ptr; + vs_alu_consts[0] = 1.0 / pPriv->w; + vs_alu_consts[1] = 1.0 / pPriv->h; + vs_alu_consts[2] = 0.0; + vs_alu_consts[3] = 0.0; + radeon_bo_unmap(vs_const_conf.bo); + + radeon_cs_space_add_persistent_bo(info->cs, ps_const_conf.bo, + RADEON_GEM_DOMAIN_GTT, 0); + radeon_cs_space_add_persistent_bo(info->cs, vs_const_conf.bo, + RADEON_GEM_DOMAIN_GTT, 0); + if (radeon_cs_space_check(info->cs)) { + radeon_bo_unref(ps_const_conf.bo); + radeon_bo_unref(vs_const_conf.bo); + ErrorF("const buffer size check failed\n"); + return; + } + +#if defined(XF86DRM_MODE) + if (info->cs) { + dst_obj.offset = 0; + src_obj.offset = 0; + dst_obj.bo = radeon_get_pixmap_bo(pPixmap); + } else +#endif + { + dst_obj.offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset; + src_obj.offset = pPriv->src_offset + info->fbLocation + pScrn->fbOffset; + dst_obj.bo = src_obj.bo = NULL; + } + dst_obj.pitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel / 8); + + src_obj.pitch = pPriv->src_pitch; + src_obj.width = pPriv->w; + src_obj.height = pPriv->h; + src_obj.bpp = 16; + src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT; + src_obj.bo = pPriv->src_bo[pPriv->currentBuffer]; + + dst_obj.width = pPixmap->drawable.width; + dst_obj.height = pPixmap->drawable.height; + dst_obj.bpp = pPixmap->drawable.bitsPerPixel; + dst_obj.domain = RADEON_GEM_DOMAIN_VRAM; + + if (!EVERGREENSetAccelState(pScrn, + &src_obj, + NULL, + &dst_obj, + accel_state->xv_vs_offset, accel_state->xv_ps_offset, + 3, 0xffffffff)) + return; + +#ifdef COMPOSITE + dstxoff = -pPixmap->screen_x + pPixmap->drawable.x; + dstyoff = -pPixmap->screen_y + pPixmap->drawable.y; +#else + dstxoff = 0; + dstyoff = 0; +#endif + + radeon_vbo_check(pScrn, 16); + radeon_cp_start(pScrn); + + evergreen_set_default_state(pScrn); + + evergreen_set_generic_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height); + evergreen_set_screen_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height); + evergreen_set_window_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height); + + /* PS bool constant */ + switch(pPriv->id) { + case FOURCC_YV12: + case FOURCC_I420: + evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (1 << 0)); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (0 << 0)); + break; + } + + /* Shader */ + vs_conf.shader_addr = accel_state->vs_mc_addr; + vs_conf.shader_size = accel_state->vs_size; + vs_conf.num_gprs = 2; + vs_conf.stack_size = 0; + vs_conf.bo = accel_state->shaders_bo; + evergreen_vs_setup(pScrn, &vs_conf, RADEON_GEM_DOMAIN_VRAM); + + ps_conf.shader_addr = accel_state->ps_mc_addr; + ps_conf.shader_size = accel_state->ps_size; + ps_conf.num_gprs = 3; + ps_conf.stack_size = 1; + ps_conf.clamp_consts = 0; + ps_conf.export_mode = 2; + ps_conf.bo = accel_state->shaders_bo; + evergreen_ps_setup(pScrn, &ps_conf, RADEON_GEM_DOMAIN_VRAM); + + /* PS alu constants */ + evergreen_set_alu_consts(pScrn, &ps_const_conf, RADEON_GEM_DOMAIN_GTT); + + /* Texture */ + switch(pPriv->id) { + case FOURCC_YV12: + case FOURCC_I420: + accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h; + + /* Y texture */ + tex_res.id = 0; + tex_res.w = accel_state->src_obj[0].width; + tex_res.h = accel_state->src_obj[0].height; + tex_res.pitch = accel_state->src_obj[0].pitch; + tex_res.depth = 0; + tex_res.dim = SQ_TEX_DIM_2D; + tex_res.base = accel_state->src_obj[0].offset; + tex_res.mip_base = accel_state->src_obj[0].offset; + tex_res.size = accel_state->src_size[0]; + tex_res.bo = accel_state->src_obj[0].bo; + tex_res.mip_bo = accel_state->src_obj[0].bo; + + tex_res.format = FMT_8; + tex_res.dst_sel_x = SQ_SEL_X; /* Y */ + tex_res.dst_sel_y = SQ_SEL_1; + tex_res.dst_sel_z = SQ_SEL_1; + tex_res.dst_sel_w = SQ_SEL_1; + + tex_res.base_level = 0; + tex_res.last_level = 0; + tex_res.perf_modulation = 0; + tex_res.interlaced = 0; + evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); + + /* Y sampler */ + tex_samp.id = 0; + tex_samp.clamp_x = SQ_TEX_CLAMP_LAST_TEXEL; + tex_samp.clamp_y = SQ_TEX_CLAMP_LAST_TEXEL; + tex_samp.clamp_z = SQ_TEX_WRAP; + + /* xxx: switch to bicubic */ + tex_samp.xy_mag_filter = SQ_TEX_XY_FILTER_BILINEAR; + tex_samp.xy_min_filter = SQ_TEX_XY_FILTER_BILINEAR; + + tex_samp.z_filter = SQ_TEX_Z_FILTER_NONE; + tex_samp.mip_filter = 0; /* no mipmap */ + evergreen_set_tex_sampler(pScrn, &tex_samp); + + /* U or V texture */ + tex_res.id = 1; + tex_res.format = FMT_8; + tex_res.w = accel_state->src_obj[0].width >> 1; + tex_res.h = accel_state->src_obj[0].height >> 1; + tex_res.pitch = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, 256); + tex_res.dst_sel_x = SQ_SEL_X; /* V or U */ + tex_res.dst_sel_y = SQ_SEL_1; + tex_res.dst_sel_z = SQ_SEL_1; + tex_res.dst_sel_w = SQ_SEL_1; + tex_res.interlaced = 0; + + tex_res.base = accel_state->src_obj[0].offset + pPriv->planev_offset; + tex_res.mip_base = accel_state->src_obj[0].offset + pPriv->planev_offset; + tex_res.size = accel_state->src_size[0] / 4; + evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); + + /* U or V sampler */ + tex_samp.id = 1; + evergreen_set_tex_sampler(pScrn, &tex_samp); + + /* U or V texture */ + tex_res.id = 2; + tex_res.format = FMT_8; + tex_res.w = accel_state->src_obj[0].width >> 1; + tex_res.h = accel_state->src_obj[0].height >> 1; + tex_res.pitch = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, 256); + tex_res.dst_sel_x = SQ_SEL_X; /* V or U */ + tex_res.dst_sel_y = SQ_SEL_1; + tex_res.dst_sel_z = SQ_SEL_1; + tex_res.dst_sel_w = SQ_SEL_1; + tex_res.interlaced = 0; + + tex_res.base = accel_state->src_obj[0].offset + pPriv->planeu_offset; + tex_res.mip_base = accel_state->src_obj[0].offset + pPriv->planeu_offset; + tex_res.size = accel_state->src_size[0] / 4; + evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); + + /* UV sampler */ + tex_samp.id = 2; + evergreen_set_tex_sampler(pScrn, &tex_samp); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h; + + /* Y texture */ + tex_res.id = 0; + tex_res.w = accel_state->src_obj[0].width; + tex_res.h = accel_state->src_obj[0].height; + tex_res.pitch = accel_state->src_obj[0].pitch >> 1; + tex_res.depth = 0; + tex_res.dim = SQ_TEX_DIM_2D; + tex_res.base = accel_state->src_obj[0].offset; + tex_res.mip_base = accel_state->src_obj[0].offset; + tex_res.size = accel_state->src_size[0]; + tex_res.bo = accel_state->src_obj[0].bo; + tex_res.mip_bo = accel_state->src_obj[0].bo; + + tex_res.format = FMT_8_8; + if (pPriv->id == FOURCC_UYVY) + tex_res.dst_sel_x = SQ_SEL_Y; /* Y */ + else + tex_res.dst_sel_x = SQ_SEL_X; /* Y */ + tex_res.dst_sel_y = SQ_SEL_1; + tex_res.dst_sel_z = SQ_SEL_1; + tex_res.dst_sel_w = SQ_SEL_1; + + tex_res.base_level = 0; + tex_res.last_level = 0; + tex_res.perf_modulation = 0; + tex_res.interlaced = 0; + evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); + + /* Y sampler */ + tex_samp.id = 0; + tex_samp.clamp_x = SQ_TEX_CLAMP_LAST_TEXEL; + tex_samp.clamp_y = SQ_TEX_CLAMP_LAST_TEXEL; + tex_samp.clamp_z = SQ_TEX_WRAP; + + tex_samp.xy_mag_filter = SQ_TEX_XY_FILTER_BILINEAR; + tex_samp.xy_min_filter = SQ_TEX_XY_FILTER_BILINEAR; + + tex_samp.z_filter = SQ_TEX_Z_FILTER_NONE; + tex_samp.mip_filter = 0; /* no mipmap */ + evergreen_set_tex_sampler(pScrn, &tex_samp); + + /* UV texture */ + tex_res.id = 1; + tex_res.format = FMT_8_8_8_8; + tex_res.w = accel_state->src_obj[0].width >> 1; + tex_res.h = accel_state->src_obj[0].height; + tex_res.pitch = accel_state->src_obj[0].pitch >> 2; + if (pPriv->id == FOURCC_UYVY) { + tex_res.dst_sel_x = SQ_SEL_X; /* V */ + tex_res.dst_sel_y = SQ_SEL_Z; /* U */ + } else { + tex_res.dst_sel_x = SQ_SEL_Y; /* V */ + tex_res.dst_sel_y = SQ_SEL_W; /* U */ + } + tex_res.dst_sel_z = SQ_SEL_1; + tex_res.dst_sel_w = SQ_SEL_1; + tex_res.interlaced = 0; + + tex_res.base = accel_state->src_obj[0].offset; + tex_res.mip_base = accel_state->src_obj[0].offset; + tex_res.size = accel_state->src_size[0]; + evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); + + /* UV sampler */ + tex_samp.id = 1; + evergreen_set_tex_sampler(pScrn, &tex_samp); + break; + } + + cb_conf.id = 0; + cb_conf.w = accel_state->dst_obj.pitch; + cb_conf.h = accel_state->dst_obj.height; + cb_conf.base = accel_state->dst_obj.offset; + cb_conf.bo = accel_state->dst_obj.bo; + + switch (accel_state->dst_obj.bpp) { + case 16: + if (pPixmap->drawable.depth == 15) { + cb_conf.format = COLOR_1_5_5_5; + cb_conf.comp_swap = 1; /* ARGB */ + } else { + cb_conf.format = COLOR_5_6_5; + cb_conf.comp_swap = 2; /* RGB */ + } + break; + case 32: + cb_conf.format = COLOR_8_8_8_8; + cb_conf.comp_swap = 1; /* ARGB */ + break; + default: + return; + } + + cb_conf.source_format = EXPORT_4C_16BPC; + cb_conf.blend_clamp = 1; + evergreen_set_render_target(pScrn, &cb_conf, accel_state->dst_obj.domain); + + /* Render setup */ + BEGIN_BATCH(23); + EREG(CB_TARGET_MASK, (0x0f << TARGET0_ENABLE_shift)); + EREG(CB_COLOR_CONTROL, ((0xcc << ROP3_shift) | + (CB_NORMAL << CB_COLOR_CONTROL__MODE_shift))); + EREG(CB_BLEND0_CONTROL, 0); + + /* Interpolator setup */ + /* export tex coords from VS */ + EREG(SPI_VS_OUT_CONFIG, ((1 - 1) << VS_EXPORT_COUNT_shift)); + EREG(SPI_VS_OUT_ID_0, (0 << SEMANTIC_0_shift)); + EREG(SPI_PS_INPUT_CNTL_0 + (0 <<2), ((0 << SEMANTIC_shift) | + (0x03 << DEFAULT_VAL_shift))); + + /* Enabling flat shading needs both FLAT_SHADE_bit in SPI_PS_INPUT_CNTL_x + * *and* FLAT_SHADE_ENA_bit in SPI_INTERP_CONTROL_0 */ + PACK0(SPI_PS_IN_CONTROL_0, 3); + E32(((1 << NUM_INTERP_shift) | + LINEAR_GRADIENT_ENA_bit)); // SPI_PS_IN_CONTROL_0 + E32(0); // SPI_PS_IN_CONTROL_1 + E32(0); // SPI_INTERP_CONTROL_0 + END_BATCH(); + + /* VS alu constants */ + evergreen_set_alu_consts(pScrn, &vs_const_conf, RADEON_GEM_DOMAIN_GTT); + + if (pPriv->vsync) { + xf86CrtcPtr crtc; + if (pPriv->desired_crtc) + crtc = pPriv->desired_crtc; + else + crtc = radeon_pick_best_crtc(pScrn, + pPriv->drw_x, + pPriv->drw_x + pPriv->dst_w, + pPriv->drw_y, + pPriv->drw_y + pPriv->dst_h); + if (crtc) + evergreen_cp_wait_vline_sync(pScrn, pPixmap, + crtc, + pPriv->drw_y - crtc->y, + (pPriv->drw_y - crtc->y) + pPriv->dst_h); + } + + while (nBox--) { + int srcX, srcY, srcw, srch; + int dstX, dstY, dstw, dsth; + float *vb; + + + dstX = pBox->x1 + dstxoff; + dstY = pBox->y1 + dstyoff; + dstw = pBox->x2 - pBox->x1; + dsth = pBox->y2 - pBox->y1; + + srcX = pPriv->src_x; + srcX += ((pBox->x1 - pPriv->drw_x) * + pPriv->src_w) / pPriv->dst_w; + srcY = pPriv->src_y; + srcY += ((pBox->y1 - pPriv->drw_y) * + pPriv->src_h) / pPriv->dst_h; + + srcw = (pPriv->src_w * dstw) / pPriv->dst_w; + srch = (pPriv->src_h * dsth) / pPriv->dst_h; + + vb = radeon_vbo_space(pScrn, 16); + + vb[0] = (float)dstX; + vb[1] = (float)dstY; + vb[2] = (float)srcX; + vb[3] = (float)srcY; + + vb[4] = (float)dstX; + vb[5] = (float)(dstY + dsth); + vb[6] = (float)srcX; + vb[7] = (float)(srcY + srch); + + vb[8] = (float)(dstX + dstw); + vb[9] = (float)(dstY + dsth); + vb[10] = (float)(srcX + srcw); + vb[11] = (float)(srcY + srch); + + radeon_vbo_commit(pScrn); + + pBox++; + } + + evergreen_finish_op(pScrn, 16); + + DamageDamageRegion(pPriv->pDraw, &pPriv->clip); +} |