sna/video: Add NV12 video copy funcs

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
This commit is contained in:
Ville Syrjälä 2017-06-09 18:06:39 +03:00 committed by Chris Wilson
parent 27d58e4b37
commit 8906d8b0e2
1 changed files with 135 additions and 11 deletions

View File

@ -233,7 +233,29 @@ sna_video_frame_set_rotation(struct sna_video *video,
/* Determine the desired destination pitch (representing the
* chroma's pitch in the planar case).
*/
if (is_planar_fourcc(frame->id)) {
if (is_nv12_fourcc(frame->id)) {
assert((width & 1) == 0);
assert((height & 1) == 0);
if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->pitch[0] = ALIGN(height, align);
frame->pitch[1] = ALIGN(height, align);
frame->size = width * frame->pitch[1] +
width / 2 * frame->pitch[0];
} else {
frame->pitch[0] = ALIGN(width, align);
frame->pitch[1] = ALIGN(width, align);
frame->size = height * frame->pitch[1] +
height / 2 * frame->pitch[0];
}
if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->UBufOffset = (int)frame->pitch[1] * width;
frame->VBufOffset = frame->UBufOffset;
} else {
frame->UBufOffset = (int)frame->pitch[1] * height;
frame->VBufOffset = frame->UBufOffset;
}
} else if (is_planar_fourcc(frame->id)) {
assert((width & 1) == 0);
assert((height & 1) == 0);
if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
@ -297,6 +319,78 @@ sna_video_frame_set_rotation(struct sna_video *video,
assert(frame->size);
}
static void plane_dims(const struct sna_video_frame *frame, int sub,
int *x, int *y, int *w, int *h)
{
*x = frame->image.x1;
*y = frame->image.y1;
*w = frame->image.x2 - frame->image.x1;
*h = frame->image.y2 - frame->image.y1;
if (sub) {
*x >>= 1; *w >>= 1;
*y >>= 1; *h >>= 1;
}
}
static void sna_memcpy_cbcr_plane(struct sna_video *video,
uint16_t *dst, const uint16_t *src,
const struct sna_video_frame *frame)
{
int dstPitch = frame->pitch[0] >> 1, srcPitch;
const uint16_t *s;
int i, j = 0;
int x, y, w, h;
plane_dims(frame, 1, &x, &y, &w, &h);
srcPitch = ALIGN((frame->width >> 1), 2);
src += y * srcPitch + x;
if (!video->textured)
x = y = 0;
switch (frame->rotation) {
case RR_Rotate_0:
dst += y * dstPitch + x;
if (srcPitch == dstPitch && srcPitch == w)
memcpy(dst, src, (srcPitch * h) << 1);
else while (h--) {
memcpy(dst, src, w << 1);
src += srcPitch;
dst += dstPitch;
}
break;
case RR_Rotate_90:
for (i = 0; i < h; i++) {
s = src;
for (j = 0; j < w; j++)
dst[i + ((x + w - j - 1) * dstPitch)] = *s++;
src += srcPitch;
}
break;
case RR_Rotate_180:
for (i = 0; i < h; i++) {
s = src;
for (j = 0; j < w; j++) {
dst[(x + w - j - 1) +
((h - i - 1) * dstPitch)] = *s++;
}
src += srcPitch;
}
break;
case RR_Rotate_270:
for (i = 0; i < h; i++) {
s = src;
for (j = 0; j < w; j++) {
dst[(h - i - 1) + (x + j * dstPitch)] = *s++;
}
src += srcPitch;
}
break;
}
}
static void sna_memcpy_plane(struct sna_video *video,
uint8_t *dst, const uint8_t *src,
const struct sna_video_frame *frame, int sub)
@ -306,15 +400,11 @@ static void sna_memcpy_plane(struct sna_video *video,
int i, j = 0;
int x, y, w, h;
x = frame->image.x1;
y = frame->image.y1;
w = frame->image.x2 - frame->image.x1;
h = frame->image.y2 - frame->image.y1;
if (sub) {
x >>= 1; w >>= 1;
y >>= 1; h >>= 1;
plane_dims(frame, sub, &x, &y, &w, &h);
if (sub)
srcPitch = ALIGN((frame->width >> 1), 4);
} else
else
srcPitch = ALIGN(frame->width, 4);
src += y * srcPitch + x;
@ -362,6 +452,17 @@ static void sna_memcpy_plane(struct sna_video *video,
}
}
static void
sna_copy_nv12_data(struct sna_video *video,
const struct sna_video_frame *frame,
const uint8_t *src, uint8_t *dst)
{
sna_memcpy_plane(video, dst, src, frame, 0);
src += frame->height * ALIGN(frame->width, 4);
dst += frame->UBufOffset;
sna_memcpy_cbcr_plane(video, (void*)dst, (void*)src, frame);
}
static void
sna_copy_planar_data(struct sna_video *video,
const struct sna_video_frame *frame,
@ -506,7 +607,28 @@ sna_video_copy_data(struct sna_video *video,
if (frame->rotation == RR_Rotate_0 && !video->tiled) {
DBG(("%s: unrotated, untiled fast paths: is-planar?=%d\n",
__FUNCTION__, is_planar_fourcc(frame->id)));
if (is_planar_fourcc(frame->id)) {
if (is_nv12_fourcc(frame->id)) {
int w = frame->image.x2 - frame->image.x1;
int h = frame->image.y2 - frame->image.y1;
if (ALIGN(h, 2) == frame->height &&
ALIGN(w, 4) == frame->pitch[0] &&
ALIGN(w, 4) == frame->pitch[1]) {
if (frame->bo) {
if (!kgem_bo_write(&video->sna->kgem, frame->bo,
buf, frame->size))
goto use_gtt;
} else {
frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size,
KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE,
(void **)&dst);
if (frame->bo == NULL)
return false;
memcpy(dst, buf, frame->size);
}
return true;
}
} else if (is_planar_fourcc(frame->id)) {
int w = frame->image.x2 - frame->image.x1;
int h = frame->image.y2 - frame->image.y1;
if (ALIGN(h, 2) == frame->height &&
@ -583,7 +705,9 @@ use_gtt: /* copy data, must use GTT so that we keep the overlay uncached */
return false;
}
if (is_planar_fourcc(frame->id))
if (is_nv12_fourcc(frame->id))
sna_copy_nv12_data(video, frame, buf, dst);
else if (is_planar_fourcc(frame->id))
sna_copy_planar_data(video, frame, buf, dst);
else
sna_copy_packed_data(video, frame, buf, dst);