diff options
| author | Jakob Bornecrantz <jakob@tungstengraphics.com> | 2008-01-28 03:12:29 +0100 | 
|---|---|---|
| committer | Jakob Bornecrantz <jakob@tungstengraphics.com> | 2008-01-28 03:14:56 +0100 | 
| commit | a2254c5a9670a3e865f0eb5acd46e905c9b146ce (patch) | |
| tree | 080e144b12585dc3dd4c7e3cae63bb3dbe004486 | |
| parent | 98361cf28c62530e34758b27aa1eea805269e0e5 (diff) | |
Added cursor support
| -rw-r--r-- | libdrm/xf86drmMode.c | 28 | ||||
| -rw-r--r-- | libdrm/xf86drmMode.h | 13 | ||||
| -rw-r--r-- | linux-core/drm_crtc.c | 57 | ||||
| -rw-r--r-- | linux-core/drm_crtc.h | 22 | ||||
| -rw-r--r-- | linux-core/drm_drv.c | 1 | ||||
| -rw-r--r-- | linux-core/intel_display.c | 108 | ||||
| -rw-r--r-- | linux-core/intel_drv.h | 1 | ||||
| -rw-r--r-- | linux-core/intel_fb.c | 26 | ||||
| -rw-r--r-- | shared-core/drm.h | 28 | ||||
| -rw-r--r-- | shared-core/i915_drv.h | 1 | ||||
| -rw-r--r-- | shared-core/i915_init.c | 5 | ||||
| -rw-r--r-- | tests/modedemo/demo.c | 47 | ||||
| -rw-r--r-- | tests/modefb/Makefile | 14 | ||||
| -rw-r--r-- | tests/modefb/demo.c | 150 | ||||
| -rwxr-xr-x | tests/modefb/test | 1 | 
15 files changed, 494 insertions, 8 deletions
| diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 0edb1d7d..86572872 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -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 diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index e2dda8ac..f5b3337c 100644 --- a/libdrm/xf86drmMode.h +++ b/libdrm/xf86drmMode.h @@ -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 diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 1e69eca3..18fa02ce 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -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 diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 65c3704a..8f6a8938 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -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); @@ -483,6 +488,21 @@ struct drm_output {  };  /** + * 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, diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index ab047ca3..b0b44c90 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -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), diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 1498a51c..88cf653c 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -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;  } diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h index 06335b18..25c3a978 100644 --- a/linux-core/intel_drv.h +++ b/linux-core/intel_drv.h @@ -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];  }; diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index b67c0fcc..bb42bc69 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -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;  } diff --git a/shared-core/drm.h b/shared-core/drm.h index 7aea3033..209a8db0 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -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)  /*@}*/ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 49e23ac3..ea89bc4c 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -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; diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 3b271b17..792c40bb 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -132,6 +132,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	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);  		dev->mode_config.fb_base = diff --git a/tests/modedemo/demo.c b/tests/modedemo/demo.c index 594d60db..1efeb272 100644 --- a/tests/modedemo/demo.c +++ b/tests/modedemo/demo.c @@ -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); +} diff --git a/tests/modefb/Makefile b/tests/modefb/Makefile new file mode 100644 index 00000000..84c6c86a --- /dev/null +++ b/tests/modefb/Makefile @@ -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 diff --git a/tests/modefb/demo.c b/tests/modefb/demo.c new file mode 100644 index 00000000..0dbf01c7 --- /dev/null +++ b/tests/modefb/demo.c @@ -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; +} diff --git a/tests/modefb/test b/tests/modefb/test new file mode 100755 index 00000000..f98e3708 --- /dev/null +++ b/tests/modefb/test @@ -0,0 +1 @@ +LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app | 
