Commit 56d1c78d authored by Jakob Bornecrantz's avatar Jakob Bornecrantz Committed by Dave Airlie

vmwgfx: Add screen object support

Signed-off-by: default avatarJakob Bornecrantz <jakob@vmware.com>
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent d991ef03
...@@ -5,6 +5,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ ...@@ -5,6 +5,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \ vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \ vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
...@@ -451,22 +451,28 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) ...@@ -451,22 +451,28 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->fman = vmw_fence_manager_init(dev_priv); dev_priv->fman = vmw_fence_manager_init(dev_priv);
if (unlikely(dev_priv->fman == NULL)) if (unlikely(dev_priv->fman == NULL))
goto out_no_fman; goto out_no_fman;
ret = vmw_kms_init(dev_priv);
if (unlikely(ret != 0)) /* Need to start the fifo to check if we can do screen objects */
goto out_no_kms; ret = vmw_3d_resource_inc(dev_priv, true);
vmw_overlay_init(dev_priv);
if (dev_priv->enable_fb) {
ret = vmw_3d_resource_inc(dev_priv, false);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto out_no_fifo; goto out_no_fifo;
vmw_kms_save_vga(dev_priv); vmw_kms_save_vga(dev_priv);
vmw_fb_init(dev_priv);
DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
"Detected device 3D availability.\n" : "Detected device 3D availability.\n" :
"Detected no device 3D availability.\n"); "Detected no device 3D availability.\n");
/* Start kms and overlay systems, needs fifo. */
ret = vmw_kms_init(dev_priv);
if (unlikely(ret != 0))
goto out_no_kms;
vmw_overlay_init(dev_priv);
/* We might be done with the fifo now */
if (dev_priv->enable_fb) {
vmw_fb_init(dev_priv);
} else { } else {
DRM_INFO("Delayed 3D detection since we're not " vmw_kms_restore_vga(dev_priv);
"running the device in SVGA mode yet.\n"); vmw_3d_resource_dec(dev_priv, true);
} }
if (dev_priv->capabilities & SVGA_CAP_IRQMASK) { if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
...@@ -483,15 +489,17 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) ...@@ -483,15 +489,17 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
return 0; return 0;
out_no_irq: out_no_irq:
if (dev_priv->enable_fb) { if (dev_priv->enable_fb)
vmw_fb_close(dev_priv); vmw_fb_close(dev_priv);
vmw_overlay_close(dev_priv);
vmw_kms_close(dev_priv);
out_no_kms:
/* We still have a 3D resource reference held */
if (dev_priv->enable_fb) {
vmw_kms_restore_vga(dev_priv); vmw_kms_restore_vga(dev_priv);
vmw_3d_resource_dec(dev_priv, false); vmw_3d_resource_dec(dev_priv, false);
} }
out_no_fifo: out_no_fifo:
vmw_overlay_close(dev_priv);
vmw_kms_close(dev_priv);
out_no_kms:
vmw_fence_manager_takedown(dev_priv->fman); vmw_fence_manager_takedown(dev_priv->fman);
out_no_fman: out_no_fman:
if (dev_priv->stealth) if (dev_priv->stealth)
......
...@@ -217,6 +217,7 @@ struct vmw_private { ...@@ -217,6 +217,7 @@ struct vmw_private {
void *fb_info; void *fb_info;
struct vmw_legacy_display *ldu_priv; struct vmw_legacy_display *ldu_priv;
struct vmw_screen_object_display *sou_priv;
struct vmw_overlay *overlay_priv; struct vmw_overlay *overlay_priv;
/* /*
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "vmwgfx_kms.h" #include "vmwgfx_kms.h"
/* Might need a hrtimer here? */ /* Might need a hrtimer here? */
#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
...@@ -474,6 +475,62 @@ static int do_surface_dirty_ldu(struct vmw_private *dev_priv, ...@@ -474,6 +475,62 @@ static int do_surface_dirty_ldu(struct vmw_private *dev_priv,
vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) *
sizeof(cmd->cr)); sizeof(cmd->cr));
return 0;
}
static int do_surface_dirty_sou(struct vmw_private *dev_priv,
struct vmw_framebuffer *framebuffer,
struct vmw_surface *surf,
unsigned flags, unsigned color,
struct drm_clip_rect *clips,
unsigned num_clips, int inc)
{
int left = clips->x2, right = clips->x1;
int top = clips->y2, bottom = clips->y1;
size_t fifo_size;
int i;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdBlitSurfaceToScreen body;
} *cmd;
fifo_size = sizeof(*cmd);
cmd = vmw_fifo_reserve(dev_priv, fifo_size);
if (unlikely(cmd == NULL)) {
DRM_ERROR("Fifo reserve failed.\n");
return -ENOMEM;
}
memset(cmd, 0, fifo_size);
cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
cmd->header.size = cpu_to_le32(sizeof(cmd->body));
cmd->body.srcImage.sid = cpu_to_le32(surf->res.id);
cmd->body.destScreenId = SVGA_ID_INVALID; /* virtual coords */
for (i = 0; i < num_clips; i++, clips += inc) {
left = min_t(int, left, (int)clips->x1);
right = max_t(int, right, (int)clips->x2);
top = min_t(int, top, (int)clips->y1);
bottom = max_t(int, bottom, (int)clips->y2);
}
cmd->body.srcRect.left = left;
cmd->body.srcRect.right = right;
cmd->body.srcRect.top = top;
cmd->body.srcRect.bottom = bottom;
cmd->body.destRect.left = left;
cmd->body.destRect.right = right;
cmd->body.destRect.top = top;
cmd->body.destRect.bottom = bottom;
vmw_fifo_commit(dev_priv, fifo_size);
return 0; return 0;
} }
...@@ -498,9 +555,8 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, ...@@ -498,9 +555,8 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return ret; return ret;
if (!num_clips || /* Are we using screen objects? */
!(dev_priv->fifo.capabilities & if (!dev_priv->sou_priv) {
SVGA_FIFO_CAP_SCREEN_OBJECT)) {
int ret; int ret;
mutex_lock(&vfbs->work_lock); mutex_lock(&vfbs->work_lock);
...@@ -528,9 +584,14 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, ...@@ -528,9 +584,14 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
inc = 2; /* skip source rects */ inc = 2; /* skip source rects */
} }
if (!dev_priv->sou_priv)
ret = do_surface_dirty_ldu(dev_priv, &vfbs->base, surf, ret = do_surface_dirty_ldu(dev_priv, &vfbs->base, surf,
flags, color, flags, color,
clips, num_clips, inc); clips, num_clips, inc);
else
ret = do_surface_dirty_sou(dev_priv, &vfbs->base, surf,
flags, color,
clips, num_clips, inc);
ttm_read_unlock(&vmaster->lock); ttm_read_unlock(&vmaster->lock);
return 0; return 0;
...@@ -618,8 +679,13 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, ...@@ -618,8 +679,13 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
vfbs->base.base.depth = mode_cmd->depth; vfbs->base.base.depth = mode_cmd->depth;
vfbs->base.base.width = mode_cmd->width; vfbs->base.base.width = mode_cmd->width;
vfbs->base.base.height = mode_cmd->height; vfbs->base.base.height = mode_cmd->height;
/* Don't need to fill start of vram with empty
* buffer if we have screen objects support.
*/
if (!dev_priv->sou_priv) {
vfbs->base.pin = &vmw_surface_dmabuf_pin; vfbs->base.pin = &vmw_surface_dmabuf_pin;
vfbs->base.unpin = &vmw_surface_dmabuf_unpin; vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
}
vfbs->surface = surface; vfbs->surface = surface;
vfbs->master = drm_master_get(file_priv->master); vfbs->master = drm_master_get(file_priv->master);
mutex_init(&vfbs->work_lock); mutex_init(&vfbs->work_lock);
...@@ -651,6 +717,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, ...@@ -651,6 +717,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
struct vmw_framebuffer_dmabuf { struct vmw_framebuffer_dmabuf {
struct vmw_framebuffer base; struct vmw_framebuffer base;
struct vmw_dma_buffer *buffer; struct vmw_dma_buffer *buffer;
uint32_t handle;
}; };
void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer) void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
...@@ -699,6 +766,63 @@ static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv, ...@@ -699,6 +766,63 @@ static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv,
return 0; return 0;
} }
static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
struct vmw_private *dev_priv,
struct vmw_framebuffer *framebuffer,
struct vmw_dma_buffer *buffer,
unsigned flags, unsigned color,
struct drm_clip_rect *clips,
unsigned num_clips, int increment)
{
struct vmw_framebuffer_dmabuf *vfbd =
vmw_framebuffer_to_vfbd(&framebuffer->base);
size_t fifo_size;
int i, ret;
struct {
uint32_t header;
SVGAFifoCmdDefineGMRFB body;
} *cmd;
struct {
uint32_t header;
SVGAFifoCmdBlitGMRFBToScreen body;
} *blits;
fifo_size = sizeof(*cmd) + sizeof(*blits) * num_clips;
cmd = kmalloc(fifo_size, GFP_KERNEL);
if (unlikely(cmd == NULL)) {
DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
return -ENOMEM;
}
memset(cmd, 0, fifo_size);
cmd->header = SVGA_CMD_DEFINE_GMRFB;
cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel;
cmd->body.format.colorDepth = framebuffer->base.depth;
cmd->body.format.reserved = 0;
cmd->body.bytesPerLine = framebuffer->base.pitch;
cmd->body.ptr.gmrId = vfbd->handle;
cmd->body.ptr.offset = 0;
blits = (void *)&cmd[1];
for (i = 0; i < num_clips; i++, clips += increment) {
blits[i].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
blits[i].body.srcOrigin.x = clips->x1;
blits[i].body.srcOrigin.y = clips->y1;
blits[i].body.destRect.left = clips->x1;
blits[i].body.destRect.top = clips->y1;
blits[i].body.destRect.right = clips->x2;
blits[i].body.destRect.bottom = clips->y2;
}
ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
fifo_size, 0, NULL);
kfree(cmd);
return ret;
}
int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
struct drm_file *file_priv, struct drm_file *file_priv,
unsigned flags, unsigned color, unsigned flags, unsigned color,
...@@ -728,9 +852,15 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, ...@@ -728,9 +852,15 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
increment = 2; increment = 2;
} }
if (dev_priv->ldu_priv) {
ret = do_dmabuf_dirty_ldu(dev_priv, &vfbd->base, dmabuf, ret = do_dmabuf_dirty_ldu(dev_priv, &vfbd->base, dmabuf,
flags, color, flags, color,
clips, num_clips, increment); clips, num_clips, increment);
} else {
ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base,
dmabuf, flags, color,
clips, num_clips, increment);
}
ttm_read_unlock(&vmaster->lock); ttm_read_unlock(&vmaster->lock);
return ret; return ret;
...@@ -801,6 +931,8 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb) ...@@ -801,6 +931,8 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
vmw_framebuffer_to_vfbd(&vfb->base); vmw_framebuffer_to_vfbd(&vfb->base);
int ret; int ret;
/* This code should not be used with screen objects */
BUG_ON(dev_priv->sou_priv);
vmw_overlay_pause_all(dev_priv); vmw_overlay_pause_all(dev_priv);
...@@ -867,9 +999,12 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, ...@@ -867,9 +999,12 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
vfbd->base.base.depth = mode_cmd->depth; vfbd->base.base.depth = mode_cmd->depth;
vfbd->base.base.width = mode_cmd->width; vfbd->base.base.width = mode_cmd->width;
vfbd->base.base.height = mode_cmd->height; vfbd->base.base.height = mode_cmd->height;
if (!dev_priv->sou_priv) {
vfbd->base.pin = vmw_framebuffer_dmabuf_pin; vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin; vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
}
vfbd->buffer = dmabuf; vfbd->buffer = dmabuf;
vfbd->handle = mode_cmd->handle;
*out = &vfbd->base; *out = &vfbd->base;
return 0; return 0;
...@@ -981,7 +1116,9 @@ int vmw_kms_init(struct vmw_private *dev_priv) ...@@ -981,7 +1116,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
dev->mode_config.max_width = 8192; dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192; dev->mode_config.max_height = 8192;
ret = vmw_kms_init_legacy_display_system(dev_priv); ret = vmw_kms_init_screen_object_display(dev_priv);
if (ret) /* Fallback */
(void)vmw_kms_init_legacy_display_system(dev_priv);
return 0; return 0;
} }
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include "drmP.h" #include "drmP.h"
#include "vmwgfx_drv.h" #include "vmwgfx_drv.h"
#define VMWGFX_NUM_DISPLAY_UNITS 8
#define vmw_framebuffer_to_vfb(x) \ #define vmw_framebuffer_to_vfb(x) \
container_of(x, struct vmw_framebuffer, base) container_of(x, struct vmw_framebuffer, base)
...@@ -128,4 +130,12 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, ...@@ -128,4 +130,12 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv); int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv); int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
/*
* Screen Objects display functions - vmwgfx_scrn.c
*/
int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv);
int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv);
int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num,
struct drm_vmw_rect *rects);
#endif #endif
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "vmwgfx_kms.h" #include "vmwgfx_kms.h"
#define VMWGFX_LDU_NUM_DU 8
#define vmw_crtc_to_ldu(x) \ #define vmw_crtc_to_ldu(x) \
container_of(x, struct vmw_legacy_display_unit, base.crtc) container_of(x, struct vmw_legacy_display_unit, base.crtc)
...@@ -384,9 +383,9 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) ...@@ -384,9 +383,9 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
drm_mode_create_dirty_info_property(dev_priv->dev); drm_mode_create_dirty_info_property(dev_priv->dev);
if (dev_priv->capabilities & SVGA_CAP_MULTIMON) { if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i) for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
vmw_ldu_init(dev_priv, i); vmw_ldu_init(dev_priv, i);
ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU); ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
} else { } else {
/* for old hardware without multimon only enable one display */ /* for old hardware without multimon only enable one display */
vmw_ldu_init(dev_priv, 0); vmw_ldu_init(dev_priv, 0);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment