Added cursor support
parent
98361cf28c
commit
a2254c5a96
|
@ -317,6 +317,34 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
|
|||
return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cursor manipulation
|
||||
*/
|
||||
|
||||
int drmModeSetCursor(int fd, uint32_t crtcId, drmBO *bo, uint32_t width, uint32_t height)
|
||||
{
|
||||
struct drm_mode_cursor arg;
|
||||
|
||||
arg.flags = DRM_MODE_CURSOR_BO;
|
||||
arg.crtc = crtcId;
|
||||
arg.width = width;
|
||||
arg.height = height;
|
||||
arg.handle = bo->handle;
|
||||
|
||||
return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
|
||||
}
|
||||
|
||||
int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
|
||||
{
|
||||
struct drm_mode_cursor arg;
|
||||
|
||||
arg.flags = DRM_MODE_CURSOR_MOVE;
|
||||
arg.crtc = crtcId;
|
||||
arg.x = x;
|
||||
arg.y = y;
|
||||
|
||||
return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output manipulation
|
||||
|
|
|
@ -197,6 +197,19 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
|
|||
uint32_t x, uint32_t y, uint32_t *outputs, int count,
|
||||
struct drm_mode_modeinfo *mode);
|
||||
|
||||
/*
|
||||
* Cursor functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set the cursor on crtc
|
||||
*/
|
||||
int drmModeSetCursor(int fd, uint32_t crtcId, drmBO *bo, uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* Move the cursor on crtc
|
||||
*/
|
||||
int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y);
|
||||
|
||||
/*
|
||||
* Output manipulation
|
||||
|
|
|
@ -1608,6 +1608,63 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int drm_mode_cursor_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_cursor *req = data;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_buffer_object *bo = NULL; /* must be set */
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!req->flags) {
|
||||
DRM_ERROR("no operation set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
crtc = idr_find(&dev->mode_config.crtc_idr, req->crtc);
|
||||
if (!crtc || (crtc->id != req->crtc)) {
|
||||
DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (req->flags & DRM_MODE_CURSOR_BO) {
|
||||
/* Turn of the cursor if handle is 0 */
|
||||
if (req->handle)
|
||||
ret = drm_get_buffer_object(dev, &bo, req->handle);
|
||||
|
||||
if (ret) {
|
||||
DRM_ERROR("invalid buffer id\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (crtc->funcs->cursor_set) {
|
||||
ret = crtc->funcs->cursor_set(crtc, bo, req->width, req->height);
|
||||
} else {
|
||||
DRM_ERROR("crtc does not support cursor\n");
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (req->flags & DRM_MODE_CURSOR_MOVE) {
|
||||
if (crtc->funcs->cursor_move) {
|
||||
ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
|
||||
} else {
|
||||
DRM_ERROR("crtc does not support cursor\n");
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_addfb - add an FB to the graphics configuration
|
||||
* @inode: inode from the ioctl
|
||||
|
|
|
@ -329,6 +329,11 @@ struct drm_crtc_funcs {
|
|||
/* Move the crtc on the current fb to the given position *optional* */
|
||||
void (*mode_set_base)(struct drm_crtc *crtc, int x, int y);
|
||||
|
||||
/* cursor controls */
|
||||
int (*cursor_set)(struct drm_crtc *crtc, struct drm_buffer_object *bo,
|
||||
uint32_t width, uint32_t height);
|
||||
int (*cursor_move)(struct drm_crtc *crtc, int x, int y);
|
||||
|
||||
/* Set gamma on the CRTC */
|
||||
void (*gamma_set)(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
|
||||
int regno);
|
||||
|
@ -482,6 +487,21 @@ struct drm_output {
|
|||
uint64_t property_values[DRM_OUTPUT_MAX_PROPERTY];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_mode_set
|
||||
*
|
||||
* Represents a single crtc the outputs that it drives with what mode
|
||||
* and from which framebuffer it scans out from.
|
||||
*/
|
||||
struct drm_mode_set
|
||||
{
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
struct drm_output **outputs;
|
||||
size_t num_outputs;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_mode_config_funcs - configure CRTCs for a given screen layout
|
||||
* @resize: adjust CRTCs as necessary for the proposed layout
|
||||
|
@ -603,6 +623,8 @@ extern int drm_mode_getoutput(struct drm_device *dev,
|
|||
void *data, struct drm_file *file_priv);
|
||||
extern int drm_mode_setcrtc(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
extern int drm_mode_cursor_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
extern int drm_mode_addfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
extern int drm_mode_rmfb(struct drm_device *dev,
|
||||
|
|
|
@ -125,6 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
|
|||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETOUTPUT, drm_mode_getoutput, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
|
|
|
@ -402,6 +402,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets the power management mode of the pipe and plane.
|
||||
*
|
||||
|
@ -956,6 +958,108 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|||
}
|
||||
}
|
||||
|
||||
#define CURSOR_A_CONTROL 0x70080
|
||||
#define CURSOR_A_BASE 0x70084
|
||||
#define CURSOR_A_POSITION 0x70088
|
||||
|
||||
#define CURSOR_B_CONTROL 0x700C0
|
||||
#define CURSOR_B_BASE 0x700C4
|
||||
#define CURSOR_B_POSITION 0x700C8
|
||||
|
||||
#define CURSOR_MODE_DISABLE 0x00
|
||||
#define CURSOR_MODE_64_32B_AX 0x07
|
||||
#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
|
||||
#define MCURSOR_GAMMA_ENABLE (1 << 26)
|
||||
|
||||
#define CURSOR_POS_MASK 0x007FF
|
||||
#define CURSOR_POS_SIGN 0x8000
|
||||
#define CURSOR_X_SHIFT 0
|
||||
#define CURSOR_Y_SHIFT 16
|
||||
|
||||
static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
struct drm_buffer_object *bo,
|
||||
uint32_t width, uint32_t height)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
uint32_t control = (pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
|
||||
uint32_t temp;
|
||||
size_t adder;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* if we want to turn of the cursor ignore width and height */
|
||||
if (!bo) {
|
||||
DRM_DEBUG("cursor off\n");
|
||||
/* turn of the cursor */
|
||||
temp = 0;
|
||||
temp |= CURSOR_MODE_DISABLE;
|
||||
|
||||
I915_WRITE(control, temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Currently we only support 64x64 cursors */
|
||||
if (width != 64 || height != 64) {
|
||||
DRM_ERROR("we currently only support 64x64 cursors\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((bo->mem.flags & DRM_BO_MASK_MEM) != DRM_BO_FLAG_MEM_VRAM) {
|
||||
DRM_ERROR("buffer needs to be in VRAM\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (bo->mem.size < width * height * 4) {
|
||||
DRM_ERROR("buffer is to small\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
adder = dev_priv->stolen_base + bo->offset;
|
||||
intel_crtc->cursor_adder = adder;
|
||||
temp = 0;
|
||||
/* set the pipe for the cursor */
|
||||
temp |= (pipe << 28);
|
||||
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
|
||||
|
||||
DRM_DEBUG("cusror base %x\n", adder);
|
||||
|
||||
I915_WRITE((pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL, temp);
|
||||
I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
uint32_t temp = 0;
|
||||
uint32_t adder;
|
||||
|
||||
if (x < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
|
||||
x = -x;
|
||||
}
|
||||
if (y < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
|
||||
y = -y;
|
||||
}
|
||||
|
||||
temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
|
||||
temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
|
||||
|
||||
adder = intel_crtc->cursor_adder;
|
||||
I915_WRITE((pipe == 0) ? CURSOR_A_POSITION : CURSOR_B_POSITION, temp);
|
||||
I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Sets the color ramps on behalf of RandR */
|
||||
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
u16 blue, int regno)
|
||||
|
@ -1084,6 +1188,8 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
|
|||
.mode_fixup = intel_crtc_mode_fixup,
|
||||
.mode_set = intel_crtc_mode_set,
|
||||
.mode_set_base = intel_pipe_set_base,
|
||||
.cursor_set = intel_crtc_cursor_set,
|
||||
.cursor_move = intel_crtc_cursor_move,
|
||||
.gamma_set = intel_crtc_gamma_set,
|
||||
.prepare = intel_crtc_prepare,
|
||||
.commit = intel_crtc_commit,
|
||||
|
@ -1113,6 +1219,8 @@ void intel_crtc_init(struct drm_device *dev, int pipe)
|
|||
intel_crtc->lut_b[i] = i;
|
||||
}
|
||||
|
||||
intel_crtc->cursor_adder = 0;
|
||||
|
||||
crtc->driver_private = intel_crtc;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ struct intel_output {
|
|||
|
||||
struct intel_crtc {
|
||||
int pipe;
|
||||
uint32_t cursor_adder;
|
||||
u8 lut_r[256], lut_g[256], lut_b[256];
|
||||
};
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ struct intelfb_par {
|
|||
struct drm_crtc *crtc;
|
||||
struct drm_display_mode *fb_mode;
|
||||
};
|
||||
|
||||
/*
|
||||
static int
|
||||
var_to_refresh(const struct fb_var_screeninfo *var)
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ var_to_refresh(const struct fb_var_screeninfo *var)
|
|||
var->vsync_len;
|
||||
|
||||
return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
|
||||
}
|
||||
}*/
|
||||
|
||||
static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
unsigned blue, unsigned transp,
|
||||
|
@ -106,10 +106,10 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
|
|||
struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
/*struct drm_device *dev = par->dev;*/
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_output *output;
|
||||
int depth, found = 0;
|
||||
/*struct drm_output *output;*/
|
||||
int depth/*, found = 0*/;
|
||||
|
||||
if (!var->pixclock)
|
||||
return -EINVAL;
|
||||
|
@ -254,6 +254,8 @@ static int intelfb_set_par(struct fb_info *info)
|
|||
struct fb_var_screeninfo *var = &info->var;
|
||||
int found = 0;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
fb->depth = (var->green.length == 6) ? 16 : 15;
|
||||
|
@ -321,9 +323,19 @@ static int intelfb_set_par(struct fb_info *info)
|
|||
}
|
||||
|
||||
if (par->crtc->enabled) {
|
||||
if (!drm_mode_equal(&par->crtc->mode, drm_mode))
|
||||
if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
|
||||
if (!drm_mode_equal(&par->crtc->mode, drm_mode)) {
|
||||
if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset))
|
||||
return -EINVAL;
|
||||
} else if (par->crtc->x != var->xoffset || par->crtc->x != var->xoffset) {
|
||||
if (!par->crtc->funcs->mode_set_base) {
|
||||
if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
par->crtc->funcs->mode_set_base(par->crtc, var->xoffset, var->yoffset);
|
||||
par->crtc->x = var->xoffset;
|
||||
par->crtc->y = var->yoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1084,6 +1084,33 @@ struct drm_mode_mode_cmd {
|
|||
struct drm_mode_modeinfo mode;
|
||||
};
|
||||
|
||||
#define DRM_MODE_CURSOR_BO 0x01
|
||||
#define DRM_MODE_CURSOR_MOVE 0x02
|
||||
|
||||
/*
|
||||
* depending on the value in flags diffrent members are used.
|
||||
*
|
||||
* CURSOR_BO uses
|
||||
* crtc
|
||||
* width
|
||||
* height
|
||||
* handle - if 0 turns the cursor of
|
||||
*
|
||||
* CURSOR_MOVE uses
|
||||
* crtc
|
||||
* x
|
||||
* y
|
||||
*/
|
||||
struct drm_mode_cursor {
|
||||
unsigned int flags;
|
||||
unsigned int crtc;
|
||||
int x;
|
||||
int y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
unsigned int handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* \name Ioctls Definitions
|
||||
*/
|
||||
|
@ -1190,6 +1217,7 @@ struct drm_mode_mode_cmd {
|
|||
#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
|
||||
|
||||
#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAB, struct drm_mode_get_property)
|
||||
#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xAC, struct drm_mode_cursor)
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ struct drm_i915_private {
|
|||
void *agp_iomap;
|
||||
unsigned int max_validate_buffers;
|
||||
struct mutex cmdbuf_mutex;
|
||||
size_t stolen_base;
|
||||
#endif
|
||||
|
||||
DRM_SPINTYPE swaps_lock;
|
||||
|
|
|
@ -131,6 +131,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
dev->types[9] = _DRM_STAT_DMA;
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
pci_read_config_dword(dev->pdev, 0x5C, &dev_priv->stolen_base);
|
||||
DRM_DEBUG("stolen base %p\n", (void*)dev_priv->stolen_base);
|
||||
}
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
dev_priv->mmiobase = drm_get_resource_start(dev, 0);
|
||||
dev_priv->mmiolen = drm_get_resource_len(dev, 0);
|
||||
|
|
|
@ -34,7 +34,9 @@ static struct drm_mode_modeinfo mode = {
|
|||
drmModeFBPtr createFB(int fd, drmModeResPtr res);
|
||||
int findConnectedOutputs(int fd, drmModeResPtr res, drmModeOutputPtr *out);
|
||||
drmModeCrtcPtr findFreeCrtc(int fd, drmModeResPtr res);
|
||||
void testCursor(int fd, uint32_t crtc);
|
||||
void prettyColors(int fd, unsigned int handle);
|
||||
void prettyCursor(int fd, unsigned int handle);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
@ -98,6 +100,11 @@ int main(int argc, char **argv)
|
|||
drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 100, 100, &out[0]->output_id, 1, &mode);
|
||||
sleep(2);
|
||||
|
||||
printf("0 0\n");
|
||||
drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 1, 1, &out[0]->output_id, 1, &mode);
|
||||
|
||||
testCursor(fd, crtc->crtc_id);
|
||||
|
||||
/* turn the crtc off just in case */
|
||||
drmModeSetCrtc(fd, crtc->crtc_id, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
|
@ -166,7 +173,7 @@ int findConnectedOutputs(int fd, drmModeResPtr res, drmModeOutputPtr *out)
|
|||
|
||||
drmModeCrtcPtr findFreeCrtc(int fd, drmModeResPtr res)
|
||||
{
|
||||
return drmModeGetCrtc(fd, res->crtcs[0]);
|
||||
return drmModeGetCrtc(fd, res->crtcs[1]);
|
||||
}
|
||||
|
||||
void draw(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int v, unsigned int *ptr)
|
||||
|
@ -200,3 +207,41 @@ void prettyColors(int fd, unsigned int handle)
|
|||
|
||||
drmBOUnmap(fd, &bo);
|
||||
}
|
||||
|
||||
void testCursor(int fd, uint32_t crtc)
|
||||
{
|
||||
drmBO bo;
|
||||
int ret;
|
||||
ret = drmBOCreate(fd, 64 * 64 * 4, 0, 0,
|
||||
DRM_BO_FLAG_READ |
|
||||
DRM_BO_FLAG_WRITE |
|
||||
DRM_BO_FLAG_MEM_VRAM |
|
||||
DRM_BO_FLAG_NO_EVICT,
|
||||
DRM_BO_HINT_DONT_FENCE, &bo);
|
||||
|
||||
prettyCursor(fd, bo.handle);
|
||||
|
||||
printf("set cursor\n");
|
||||
drmModeSetCursor(fd, crtc, &bo, 64, 64);
|
||||
printf("move cursor 0, 0\n");
|
||||
drmModeMoveCursor(fd, crtc, 0, 0);
|
||||
sleep(2);
|
||||
printf("move cursor 40, 40\n");
|
||||
drmModeMoveCursor(fd, crtc, 40, 40);
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
void prettyCursor(int fd, unsigned int handle)
|
||||
{
|
||||
drmBO bo;
|
||||
unsigned int *ptr;
|
||||
int i;
|
||||
|
||||
drmBOReference(fd, handle, &bo);
|
||||
drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, (void**)&ptr);
|
||||
|
||||
for (i = 0; i < (64 * 64); i++)
|
||||
ptr[i] = 0xFFFF00FF;
|
||||
|
||||
drmBOUnmap(fd, &bo);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
all: app
|
||||
|
||||
#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \
|
||||
# -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \
|
||||
|
||||
app: demo.c
|
||||
@gcc $(CFLAGS) -o app -Wall demo.c
|
||||
|
||||
clean:
|
||||
@rm -f app
|
||||
|
||||
run: app
|
||||
sudo ./test
|
|
@ -0,0 +1,150 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "linux/fb.h"
|
||||
#include "sys/ioctl.h"
|
||||
|
||||
|
||||
void setMode(struct fb_var_screeninfo *var);
|
||||
void pan(int fd, struct fb_var_screeninfo *var, int x, int y);
|
||||
void cursor(int fd);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct fb_var_screeninfo var;
|
||||
struct fb_fix_screeninfo fix;
|
||||
const char* name = "/dev/fb0";
|
||||
|
||||
int fd = open(name, O_RDONLY);
|
||||
|
||||
if (fd == -1) {
|
||||
printf("open %s : %s\n", name, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&var, 0, sizeof(struct fb_var_screeninfo));
|
||||
memset(&fix, 0, sizeof(struct fb_fix_screeninfo));
|
||||
|
||||
if (ioctl(fd, FBIOGET_VSCREENINFO, &var))
|
||||
printf("var %s\n", strerror(errno));
|
||||
if (ioctl(fd, FBIOGET_FSCREENINFO, &fix))
|
||||
printf("fix %s\n", strerror(errno));
|
||||
|
||||
setMode(&var);
|
||||
printf("pan: 0, 0\n");
|
||||
pan(fd, &var, 0, 0);
|
||||
sleep(2);
|
||||
printf("pan: 100, 0\n");
|
||||
pan(fd, &var, 100, 0);
|
||||
sleep(2);
|
||||
printf("pan: 0, 100\n");
|
||||
pan(fd, &var, 0, 100);
|
||||
sleep(2);
|
||||
printf("pan: 100, 100\n");
|
||||
pan(fd, &var, 100, 100);
|
||||
sleep(2);
|
||||
printf("pan: 0, 0\n");
|
||||
pan(fd, &var, 0, 0);
|
||||
sleep(2);
|
||||
|
||||
printf("cursor\n");
|
||||
cursor(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pan(int fd, struct fb_var_screeninfo *var, int x, int y)
|
||||
{
|
||||
var->xoffset = x;
|
||||
var->yoffset = y;
|
||||
|
||||
var->activate = FB_ACTIVATE_NOW;
|
||||
|
||||
if (ioctl(fd, FBIOPUT_VSCREENINFO, var))
|
||||
printf("pan error: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently isn't supported in the driver
|
||||
*/
|
||||
void cursor(int fd)
|
||||
{
|
||||
struct fb_cursor cur;
|
||||
void *data = malloc(64 * 64 * 4);
|
||||
memset(&cur, 0, sizeof(cur));
|
||||
|
||||
cur.set = FB_CUR_SETIMAGE | FB_CUR_SETPOS | FB_CUR_SETSIZE;
|
||||
cur.enable = 1;
|
||||
cur.image.dx = 1;
|
||||
cur.image.dy = 1;
|
||||
cur.image.width = 2;
|
||||
cur.image.height = 2;
|
||||
cur.image.depth = 32;
|
||||
cur.image.data = data;
|
||||
|
||||
if (ioctl(fd, FBIO_CURSOR, &cur))
|
||||
printf("cursor error: %s\n", strerror(errno));
|
||||
|
||||
sleep(2);
|
||||
|
||||
memset(&cur, 0, sizeof(cur));
|
||||
cur.set = FB_CUR_SETPOS;
|
||||
cur.enable = 0;
|
||||
cur.image.dx = 100;
|
||||
cur.image.dy = 100;
|
||||
|
||||
if (ioctl(fd, FBIO_CURSOR, &cur))
|
||||
printf("cursor error: %s\n", strerror(errno));
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
struct drm_mode
|
||||
{
|
||||
int clock;
|
||||
int hdisplay;
|
||||
int hsync_start;
|
||||
int hsync_end;
|
||||
int htotal;
|
||||
int hskew;
|
||||
int vdisplay;
|
||||
int vsync_start;
|
||||
int vsync_end;
|
||||
int vtotal;
|
||||
int vscan;
|
||||
int vrefresh;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct drm_mode mode =
|
||||
{
|
||||
.clock = 25200,
|
||||
.hdisplay = 640,
|
||||
.hsync_start = 656,
|
||||
.hsync_end = 752,
|
||||
.htotal = 800,
|
||||
.hskew = 0,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 490,
|
||||
.vsync_end = 492,
|
||||
.vtotal = 525,
|
||||
.vscan = 0,
|
||||
.vrefresh = 60000, /* vertical refresh * 1000 */
|
||||
.flags = 10,
|
||||
};
|
||||
|
||||
void setMode(struct fb_var_screeninfo *var) {
|
||||
var->activate = FB_ACTIVATE_NOW;
|
||||
var->xres = mode.hdisplay;
|
||||
var->right_margin = mode.hsync_start - mode.hdisplay;
|
||||
var->hsync_len = mode.hsync_end - mode.hsync_start;
|
||||
var->left_margin = mode.htotal - mode.hsync_end;
|
||||
var->yres = mode.vdisplay;
|
||||
var->lower_margin = mode.vsync_start - mode.vdisplay;
|
||||
var->vsync_len = mode.vsync_end - mode.vsync_start;
|
||||
var->upper_margin = mode.vtotal - mode.vsync_end;
|
||||
var->pixclock = 10000000 / mode.htotal * 1000 / mode.vtotal * 100;
|
||||
/* avoid overflow */
|
||||
var->pixclock = var->pixclock * 1000 / mode.vrefresh;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app
|
Loading…
Reference in New Issue