summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2019-01-09 09:20:45 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2019-01-28 14:47:55 +0100
commit357ce6e48c2e8f2ba2b2d889d4f2041818947eb3 (patch)
treee84cf0693f0d1176422a0f3445825197ba5ec0dd
parent86189966c3dee0e0c10dd4926cebbe478129c6f0 (diff)
vmwgfx: Limit the number of cliprects in a drm present command v3
The drm present command number of cliprects should not exceed DRM_MODE_FB_DIRTY_MAX_CLIPS. If that number is exceeded, split the command up. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com> #v2 Reviewed-by: Deepak Rawat < drawat@vmware.com> #v1
-rw-r--r--vmwgfx/vmwgfx_drmi.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c
index 82bf5f5..a420bd9 100644
--- a/vmwgfx/vmwgfx_drmi.c
+++ b/vmwgfx/vmwgfx_drmi.c
@@ -44,6 +44,7 @@
#include "svga3d_reg.h"
#include "vmwgfx_driver.h"
+#include "common_compat.h"
static int
vmwgfx_fence_wait(int drm_fd, uint32_t handle, Bool unref)
@@ -138,6 +139,7 @@ vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
{
BoxPtr clips = REGION_RECTS(region);
unsigned int num_clips = REGION_NUM_RECTS(region);
+ unsigned int alloc_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);
struct drm_vmw_present_arg arg;
unsigned int i;
struct drm_vmw_rect *rects, *r;
@@ -146,35 +148,42 @@ vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
if (num_clips == 0)
return 0;
- rects = calloc(num_clips, sizeof(*rects));
+ rects = malloc(alloc_clips * sizeof(*rects));
if (!rects) {
LogMessage(X_ERROR, "Failed to alloc cliprects for "
"present.\n");
return -1;
}
- memset(&arg, 0, sizeof(arg));
- arg.fb_id = fb_id;
- arg.sid = handle;
- arg.dest_x = dst_x;
- arg.dest_y = dst_y;
- arg.num_clips = num_clips;
- arg.clips_ptr = (unsigned long) rects;
+ while (num_clips > 0) {
+ unsigned int cur_clips = min(num_clips, DRM_MODE_FB_DIRTY_MAX_CLIPS);
- for (i = 0, r = rects; i < num_clips; ++i, ++r, ++clips) {
- r->x = clips->x1;
- r->y = clips->y1;
- r->w = clips->x2 - clips->x1;
- r->h = clips->y2 - clips->y1;
- }
+ memset(&arg, 0, sizeof(arg));
+ memset(rects, 0, alloc_clips * sizeof(*rects));
+ arg.fb_id = fb_id;
+ arg.sid = handle;
+ arg.dest_x = dst_x;
+ arg.dest_y = dst_y;
+ arg.num_clips = cur_clips;
+ arg.clips_ptr = (unsigned long) rects;
+
+ for (i = 0, r = rects; i < cur_clips; ++i, ++r, ++clips) {
+ r->x = clips->x1;
+ r->y = clips->y1;
+ r->w = clips->x2 - clips->x1;
+ r->h = clips->y2 - clips->y1;
+ }
- ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT, &arg, sizeof(arg));
- if (ret) {
- LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret));
+ ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT, &arg, sizeof(arg));
+ if (ret)
+ LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret));
+
+ num_clips -= cur_clips;
}
free(rects);
- return ((ret != 0) ? -1 : 0);
+
+ return 0;
}