summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drm_crtc.c14
-rw-r--r--linux-core/drm_crtc.h4
-rw-r--r--linux-core/intel_display.c1
-rw-r--r--tests/modedemo/demo.c21
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);