summaryrefslogtreecommitdiff
path: root/src/sna/gen3_render.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-02-28 14:35:54 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2013-02-28 21:18:49 +0000
commit89038ddb96aabc4bc1f04402b2aca0ce546e8bf3 (patch)
tree9632a9a2eb30e7754d0b2798926070a1fe3fd639 /src/sna/gen3_render.c
parenta0a2faefdefbea63669dfeb49f7e701196ab5631 (diff)
sna/video: Correct scaling of source offsets
When applying pan and zoom to a mismatched video, it would inevitably miscompute the origin and scale factors. Reported-by: Matti Hamalainen <ccr@tnsp.org> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61610 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna/gen3_render.c')
-rw-r--r--src/sna/gen3_render.c105
1 files changed, 54 insertions, 51 deletions
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 0bac8d31..33116124 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3024,8 +3024,10 @@ gen3_composite_picture(struct sna *sna,
switch (source->type) {
case SourcePictTypeSolidFill:
- DBG(("%s: solid fill [%08x], format %x\n",
- __FUNCTION__, source->solidFill.color, picture->format));
+ DBG(("%s: solid fill [%08x], format %08x\n",
+ __FUNCTION__,
+ (unsigned)source->solidFill.color,
+ (unsigned)picture->format));
ret = gen3_init_solid(channel, source->solidFill.color);
break;
@@ -5103,10 +5105,8 @@ gen3_emit_video_state(struct sna *sna,
OUT_BATCH(SS2_COLORSPACE_CONVERSION |
(FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
- OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCX_ADDR_MODE_SHIFT) |
- (TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCY_ADDR_MODE_SHIFT) |
+ OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
+ (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
(0 << SS3_TEXTUREMAP_INDEX_SHIFT) |
SS3_NORMALIZED_COORDS);
OUT_BATCH(0x00000000);
@@ -5220,30 +5220,24 @@ gen3_emit_video_state(struct sna *sna,
/* sampler 0 */
OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
- OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCX_ADDR_MODE_SHIFT) |
- (TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCY_ADDR_MODE_SHIFT) |
+ OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
+ (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
(0 << SS3_TEXTUREMAP_INDEX_SHIFT) |
SS3_NORMALIZED_COORDS);
OUT_BATCH(0x00000000);
/* sampler 1 */
OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
- OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCX_ADDR_MODE_SHIFT) |
- (TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCY_ADDR_MODE_SHIFT) |
+ OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
+ (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
(1 << SS3_TEXTUREMAP_INDEX_SHIFT) |
SS3_NORMALIZED_COORDS);
OUT_BATCH(0x00000000);
/* sampler 2 */
OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT));
- OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCX_ADDR_MODE_SHIFT) |
- (TEXCOORDMODE_CLAMP_EDGE <<
- SS3_TCY_ADDR_MODE_SHIFT) |
+ OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) |
+ (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) |
(2 << SS3_TEXTUREMAP_INDEX_SHIFT) |
SS3_NORMALIZED_COORDS);
OUT_BATCH(0x00000000);
@@ -5359,7 +5353,6 @@ gen3_emit_video_state(struct sna *sna,
(sna->kgem.nbatch - id - 2);
}
}
-
}
static void
@@ -5395,37 +5388,51 @@ gen3_render_video(struct sna *sna,
struct sna_video *video,
struct sna_video_frame *frame,
RegionPtr dstRegion,
- short src_w, short src_h,
- short drw_w, short drw_h,
- short dx, short dy,
PixmapPtr pixmap)
{
struct sna_pixmap *priv = sna_pixmap(pixmap);
BoxPtr pbox = REGION_RECTS(dstRegion);
int nbox = REGION_NUM_RECTS(dstRegion);
- int width = dstRegion->extents.x2 - dstRegion->extents.x1;
- int height = dstRegion->extents.y2 - dstRegion->extents.y1;
+ int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
+ int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
+ int src_width = frame->src.x2 - frame->src.x1;
+ int src_height = frame->src.y2 - frame->src.y1;
+ float src_offset_x, src_offset_y;
float src_scale_x, src_scale_y;
int pix_xoff, pix_yoff;
struct kgem_bo *dst_bo;
bool bilinear;
int copy = 0;
- DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__, src_w, src_h, drw_w, drw_h));
+ DBG(("%s: src:%dx%d (frame:%dx%d) -> dst:%dx%d\n", __FUNCTION__,
+ src_width, src_height, frame->width, frame->height, dst_width, dst_height));
dst_bo = priv->gpu_bo;
if (dst_bo == NULL)
return false;
+ bilinear = src_width != dst_width || src_height != dst_height;
+
+ src_scale_x = (float)src_width / dst_width / frame->width;
+ src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
+
+ src_scale_y = (float)src_height / dst_height / frame->height;
+ src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
+ DBG(("%s: src offset (%f, %f), scale (%f, %f)\n",
+ __FUNCTION__, src_offset_x, src_offset_y, src_scale_x, src_scale_y));
+
if (too_large(pixmap->drawable.width, pixmap->drawable.height) ||
!gen3_check_pitch_3d(dst_bo)) {
int bpp = pixmap->drawable.bitsPerPixel;
+ if (too_large(dst_width, dst_height))
+ return false;
+
dst_bo = kgem_create_2d(&sna->kgem,
- width, height, bpp,
+ dst_width, dst_height, bpp,
kgem_choose_tiling(&sna->kgem,
I915_TILING_X,
- width, height, bpp),
+ dst_width, dst_height, bpp),
0);
if (!dst_bo)
return false;
@@ -5434,9 +5441,6 @@ gen3_render_video(struct sna *sna,
pix_yoff = -dstRegion->extents.y1;
copy = 1;
} else {
- width = pixmap->drawable.width;
- height = pixmap->drawable.height;
-
/* Set up the offset for translating from the given region
* (in screen coordinates) to the backing pixmap.
*/
@@ -5447,32 +5451,27 @@ gen3_render_video(struct sna *sna,
pix_xoff = 0;
pix_yoff = 0;
#endif
- }
- bilinear = src_w != drw_w || src_h != drw_h;
-
- src_scale_x = ((float)src_w / frame->width) / drw_w;
- src_scale_y = ((float)src_h / frame->height) / drw_h;
-
- DBG(("%s: src offset=(%d, %d), scale=(%f, %f), dst offset=(%d, %d)\n",
- __FUNCTION__,
- dx, dy, src_scale_x, src_scale_y, pix_xoff, pix_yoff));
+ dst_width = pixmap->drawable.width;
+ dst_height = pixmap->drawable.height;
+ }
gen3_video_get_batch(sna, dst_bo);
gen3_emit_video_state(sna, video, frame, pixmap,
- dst_bo, width, height, bilinear);
+ dst_bo, dst_width, dst_height, bilinear);
do {
int nbox_this_time = gen3_get_inline_rectangles(sna, nbox, 4);
if (nbox_this_time == 0) {
gen3_video_get_batch(sna, dst_bo);
gen3_emit_video_state(sna, video, frame, pixmap,
- dst_bo, width, height, bilinear);
+ dst_bo, dst_width, dst_height, bilinear);
nbox_this_time = gen3_get_inline_rectangles(sna, nbox, 4);
+ assert(nbox_this_time);
}
nbox -= nbox_this_time;
OUT_BATCH(PRIM3D_RECTLIST | (12 * nbox_this_time - 1));
- while (nbox_this_time--) {
+ do {
int box_x1 = pbox->x1;
int box_y1 = pbox->y1;
int box_x2 = pbox->x2;
@@ -5480,27 +5479,31 @@ gen3_render_video(struct sna *sna,
pbox++;
- DBG(("%s: box (%d, %d), (%d, %d)\n",
- __FUNCTION__, box_x1, box_y1, box_x2, box_y2));
+ DBG(("%s: dst (%d, %d), (%d, %d) + (%d, %d); src (%f, %f), (%f, %f)\n",
+ __FUNCTION__, box_x1, box_y1, box_x2, box_y2, pix_xoff, pix_yoff,
+ box_x1 * src_scale_x + src_offset_x,
+ box_y1 * src_scale_y + src_offset_y,
+ box_x2 * src_scale_x + src_offset_x,
+ box_y2 * src_scale_y + src_offset_y));
/* bottom right */
OUT_BATCH_F(box_x2 + pix_xoff);
OUT_BATCH_F(box_y2 + pix_yoff);
- OUT_BATCH_F((box_x2 - dx) * src_scale_x);
- OUT_BATCH_F((box_y2 - dy) * src_scale_y);
+ OUT_BATCH_F(box_x2 * src_scale_x + src_offset_x);
+ OUT_BATCH_F(box_y2 * src_scale_y + src_offset_y);
/* bottom left */
OUT_BATCH_F(box_x1 + pix_xoff);
OUT_BATCH_F(box_y2 + pix_yoff);
- OUT_BATCH_F((box_x1 - dx) * src_scale_x);
- OUT_BATCH_F((box_y2 - dy) * src_scale_y);
+ OUT_BATCH_F(box_x1 * src_scale_x + src_offset_x);
+ OUT_BATCH_F(box_y2 * src_scale_y + src_offset_y);
/* top left */
OUT_BATCH_F(box_x1 + pix_xoff);
OUT_BATCH_F(box_y1 + pix_yoff);
- OUT_BATCH_F((box_x1 - dx) * src_scale_x);
- OUT_BATCH_F((box_y1 - dy) * src_scale_y);
- }
+ OUT_BATCH_F(box_x1 * src_scale_x + src_offset_x);
+ OUT_BATCH_F(box_y1 * src_scale_y + src_offset_y);
+ } while (--nbox_this_time);
} while (nbox);
if (copy) {