diff options
-rw-r--r-- | linux-core/drm_crtc.c | 14 | ||||
-rw-r--r-- | linux-core/drm_crtc.h | 4 | ||||
-rw-r--r-- | linux-core/intel_display.c | 1 | ||||
-rw-r--r-- | tests/modedemo/demo.c | 21 |
4 files changed, 29 insertions, 11 deletions
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fdf4c70e..1e69eca3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1048,6 +1048,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_crtc **save_crtcs, *new_crtc; bool save_enabled = crtc->enabled; bool changed = false; + bool flip_or_move = false; struct drm_output *output; int count = 0, ro; @@ -1055,11 +1056,13 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, if (!save_crtcs) return -ENOMEM; + /* We should be able to check here if the fb has the same properties + * and then just flip_or_move it */ if (crtc->fb != fb) changed = true; if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) - changed = true; + flip_or_move = true; if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) changed = true; @@ -1082,6 +1085,10 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } } + /* mode_set_base is not a required function */ + if (flip_or_move && !crtc->funcs->mode_set_base) + changed = true; + if (changed) { crtc->fb = fb; crtc->enabled = (new_mode != NULL); @@ -1102,7 +1109,10 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, crtc->desired_mode = new_mode; } drm_disable_unused_functions(dev); + } else if (flip_or_move) { + crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y); } + kfree(save_crtcs); return 0; } @@ -1564,6 +1574,7 @@ int drm_mode_setcrtc(struct drm_device *dev, if (crtc_req->count_outputs > 0) { u32 out_id; + /* Maybe we should check that count_outputs is a sensible value. */ output_set = kmalloc(crtc_req->count_outputs * sizeof(struct drm_output *), GFP_KERNEL); if (!output_set) { @@ -1589,6 +1600,7 @@ int drm_mode_setcrtc(struct drm_device *dev, } } + /* What happens to output_set, leak? */ ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb); out: diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 54e0c000..65c3704a 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -325,6 +325,10 @@ struct drm_crtc_funcs { /* Actually set the mode */ void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, int x, int y); + + /* Move the crtc on the current fb to the given position *optional* */ + void (*mode_set_base)(struct drm_crtc *crtc, int x, int y); + /* Set gamma on the CRTC */ void (*gamma_set)(struct drm_crtc *crtc, u16 r, u16 g, u16 b, int regno); diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index a81cfe69..e75d3c07 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -1083,6 +1083,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .unlock = intel_crtc_unlock, .mode_fixup = intel_crtc_mode_fixup, .mode_set = intel_crtc_mode_set, + .mode_set_base = intel_pipe_set_base, .gamma_set = intel_crtc_gamma_set, .prepare = intel_crtc_prepare, .commit = intel_crtc_commit, diff --git a/tests/modedemo/demo.c b/tests/modedemo/demo.c index 44ebacd3..594d60db 100644 --- a/tests/modedemo/demo.c +++ b/tests/modedemo/demo.c @@ -9,9 +9,10 @@ #include "xf86drm.h" #include "xf86drmMode.h" -/* setting this to 2024 gets the pitch wrong check it */ #define SIZE_X 2048 #define SIZE_Y 2048 +/* Pitch needs to be power of two */ +#define PITCH 2048 static struct drm_mode_modeinfo mode = { .name = "Test mode", @@ -82,19 +83,19 @@ int main(int argc, char **argv) prettyColors(fd, framebuffer->handle); printf("0 0\n"); - drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 0, 0, &out[1]->output_id, 1, &mode); + drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 0, 0, &out[0]->output_id, 1, &mode); sleep(2); printf("0 100\n"); - drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 0, 100, &out[1]->output_id, 1, &mode); + drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 0, 100, &out[0]->output_id, 1, &mode); sleep(2); printf("100 0\n"); - drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 100, 0, &out[1]->output_id, 1, &mode); + drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 100, 0, &out[0]->output_id, 1, &mode); sleep(2); printf("100 100\n"); - drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 100, 100, &out[1]->output_id, 1, &mode); + drmModeSetCrtc(fd, crtc->crtc_id, framebuffer->buffer_id, 100, 100, &out[0]->output_id, 1, &mode); sleep(2); /* turn the crtc off just in case */ @@ -124,7 +125,7 @@ drmModeFBPtr createFB(int fd, drmModeResPtr res) if (ret) goto err; - ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, SIZE_X*4, &bo, &fb); + ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, &bo, &fb); if (ret) goto err_bo; @@ -165,7 +166,7 @@ int findConnectedOutputs(int fd, drmModeResPtr res, drmModeOutputPtr *out) drmModeCrtcPtr findFreeCrtc(int fd, drmModeResPtr res) { - return drmModeGetCrtc(fd, res->crtcs[1]); + return drmModeGetCrtc(fd, res->crtcs[0]); } void draw(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int v, unsigned int *ptr) @@ -174,7 +175,7 @@ void draw(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsign for (i = x; i < x + w; i++) for(j = y; j < y + h; j++) - ptr[(i * SIZE_X) + j] = v; + ptr[(i * PITCH) + j] = v; } @@ -182,7 +183,7 @@ void prettyColors(int fd, unsigned int handle) { drmBO bo; unsigned int *ptr; - int i, j; + int i; drmBOReference(fd, handle, &bo); drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, (void**)&ptr); @@ -191,7 +192,7 @@ void prettyColors(int fd, unsigned int handle) ptr[i] = 0xFFFFFFFF; for (i = 0; i < 8; i++) - draw(i*40, i*40, 40, 40, 0, ptr); + draw(i * 40, i * 40, 40, 40, 0, ptr); draw(200, 100, 40, 40, 0xff00ff, ptr); |