summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sna/sna_video.c56
-rw-r--r--src/sna/sna_video.h33
-rw-r--r--src/sna/sna_video_overlay.c13
-rw-r--r--src/sna/sna_video_sprite.c39
4 files changed, 105 insertions, 36 deletions
diff --git a/src/sna/sna_video.c b/src/sna/sna_video.c
index 833e6f23..2f4a7e4f 100644
--- a/src/sna/sna_video.c
+++ b/src/sna/sna_video.c
@@ -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);
}
diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h
index f0ad28f4..f3978f84 100644
--- a/src/sna/sna_video.h
+++ b/src/sna/sna_video.h
@@ -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;
}
diff --git a/src/sna/sna_video_overlay.c b/src/sna/sna_video_overlay.c
index 434d11f4..7a5b5dbf 100644
--- a/src/sna/sna_video_overlay.c
+++ b/src/sna/sna_video_overlay.c
@@ -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 */
diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index a20e9b9c..221ba793 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -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;