Rev 5078 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5078 | Rev 6296 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /************************************************************************** |
1 | /************************************************************************** |
2 | * |
2 | * |
3 | * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA |
3 | * Copyright © 2011-2015 VMware, Inc., Palo Alto, CA., USA |
4 | * All Rights Reserved. |
4 | * All Rights Reserved. |
5 | * |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the |
7 | * copy of this software and associated documentation files (the |
8 | * "Software"), to deal in the Software without restriction, including |
8 | * "Software"), to deal in the Software without restriction, including |
Line 24... | Line 24... | ||
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | * |
25 | * |
26 | **************************************************************************/ |
26 | **************************************************************************/ |
Line 27... | Line 27... | ||
27 | 27 | ||
- | 28 | #include "vmwgfx_kms.h" |
|
Line 28... | Line 29... | ||
28 | #include "vmwgfx_kms.h" |
29 | #include |
29 | 30 | ||
30 | 31 | ||
31 | #define vmw_crtc_to_sou(x) \ |
32 | #define vmw_crtc_to_sou(x) \ |
32 | container_of(x, struct vmw_screen_object_unit, base.crtc) |
33 | container_of(x, struct vmw_screen_object_unit, base.crtc) |
33 | #define vmw_encoder_to_sou(x) \ |
34 | #define vmw_encoder_to_sou(x) \ |
Line -... | Line 35... | ||
- | 35 | container_of(x, struct vmw_screen_object_unit, base.encoder) |
|
- | 36 | #define vmw_connector_to_sou(x) \ |
|
- | 37 | container_of(x, struct vmw_screen_object_unit, base.connector) |
|
- | 38 | ||
- | 39 | /** |
|
- | 40 | * struct vmw_kms_sou_surface_dirty - Closure structure for |
|
- | 41 | * blit surface to screen command. |
|
- | 42 | * @base: The base type we derive from. Used by vmw_kms_helper_dirty(). |
|
- | 43 | * @left: Left side of bounding box. |
|
- | 44 | * @right: Right side of bounding box. |
|
- | 45 | * @top: Top side of bounding box. |
|
- | 46 | * @bottom: Bottom side of bounding box. |
|
- | 47 | * @dst_x: Difference between source clip rects and framebuffer coordinates. |
|
- | 48 | * @dst_y: Difference between source clip rects and framebuffer coordinates. |
|
- | 49 | * @sid: Surface id of surface to copy from. |
|
- | 50 | */ |
|
- | 51 | struct vmw_kms_sou_surface_dirty { |
|
- | 52 | struct vmw_kms_dirty base; |
|
- | 53 | s32 left, right, top, bottom; |
|
- | 54 | s32 dst_x, dst_y; |
|
- | 55 | u32 sid; |
|
- | 56 | }; |
|
- | 57 | ||
- | 58 | /* |
|
- | 59 | * SVGA commands that are used by this code. Please see the device headers |
|
- | 60 | * for explanation. |
|
- | 61 | */ |
|
- | 62 | struct vmw_kms_sou_readback_blit { |
|
- | 63 | uint32 header; |
|
- | 64 | SVGAFifoCmdBlitScreenToGMRFB body; |
|
- | 65 | }; |
|
- | 66 | ||
- | 67 | struct vmw_kms_sou_dmabuf_blit { |
|
- | 68 | uint32 header; |
|
- | 69 | SVGAFifoCmdBlitGMRFBToScreen body; |
|
- | 70 | }; |
|
- | 71 | ||
- | 72 | struct vmw_kms_sou_dirty_cmd { |
|
- | 73 | SVGA3dCmdHeader header; |
|
- | 74 | SVGA3dCmdBlitSurfaceToScreen body; |
|
- | 75 | }; |
|
- | 76 | ||
- | 77 | ||
34 | container_of(x, struct vmw_screen_object_unit, base.encoder) |
78 | /* |
35 | #define vmw_connector_to_sou(x) \ |
79 | * Other structs. |
Line 36... | Line 80... | ||
36 | container_of(x, struct vmw_screen_object_unit, base.connector) |
80 | */ |
- | 81 | ||
- | 82 | struct vmw_screen_object_display { |
|
37 | 83 | unsigned num_implicit; |
|
Line 38... | Line 84... | ||
38 | struct vmw_screen_object_display { |
84 | |
39 | unsigned num_implicit; |
85 | struct vmw_framebuffer *implicit_fb; |
40 | 86 | SVGAFifoCmdDefineGMRFB cur; |
|
Line 54... | Line 100... | ||
54 | bool active_implicit; |
100 | bool active_implicit; |
55 | }; |
101 | }; |
Line 56... | Line 102... | ||
56 | 102 | ||
57 | static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) |
103 | static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) |
58 | { |
104 | { |
59 | // vmw_display_unit_cleanup(&sou->base); |
105 | vmw_du_cleanup(&sou->base); |
60 | kfree(sou); |
106 | kfree(sou); |
Line 61... | Line 107... | ||
61 | } |
107 | } |
Line 199... | Line 245... | ||
199 | * Free the backing store. |
245 | * Free the backing store. |
200 | */ |
246 | */ |
201 | static void vmw_sou_backing_free(struct vmw_private *dev_priv, |
247 | static void vmw_sou_backing_free(struct vmw_private *dev_priv, |
202 | struct vmw_screen_object_unit *sou) |
248 | struct vmw_screen_object_unit *sou) |
203 | { |
249 | { |
204 | struct ttm_buffer_object *bo; |
- | |
205 | - | ||
206 | if (unlikely(sou->buffer == NULL)) |
250 | vmw_dmabuf_unreference(&sou->buffer); |
207 | return; |
- | |
208 | - | ||
209 | bo = &sou->buffer->base; |
- | |
210 | ttm_bo_unref(&bo); |
- | |
211 | sou->buffer = NULL; |
- | |
212 | sou->buffer_size = 0; |
251 | sou->buffer_size = 0; |
213 | } |
252 | } |
Line 214... | Line 253... | ||
214 | 253 | ||
215 | /** |
254 | /** |
Line 232... | Line 271... | ||
232 | return -ENOMEM; |
271 | return -ENOMEM; |
Line 233... | Line 272... | ||
233 | 272 | ||
234 | /* After we have alloced the backing store might not be able to |
273 | /* After we have alloced the backing store might not be able to |
235 | * resume the overlays, this is preferred to failing to alloc. |
274 | * resume the overlays, this is preferred to failing to alloc. |
236 | */ |
275 | */ |
237 | // vmw_overlay_pause_all(dev_priv); |
276 | vmw_overlay_pause_all(dev_priv); |
238 | ret = vmw_dmabuf_init(dev_priv, sou->buffer, size, |
277 | ret = vmw_dmabuf_init(dev_priv, sou->buffer, size, |
239 | &vmw_vram_ne_placement, |
278 | &vmw_vram_ne_placement, |
240 | false, &vmw_dmabuf_bo_free); |
279 | false, &vmw_dmabuf_bo_free); |
Line 241... | Line 280... | ||
241 | // vmw_overlay_resume_all(dev_priv); |
280 | vmw_overlay_resume_all(dev_priv); |
242 | 281 | ||
243 | if (unlikely(ret != 0)) |
282 | if (unlikely(ret != 0)) |
244 | sou->buffer = NULL; /* vmw_dmabuf_init frees on error */ |
283 | sou->buffer = NULL; /* vmw_dmabuf_init frees on error */ |
Line 271... | Line 310... | ||
271 | sou = vmw_crtc_to_sou(crtc); |
310 | sou = vmw_crtc_to_sou(crtc); |
272 | vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL; |
311 | vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL; |
273 | dev_priv = vmw_priv(crtc->dev); |
312 | dev_priv = vmw_priv(crtc->dev); |
Line 274... | Line 313... | ||
274 | 313 | ||
275 | if (set->num_connectors > 1) { |
314 | if (set->num_connectors > 1) { |
276 | DRM_ERROR("to many connectors\n"); |
315 | DRM_ERROR("Too many connectors\n"); |
277 | return -EINVAL; |
316 | return -EINVAL; |
Line 278... | Line 317... | ||
278 | } |
317 | } |
279 | 318 | ||
280 | if (set->num_connectors == 1 && |
319 | if (set->num_connectors == 1 && |
281 | set->connectors[0] != &sou->base.connector) { |
320 | set->connectors[0] != &sou->base.connector) { |
282 | DRM_ERROR("connector doesn't match %p %p\n", |
321 | DRM_ERROR("Connector doesn't match %p %p\n", |
283 | set->connectors[0], &sou->base.connector); |
322 | set->connectors[0], &sou->base.connector); |
Line 284... | Line 323... | ||
284 | return -EINVAL; |
323 | return -EINVAL; |
Line 328... | Line 367... | ||
328 | set->y + mode->vdisplay > fb->height) { |
367 | set->y + mode->vdisplay > fb->height) { |
329 | DRM_ERROR("set outside of framebuffer\n"); |
368 | DRM_ERROR("set outside of framebuffer\n"); |
330 | return -EINVAL; |
369 | return -EINVAL; |
331 | } |
370 | } |
Line 332... | Line 371... | ||
332 | 371 | ||
Line 333... | Line 372... | ||
333 | // vmw_fb_off(dev_priv); |
372 | vmw_svga_enable(dev_priv); |
334 | 373 | ||
335 | if (mode->hdisplay != crtc->mode.hdisplay || |
374 | if (mode->hdisplay != crtc->mode.hdisplay || |
336 | mode->vdisplay != crtc->mode.vdisplay) { |
375 | mode->vdisplay != crtc->mode.vdisplay) { |
Line 387... | Line 426... | ||
387 | crtc->enabled = true; |
426 | crtc->enabled = true; |
Line 388... | Line 427... | ||
388 | 427 | ||
389 | return 0; |
428 | return 0; |
Line -... | Line 429... | ||
- | 429 | } |
|
- | 430 | ||
- | 431 | /** |
|
- | 432 | * Returns if this unit can be page flipped. |
|
- | 433 | * Must be called with the mode_config mutex held. |
|
- | 434 | */ |
|
- | 435 | static bool vmw_sou_screen_object_flippable(struct vmw_private *dev_priv, |
|
- | 436 | struct drm_crtc *crtc) |
|
- | 437 | { |
|
- | 438 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
|
- | 439 | ||
- | 440 | if (!sou->base.is_implicit) |
|
- | 441 | return true; |
|
- | 442 | ||
- | 443 | if (dev_priv->sou_priv->num_implicit != 1) |
|
- | 444 | return false; |
|
- | 445 | ||
- | 446 | return true; |
|
- | 447 | } |
|
- | 448 | ||
- | 449 | /** |
|
- | 450 | * Update the implicit fb to the current fb of this crtc. |
|
- | 451 | * Must be called with the mode_config mutex held. |
|
- | 452 | */ |
|
- | 453 | static void vmw_sou_update_implicit_fb(struct vmw_private *dev_priv, |
|
- | 454 | struct drm_crtc *crtc) |
|
- | 455 | { |
|
- | 456 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
|
- | 457 | ||
- | 458 | BUG_ON(!sou->base.is_implicit); |
|
- | 459 | ||
- | 460 | dev_priv->sou_priv->implicit_fb = |
|
390 | } |
461 | vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb); |
391 | 462 | } |
|
392 | static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { |
463 | static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { |
393 | .save = vmw_du_crtc_save, |
464 | .save = vmw_du_crtc_save, |
394 | .restore = vmw_du_crtc_restore, |
465 | .restore = vmw_du_crtc_restore, |
Line 420... | Line 491... | ||
420 | static void vmw_sou_connector_destroy(struct drm_connector *connector) |
491 | static void vmw_sou_connector_destroy(struct drm_connector *connector) |
421 | { |
492 | { |
422 | vmw_sou_destroy(vmw_connector_to_sou(connector)); |
493 | vmw_sou_destroy(vmw_connector_to_sou(connector)); |
423 | } |
494 | } |
Line 424... | Line 495... | ||
424 | 495 | ||
425 | static struct drm_connector_funcs vmw_legacy_connector_funcs = { |
496 | static struct drm_connector_funcs vmw_sou_connector_funcs = { |
426 | .dpms = vmw_du_connector_dpms, |
497 | .dpms = vmw_du_connector_dpms, |
427 | .save = vmw_du_connector_save, |
498 | .save = vmw_du_connector_save, |
428 | .restore = vmw_du_connector_restore, |
499 | .restore = vmw_du_connector_restore, |
429 | .detect = vmw_du_connector_detect, |
500 | .detect = vmw_du_connector_detect, |
Line 455... | Line 526... | ||
455 | sou->base.pref_width = dev_priv->initial_width; |
526 | sou->base.pref_width = dev_priv->initial_width; |
456 | sou->base.pref_height = dev_priv->initial_height; |
527 | sou->base.pref_height = dev_priv->initial_height; |
457 | sou->base.pref_mode = NULL; |
528 | sou->base.pref_mode = NULL; |
458 | sou->base.is_implicit = true; |
529 | sou->base.is_implicit = true; |
Line 459... | Line 530... | ||
459 | 530 | ||
460 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, |
531 | drm_connector_init(dev, connector, &vmw_sou_connector_funcs, |
461 | DRM_MODE_CONNECTOR_VIRTUAL); |
532 | DRM_MODE_CONNECTOR_VIRTUAL); |
Line 462... | Line 533... | ||
462 | connector->status = vmw_du_connector_detect(connector, true); |
533 | connector->status = vmw_du_connector_detect(connector, true); |
463 | 534 | ||
Line 478... | Line 549... | ||
478 | 1); |
549 | 1); |
Line 479... | Line 550... | ||
479 | 550 | ||
480 | return 0; |
551 | return 0; |
Line 481... | Line 552... | ||
481 | } |
552 | } |
482 | 553 | ||
483 | int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv) |
554 | int vmw_kms_sou_init_display(struct vmw_private *dev_priv) |
484 | { |
555 | { |
Line 485... | Line 556... | ||
485 | struct drm_device *dev = dev_priv->dev; |
556 | struct drm_device *dev = dev_priv->dev; |
Line 502... | Line 573... | ||
502 | goto err_no_mem; |
573 | goto err_no_mem; |
Line 503... | Line 574... | ||
503 | 574 | ||
504 | dev_priv->sou_priv->num_implicit = 0; |
575 | dev_priv->sou_priv->num_implicit = 0; |
Line -... | Line 576... | ||
- | 576 | dev_priv->sou_priv->implicit_fb = NULL; |
|
- | 577 | ||
- | 578 | ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); |
|
Line 505... | Line 579... | ||
505 | dev_priv->sou_priv->implicit_fb = NULL; |
579 | if (unlikely(ret != 0)) |
506 | 580 | goto err_free; |
|
507 | 581 | ||
Line 508... | Line 582... | ||
508 | ret = drm_mode_create_dirty_info_property(dev); |
582 | ret = drm_mode_create_dirty_info_property(dev); |
509 | if (unlikely(ret != 0)) |
583 | if (unlikely(ret != 0)) |
Line -... | Line 584... | ||
- | 584 | goto err_vblank_cleanup; |
|
- | 585 | ||
510 | goto err_vblank_cleanup; |
586 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) |
Line 511... | Line 587... | ||
511 | 587 | vmw_sou_init(dev_priv, i); |
|
Line 512... | Line 588... | ||
512 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) |
588 | |
513 | vmw_sou_init(dev_priv, i); |
589 | dev_priv->active_display_unit = vmw_du_screen_object; |
514 | 590 | ||
515 | DRM_INFO("Screen objects system initialized\n"); |
591 | DRM_INFO("Screen Objects Display Unit initialized\n"); |
516 | 592 | ||
517 | return 0; |
593 | return 0; |
518 | 594 | ||
519 | err_vblank_cleanup: |
595 | err_vblank_cleanup: |
Line 520... | Line 596... | ||
520 | // drm_vblank_cleanup(dev); |
596 | drm_vblank_cleanup(dev); |
521 | err_free: |
597 | err_free: |
522 | kfree(dev_priv->sou_priv); |
598 | kfree(dev_priv->sou_priv); |
Line 523... | Line 599... | ||
523 | dev_priv->sou_priv = NULL; |
599 | dev_priv->sou_priv = NULL; |
524 | err_no_mem: |
600 | err_no_mem: |
Line 525... | Line 601... | ||
525 | return ret; |
601 | return ret; |
Line 526... | Line 602... | ||
526 | } |
602 | } |
Line 527... | Line 603... | ||
527 | 603 | ||
528 | int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv) |
604 | int vmw_kms_sou_close_display(struct vmw_private *dev_priv) |
Line -... | Line 605... | ||
- | 605 | { |
|
- | 606 | struct drm_device *dev = dev_priv->dev; |
|
- | 607 | ||
- | 608 | if (!dev_priv->sou_priv) |
|
- | 609 | return -ENOSYS; |
|
- | 610 | ||
- | 611 | drm_vblank_cleanup(dev); |
|
- | 612 | ||
- | 613 | kfree(dev_priv->sou_priv); |
|
- | 614 | ||
- | 615 | return 0; |
|
- | 616 | } |
|
- | 617 | ||
- | 618 | static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv, |
|
- | 619 | struct vmw_framebuffer *framebuffer) |
|
- | 620 | { |
|
- | 621 | struct vmw_dma_buffer *buf = |
|
- | 622 | container_of(framebuffer, struct vmw_framebuffer_dmabuf, |
|
- | 623 | base)->buffer; |
|
- | 624 | int depth = framebuffer->base.depth; |
|
- | 625 | struct { |
|
- | 626 | uint32_t header; |
|
- | 627 | SVGAFifoCmdDefineGMRFB body; |
|
- | 628 | } *cmd; |
|
- | 629 | ||
- | 630 | /* Emulate RGBA support, contrary to svga_reg.h this is not |
|
- | 631 | * supported by hosts. This is only a problem if we are reading |
|
- | 632 | * this value later and expecting what we uploaded back. |
|
- | 633 | */ |
|
- | 634 | if (depth == 32) |
|
- | 635 | depth = 24; |
|
- | 636 | ||
- | 637 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
|
- | 638 | if (!cmd) { |
|
- | 639 | DRM_ERROR("Out of fifo space for dirty framebuffer command.\n"); |
|
- | 640 | return -ENOMEM; |
|
- | 641 | } |
|
529 | { |
642 | |
- | 643 | cmd->header = SVGA_CMD_DEFINE_GMRFB; |
|
530 | struct drm_device *dev = dev_priv->dev; |
644 | cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel; |
- | 645 | cmd->body.format.colorDepth = depth; |
|
- | 646 | cmd->body.format.reserved = 0; |
|
- | 647 | cmd->body.bytesPerLine = framebuffer->base.pitches[0]; |
|
- | 648 | /* Buffer is reserved in vram or GMR */ |
|
531 | 649 | vmw_bo_get_guest_ptr(&buf->base, &cmd->body.ptr); |
|
532 | if (!dev_priv->sou_priv) |
650 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
533 | return -ENOSYS; |
651 | |
534 | - | ||
535 | // drm_vblank_cleanup(dev); |
652 | return 0; |
- | 653 | } |
|
- | 654 | ||
536 | 655 | /** |
|
- | 656 | * vmw_sou_surface_fifo_commit - Callback to fill in and submit a |
|
- | 657 | * blit surface to screen command. |
|
- | 658 | * |
|
- | 659 | * @dirty: The closure structure. |
|
- | 660 | * |
|
Line 537... | Line 661... | ||
537 | kfree(dev_priv->sou_priv); |
661 | * Fills in the missing fields in the command, and translates the cliprects |
538 | 662 | * to match the destination bounding box encoded. |
|
Line -... | Line 663... | ||
- | 663 | */ |
|
- | 664 | static void vmw_sou_surface_fifo_commit(struct vmw_kms_dirty *dirty) |
|
- | 665 | { |
|
- | 666 | struct vmw_kms_sou_surface_dirty *sdirty = |
|
- | 667 | container_of(dirty, typeof(*sdirty), base); |
|
- | 668 | struct vmw_kms_sou_dirty_cmd *cmd = dirty->cmd; |
|
- | 669 | s32 trans_x = dirty->unit->crtc.x - sdirty->dst_x; |
|
- | 670 | s32 trans_y = dirty->unit->crtc.y - sdirty->dst_y; |
|
- | 671 | size_t region_size = dirty->num_hits * sizeof(SVGASignedRect); |
|
- | 672 | SVGASignedRect *blit = (SVGASignedRect *) &cmd[1]; |
|
- | 673 | int i; |
|
- | 674 | ||
- | 675 | cmd->header.id = SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN; |
|
- | 676 | cmd->header.size = sizeof(cmd->body) + region_size; |
|
- | 677 | ||
- | 678 | /* |
|
- | 679 | * Use the destination bounding box to specify destination - and |
|
- | 680 | * source bounding regions. |
|
539 | return 0; |
681 | */ |
- | 682 | cmd->body.destRect.left = sdirty->left; |
|
540 | } |
683 | cmd->body.destRect.right = sdirty->right; |
- | 684 | cmd->body.destRect.top = sdirty->top; |
|
- | 685 | cmd->body.destRect.bottom = sdirty->bottom; |
|
- | 686 | ||
Line -... | Line 687... | ||
- | 687 | cmd->body.srcRect.left = sdirty->left + trans_x; |
|
- | 688 | cmd->body.srcRect.right = sdirty->right + trans_x; |
|
541 | 689 | cmd->body.srcRect.top = sdirty->top + trans_y; |
|
- | 690 | cmd->body.srcRect.bottom = sdirty->bottom + trans_y; |
|
542 | /** |
691 | |
Line 543... | Line 692... | ||
543 | * Returns if this unit can be page flipped. |
692 | cmd->body.srcImage.sid = sdirty->sid; |
544 | * Must be called with the mode_config mutex held. |
693 | cmd->body.destScreenId = dirty->unit->unit; |
- | 694 | ||
- | 695 | /* Blits are relative to the destination rect. Translate. */ |
|
- | 696 | for (i = 0; i < dirty->num_hits; ++i, ++blit) { |
|
545 | */ |
697 | blit->left -= sdirty->left; |
- | 698 | blit->right -= sdirty->left; |
|
546 | bool vmw_kms_screen_object_flippable(struct vmw_private *dev_priv, |
699 | blit->top -= sdirty->top; |
547 | struct drm_crtc *crtc) |
700 | blit->bottom -= sdirty->top; |
548 | { |
- | |
549 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
701 | } |
- | 702 | ||
- | 703 | vmw_fifo_commit(dirty->dev_priv, region_size + sizeof(*cmd)); |
|
550 | 704 | ||
- | 705 | sdirty->left = sdirty->top = S32_MAX; |
|
- | 706 | sdirty->right = sdirty->bottom = S32_MIN; |
|
- | 707 | } |
|
- | 708 | ||
- | 709 | /** |
|
- | 710 | * vmw_sou_surface_clip - Callback to encode a blit surface to screen cliprect. |
|
- | 711 | * |
|
- | 712 | * @dirty: The closure structure |
|
- | 713 | * |
|
- | 714 | * Encodes a SVGASignedRect cliprect and updates the bounding box of the |
|
- | 715 | * BLIT_SURFACE_TO_SCREEN command. |
|
- | 716 | */ |
|
- | 717 | static void vmw_sou_surface_clip(struct vmw_kms_dirty *dirty) |
|
- | 718 | { |
|
Line 551... | Line 719... | ||
551 | if (!sou->base.is_implicit) |
719 | struct vmw_kms_sou_surface_dirty *sdirty = |
- | 720 | container_of(dirty, typeof(*sdirty), base); |
|
Line -... | Line 721... | ||
- | 721 | struct vmw_kms_sou_dirty_cmd *cmd = dirty->cmd; |
|
- | 722 | SVGASignedRect *blit = (SVGASignedRect *) &cmd[1]; |
|
- | 723 | ||
- | 724 | /* Destination rect. */ |
|
- | 725 | blit += dirty->num_hits; |
|
- | 726 | blit->left = dirty->unit_x1; |
|
- | 727 | blit->top = dirty->unit_y1; |
|
- | 728 | blit->right = dirty->unit_x2; |
|
- | 729 | blit->bottom = dirty->unit_y2; |
|
- | 730 | ||
- | 731 | /* Destination bounding box */ |
|
- | 732 | sdirty->left = min_t(s32, sdirty->left, dirty->unit_x1); |
|
- | 733 | sdirty->top = min_t(s32, sdirty->top, dirty->unit_y1); |
|
- | 734 | sdirty->right = max_t(s32, sdirty->right, dirty->unit_x2); |
|
- | 735 | sdirty->bottom = max_t(s32, sdirty->bottom, dirty->unit_y2); |
|
- | 736 | ||
- | 737 | dirty->num_hits++; |
|
- | 738 | } |
|
- | 739 | ||
- | 740 | /** |
|
- | 741 | * vmw_kms_sou_do_surface_dirty - Dirty part of a surface backed framebuffer |
|
- | 742 | * |
|
- | 743 | * @dev_priv: Pointer to the device private structure. |
|
- | 744 | * @framebuffer: Pointer to the surface-buffer backed framebuffer. |
|
- | 745 | * @clips: Array of clip rects. Either @clips or @vclips must be NULL. |
|
- | 746 | * @vclips: Alternate array of clip rects. Either @clips or @vclips must |
|
- | 747 | * be NULL. |
|
- | 748 | * @srf: Pointer to surface to blit from. If NULL, the surface attached |
|
- | 749 | * to @framebuffer will be used. |
|
- | 750 | * @dest_x: X coordinate offset to align @srf with framebuffer coordinates. |
|
- | 751 | * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates. |
|
- | 752 | * @num_clips: Number of clip rects in @clips. |
|
- | 753 | * @inc: Increment to use when looping over @clips. |
|
- | 754 | * @out_fence: If non-NULL, will return a ref-counted pointer to a |
|
- | 755 | * struct vmw_fence_obj. The returned fence pointer may be NULL in which |
|
- | 756 | * case the device has already synchronized. |
|
- | 757 | * |
|
- | 758 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if |
|
- | 759 | * interrupted. |
|
- | 760 | */ |
|
- | 761 | int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, |
|
- | 762 | struct vmw_framebuffer *framebuffer, |
|
- | 763 | struct drm_clip_rect *clips, |
|
- | 764 | struct drm_vmw_rect *vclips, |
|
- | 765 | struct vmw_resource *srf, |
|
552 | return true; |
766 | s32 dest_x, |
- | 767 | s32 dest_y, |
|
- | 768 | unsigned num_clips, int inc, |
|
- | 769 | struct vmw_fence_obj **out_fence) |
|
- | 770 | { |
|
- | 771 | struct vmw_framebuffer_surface *vfbs = |
|
- | 772 | container_of(framebuffer, typeof(*vfbs), base); |
|
- | 773 | struct vmw_kms_sou_surface_dirty sdirty; |
|
- | 774 | int ret; |
|
- | 775 | ||
- | 776 | if (!srf) |
|
- | 777 | srf = &vfbs->surface->res; |
|
- | 778 | ||
553 | 779 | ret = vmw_kms_helper_resource_prepare(srf, true); |
|
- | 780 | if (ret) |
|
- | 781 | return ret; |
|
554 | if (dev_priv->sou_priv->num_implicit != 1) |
782 | |
Line -... | Line 783... | ||
- | 783 | sdirty.base.fifo_commit = vmw_sou_surface_fifo_commit; |
|
- | 784 | sdirty.base.clip = vmw_sou_surface_clip; |
|
- | 785 | sdirty.base.dev_priv = dev_priv; |
|
- | 786 | sdirty.base.fifo_reserve_size = sizeof(struct vmw_kms_sou_dirty_cmd) + |
|
- | 787 | sizeof(SVGASignedRect) * num_clips; |
|
- | 788 | ||
- | 789 | sdirty.sid = srf->id; |
|
- | 790 | sdirty.left = sdirty.top = S32_MAX; |
|
- | 791 | sdirty.right = sdirty.bottom = S32_MIN; |
|
- | 792 | sdirty.dst_x = dest_x; |
|
- | 793 | sdirty.dst_y = dest_y; |
|
555 | return false; |
794 | |
- | 795 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, |
|
Line -... | Line 796... | ||
- | 796 | dest_x, dest_y, num_clips, inc, |
|
- | 797 | &sdirty.base); |
|
- | 798 | vmw_kms_helper_resource_finish(srf, out_fence); |
|
556 | 799 | ||
- | 800 | return ret; |
|
- | 801 | } |
|
- | 802 | ||
- | 803 | /** |
|
557 | return true; |
804 | * vmw_sou_dmabuf_fifo_commit - Callback to submit a set of readback clips. |
- | 805 | * |
|
- | 806 | * @dirty: The closure structure. |
|
- | 807 | * |
|
- | 808 | * Commits a previously built command buffer of readback clips. |
|
- | 809 | */ |
|
- | 810 | static void vmw_sou_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) |
|
- | 811 | { |
|
- | 812 | vmw_fifo_commit(dirty->dev_priv, |
|
- | 813 | sizeof(struct vmw_kms_sou_dmabuf_blit) * |
|
- | 814 | dirty->num_hits); |
|
- | 815 | } |
|
- | 816 | ||
- | 817 | /** |
|
- | 818 | * vmw_sou_dmabuf_clip - Callback to encode a readback cliprect. |
|
- | 819 | * |
|
- | 820 | * @dirty: The closure structure |
|
- | 821 | * |
|
- | 822 | * Encodes a BLIT_GMRFB_TO_SCREEN cliprect. |
|
- | 823 | */ |
|
- | 824 | static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty) |
|
- | 825 | { |
|
- | 826 | struct vmw_kms_sou_dmabuf_blit *blit = dirty->cmd; |
|
- | 827 | ||
- | 828 | blit += dirty->num_hits; |
|
- | 829 | blit->header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN; |
|
- | 830 | blit->body.destScreenId = dirty->unit->unit; |
|
- | 831 | blit->body.srcOrigin.x = dirty->fb_x; |
|
- | 832 | blit->body.srcOrigin.y = dirty->fb_y; |
|
- | 833 | blit->body.destRect.left = dirty->unit_x1; |
|
- | 834 | blit->body.destRect.top = dirty->unit_y1; |
|
- | 835 | blit->body.destRect.right = dirty->unit_x2; |
|
- | 836 | blit->body.destRect.bottom = dirty->unit_y2; |
|
- | 837 | dirty->num_hits++; |
|
- | 838 | } |
|
- | 839 | ||
- | 840 | /** |
|
- | 841 | * vmw_kms_do_dmabuf_dirty - Dirty part of a dma-buffer backed framebuffer |
|
- | 842 | * |
|
- | 843 | * @dev_priv: Pointer to the device private structure. |
|
558 | } |
844 | * @framebuffer: Pointer to the dma-buffer backed framebuffer. |
- | 845 | * @clips: Array of clip rects. |
|
- | 846 | * @num_clips: Number of clip rects in @clips. |
|
- | 847 | * @increment: Increment to use when looping over @clips. |
|
- | 848 | * @interruptible: Whether to perform waits interruptible if possible. |
|
- | 849 | * @out_fence: If non-NULL, will return a ref-counted pointer to a |
|
- | 850 | * struct vmw_fence_obj. The returned fence pointer may be NULL in which |
|
- | 851 | * case the device has already synchronized. |
|
Line -... | Line 852... | ||
- | 852 | * |
|
559 | 853 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if |
|
560 | /** |
854 | * interrupted. |
- | 855 | */ |
|
- | 856 | int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv, |
|
- | 857 | struct vmw_framebuffer *framebuffer, |
|
- | 858 | struct drm_clip_rect *clips, |
|
- | 859 | unsigned num_clips, int increment, |
|
- | 860 | bool interruptible, |
|
- | 861 | struct vmw_fence_obj **out_fence) |
|
- | 862 | { |
|
- | 863 | struct vmw_dma_buffer *buf = |
|
- | 864 | container_of(framebuffer, struct vmw_framebuffer_dmabuf, |
|
- | 865 | base)->buffer; |
|
- | 866 | struct vmw_kms_dirty dirty; |
|
- | 867 | int ret; |
|
- | 868 | ||
561 | * Update the implicit fb to the current fb of this crtc. |
869 | ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible, |
- | 870 | false); |
|
Line 562... | Line -... | ||
562 | * Must be called with the mode_config mutex held. |
- | |
563 | */ |
- | |
564 | void vmw_kms_screen_object_update_implicit_fb(struct vmw_private *dev_priv, |
- | |
Line -... | Line 871... | ||
- | 871 | if (ret) |
|
- | 872 | return ret; |
|
- | 873 | ||
- | 874 | ret = do_dmabuf_define_gmrfb(dev_priv, framebuffer); |
|
- | 875 | if (unlikely(ret != 0)) |
|
- | 876 | goto out_revert; |
|
- | 877 | ||
- | 878 | dirty.fifo_commit = vmw_sou_dmabuf_fifo_commit; |
|
- | 879 | dirty.clip = vmw_sou_dmabuf_clip; |
|
- | 880 | dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_dmabuf_blit) * |
|
- | 881 | num_clips; |
|
- | 882 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, NULL, |
|
- | 883 | 0, 0, num_clips, increment, &dirty); |
|
Line -... | Line 884... | ||
- | 884 | vmw_kms_helper_buffer_finish(dev_priv, NULL, buf, out_fence, NULL); |
|
- | 885 | ||
- | 886 | return ret; |
|
565 | struct drm_crtc *crtc) |
887 | |
- | 888 | out_revert: |
|
- | 889 | vmw_kms_helper_buffer_revert(buf); |
|
- | 890 | ||
- | 891 | return ret; |
|
566 | { |
892 | } |
567 | struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc); |
- | |
568 | - | ||
569 | BUG_ON(!sou->base.is_implicit); |
- | |
570 | - | ||
571 | dev_priv->sou_priv->implicit_fb = |
- | |
572 | vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb); |
- | |
573 | } |
893 | |
574 | - | ||
Line -... | Line 894... | ||
- | 894 | ||
- | 895 | /** |
|
- | 896 | * vmw_sou_readback_fifo_commit - Callback to submit a set of readback clips. |
|
- | 897 | * |
|
- | 898 | * @dirty: The closure structure. |
|
- | 899 | * |
|
- | 900 | * Commits a previously built command buffer of readback clips. |
|
- | 901 | */ |
|
- | 902 | static void vmw_sou_readback_fifo_commit(struct vmw_kms_dirty *dirty) |
|
- | 903 | { |
|
- | 904 | vmw_fifo_commit(dirty->dev_priv, |
|
- | 905 | sizeof(struct vmw_kms_sou_readback_blit) * |
|
- | 906 | dirty->num_hits); |
|
- | 907 | } |
|
- | 908 | ||
- | 909 | /** |
|
- | 910 | * vmw_sou_readback_clip - Callback to encode a readback cliprect. |
|
- | 911 | * |
|
- | 912 | * @dirty: The closure structure |
|
- | 913 | * |
|
- | 914 | * Encodes a BLIT_SCREEN_TO_GMRFB cliprect. |
|
- | 915 | */ |
|
- | 916 | static void vmw_sou_readback_clip(struct vmw_kms_dirty *dirty) |
|
- | 917 | { |
|
- | 918 | struct vmw_kms_sou_readback_blit *blit = dirty->cmd; |
|
- | 919 | ||
575 | #include "bitmap.h" |
920 | blit += dirty->num_hits; |
- | 921 | blit->header = SVGA_CMD_BLIT_SCREEN_TO_GMRFB; |
|
- | 922 | blit->body.srcScreenId = dirty->unit->unit; |
|
576 | 923 | blit->body.destOrigin.x = dirty->fb_x; |
|
- | 924 | blit->body.destOrigin.y = dirty->fb_y; |
|
- | 925 | blit->body.srcRect.left = dirty->unit_x1; |
|
577 | typedef struct |
926 | blit->body.srcRect.top = dirty->unit_y1; |
- | 927 | blit->body.srcRect.right = dirty->unit_x2; |
|
- | 928 | blit->body.srcRect.bottom = dirty->unit_y2; |
|
- | 929 | dirty->num_hits++; |
|
- | 930 | } |
|
578 | { |
931 | |
- | 932 | /** |
|
Line 579... | Line 933... | ||
579 | kobj_t header; |
933 | * vmw_kms_sou_readback - Perform a readback from the screen object system to |
- | 934 | * a dma-buffer backed framebuffer. |
|
- | 935 | * |
|
Line -... | Line 936... | ||
- | 936 | * @dev_priv: Pointer to the device private structure. |
|
580 | 937 | * @file_priv: Pointer to a struct drm_file identifying the caller. |
|
581 | uint32_t *data; |
938 | * Must be set to NULL if @user_fence_rep is NULL. |
- | 939 | * @vfb: Pointer to the dma-buffer backed framebuffer. |
|
582 | uint32_t hot_x; |
940 | * @user_fence_rep: User-space provided structure for fence information. |
583 | uint32_t hot_y; |
941 | * Must be set to non-NULL if @file_priv is non-NULL. |
584 | 942 | * @vclips: Array of clip rects. |
|
- | 943 | * @num_clips: Number of clip rects in @vclips. |
|
585 | struct list_head list; |
944 | * |
586 | // struct drm_i915_gem_object *cobj; |
945 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if |
587 | }cursor_t; |
946 | * interrupted. |
588 | 947 | */ |
|
- | 948 | int vmw_kms_sou_readback(struct vmw_private *dev_priv, |
|
589 | 949 | struct drm_file *file_priv, |
|
- | 950 | struct vmw_framebuffer *vfb, |
|
590 | struct tag_display |
951 | struct drm_vmw_fence_rep __user *user_fence_rep, |
591 | { |
952 | struct drm_vmw_rect *vclips, |
- | 953 | uint32_t num_clips) |
|
- | 954 | { |
|
592 | int x; |
955 | struct vmw_dma_buffer *buf = |
- | 956 | container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer; |
|
- | 957 | struct vmw_kms_dirty dirty; |
|
- | 958 | int ret; |
|
- | 959 | ||
Line 593... | Line 960... | ||
593 | int y; |
960 | ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, true, false); |
594 | int width; |
961 | if (ret) |
595 | int height; |
962 | return ret; |
596 | int bpp; |
963 | |
Line 726... | Line 1093... | ||
726 | os_display->width, os_display->height, crtc); |
1093 | os_display->width, os_display->height, crtc); |
727 | } |
1094 | } |
Line 728... | Line 1095... | ||
728 | 1095 | ||
729 | return ret; |
1096 | return ret; |
- | 1097 | }; |