/** * Send the fifo command to create a screen. */ static int vmw_sou_fifo_create(struct vmw_private *dev_priv, struct vmw_screen_object_unit *sou, uint32_t x, uint32_t y, struct drm_display_mode *mode) { size_t fifo_size; struct { struct { uint32_t cmdType; } header; SVGAScreenObject obj; } *cmd; BUG_ON(!sou->buffer); fifo_size = sizeof(*cmd); cmd = vmw_fifo_reserve(dev_priv, fifo_size); /* The hardware has hung, nothing we can do about it here. */ if (unlikely(cmd == NULL)) { DRM_ERROR("Fifo reserve failed.\n"); return -ENOMEM; } memset(cmd, 0, fifo_size); cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN; cmd->obj.structSize = sizeof(SVGAScreenObject); cmd->obj.id = sou->base.unit; cmd->obj.flags = SVGA_SCREEN_HAS_ROOT | (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0); cmd->obj.size.width = mode->hdisplay; cmd->obj.size.height = mode->vdisplay; if (sou->base.is_implicit) { cmd->obj.root.x = x; cmd->obj.root.y = y; } else { cmd->obj.root.x = sou->base.gui_x; cmd->obj.root.y = sou->base.gui_y; } sou->base.set_gui_x = cmd->obj.root.x; sou->base.set_gui_y = cmd->obj.root.y; /* Ok to assume that buffer is pinned in vram */ vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr); cmd->obj.backingStore.pitch = mode->hdisplay * 4; vmw_fifo_commit(dev_priv, fifo_size); sou->defined = true; return 0; }
/** * vmw_stdu_dmabuf_fifo_commit - Callback to fill in and submit a DMA command. * * @dirty: The closure structure. * * Fills in the missing fields in a DMA command, and optionally encodes * a screen target update command, depending on transfer direction. */ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) { struct vmw_stdu_dirty *ddirty = container_of(dirty, struct vmw_stdu_dirty, base); struct vmw_screen_target_display_unit *stdu = container_of(dirty->unit, typeof(*stdu), base); struct vmw_stdu_dma *cmd = dirty->cmd; struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1]; SVGA3dCmdSurfaceDMASuffix *suffix = (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits]; size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix); if (!dirty->num_hits) { vmw_fifo_commit(dirty->dev_priv, 0); return; } cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; cmd->header.size = sizeof(cmd->body) + blit_size; vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr); cmd->body.guest.pitch = ddirty->pitch; cmd->body.host.sid = stdu->display_srf->res.id; cmd->body.host.face = 0; cmd->body.host.mipmap = 0; cmd->body.transfer = ddirty->transfer; suffix->suffixSize = sizeof(*suffix); suffix->maximumOffset = ddirty->buf->base.num_pages * PAGE_SIZE; if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { blit_size += sizeof(struct vmw_stdu_update); vmw_stdu_populate_update(&suffix[1], stdu->base.unit, ddirty->left, ddirty->right, ddirty->top, ddirty->bottom); } vmw_fifo_commit(dirty->dev_priv, sizeof(*cmd) + blit_size); ddirty->left = ddirty->top = S32_MAX; ddirty->right = ddirty->bottom = S32_MIN; }
static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer) { struct vmw_dma_buffer *buf = container_of(framebuffer, struct vmw_framebuffer_dmabuf, base)->buffer; int depth = framebuffer->base.depth; struct { uint32_t header; SVGAFifoCmdDefineGMRFB body; } *cmd; /* Emulate RGBA support, contrary to svga_reg.h this is not * supported by hosts. This is only a problem if we are reading * this value later and expecting what we uploaded back. */ if (depth == 32) depth = 24; cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); if (!cmd) { DRM_ERROR("Out of fifo space for dirty framebuffer command.\n"); return -ENOMEM; } cmd->header = SVGA_CMD_DEFINE_GMRFB; cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel; cmd->body.format.colorDepth = depth; cmd->body.format.reserved = 0; cmd->body.bytesPerLine = framebuffer->base.pitches[0]; /* Buffer is reserved in vram or GMR */ vmw_bo_get_guest_ptr(&buf->base, &cmd->body.ptr); vmw_fifo_commit(dev_priv, sizeof(*cmd)); return 0; }
/** * Send put command to hw. * * Returns * -ERESTARTSYS if interrupted by a signal. */ static int vmw_overlay_send_put(struct vmw_private *dev_priv, struct vmw_dma_buffer *buf, struct drm_vmw_control_stream_arg *arg, bool interruptible) { struct vmw_escape_video_flush *flush; size_t fifo_size; bool have_so = dev_priv->sou_priv ? true : false; int i, num_items; SVGAGuestPtr ptr; struct { struct vmw_escape_header escape; struct { uint32_t cmdType; uint32_t streamId; } header; } *cmds; struct { uint32_t registerId; uint32_t value; } *items; /* defines are a index needs + 1 */ if (have_so) num_items = SVGA_VIDEO_DST_SCREEN_ID + 1; else num_items = SVGA_VIDEO_PITCH_3 + 1; fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items; cmds = vmw_fifo_reserve(dev_priv, fifo_size); /* hardware has hung, can't do anything here */ if (!cmds) return -ENOMEM; items = (typeof(items))&cmds[1]; flush = (struct vmw_escape_video_flush *)&items[num_items]; /* the size is header + number of items */ fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1)); cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; cmds->header.streamId = arg->stream_id; /* the IDs are neatly numbered */ for (i = 0; i < num_items; i++) items[i].registerId = i; vmw_bo_get_guest_ptr(&buf->base, &ptr); ptr.offset += arg->offset; items[SVGA_VIDEO_ENABLED].value = true; items[SVGA_VIDEO_FLAGS].value = arg->flags; items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset; items[SVGA_VIDEO_FORMAT].value = arg->format; items[SVGA_VIDEO_COLORKEY].value = arg->color_key; items[SVGA_VIDEO_SIZE].value = arg->size; items[SVGA_VIDEO_WIDTH].value = arg->width; items[SVGA_VIDEO_HEIGHT].value = arg->height; items[SVGA_VIDEO_SRC_X].value = arg->src.x; items[SVGA_VIDEO_SRC_Y].value = arg->src.y; items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w; items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h; items[SVGA_VIDEO_DST_X].value = arg->dst.x; items[SVGA_VIDEO_DST_Y].value = arg->dst.y; items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w; items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h; items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0]; items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1]; items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2]; if (have_so) { items[SVGA_VIDEO_DATA_GMRID].value = ptr.gmrId; items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID; } fill_flush(flush, arg->stream_id); vmw_fifo_commit(dev_priv, fifo_size); return 0; }