sna/video: Use pwrite for upload of unclipped, unrotated frames

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2011-06-21 12:28:13 +01:00
parent 2f6afb5b1f
commit ea71133da7
8 changed files with 97 additions and 74 deletions

View File

@ -2837,7 +2837,7 @@ gen3_emit_video_state(struct sna *sna,
OUT_BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
frame->bo,
I915_GEM_DOMAIN_SAMPLER << 16,
frame->YBufOffset));
0));
ms3 = MAPSURF_422;
switch (frame->id) {
@ -2951,7 +2951,7 @@ gen3_emit_video_state(struct sna *sna,
OUT_BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
frame->bo,
I915_GEM_DOMAIN_SAMPLER << 16,
frame->YBufOffset));
0));
ms3 = MAPSURF_8BIT | MT_8BIT_I8;
ms3 |= (frame->height - 1) << MS3_HEIGHT_SHIFT;

View File

@ -1546,8 +1546,8 @@ static void gen4_video_bind_surfaces(struct sna *sna,
uint16_t offset;
int n_src, n;
src_surf_base[0] = frame->YBufOffset;
src_surf_base[1] = frame->YBufOffset;
src_surf_base[0] = 0;
src_surf_base[1] = 0;
src_surf_base[2] = frame->VBufOffset;
src_surf_base[3] = frame->VBufOffset;
src_surf_base[4] = frame->UBufOffset;

View File

@ -1559,8 +1559,8 @@ static void gen5_video_bind_surfaces(struct sna *sna,
uint16_t offset;
src_surf_base[0] = frame->YBufOffset;
src_surf_base[1] = frame->YBufOffset;
src_surf_base[0] = 0;
src_surf_base[1] = 0;
src_surf_base[2] = frame->VBufOffset;
src_surf_base[3] = frame->VBufOffset;
src_surf_base[4] = frame->UBufOffset;

View File

@ -1735,8 +1735,8 @@ static void gen6_emit_video_state(struct sna *sna,
gen6_get_batch(sna);
src_surf_base[0] = frame->YBufOffset;
src_surf_base[1] = frame->YBufOffset;
src_surf_base[0] = 0;
src_surf_base[1] = 0;
src_surf_base[2] = frame->VBufOffset;
src_surf_base[3] = frame->VBufOffset;
src_surf_base[4] = frame->UBufOffset;

View File

@ -274,10 +274,8 @@ uint32_t kgem_add_reloc(struct kgem *kgem,
void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo, int prot);
uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo);
Bool kgem_bo_write(struct kgem *kgem,
struct kgem_bo *bo,
const void *data,
int length);
Bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo,
const void *data, int length);
static inline bool kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
{

View File

@ -236,16 +236,12 @@ sna_video_frame_init(struct sna *sna,
frame->pitch[1] = 0;
}
frame->YBufOffset = 0;
if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->UBufOffset =
frame->YBufOffset + frame->pitch[1] * width;
frame->UBufOffset = frame->pitch[1] * width;
frame->VBufOffset =
frame->UBufOffset + frame->pitch[0] * width / 2;
} else {
frame->UBufOffset =
frame->YBufOffset + frame->pitch[1] * height;
frame->UBufOffset = frame->pitch[1] * height;
frame->VBufOffset =
frame->UBufOffset + frame->pitch[0] * height / 2;
}
@ -319,52 +315,50 @@ static void sna_memcpy_plane(unsigned char *dst, unsigned char *src,
static void
sna_copy_planar_data(struct sna *sna,
struct sna_video *video,
struct sna_video_frame *frame,
unsigned char *buf,
const struct sna_video_frame *frame,
unsigned char *src,
unsigned char *dst,
int srcPitch, int srcPitch2,
int srcH, int top, int left)
{
unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
unsigned char *src1, *dst1;
/* Copy Y data */
src1 = buf + (top * srcPitch) + left;
src1 = src + (top * srcPitch) + left;
dst1 = dst + frame->YBufOffset;
sna_memcpy_plane(dst1, src1,
sna_memcpy_plane(dst, src1,
frame->height, frame->width,
frame->pitch[1], srcPitch,
video->rotation);
/* Copy V data for YV12, or U data for I420 */
src2 = buf + /* start of YUV data */
src1 = src + /* start of YUV data */
(srcH * srcPitch) + /* move over Luma plane */
((top >> 1) * srcPitch2) + /* move down from by top lines */
(left >> 1); /* move left by left pixels */
if (frame->id == FOURCC_I420)
dst2 = dst + frame->UBufOffset;
dst1 = dst + frame->UBufOffset;
else
dst2 = dst + frame->VBufOffset;
dst1 = dst + frame->VBufOffset;
sna_memcpy_plane(dst2, src2,
sna_memcpy_plane(dst1, src1,
frame->height / 2, frame->width / 2,
frame->pitch[0], srcPitch2,
video->rotation);
/* Copy U data for YV12, or V data for I420 */
src3 = buf + /* start of YUV data */
src1 = src + /* start of YUV data */
(srcH * srcPitch) + /* move over Luma plane */
((srcH >> 1) * srcPitch2) + /* move over Chroma plane */
((top >> 1) * srcPitch2) + /* move down from by top lines */
(left >> 1); /* move left by left pixels */
if (frame->id == FOURCC_I420)
dst3 = dst + frame->VBufOffset;
dst1 = dst + frame->VBufOffset;
else
dst3 = dst + frame->UBufOffset;
dst1 = dst + frame->UBufOffset;
sna_memcpy_plane(dst3, src3,
sna_memcpy_plane(dst1, src1,
frame->height / 2, frame->width / 2,
frame->pitch[0], srcPitch2,
video->rotation);
@ -373,99 +367,99 @@ sna_copy_planar_data(struct sna *sna,
static void
sna_copy_packed_data(struct sna *sna,
struct sna_video *video,
struct sna_video_frame *frame,
const struct sna_video_frame *frame,
unsigned char *buf,
unsigned char *dst,
int srcPitch,
int top, int left)
{
int w = frame->width;
int h = frame->height;
unsigned char *src;
unsigned char *s;
int i, j;
src = buf + (top * srcPitch) + (left << 1);
dst += frame->YBufOffset;
switch (video->rotation) {
case RR_Rotate_0:
frame->width <<= 1;
for (i = 0; i < frame->height; i++) {
memcpy(dst, src, frame->width);
w <<= 1;
for (i = 0; i < h; i++) {
memcpy(dst, src, w);
src += srcPitch;
dst += frame->pitch[0];
}
break;
case RR_Rotate_90:
frame->height <<= 1;
for (i = 0; i < frame->height; i += 2) {
h <<= 1;
for (i = 0; i < h; i += 2) {
s = src;
for (j = 0; j < frame->width; j++) {
for (j = 0; j < w; j++) {
/* Copy Y */
dst[(i + 0) + ((frame->width - j - 1) * frame->pitch[0])] = *s++;
dst[(i + 0) + ((w - j - 1) * frame->pitch[0])] = *s++;
(void)*s++;
}
src += srcPitch;
}
frame->height >>= 1;
h >>= 1;
src = buf + (top * srcPitch) + (left << 1);
for (i = 0; i < frame->height; i += 2) {
for (j = 0; j < frame->width; j += 2) {
for (i = 0; i < h; i += 2) {
for (j = 0; j < w; j += 2) {
/* Copy U */
dst[((i * 2) + 1) + ((frame->width - j - 1) * frame->pitch[0])] =
dst[((i * 2) + 1) + ((w - j - 1) * frame->pitch[0])] =
src[(j * 2) + 1 + (i * srcPitch)];
dst[((i * 2) + 1) + ((frame->width - j - 2) * frame->pitch[0])] =
dst[((i * 2) + 1) + ((w - j - 2) * frame->pitch[0])] =
src[(j * 2) + 1 + ((i + 1) * srcPitch)];
/* Copy V */
dst[((i * 2) + 3) + ((frame->width - j - 1) * frame->pitch[0])] =
dst[((i * 2) + 3) + ((w - j - 1) * frame->pitch[0])] =
src[(j * 2) + 3 + (i * srcPitch)];
dst[((i * 2) + 3) + ((frame->width - j - 2) * frame->pitch[0])] =
dst[((i * 2) + 3) + ((w - j - 2) * frame->pitch[0])] =
src[(j * 2) + 3 + ((i + 1) * srcPitch)];
}
}
break;
case RR_Rotate_180:
frame->width <<= 1;
for (i = 0; i < frame->height; i++) {
w <<= 1;
for (i = 0; i < h; i++) {
s = src;
for (j = 0; j < frame->width; j += 4) {
dst[(frame->width - j - 4) + ((frame->height - i - 1) * frame->pitch[0])] =
for (j = 0; j < w; j += 4) {
dst[(w - j - 4) + ((h - i - 1) * frame->pitch[0])] =
*s++;
dst[(frame->width - j - 3) + ((frame->height - i - 1) * frame->pitch[0])] =
dst[(w - j - 3) + ((h - i - 1) * frame->pitch[0])] =
*s++;
dst[(frame->width - j - 2) + ((frame->height - i - 1) * frame->pitch[0])] =
dst[(w - j - 2) + ((h - i - 1) * frame->pitch[0])] =
*s++;
dst[(frame->width - j - 1) + ((frame->height - i - 1) * frame->pitch[0])] =
dst[(w - j - 1) + ((h - i - 1) * frame->pitch[0])] =
*s++;
}
src += srcPitch;
}
break;
case RR_Rotate_270:
frame->height <<= 1;
for (i = 0; i < frame->height; i += 2) {
h <<= 1;
for (i = 0; i < h; i += 2) {
s = src;
for (j = 0; j < frame->width; j++) {
for (j = 0; j < w; j++) {
/* Copy Y */
dst[(frame->height - i - 2) + (j * frame->pitch[0])] = *s++;
dst[(h - i - 2) + (j * frame->pitch[0])] = *s++;
(void)*s++;
}
src += srcPitch;
}
frame->height >>= 1;
h >>= 1;
src = buf + (top * srcPitch) + (left << 1);
for (i = 0; i < frame->height; i += 2) {
for (j = 0; j < frame->width; j += 2) {
for (i = 0; i < h; i += 2) {
for (j = 0; j < w; j += 2) {
/* Copy U */
dst[(((frame->height - i) * 2) - 3) + (j * frame->pitch[0])] =
dst[(((h - i) * 2) - 3) + (j * frame->pitch[0])] =
src[(j * 2) + 1 + (i * srcPitch)];
dst[(((frame->height - i) * 2) - 3) +
dst[(((h - i) * 2) - 3) +
((j + 1) * frame->pitch[0])] =
src[(j * 2) + 1 + ((i + 1) * srcPitch)];
/* Copy V */
dst[(((frame->height - i) * 2) - 1) + (j * frame->pitch[0])] =
dst[(((h - i) * 2) - 1) + (j * frame->pitch[0])] =
src[(j * 2) + 3 + (i * srcPitch)];
dst[(((frame->height - i) * 2) - 1) +
dst[(((h - i) * 2) - 1) +
((j + 1) * frame->pitch[0])] =
src[(j * 2) + 3 + ((i + 1) * srcPitch)];
}
@ -488,6 +482,38 @@ sna_video_copy_data(struct sna *sna,
if (frame->bo == NULL)
return FALSE;
/* In the common case, we can simply the upload to a single pwrite */
if (video->rotation == RR_Rotate_0) {
if (is_planar_fourcc(frame->id)) {
uint16_t pitch[2] = {
ALIGN((frame->width >> 1), 0x4),
ALIGN(frame->width, 0x4),
};
if (pitch[0] == frame->pitch[0] &&
pitch[1] == frame->pitch[1] &&
top == 0 && left == 0) {
kgem_bo_write(&sna->kgem, frame->bo,
buf,
pitch[1]*frame->height +
pitch[0]*frame->height);
if (frame->id != FOURCC_I420) {
uint32_t tmp;
tmp = frame->VBufOffset;
frame->VBufOffset = frame->UBufOffset;
frame->UBufOffset = tmp;
}
return TRUE;
}
} else {
if (frame->width*2 == frame->pitch[0]) {
kgem_bo_write(&sna->kgem, frame->bo,
buf + (top * frame->width*2) + (left << 1),
frame->height*frame->width*2);
return TRUE;
}
}
}
/* copy data */
dst = kgem_bo_map(&sna->kgem, frame->bo, PROT_READ | PROT_WRITE);
if (dst == NULL)

View File

@ -64,13 +64,12 @@ struct sna_video {
struct sna_video_frame {
struct kgem_bo *bo;
int id;
int width, height;
int pitch[2];
int size;
uint32_t YBufOffset;
uint32_t id;
uint32_t size;
uint32_t UBufOffset;
uint32_t VBufOffset;
uint16_t width, height;
uint16_t pitch[2];
};
void sna_video_init(struct sna *sna, ScreenPtr screen);

View File

@ -398,7 +398,7 @@ sna_video_overlay_show(struct sna *sna,
request.stride_Y = frame->pitch[0];
request.stride_UV = 0;
}
request.offset_Y = frame->YBufOffset;
request.offset_Y = 0;
request.offset_U = frame->UBufOffset;
request.offset_V = frame->VBufOffset;
DBG(("%s: handle=%d, stride_Y=%d, stride_UV=%d, off_Y: %i, off_U: %i, off_V: %i\n",