From 9eb310afc4a96304b47d4897c58ca3bb733362a9 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Sun, 27 May 2018 14:46:02 +0200 Subject: Add missing draw columns features --- char.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- harddoomdev.c | 55 ++++++++++++++++++++++++++++++++---- harddoomdev.h | 4 ++- private_data.h | 9 ++++++ surface.c | 48 ++++++++++++++++++++++++++++--- 5 files changed, 193 insertions(+), 12 deletions(-) diff --git a/char.c b/char.c index b1c52ec..bb70d1b 100644 --- a/char.c +++ b/char.c @@ -251,9 +251,96 @@ error_data: return err; } +void free_colors(struct colors_data *colors_data); +int colors_release(struct inode *inode, struct file *filp) +{ + struct colors_data *colors_data; + + colors_data = filp->private_data; + + free_colors(colors_data); + + kfree(colors_data); + + return 0; +} + +struct file_operations colors_fops = { + .owner = THIS_MODULE, + .release = colors_release + +}; + +int alloc_colors(struct doomdev_ioctl_create_colormaps *params, + struct colors_data *colors_data) +{ + int err; + int not_written; + + colors_data->number = params->num; + + colors_data->colors_cpu = + dma_alloc_coherent(colors_data->doom_data->pci_device, + HARDDOOM_COLORMAP_SIZE * params->num, + &colors_data->colors_dev, + GFP_KERNEL); + ORFAIL_NULL(colors_data->colors_cpu, -ENOMEM, error_colors); + + not_written = copy_from_user(colors_data->colors_cpu, + (void __user *) params->data_ptr, + HARDDOOM_COLORMAP_SIZE * params->num); + + if (not_written) { + err = -EFAULT; + goto error_copy; + } + + return 0; + +error_copy: + dma_free_coherent(colors_data->doom_data->pci_device, + HARDDOOM_COLORMAP_SIZE * params->num, + colors_data->colors_cpu, colors_data->colors_dev); +error_colors: + return err; + +} + +void free_colors(struct colors_data *colors_data) +{ + dma_free_coherent(colors_data->doom_data->pci_device, + HARDDOOM_COLORMAP_SIZE * colors_data->number, + colors_data->colors_cpu, colors_data->colors_dev); +} + long doom_create_colormaps(struct file *filp, unsigned long arg) { - return -1; + int err; + struct doomdev_ioctl_create_colormaps *params; + struct colors_data *colors_data; + int fd; + struct doom_data *doom_data; + + params = (struct doomdev_ioctl_create_colormaps *) arg; + + colors_data = kmalloc(sizeof(*colors_data), GFP_KERNEL); + ORFAIL_NULL(colors_data, -ENOMEM, error_data); + doom_data = container_of(filp->f_inode->i_cdev, struct doom_data, cdev); + colors_data->doom_data = doom_data; + + ORFAIL(alloc_colors(params, colors_data), error_colors); + + fd = anon_inode_getfd("doom_colors", &colors_fops, colors_data, 0); + ORFAIL(fd, error_inode); + + return fd; + +error_inode: + free_colors(colors_data); +error_colors: + kfree(colors_data); +error_data: + return err; } long doom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) diff --git a/harddoomdev.c b/harddoomdev.c index c4489aa..067293e 100644 --- a/harddoomdev.c +++ b/harddoomdev.c @@ -149,6 +149,22 @@ void set_flat(struct doom_data *doom_data, dma_addr_t flat_dev) } } +void set_colormap(struct doom_data *doom_data, dma_addr_t colors_dev) +{ + if (doom_data->colors_addr != colors_dev) { + doom_data->colors_addr = colors_dev; + send_command(doom_data, HARDDOOM_CMD_COLORMAP_ADDR(colors_dev)); + } +} + +void set_trans(struct doom_data *doom_data, dma_addr_t colors_dev) +{ + if (doom_data->trans_addr != colors_dev) { + doom_data->trans_addr = colors_dev; + send_command(doom_data, HARDDOOM_CMD_TRANSLATION_ADDR(colors_dev)); + } +} + void set_ustart(struct doom_data *doom_data, uint32_t ustart) { send_command(doom_data, HARDDOOM_CMD_USTART(ustart)); @@ -211,17 +227,35 @@ void copy_rect(struct surface_data *dst_data, struct surface_data *src_data, } void draw_column(struct surface_data *surface_data, - struct texture_data *texture_data, struct doomdev_column column) + struct texture_data *texture_data, struct doomdev_column column, + struct colors_data *colors_data, struct colors_data *trans_data, + uint8_t flags, uint8_t trans_idx) { set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev); set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height); - set_texture_pt(surface_data->doom_data, texture_data->page_table_dev); - set_texture_dims(surface_data->doom_data, texture_data->size, texture_data->height); + set_draw_params(surface_data->doom_data, flags); set_xy_a(surface_data->doom_data, column.x, column.y1); set_xy_b(surface_data->doom_data, column.x, column.y2); - set_ustart(surface_data->doom_data, column.ustart); - set_ustep(surface_data->doom_data, column.ustep); - set_draw_params(surface_data->doom_data, 0); + + if (!(flags & HARDDOOM_DRAW_PARAMS_FUZZ)) { + set_texture_pt(surface_data->doom_data, + texture_data->page_table_dev); + set_texture_dims(surface_data->doom_data, + texture_data->size, texture_data->height); + set_ustart(surface_data->doom_data, column.ustart); + set_ustep(surface_data->doom_data, column.ustep); + } + + if (flags & HARDDOOM_DRAW_PARAMS_FUZZ || + flags & HARDDOOM_DRAW_PARAMS_COLORMAP) { + set_colormap(surface_data->doom_data, colors_data->colors_dev + + HARDDOOM_COLORMAP_SIZE * column.colormap_idx); + } + + if (flags & HARDDOOM_DRAW_PARAMS_TRANSLATE) { + set_trans(surface_data->doom_data, trans_data->colors_dev + + HARDDOOM_COLORMAP_SIZE * trans_idx); + } send_command(surface_data->doom_data, HARDDOOM_CMD_DRAW_COLUMN(column.texture_offset)); @@ -284,6 +318,15 @@ void start_dev(struct pci_dev *dev) doomdev_write(iomem, HARDDOOM_INTR_ENABLE, HARDDOOM_INTR_MASK); doomdev_write(iomem, HARDDOOM_ENABLE, HARDDOOM_ENABLE_ALL ^ HARDDOOM_ENABLE_FETCH_CMD); + + set_surf_dst_pt(data, 0); + set_surf_src_pt(data, 0); + set_texture_pt(data, 0); + set_flat(data, 0); + set_colormap(data, 0); + set_surf_dims(data, 0, 0); + set_texture_dims(data, 0, 0); + set_draw_params(data, 0); } void shutdown_dev(struct pci_dev *dev) diff --git a/harddoomdev.h b/harddoomdev.h index 4ddd01e..90d2b51 100644 --- a/harddoomdev.h +++ b/harddoomdev.h @@ -20,7 +20,9 @@ void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect rect) void copy_rect(struct surface_data *dst_data, struct surface_data *src_data, struct doomdev_copy_rect rect); void draw_column(struct surface_data *surface_data, - struct texture_data *texture_data, struct doomdev_column column); + struct texture_data *texture_data, struct doomdev_column column, + struct colors_data *colors_data, struct colors_data *trans_data, + uint8_t flags, uint8_t trans_idx); void draw_span(struct surface_data *surface_data, struct flat_data *flat_data, struct doomdev_span span); void draw_background(struct surface_data *surface_data, diff --git a/private_data.h b/private_data.h index e374f25..65eb948 100644 --- a/private_data.h +++ b/private_data.h @@ -65,4 +65,13 @@ struct flat_data { dma_addr_t flat_dev; }; +struct colors_data { + struct doom_data *doom_data; + + uint32_t number; + + uint8_t *colors_cpu; + dma_addr_t colors_dev; +}; + #endif diff --git a/surface.c b/surface.c index fddc0fe..cbb9406 100644 --- a/surface.c +++ b/surface.c @@ -93,17 +93,48 @@ long draw_columns(struct file *filp, unsigned long arg) struct doomdev_surf_ioctl_draw_columns *param; struct surface_data *surface_data; struct texture_data *texture_data; + struct colors_data *colors_data; + struct colors_data *trans_data; struct doomdev_column *columns; struct fd texture_fds; + struct fd colors_fds; + struct fd trans_fds; + uint8_t flags; + bool got_colors = false; + bool got_trans = false; int i; surface_data = filp->private_data; param = (struct doomdev_surf_ioctl_draw_columns *) arg; - // temp - if (param->draw_flags & DOOMDEV_DRAW_FLAGS_FUZZ) { - return 0x400; + flags = param->draw_flags; + + if (flags & DOOMDEV_DRAW_FLAGS_FUZZ || + flags & DOOMDEV_DRAW_FLAGS_COLORMAP) { + if (flags & DOOMDEV_DRAW_FLAGS_FUZZ) { + flags = DOOMDEV_DRAW_FLAGS_FUZZ; + } + + colors_fds = fdget(param->colormaps_fd); + colors_data = colors_fds.file->private_data; + + got_colors = true; + + if (surface_data->doom_data != colors_data->doom_data) { + return -EINVAL; + } + } + + if (flags & DOOMDEV_DRAW_FLAGS_TRANSLATE) { + trans_fds = fdget(param->translations_fd); + trans_data = trans_fds.file->private_data; + + got_trans = true; + + if (surface_data->doom_data != trans_data->doom_data) { + return -EINVAL; + } } texture_fds = fdget(param->texture_fd); @@ -118,13 +149,22 @@ long draw_columns(struct file *filp, unsigned long arg) mutex_lock(&surface_data->doom_data->cmd_mutex); for (i = 0; i < param->columns_num; i++) { - draw_column(surface_data, texture_data, columns[i]); + draw_column(surface_data, texture_data, columns[i], colors_data, + trans_data, flags, param->translation_idx); } mutex_unlock(&surface_data->doom_data->cmd_mutex); fdput(texture_fds); + if (got_colors) { + fdput(colors_fds); + } + + if (got_trans) { + fdput(trans_fds); + } + return param->columns_num; } -- cgit v1.2.3