Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 174503
b: refs/heads/master
c: 884840a
h: refs/heads/master
i:
  174501: 660081f
  174499: 7527d4e
  174495: 2e504e3
v: v3
  • Loading branch information
Jakob Bornecrantz authored and Dave Airlie committed Dec 3, 2009
1 parent 6dd4bfa commit f9df54e
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c3a73ba13bac7fd96030f39202b2d37fb19c46a6
refs/heads/master: 884840aa3ce3214259e69557be5b4ce0d781ffa4
104 changes: 104 additions & 0 deletions trunk/drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
drm_tv_subconnector_enum_list)

static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
{ DRM_MODE_DIRTY_OFF, "Off" },
{ DRM_MODE_DIRTY_ON, "On" },
{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
};

DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
drm_dirty_info_enum_list)

struct drm_conn_prop_enum_list {
int type;
char *name;
Expand Down Expand Up @@ -801,6 +810,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_mode_create_dithering_property);

/**
* drm_mode_create_dirty_property - create dirty property
* @dev: DRM device
*
* Called by a driver the first time it's needed, must be attached to desired
* connectors.
*/
int drm_mode_create_dirty_info_property(struct drm_device *dev)
{
struct drm_property *dirty_info;
int i;

if (dev->mode_config.dirty_info_property)
return 0;

dirty_info =
drm_property_create(dev, DRM_MODE_PROP_ENUM |
DRM_MODE_PROP_IMMUTABLE,
"dirty",
ARRAY_SIZE(drm_dirty_info_enum_list));
for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++)
drm_property_add_enum(dirty_info, i,
drm_dirty_info_enum_list[i].type,
drm_dirty_info_enum_list[i].name);
dev->mode_config.dirty_info_property = dirty_info;

return 0;
}
EXPORT_SYMBOL(drm_mode_create_dirty_info_property);

/**
* drm_mode_config_init - initialize DRM mode_configuration structure
* @dev: DRM device
Expand Down Expand Up @@ -1753,6 +1792,71 @@ int drm_mode_getfb(struct drm_device *dev,
return ret;
}

int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_clip_rect __user *clips_ptr;
struct drm_clip_rect *clips = NULL;
struct drm_mode_fb_dirty_cmd *r = data;
struct drm_mode_object *obj;
struct drm_framebuffer *fb;
unsigned flags;
int num_clips;
int ret = 0;

mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
if (!obj) {
DRM_ERROR("invalid framebuffer id\n");
ret = -EINVAL;
goto out_err1;
}
fb = obj_to_fb(obj);

num_clips = r->num_clips;
clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;

if (!num_clips != !clips_ptr) {
ret = -EINVAL;
goto out_err1;
}

flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;

/* If userspace annotates copy, clips must come in pairs */
if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
ret = -EINVAL;
goto out_err1;
}

if (num_clips && clips_ptr) {
clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
if (!clips) {
ret = -ENOMEM;
goto out_err1;
}

ret = copy_from_user(clips, clips_ptr,
num_clips * sizeof(*clips));
if (ret)
goto out_err2;
}

if (fb->funcs->dirty) {
ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips);
} else {
ret = -ENOSYS;
goto out_err2;
}

out_err2:
kfree(clips);
out_err1:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}


/**
* drm_fb_release - remove and free the FBs on this file
* @filp: file * from the ioctl
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/gpu/drm/drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW)
};

#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
Expand Down
1 change: 1 addition & 0 deletions trunk/include/drm/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ struct drm_gem_open {
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)

/**
* Device specific ioctls should only be in their respective headers
Expand Down
19 changes: 19 additions & 0 deletions trunk/include/drm/drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,21 @@ struct drm_framebuffer_funcs {
int (*create_handle)(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned int *handle);
/**
* Optinal callback for the dirty fb ioctl.
*
* Userspace can notify the driver via this callback
* that a area of the framebuffer has changed and should
* be flushed to the display hardware.
*
* See documentation in drm_mode.h for the struct
* drm_mode_fb_dirty_cmd for more information as all
* the semantics and arguments have a one to one mapping
* on this function.
*/
int (*dirty)(struct drm_framebuffer *framebuffer, unsigned flags,
unsigned color, struct drm_clip_rect *clips,
unsigned num_clips);
};

struct drm_framebuffer {
Expand Down Expand Up @@ -610,6 +625,7 @@ struct drm_mode_config {
/* Optional properties */
struct drm_property *scaling_mode_property;
struct drm_property *dithering_mode_property;
struct drm_property *dirty_info_property;
};

#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
Expand Down Expand Up @@ -718,6 +734,7 @@ extern int drm_mode_create_tv_properties(struct drm_device *dev, int num_formats
char *formats[]);
extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);
extern int drm_mode_create_dithering_property(struct drm_device *dev);
extern int drm_mode_create_dirty_info_property(struct drm_device *dev);
extern char *drm_get_encoder_name(struct drm_encoder *encoder);

extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
Expand Down Expand Up @@ -745,6 +762,8 @@ extern int drm_mode_rmfb(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_getfb(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_addmode_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_rmmode_ioctl(struct drm_device *dev,
Expand Down
44 changes: 44 additions & 0 deletions trunk/include/drm/drm_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
#define DRM_MODE_DITHERING_OFF 0
#define DRM_MODE_DITHERING_ON 1

/* Dirty info options */
#define DRM_MODE_DIRTY_OFF 0
#define DRM_MODE_DIRTY_ON 1
#define DRM_MODE_DIRTY_ANNOTATE 2

struct drm_mode_modeinfo {
__u32 clock;
__u16 hdisplay, hsync_start, hsync_end, htotal, hskew;
Expand Down Expand Up @@ -222,6 +227,45 @@ struct drm_mode_fb_cmd {
__u32 handle;
};

#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
#define DRM_MODE_FB_DIRTY_FLAGS 0x03

/*
* Mark a region of a framebuffer as dirty.
*
* Some hardware does not automatically update display contents
* as a hardware or software draw to a framebuffer. This ioctl
* allows userspace to tell the kernel and the hardware what
* regions of the framebuffer have changed.
*
* The kernel or hardware is free to update more then just the
* region specified by the clip rects. The kernel or hardware
* may also delay and/or coalesce several calls to dirty into a
* single update.
*
* Userspace may annotate the updates, the annotates are a
* promise made by the caller that the change is either a copy
* of pixels or a fill of a single color in the region specified.
*
* If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then
* the number of updated regions are half of num_clips given,
* where the clip rects are paired in src and dst. The width and
* height of each one of the pairs must match.
*
* If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller
* promises that the region specified of the clip rects is filled
* completely with a single color as given in the color argument.
*/

struct drm_mode_fb_dirty_cmd {
__u32 fb_id;
__u32 flags;
__u32 color;
__u32 num_clips;
__u64 clips_ptr;
};

struct drm_mode_mode_cmd {
__u32 connector_id;
struct drm_mode_modeinfo mode;
Expand Down

0 comments on commit f9df54e

Please sign in to comment.