sna/video: YUV420 is not supported by sprites, replace it with a RGB passthrough

As YUV420 is not supported by any of the current sprite implementations
drop it. Instead implement some RGB passthroughs.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-08-16 21:11:33 +01:00
parent c610d37dae
commit 85e89f2121
4 changed files with 105 additions and 36 deletions

View File

@ -226,26 +226,50 @@ sna_video_frame_init(struct sna_video *video,
}
frame->size *= frame->pitch[0] + frame->pitch[1];
} else {
if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->pitch[0] = ALIGN((height << 1), align);
frame->size = (int)frame->pitch[0] * width;
} else {
frame->pitch[0] = ALIGN((width << 1), align);
frame->size = (int)frame->pitch[0] * height;
switch (frame->id) {
case FOURCC_RGB888:
if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->pitch[0] = ALIGN((height << 2), align);
frame->size = (int)frame->pitch[0] * width;
} else {
frame->pitch[0] = ALIGN((width << 2), align);
frame->size = (int)frame->pitch[0] * height;
}
frame->UBufOffset = frame->VBufOffset = 0;
break;
case FOURCC_RGB565:
if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->pitch[0] = ALIGN((height << 1), align);
frame->size = (int)frame->pitch[0] * width;
} else {
frame->pitch[0] = ALIGN((width << 1), align);
frame->size = (int)frame->pitch[0] * height;
}
frame->UBufOffset = frame->VBufOffset = 0;
break;
default:
if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->pitch[0] = ALIGN((height << 1), align);
frame->size = (int)frame->pitch[0] * width;
} else {
frame->pitch[0] = ALIGN((width << 1), align);
frame->size = (int)frame->pitch[0] * height;
}
if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->UBufOffset = (int)frame->pitch[1] * width;
frame->VBufOffset =
frame->UBufOffset + (int)frame->pitch[0] * width / 2;
} else {
frame->UBufOffset = (int)frame->pitch[1] * height;
frame->VBufOffset =
frame->UBufOffset + (int)frame->pitch[0] * height / 2;
}
break;
}
frame->pitch[1] = 0;
}
if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
frame->UBufOffset = (int)frame->pitch[1] * width;
frame->VBufOffset =
frame->UBufOffset + (int)frame->pitch[0] * width / 2;
} else {
frame->UBufOffset = (int)frame->pitch[1] * height;
frame->VBufOffset =
frame->UBufOffset + (int)frame->pitch[0] * height / 2;
}
assert(frame->size);
}

View File

@ -35,6 +35,10 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SNA_XVMC 1
#endif
#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X')
#define FOURCC_RGB565 ((16 << 24) + ('B' << 16) + ('G' << 8) + 'R')
#define FOURCC_RGB888 ((24 << 24) + ('B' << 16) + ('G' << 8) + 'R')
/*
* Below, a dummy picture type that is used in XvPutImage
* only to do an overlay update.
@ -49,6 +53,22 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
XvTopToBottom \
}
#define XVMC_RGB565 { \
FOURCC_RGB565, XvRGB, LSBFirst, \
{'P', 'A', 'S', 'S', 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'R', 'G', 'B', '1', '6'}, \
16, XvPacked, 1, 16, 0x1f<<11, 0x3f<<5, 0x1f<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
{'B', 'G', 'R', 'X', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
XvTopToBottom \
}
#define XVMC_RGB888 { \
FOURCC_RGB888, XvRGB, LSBFirst, \
{'P', 'A', 'S', 'S', 'T', 'H', 'R', 'O', 'U', 'G', 'H', 'R', 'G', 'B', '2', '4'}, \
32, XvPacked, 1, 24, 0xff<<16, 0xff<<8, 0xff<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
{'B', 'G', 'R', 'X', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
XvTopToBottom \
}
struct sna_video {
struct sna *sna;
@ -116,11 +136,16 @@ int sna_xv_fixup_formats(ScreenPtr screen,
int sna_xv_alloc_port(unsigned long port, XvPortPtr in, XvPortPtr *out);
int sna_xv_free_port(XvPortPtr port);
#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X')
static inline int xvmc_passthrough(int id)
{
return id == FOURCC_XVMC;
switch (id) {
case FOURCC_XVMC:
case FOURCC_RGB565:
case FOURCC_RGB888:
return true;
default:
return false;
}
}
static inline int is_planar_fourcc(int id)
@ -130,8 +155,6 @@ static inline int is_planar_fourcc(int id)
case FOURCC_I420:
case FOURCC_XVMC:
return 1;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
return 0;
}

View File

@ -600,6 +600,7 @@ sna_video_overlay_query(ClientPtr client,
int *offsets)
{
struct sna_video *video = port->devPriv.ptr;
struct sna_video_frame frame;
struct sna *sna = video->sna;
int size, tmp;
@ -624,9 +625,17 @@ sna_video_overlay_query(ClientPtr client,
switch (format->id) {
case FOURCC_XVMC:
*h = (*h + 1) & ~1;
sna_video_frame_init(video, format->id, *w, *h, &frame);
size = sizeof(uint32_t);
if (pitches)
pitches[0] = size;
if (pitches) {
pitches[0] = frame.pitch[1];
pitches[1] = frame.pitch[0];
pitches[2] = frame.pitch[0];
}
if (offsets) {
offsets[1] = frame.UBufOffset;
offsets[2] = frame.VBufOffset;
}
break;
/* IA44 is for XvMC only */

View File

@ -51,7 +51,7 @@
static Atom xvColorKey, xvAlwaysOnTop;
static XvFormatRec formats[] = { {15}, {16}, {24} };
static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVMC_YUV };
static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVMC_RGB888, XVMC_RGB565 };
static const XvAttributeRec attribs[] = {
{ XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_COLORKEY" },
};
@ -232,7 +232,17 @@ sna_video_sprite_show(struct sna *sna,
uint32_t offsets[4], pitches[4], handles[4];
uint32_t pixel_format;
handles[0] = frame->bo->handle;
pitches[0] = frame->pitch[0];
offsets[0] = 0;
switch (frame->id) {
case FOURCC_RGB565:
pixel_format = DRM_FORMAT_RGB565;
break;
case FOURCC_RGB888:
pixel_format = DRM_FORMAT_XRGB8888;
break;
case FOURCC_UYVY:
pixel_format = DRM_FORMAT_UYVY;
break;
@ -242,13 +252,9 @@ sna_video_sprite_show(struct sna *sna,
break;
}
handles[0] = frame->bo->handle;
pitches[0] = frame->pitch[0];
offsets[0] = 0;
DBG(("%s: creating new fb for handle=%d, width=%d, height=%d, stride=%d\n",
__FUNCTION__, frame->bo->handle,
frame->width, frame->height, frame->pitch[0]));
frame->width, frame->height, pitches[0]));
if (drmModeAddFB2(sna->kgem.fd,
frame->width, frame->height, pixel_format,
@ -420,6 +426,8 @@ static int sna_video_sprite_query(ClientPtr client,
int *pitches,
int *offsets)
{
struct sna_video *video = port->devPriv.ptr;
struct sna_video_frame frame;
int size;
if (*w > IMAGE_MAX_WIDTH)
@ -427,20 +435,22 @@ static int sna_video_sprite_query(ClientPtr client,
if (*h > IMAGE_MAX_HEIGHT)
*h = IMAGE_MAX_HEIGHT;
*w = (*w + 1) & ~1;
if (offsets)
offsets[0] = 0;
switch (format->id) {
case FOURCC_XVMC:
*h = (*h + 1) & ~1;
size = sizeof(uint32_t);
case FOURCC_RGB888:
case FOURCC_RGB565:
sna_video_frame_init(video, format->id, *w, *h, &frame);
if (pitches)
pitches[0] = size;
pitches[0] = frame.pitch[0];
size = 4;
break;
case FOURCC_YUY2:
default:
*w = (*w + 1) & ~1;
*h = (*h + 1) & ~1;
size = *w << 1;
if (pitches)
pitches[0] = size;
@ -518,8 +528,11 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
ARRAY_SIZE(formats));
adaptor->nAttributes = ARRAY_SIZE(attribs);
adaptor->pAttributes = (XvAttributeRec *)attribs;
adaptor->nImages = ARRAY_SIZE(images);
adaptor->pImages = (XvImageRec *)images;
adaptor->nImages = 3;
if (sna->kgem.gen == 071)
adaptor->nImages = 4;
adaptor->ddAllocatePort = sna_xv_alloc_port;
adaptor->ddFreePort = sna_xv_free_port;
adaptor->ddPutVideo = NULL;