2 * Copyright 2013 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Authors: Dave Airlie
26 #include <linux/gfp.h>
27 #include <linux/slab.h>
30 #include "qxl_object.h"
33 qxl_image_create_helper(struct qxl_device
*qdev
,
34 struct qxl_release
*release
,
35 struct qxl_bo
**image_bo
,
37 int width
, int height
,
38 int depth
, unsigned int hash
,
41 struct qxl_image
*image
;
42 struct qxl_data_chunk
*chunk
;
45 int linesize
= width
* depth
/ 8;
46 struct qxl_bo
*chunk_bo
;
50 /* FIXME: Check integer overflow */
51 /* TODO: variable number of chunks */
52 chunk_stride
= stride
; /* TODO: should use linesize, but it renders
53 wrong (check the bitmaps are sent correctly
55 ret
= qxl_alloc_bo_reserved(qdev
, sizeof(*chunk
) + height
* chunk_stride
,
58 ptr
= qxl_bo_kmap_atomic_page(qdev
, chunk_bo
, 0);
60 chunk
->data_size
= height
* chunk_stride
;
61 chunk
->prev_chunk
= 0;
62 chunk
->next_chunk
= 0;
63 qxl_bo_kunmap_atomic_page(qdev
, chunk_bo
, ptr
);
66 void *k_data
, *i_data
;
70 if (stride
== linesize
&& chunk_stride
== stride
) {
71 remain
= linesize
* height
;
73 i_data
= (void *)data
;
76 ptr
= qxl_bo_kmap_atomic_page(qdev
, chunk_bo
, page
<< PAGE_SHIFT
);
81 size
= PAGE_SIZE
- offsetof(struct qxl_data_chunk
, data
);
86 size
= min(size
, remain
);
88 memcpy(k_data
, i_data
, size
);
90 qxl_bo_kunmap_atomic_page(qdev
, chunk_bo
, ptr
);
96 unsigned page_base
, page_offset
, out_offset
;
97 for (i
= 0 ; i
< height
; ++i
) {
98 i_data
= (void *)data
+ i
* stride
;
100 out_offset
= offsetof(struct qxl_data_chunk
, data
) + i
* chunk_stride
;
103 page_base
= out_offset
& PAGE_MASK
;
104 page_offset
= offset_in_page(out_offset
);
106 size
= min((int)(PAGE_SIZE
- page_offset
), remain
);
108 ptr
= qxl_bo_kmap_atomic_page(qdev
, chunk_bo
, page_base
);
109 k_data
= ptr
+ page_offset
;
110 memcpy(k_data
, i_data
, size
);
111 qxl_bo_kunmap_atomic_page(qdev
, chunk_bo
, ptr
);
121 qxl_bo_kunmap(chunk_bo
);
124 ret
= qxl_alloc_bo_reserved(qdev
, sizeof(*image
), image_bo
);
126 ptr
= qxl_bo_kmap_atomic_page(qdev
, *image_bo
, 0);
129 image
->descriptor
.id
= 0;
130 image
->descriptor
.type
= SPICE_IMAGE_TYPE_BITMAP
;
132 image
->descriptor
.flags
= 0;
133 image
->descriptor
.width
= width
;
134 image
->descriptor
.height
= height
;
138 /* TODO: BE? check by arch? */
139 image
->u
.bitmap
.format
= SPICE_BITMAP_FMT_1BIT_BE
;
142 image
->u
.bitmap
.format
= SPICE_BITMAP_FMT_24BIT
;
145 image
->u
.bitmap
.format
= SPICE_BITMAP_FMT_32BIT
;
148 DRM_ERROR("unsupported image bit depth\n");
149 return -EINVAL
; /* TODO: cleanup */
151 image
->u
.bitmap
.flags
= QXL_BITMAP_TOP_DOWN
;
152 image
->u
.bitmap
.x
= width
;
153 image
->u
.bitmap
.y
= height
;
154 image
->u
.bitmap
.stride
= chunk_stride
;
155 image
->u
.bitmap
.palette
= 0;
156 image
->u
.bitmap
.data
= qxl_bo_physical_address(qdev
, chunk_bo
, 0);
157 qxl_release_add_res(qdev
, release
, chunk_bo
);
158 qxl_bo_unreserve(chunk_bo
);
159 qxl_bo_unref(&chunk_bo
);
161 qxl_bo_kunmap_atomic_page(qdev
, *image_bo
, ptr
);
166 int qxl_image_create(struct qxl_device
*qdev
,
167 struct qxl_release
*release
,
168 struct qxl_bo
**image_bo
,
170 int x
, int y
, int width
, int height
,
171 int depth
, int stride
)
173 data
+= y
* stride
+ x
* (depth
/ 8);
174 return qxl_image_create_helper(qdev
, release
, image_bo
, data
,
175 width
, height
, depth
, 0, stride
);
This page took 0.03591 seconds and 6 git commands to generate.