drm: qxl: Atomic phase 1: convert cursor to universal plane
In preparation for atomic conversion, let's use the transitional atomic helpers drm_plane_helper_update/disable. Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk> Link: http://patchwork.freedesktop.org/patch/msgid/20170227204328.18761-6-krisman@collabora.co.uk Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
d3e7e42db2
commit
1277eed5fe
@ -30,6 +30,7 @@
|
|||||||
#include "qxl_object.h"
|
#include "qxl_object.h"
|
||||||
#include "drm_crtc_helper.h"
|
#include "drm_crtc_helper.h"
|
||||||
#include <drm/drm_plane_helper.h>
|
#include <drm/drm_plane_helper.h>
|
||||||
|
#include <drm/drm_atomic_helper.h>
|
||||||
|
|
||||||
static bool qxl_head_enabled(struct qxl_head *head)
|
static bool qxl_head_enabled(struct qxl_head *head)
|
||||||
{
|
{
|
||||||
@ -256,7 +257,6 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc)
|
|||||||
struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
|
struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
|
||||||
|
|
||||||
drm_crtc_cleanup(crtc);
|
drm_crtc_cleanup(crtc);
|
||||||
qxl_bo_unref(&qxl_crtc->cursor_bo);
|
|
||||||
kfree(qxl_crtc);
|
kfree(qxl_crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,234 +304,7 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
qxl_hide_cursor(struct qxl_device *qdev)
|
|
||||||
{
|
|
||||||
struct qxl_release *release;
|
|
||||||
struct qxl_cursor_cmd *cmd;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
|
|
||||||
&release, NULL);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = qxl_release_reserve_list(release, true);
|
|
||||||
if (ret) {
|
|
||||||
qxl_release_free(qdev, release);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
|
|
||||||
cmd->type = QXL_CURSOR_HIDE;
|
|
||||||
qxl_release_unmap(qdev, release, &cmd->release_info);
|
|
||||||
|
|
||||||
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
|
|
||||||
qxl_release_fence_buffer_objects(release);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int qxl_crtc_apply_cursor(struct drm_crtc *crtc)
|
|
||||||
{
|
|
||||||
struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
|
|
||||||
struct drm_device *dev = crtc->dev;
|
|
||||||
struct qxl_device *qdev = dev->dev_private;
|
|
||||||
struct qxl_cursor_cmd *cmd;
|
|
||||||
struct qxl_release *release;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!qcrtc->cursor_bo)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
|
|
||||||
QXL_RELEASE_CURSOR_CMD,
|
|
||||||
&release, NULL);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = qxl_release_list_add(release, qcrtc->cursor_bo);
|
|
||||||
if (ret)
|
|
||||||
goto out_free_release;
|
|
||||||
|
|
||||||
ret = qxl_release_reserve_list(release, false);
|
|
||||||
if (ret)
|
|
||||||
goto out_free_release;
|
|
||||||
|
|
||||||
cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
|
|
||||||
cmd->type = QXL_CURSOR_SET;
|
|
||||||
cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
|
|
||||||
cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
|
|
||||||
|
|
||||||
cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0);
|
|
||||||
|
|
||||||
cmd->u.set.visible = 1;
|
|
||||||
qxl_release_unmap(qdev, release, &cmd->release_info);
|
|
||||||
|
|
||||||
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
|
|
||||||
qxl_release_fence_buffer_objects(release);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
out_free_release:
|
|
||||||
qxl_release_free(qdev, release);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
|
|
||||||
struct drm_file *file_priv,
|
|
||||||
uint32_t handle,
|
|
||||||
uint32_t width,
|
|
||||||
uint32_t height, int32_t hot_x, int32_t hot_y)
|
|
||||||
{
|
|
||||||
struct drm_device *dev = crtc->dev;
|
|
||||||
struct qxl_device *qdev = dev->dev_private;
|
|
||||||
struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
|
|
||||||
struct drm_gem_object *obj;
|
|
||||||
struct qxl_cursor *cursor;
|
|
||||||
struct qxl_cursor_cmd *cmd;
|
|
||||||
struct qxl_bo *cursor_bo, *user_bo;
|
|
||||||
struct qxl_release *release;
|
|
||||||
void *user_ptr;
|
|
||||||
|
|
||||||
int size = 64*64*4;
|
|
||||||
int ret = 0;
|
|
||||||
if (!handle)
|
|
||||||
return qxl_hide_cursor(qdev);
|
|
||||||
|
|
||||||
obj = drm_gem_object_lookup(file_priv, handle);
|
|
||||||
if (!obj) {
|
|
||||||
DRM_ERROR("cannot find cursor object\n");
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
user_bo = gem_to_qxl_bo(obj);
|
|
||||||
|
|
||||||
ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
|
|
||||||
if (ret)
|
|
||||||
goto out_unref;
|
|
||||||
|
|
||||||
ret = qxl_bo_kmap(user_bo, &user_ptr);
|
|
||||||
if (ret)
|
|
||||||
goto out_unpin;
|
|
||||||
|
|
||||||
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
|
|
||||||
QXL_RELEASE_CURSOR_CMD,
|
|
||||||
&release, NULL);
|
|
||||||
if (ret)
|
|
||||||
goto out_kunmap;
|
|
||||||
|
|
||||||
ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_cursor) + size,
|
|
||||||
&cursor_bo);
|
|
||||||
if (ret)
|
|
||||||
goto out_free_release;
|
|
||||||
|
|
||||||
ret = qxl_release_reserve_list(release, false);
|
|
||||||
if (ret)
|
|
||||||
goto out_free_bo;
|
|
||||||
|
|
||||||
ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
|
|
||||||
if (ret)
|
|
||||||
goto out_backoff;
|
|
||||||
|
|
||||||
cursor->header.unique = 0;
|
|
||||||
cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
|
|
||||||
cursor->header.width = 64;
|
|
||||||
cursor->header.height = 64;
|
|
||||||
cursor->header.hot_spot_x = hot_x;
|
|
||||||
cursor->header.hot_spot_y = hot_y;
|
|
||||||
cursor->data_size = size;
|
|
||||||
cursor->chunk.next_chunk = 0;
|
|
||||||
cursor->chunk.prev_chunk = 0;
|
|
||||||
cursor->chunk.data_size = size;
|
|
||||||
|
|
||||||
memcpy(cursor->chunk.data, user_ptr, size);
|
|
||||||
|
|
||||||
qxl_bo_kunmap(cursor_bo);
|
|
||||||
|
|
||||||
qxl_bo_kunmap(user_bo);
|
|
||||||
|
|
||||||
qcrtc->cur_x += qcrtc->hot_spot_x - hot_x;
|
|
||||||
qcrtc->cur_y += qcrtc->hot_spot_y - hot_y;
|
|
||||||
qcrtc->hot_spot_x = hot_x;
|
|
||||||
qcrtc->hot_spot_y = hot_y;
|
|
||||||
|
|
||||||
cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
|
|
||||||
cmd->type = QXL_CURSOR_SET;
|
|
||||||
cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
|
|
||||||
cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
|
|
||||||
|
|
||||||
cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0);
|
|
||||||
|
|
||||||
cmd->u.set.visible = 1;
|
|
||||||
qxl_release_unmap(qdev, release, &cmd->release_info);
|
|
||||||
|
|
||||||
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
|
|
||||||
qxl_release_fence_buffer_objects(release);
|
|
||||||
|
|
||||||
/* finish with the userspace bo */
|
|
||||||
qxl_bo_unpin(user_bo);
|
|
||||||
|
|
||||||
drm_gem_object_unreference_unlocked(obj);
|
|
||||||
|
|
||||||
qxl_bo_unref (&qcrtc->cursor_bo);
|
|
||||||
qcrtc->cursor_bo = cursor_bo;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
out_backoff:
|
|
||||||
qxl_release_backoff_reserve_list(release);
|
|
||||||
out_free_bo:
|
|
||||||
qxl_bo_unref(&cursor_bo);
|
|
||||||
out_free_release:
|
|
||||||
qxl_release_free(qdev, release);
|
|
||||||
out_kunmap:
|
|
||||||
qxl_bo_kunmap(user_bo);
|
|
||||||
out_unpin:
|
|
||||||
qxl_bo_unpin(user_bo);
|
|
||||||
out_unref:
|
|
||||||
drm_gem_object_unreference_unlocked(obj);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int qxl_crtc_cursor_move(struct drm_crtc *crtc,
|
|
||||||
int x, int y)
|
|
||||||
{
|
|
||||||
struct drm_device *dev = crtc->dev;
|
|
||||||
struct qxl_device *qdev = dev->dev_private;
|
|
||||||
struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
|
|
||||||
struct qxl_release *release;
|
|
||||||
struct qxl_cursor_cmd *cmd;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
|
|
||||||
&release, NULL);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = qxl_release_reserve_list(release, true);
|
|
||||||
if (ret) {
|
|
||||||
qxl_release_free(qdev, release);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
qcrtc->cur_x = x;
|
|
||||||
qcrtc->cur_y = y;
|
|
||||||
|
|
||||||
cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
|
|
||||||
cmd->type = QXL_CURSOR_MOVE;
|
|
||||||
cmd->u.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
|
|
||||||
cmd->u.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
|
|
||||||
qxl_release_unmap(qdev, release, &cmd->release_info);
|
|
||||||
|
|
||||||
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
|
|
||||||
qxl_release_fence_buffer_objects(release);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct drm_crtc_funcs qxl_crtc_funcs = {
|
static const struct drm_crtc_funcs qxl_crtc_funcs = {
|
||||||
.cursor_set2 = qxl_crtc_cursor_set2,
|
|
||||||
.cursor_move = qxl_crtc_cursor_move,
|
|
||||||
.set_config = drm_crtc_helper_set_config,
|
.set_config = drm_crtc_helper_set_config,
|
||||||
.destroy = qxl_crtc_destroy,
|
.destroy = qxl_crtc_destroy,
|
||||||
.page_flip = qxl_crtc_page_flip,
|
.page_flip = qxl_crtc_page_flip,
|
||||||
@ -723,12 +496,6 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
|
|||||||
bo->surf.stride, bo->surf.format);
|
bo->surf.stride, bo->surf.format);
|
||||||
qxl_io_create_primary(qdev, 0, bo);
|
qxl_io_create_primary(qdev, 0, bo);
|
||||||
bo->is_primary = true;
|
bo->is_primary = true;
|
||||||
|
|
||||||
ret = qxl_crtc_apply_cursor(crtc);
|
|
||||||
if (ret) {
|
|
||||||
DRM_ERROR("could not set cursor after modeset");
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bo->is_primary) {
|
if (bo->is_primary) {
|
||||||
@ -788,6 +555,188 @@ static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
|
|||||||
.commit = qxl_crtc_commit,
|
.commit = qxl_crtc_commit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int qxl_plane_atomic_check(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *state)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qxl_cursor_atomic_update(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *old_state)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = plane->dev;
|
||||||
|
struct qxl_device *qdev = dev->dev_private;
|
||||||
|
struct drm_framebuffer *fb = plane->state->fb;
|
||||||
|
struct qxl_release *release;
|
||||||
|
struct qxl_cursor_cmd *cmd;
|
||||||
|
struct qxl_cursor *cursor;
|
||||||
|
struct drm_gem_object *obj;
|
||||||
|
struct qxl_bo *cursor_bo, *user_bo = NULL;
|
||||||
|
int ret;
|
||||||
|
void *user_ptr;
|
||||||
|
int size = 64*64*4;
|
||||||
|
|
||||||
|
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
|
||||||
|
QXL_RELEASE_CURSOR_CMD,
|
||||||
|
&release, NULL);
|
||||||
|
|
||||||
|
cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
|
||||||
|
|
||||||
|
if (fb != old_state->fb) {
|
||||||
|
obj = to_qxl_framebuffer(fb)->obj;
|
||||||
|
user_bo = gem_to_qxl_bo(obj);
|
||||||
|
|
||||||
|
/* pinning is done in the prepare/cleanup framevbuffer */
|
||||||
|
ret = qxl_bo_kmap(user_bo, &user_ptr);
|
||||||
|
if (ret)
|
||||||
|
goto out_free_release;
|
||||||
|
|
||||||
|
ret = qxl_alloc_bo_reserved(qdev, release,
|
||||||
|
sizeof(struct qxl_cursor) + size,
|
||||||
|
&cursor_bo);
|
||||||
|
if (ret)
|
||||||
|
goto out_kunmap;
|
||||||
|
|
||||||
|
ret = qxl_release_reserve_list(release, true);
|
||||||
|
if (ret)
|
||||||
|
goto out_free_bo;
|
||||||
|
|
||||||
|
ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
|
||||||
|
if (ret)
|
||||||
|
goto out_backoff;
|
||||||
|
|
||||||
|
cursor->header.unique = 0;
|
||||||
|
cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
|
||||||
|
cursor->header.width = 64;
|
||||||
|
cursor->header.height = 64;
|
||||||
|
cursor->header.hot_spot_x = fb->hot_x;
|
||||||
|
cursor->header.hot_spot_y = fb->hot_y;
|
||||||
|
cursor->data_size = size;
|
||||||
|
cursor->chunk.next_chunk = 0;
|
||||||
|
cursor->chunk.prev_chunk = 0;
|
||||||
|
cursor->chunk.data_size = size;
|
||||||
|
memcpy(cursor->chunk.data, user_ptr, size);
|
||||||
|
qxl_bo_kunmap(cursor_bo);
|
||||||
|
qxl_bo_kunmap(user_bo);
|
||||||
|
|
||||||
|
cmd->u.set.visible = 1;
|
||||||
|
cmd->u.set.shape = qxl_bo_physical_address(qdev,
|
||||||
|
cursor_bo, 0);
|
||||||
|
cmd->type = QXL_CURSOR_SET;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = qxl_release_reserve_list(release, true);
|
||||||
|
if (ret)
|
||||||
|
goto out_free_release;
|
||||||
|
|
||||||
|
cmd->type = QXL_CURSOR_MOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->u.position.x = plane->state->crtc_x + fb->hot_x;
|
||||||
|
cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
|
||||||
|
|
||||||
|
qxl_release_unmap(qdev, release, &cmd->release_info);
|
||||||
|
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
|
||||||
|
qxl_release_fence_buffer_objects(release);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
out_backoff:
|
||||||
|
qxl_release_backoff_reserve_list(release);
|
||||||
|
out_free_bo:
|
||||||
|
qxl_bo_unref(&cursor_bo);
|
||||||
|
out_kunmap:
|
||||||
|
qxl_bo_kunmap(user_bo);
|
||||||
|
out_free_release:
|
||||||
|
qxl_release_free(qdev, release);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void qxl_cursor_atomic_disable(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *old_state)
|
||||||
|
{
|
||||||
|
struct qxl_device *qdev = plane->dev->dev_private;
|
||||||
|
struct qxl_release *release;
|
||||||
|
struct qxl_cursor_cmd *cmd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
|
||||||
|
QXL_RELEASE_CURSOR_CMD,
|
||||||
|
&release, NULL);
|
||||||
|
if (ret)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ret = qxl_release_reserve_list(release, true);
|
||||||
|
if (ret) {
|
||||||
|
qxl_release_free(qdev, release);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
|
||||||
|
cmd->type = QXL_CURSOR_HIDE;
|
||||||
|
qxl_release_unmap(qdev, release, &cmd->release_info);
|
||||||
|
|
||||||
|
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
|
||||||
|
qxl_release_fence_buffer_objects(release);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qxl_plane_prepare_fb(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *new_state)
|
||||||
|
{
|
||||||
|
struct drm_gem_object *obj;
|
||||||
|
struct qxl_bo *user_bo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!new_state->fb)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
obj = to_qxl_framebuffer(new_state->fb)->obj;
|
||||||
|
user_bo = gem_to_qxl_bo(obj);
|
||||||
|
|
||||||
|
ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qxl_plane_cleanup_fb(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *old_state)
|
||||||
|
{
|
||||||
|
struct drm_gem_object *obj;
|
||||||
|
struct qxl_bo *user_bo;
|
||||||
|
|
||||||
|
if (!plane->state->fb) {
|
||||||
|
/* we never executed prepare_fb, so there's nothing to
|
||||||
|
* unpin.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = to_qxl_framebuffer(plane->state->fb)->obj;
|
||||||
|
user_bo = gem_to_qxl_bo(obj);
|
||||||
|
qxl_bo_unpin(user_bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint32_t qxl_cursor_plane_formats[] = {
|
||||||
|
DRM_FORMAT_ARGB8888,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = {
|
||||||
|
.atomic_check = qxl_plane_atomic_check,
|
||||||
|
.atomic_update = qxl_cursor_atomic_update,
|
||||||
|
.atomic_disable = qxl_cursor_atomic_disable,
|
||||||
|
.prepare_fb = qxl_plane_prepare_fb,
|
||||||
|
.cleanup_fb = qxl_plane_cleanup_fb,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct drm_plane_funcs qxl_cursor_plane_funcs = {
|
||||||
|
.update_plane = drm_plane_helper_update,
|
||||||
|
.disable_plane = drm_plane_helper_disable,
|
||||||
|
.destroy = drm_primary_helper_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
static const uint32_t qxl_primary_plane_formats[] = {
|
static const uint32_t qxl_primary_plane_formats[] = {
|
||||||
DRM_FORMAT_XRGB8888,
|
DRM_FORMAT_XRGB8888,
|
||||||
DRM_FORMAT_ARGB8888,
|
DRM_FORMAT_ARGB8888,
|
||||||
@ -814,6 +763,11 @@ static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
|
|||||||
funcs = &qxl_primary_plane_funcs;
|
funcs = &qxl_primary_plane_funcs;
|
||||||
formats = qxl_primary_plane_formats;
|
formats = qxl_primary_plane_formats;
|
||||||
num_formats = ARRAY_SIZE(qxl_primary_plane_formats);
|
num_formats = ARRAY_SIZE(qxl_primary_plane_formats);
|
||||||
|
} else if (type == DRM_PLANE_TYPE_CURSOR) {
|
||||||
|
funcs = &qxl_cursor_plane_funcs;
|
||||||
|
formats = qxl_cursor_plane_formats;
|
||||||
|
helper_funcs = &qxl_cursor_helper_funcs;
|
||||||
|
num_formats = ARRAY_SIZE(qxl_cursor_plane_formats);
|
||||||
} else {
|
} else {
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
@ -840,7 +794,7 @@ free_plane:
|
|||||||
static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
|
static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
|
||||||
{
|
{
|
||||||
struct qxl_crtc *qxl_crtc;
|
struct qxl_crtc *qxl_crtc;
|
||||||
struct drm_plane *primary;
|
struct drm_plane *primary, *cursor;
|
||||||
struct qxl_device *qdev = dev->dev_private;
|
struct qxl_device *qdev = dev->dev_private;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -854,15 +808,24 @@ static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
|
|||||||
goto free_mem;
|
goto free_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = drm_crtc_init_with_planes(dev, &qxl_crtc->base, primary, NULL,
|
cursor = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_CURSOR);
|
||||||
|
if (IS_ERR(cursor)) {
|
||||||
|
r = -ENOMEM;
|
||||||
|
goto clean_primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = drm_crtc_init_with_planes(dev, &qxl_crtc->base, primary, cursor,
|
||||||
&qxl_crtc_funcs, NULL);
|
&qxl_crtc_funcs, NULL);
|
||||||
if (r)
|
if (r)
|
||||||
goto clean_primary;
|
goto clean_cursor;
|
||||||
|
|
||||||
qxl_crtc->index = crtc_id;
|
qxl_crtc->index = crtc_id;
|
||||||
drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
|
drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
clean_cursor:
|
||||||
|
drm_plane_cleanup(cursor);
|
||||||
|
kfree(cursor);
|
||||||
clean_primary:
|
clean_primary:
|
||||||
drm_plane_cleanup(primary);
|
drm_plane_cleanup(primary);
|
||||||
kfree(primary);
|
kfree(primary);
|
||||||
@ -1213,8 +1176,8 @@ int qxl_modeset_init(struct qxl_device *qdev)
|
|||||||
qdev->ddev.mode_config.funcs = (void *)&qxl_mode_funcs;
|
qdev->ddev.mode_config.funcs = (void *)&qxl_mode_funcs;
|
||||||
|
|
||||||
/* modes will be validated against the framebuffer size */
|
/* modes will be validated against the framebuffer size */
|
||||||
qdev->ddev.mode_config.min_width = 320;
|
qdev->ddev.mode_config.min_width = 0;
|
||||||
qdev->ddev.mode_config.min_height = 200;
|
qdev->ddev.mode_config.min_height = 0;
|
||||||
qdev->ddev.mode_config.max_width = 8192;
|
qdev->ddev.mode_config.max_width = 8192;
|
||||||
qdev->ddev.mode_config.max_height = 8192;
|
qdev->ddev.mode_config.max_height = 8192;
|
||||||
|
|
||||||
|
@ -134,11 +134,6 @@ struct qxl_bo_list {
|
|||||||
struct qxl_crtc {
|
struct qxl_crtc {
|
||||||
struct drm_crtc base;
|
struct drm_crtc base;
|
||||||
int index;
|
int index;
|
||||||
int cur_x;
|
|
||||||
int cur_y;
|
|
||||||
int hot_spot_x;
|
|
||||||
int hot_spot_y;
|
|
||||||
struct qxl_bo *cursor_bo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qxl_output {
|
struct qxl_output {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user