@@ -69,6 +69,7 @@ intel_drv_la_SOURCES = \
i965_reg.h \
i965_video.c \
i965_render.c \
+ intel_sprite.c \
$(NULL)
if DRI
@@ -334,6 +334,7 @@ typedef struct intel_screen_private {
int colorKey;
XF86VideoAdaptorPtr adaptor;
+ XF86VideoAdaptorPtr sprite_adaptor;
ScreenBlockHandlerProcPtr BlockHandler;
Bool overlayOn;
@@ -461,6 +462,7 @@ extern void intel_mode_fini(intel_screen_private *intel);
extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
extern int intel_crtc_id(xf86CrtcPtr crtc);
+extern int intel_crtc_to_sprite(xf86CrtcPtr crtc);
extern int intel_output_dpms_status(xf86OutputPtr output);
enum DRI2FrameEventType {
@@ -518,6 +520,7 @@ extern void I915EmitInvarientState(ScrnInfoPtr scrn);
extern void I830EmitFlush(ScrnInfoPtr scrn);
extern void I830InitVideo(ScreenPtr pScreen);
+extern XF86VideoAdaptorPtr intel_setup_sprite(ScreenPtr screen);
extern xf86CrtcPtr intel_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
xf86CrtcPtr desired, BoxPtr crtc_box_ret);
@@ -75,6 +75,7 @@ struct intel_crtc {
dri_bo *rotate_bo;
uint32_t rotate_pitch;
uint32_t rotate_fb_id;
+ uint32_t sprite_id;
xf86CrtcPtr crtc;
struct list link;
};
@@ -1564,9 +1565,50 @@ drm_wakeup_handler(pointer data, int err, pointer p)
drmHandleEvent(mode->fd, &mode->event_context);
}
+static void intel_crtc_find_plane(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
+{
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ struct intel_crtc *intel_crtc = crtc->driver_private;
+ drmModePlaneRes *plane_resources;
+ drmModePlane *ovr;
+ uint32_t id = 0;
+ int i;
+
+ plane_resources = drmModeGetPlaneResources(intel->drmSubFD);
+ if (!plane_resources) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "failed to get plane resources: %s\n",
+ strerror(errno));
+ goto out;
+ }
+
+ for (i = 0; i < plane_resources->count_planes; i++) {
+ ovr = drmModeGetPlane(intel->drmSubFD,
+ plane_resources->planes[i]);
+ if (!ovr) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "failed to get plane info: %s\n",
+ strerror(errno));
+ continue;
+ }
+
+ if (ovr->possible_crtcs & (1 << intel_crtc_to_pipe(crtc))) {
+ id = ovr->plane_id;
+ drmModeFreePlane(ovr);
+ break;
+ }
+ drmModeFreePlane(ovr);
+ }
+
+ free(plane_resources);
+out:
+ intel_crtc->sprite_id = id;
+}
+
Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
+ struct intel_crtc *intel_crtc;
struct drm_i915_getparam gp;
struct intel_mode *mode;
unsigned int i;
@@ -1597,6 +1639,9 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
for (i = 0; i < mode->mode_res->count_crtcs; i++)
intel_crtc_init(scrn, mode, i);
+ list_for_each_entry(intel_crtc, &mode->crtcs, link)
+ intel_crtc_find_plane(scrn, intel_crtc->crtc);
+
for (i = 0; i < mode->mode_res->count_connectors; i++)
intel_output_init(scrn, mode, i);
@@ -1618,6 +1663,8 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
}
intel->modes = mode;
+
+
return TRUE;
}
@@ -1687,3 +1734,9 @@ int intel_crtc_to_pipe(xf86CrtcPtr crtc)
struct intel_crtc *intel_crtc = crtc->driver_private;
return intel_crtc->pipe;
}
+
+int intel_crtc_to_sprite(xf86CrtcPtr crtc)
+{
+ struct intel_crtc *intel_crtc = crtc->driver_private;
+ return intel_crtc->sprite_id;
+}
new file mode 100644
@@ -0,0 +1,291 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <xf86drmMode.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+#include "randrstr.h"
+#include "windowstr.h"
+#include "damage.h"
+#include "intel.h"
+#include "intel_video.h"
+#include "i830_reg.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "dixstruct.h"
+#include "fourcc.h"
+
+#define IMAGE_MAX_WIDTH 2048
+#define IMAGE_MAX_HEIGHT 2048
+
+static XF86VideoFormatRec xv_formats[] = {
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static XF86ImageRec xv_images[] = {
+ XVIMAGE_YUY2,
+ XVIMAGE_UYVY,
+};
+
+static const XF86VideoEncodingRec xv_dummy_encoding[] = {
+ {
+ 0,
+ "XV_IMAGE",
+ IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+ {1, 1}
+ }
+};
+
+static void intel_sprite_stop(ScrnInfoPtr scrn, pointer data, Bool shutdown)
+{
+}
+
+static int intel_sprite_set_attr(ScrnInfoPtr scrn, Atom attribute, INT32 value,
+ pointer data)
+{
+ return Success;
+}
+
+static int intel_sprite_get_attr(ScrnInfoPtr scrn, Atom attribute, INT32 *value,
+ pointer data)
+{
+ return Success;
+}
+
+static void intel_sprite_best_size(ScrnInfoPtr scrn, Bool motion, short vid_w,
+ short vid_h, short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data)
+{
+ *p_w = vid_w;
+ *p_h = vid_h;
+}
+
+static int intel_sprite_put(ScrnInfoPtr scrn, short src_x, short src_y,
+ short drw_x, short drw_y, short src_w, short src_h,
+ short drw_w, short drw_h, int id,
+ unsigned char *buf, short width, short height,
+ Bool sync, RegionPtr clipBoxes, pointer data,
+ DrawablePtr drawable)
+{
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ intel_adaptor_private *adaptor_priv = intel_get_sprite_adaptor_private(intel);
+ dri_bo *new_frame;
+ unsigned char *src, *dst, *dst_base;
+ int pitch, i;
+ xf86CrtcPtr crtc;
+ BoxRec dst_box;
+ int ret, top, left, lines, pixel_width;
+ int plane_id;
+ uint32_t fb_id;
+ unsigned long alloc_pitch;
+
+ ret = intel_clip_video_helper(scrn, adaptor_priv, &crtc, &dst_box,
+ src_x, src_y, drw_x, drw_y,
+ src_w, src_h, drw_w, drw_h,
+ id, &top, &left, &pixel_width, &lines,
+ clipBoxes, width, height);
+ if (!ret)
+ return Success;
+
+ plane_id = intel_crtc_to_sprite(crtc);
+ if (!plane_id) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "no planes available for crtc\n");
+ return Success;
+ }
+
+ new_frame = adaptor_priv->buf;
+ pitch = ALIGN(pixel_width, 64);
+
+ if (!new_frame) {
+ uint32_t tiling_mode = I915_TILING_X;
+
+ new_frame = drm_intel_bo_alloc_tiled(intel->bufmgr,
+ "sprite buffer",
+ pixel_width, lines,
+ drawable->bitsPerPixel / 8,
+ &tiling_mode, &alloc_pitch,
+ BO_ALLOC_FOR_RENDER);
+ if (!new_frame) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "failed to create bo for video data: %s\n",
+ strerror(errno));
+ return BadAlloc;
+ }
+ adaptor_priv->reusable = TRUE;
+ adaptor_priv->buf = new_frame;
+ }
+
+ if (drm_intel_gem_bo_map_gtt(new_frame))
+ return BadAlloc;
+
+ dst_base = new_frame->virtual;
+ dst = dst_base + adaptor_priv->YBufOffset;
+
+ src = buf + (top * (width * 2)) + (left << 1);
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, width * 2);
+ src += width * 2;
+ dst += pitch;
+ }
+
+ drm_intel_gem_bo_unmap_gtt(new_frame);
+
+ ret = drmModeAddFB2(intel->drmSubFD, pixel_width, lines,
+ V4L2_PIX_FMT_RGB32, drawable->depth,
+ drawable->bitsPerPixel, alloc_pitch,
+ new_frame->handle, &fb_id);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "failed to add fb for video data: %s\n",
+ strerror(errno));
+ return BadAlloc;
+ }
+
+ ret = drmModeSetPlane(intel->drmSubFD, plane_id, intel_crtc_id(crtc),
+ fb_id, left, top, 0, 0);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "failed to enable plane for video data: %s\n",
+ strerror(errno));
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+static int intel_sprite_query_attrs(ScrnInfoPtr scrn, int id, unsigned short *w,
+ unsigned short *h, int *pitches,
+ int *offsets)
+{
+ int size;
+
+ if (*w > IMAGE_MAX_WIDTH)
+ *w = IMAGE_MAX_WIDTH;
+ if (*h > IMAGE_MAX_HEIGHT)
+ *h = IMAGE_MAX_HEIGHT;
+
+ *w = (*w + 1) & ~1;
+ if (offsets)
+ offsets[0] = 0;
+
+ switch (id) {
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if (pitches)
+ pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+XF86VideoAdaptorPtr intel_setup_sprite(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ XF86VideoAdaptorPtr adapt;
+ intel_adaptor_private *adaptor_priv;
+ drmModePlaneRes *plane_resources;
+ drmModePlane *planes;
+
+ adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
+ sizeof(intel_adaptor_private) + sizeof(DevUnion));
+ if (!adapt)
+ goto err;
+
+ plane_resources = drmModeGetPlaneResources(intel->drmSubFD);
+ if (!plane_resources) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "No sprite support\n");
+ goto err_free_adaptor;
+ }
+
+ planes = calloc(plane_resources->count_planes, sizeof(*planes));
+ if (!planes) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Out of memory in %s\n",
+ __func__);
+ goto err_free_res;
+ }
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT */ ;
+ adapt->name = "Intel(R) Video Sprite";
+ adapt->nEncodings = ARRAY_SIZE(xv_dummy_encoding);
+ adapt->pEncodings = xnfalloc(sizeof(xv_dummy_encoding));
+ memcpy(adapt->pEncodings, xv_dummy_encoding, sizeof(xv_dummy_encoding));
+ adapt->nFormats = ARRAY_SIZE(xv_formats);
+ adapt->pFormats = xv_formats;
+ adapt->nPorts = 1;
+ adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
+
+ adaptor_priv = (intel_adaptor_private *)&adapt->pPortPrivates[1];
+ adapt->pPortPrivates[0].ptr = (pointer) (adaptor_priv);
+
+ adapt->nAttributes = 0;
+ adapt->pAttributes = NULL;
+
+ adapt->nImages = ARRAY_SIZE(xv_images);
+ adapt->pImages = xv_images;
+
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = intel_sprite_stop;
+ adapt->SetPortAttribute = intel_sprite_set_attr;
+ adapt->GetPortAttribute = intel_sprite_get_attr;
+ adapt->QueryBestSize = intel_sprite_best_size;
+ adapt->PutImage = intel_sprite_put;
+ adapt->QueryImageAttributes = intel_sprite_query_attrs;
+
+ adaptor_priv->textured = FALSE;
+ adaptor_priv->colorKey = intel->colorKey & ((1 << scrn->depth) - 1);
+ adaptor_priv->brightness = -19; /* (255/219) * -16 */
+ adaptor_priv->contrast = 75; /* 255/219 * 64 */
+ adaptor_priv->saturation = 146; /* 128/112 * 128 */
+ adaptor_priv->desired_crtc = NULL;
+ adaptor_priv->buf = NULL;
+ adaptor_priv->old_buf[0] = NULL;
+ adaptor_priv->old_buf[1] = NULL;
+ adaptor_priv->gamma5 = 0xc0c0c0;
+ adaptor_priv->gamma4 = 0x808080;
+ adaptor_priv->gamma3 = 0x404040;
+ adaptor_priv->gamma2 = 0x202020;
+ adaptor_priv->gamma1 = 0x101010;
+ adaptor_priv->gamma0 = 0x080808;
+ adaptor_priv->planes = planes;
+
+ adaptor_priv->rotation = RR_Rotate_0;
+
+ /* gotta uninit this someplace */
+ REGION_NULL(screen, &adaptor_priv->clip);
+
+ intel->sprite_adaptor = adapt;
+
+ free(plane_resources);
+
+ return adapt;
+
+err_free_res:
+ free(plane_resources);
+err_free_adaptor:
+ free(adapt);
+err:
+ return NULL;
+}
@@ -337,7 +337,8 @@ void I830InitVideo(ScreenPtr screen)
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
- XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
+ XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL,
+ spriteAdaptor = NULL;
int num_adaptors;
num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors);
@@ -345,7 +346,7 @@ void I830InitVideo(ScreenPtr screen)
* adaptors.
*/
newAdaptors =
- malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
+ malloc((num_adaptors + 3) * sizeof(XF86VideoAdaptorPtr *));
if (newAdaptors == NULL)
return;
@@ -388,6 +389,13 @@ void I830InitVideo(ScreenPtr screen)
}
}
+
+ spriteAdaptor = intel_setup_sprite(screen);
+ if (spriteAdaptor) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "Set up video sprite\n");
+ adaptors[num_adaptors++] = spriteAdaptor;
+ }
+
if (overlayAdaptor && intel->XvPreferOverlay)
adaptors[num_adaptors++] = overlayAdaptor;
@@ -405,10 +413,9 @@ void I830InitVideo(ScreenPtr screen)
intel->XvEnabled = FALSE;
}
-#ifdef INTEL_XVMC
if (texturedAdaptor)
intel_xvmc_adaptor_init(screen);
-#endif
+
free(adaptors);
}
@@ -1226,7 +1233,7 @@ intel_display_overlay(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
src_w, src_h, drw_w, drw_h);
}
-static Bool
+Bool
intel_clip_video_helper(ScrnInfoPtr scrn,
intel_adaptor_private *adaptor_priv,
xf86CrtcPtr * crtc_ret,
@@ -55,6 +55,8 @@ typedef struct {
drm_intel_bo *buf, *old_buf[2];
Bool reusable;
+ struct _drmModePlane *planes;
+
Bool textured;
Rotation rotation; /* should remove intel->rotation later */
@@ -67,6 +69,12 @@ intel_get_adaptor_private(intel_screen_private *intel)
return intel->adaptor->pPortPrivates[0].ptr;
}
+static inline intel_adaptor_private *
+intel_get_sprite_adaptor_private(intel_screen_private *intel)
+{
+ return intel->sprite_adaptor->pPortPrivates[0].ptr;
+}
+
void I915DisplayVideoTextured(ScrnInfoPtr scrn,
intel_adaptor_private *adaptor_priv,
int id, RegionPtr dstRegion, short width,
@@ -93,3 +101,16 @@ void i965_free_video(ScrnInfoPtr scrn);
int is_planar_fourcc(int id);
void intel_video_block_handler(intel_screen_private *intel);
+
+extern Bool intel_clip_video_helper(ScrnInfoPtr scrn,
+ intel_adaptor_private *adaptor_priv,
+ xf86CrtcPtr * crtc_ret,
+ BoxPtr dst,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id,
+ int *top, int* left, int* npixels,
+ int *nlines,
+ RegionPtr reg, INT32 width, INT32 height);