1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "qxl_drv.h"
24#include "qxl_object.h"
25
26static int alloc_clips(struct qxl_device *qdev,
27 struct qxl_release *release,
28 unsigned int num_clips,
29 struct qxl_bo **clips_bo)
30{
31 int size = sizeof(struct qxl_clip_rects) + sizeof(struct qxl_rect) * num_clips;
32
33 return qxl_alloc_bo_reserved(qdev, release, size, clips_bo);
34}
35
36
37
38
39static struct qxl_rect *drawable_set_clipping(struct qxl_device *qdev,
40 unsigned int num_clips,
41 struct qxl_bo *clips_bo)
42{
43 struct qxl_clip_rects *dev_clips;
44 int ret;
45
46 ret = qxl_bo_kmap(clips_bo, (void **)&dev_clips);
47 if (ret) {
48 return NULL;
49 }
50 dev_clips->num_rects = num_clips;
51 dev_clips->chunk.next_chunk = 0;
52 dev_clips->chunk.prev_chunk = 0;
53 dev_clips->chunk.data_size = sizeof(struct qxl_rect) * num_clips;
54 return (struct qxl_rect *)dev_clips->chunk.data;
55}
56
57static int
58alloc_drawable(struct qxl_device *qdev, struct qxl_release **release)
59{
60 return qxl_alloc_release_reserved(qdev, sizeof(struct qxl_drawable),
61 QXL_RELEASE_DRAWABLE, release, NULL);
62}
63
64static void
65free_drawable(struct qxl_device *qdev, struct qxl_release *release)
66{
67 qxl_release_free(qdev, release);
68}
69
70
71static int
72make_drawable(struct qxl_device *qdev, int surface, uint8_t type,
73 const struct qxl_rect *rect,
74 struct qxl_release *release)
75{
76 struct qxl_drawable *drawable;
77 int i;
78
79 drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
80 if (!drawable)
81 return -ENOMEM;
82
83 drawable->type = type;
84
85 drawable->surface_id = surface;
86 drawable->effect = QXL_EFFECT_OPAQUE;
87 drawable->self_bitmap = 0;
88 drawable->self_bitmap_area.top = 0;
89 drawable->self_bitmap_area.left = 0;
90 drawable->self_bitmap_area.bottom = 0;
91 drawable->self_bitmap_area.right = 0;
92
93 drawable->clip.type = SPICE_CLIP_TYPE_NONE;
94
95
96
97
98
99
100
101 for (i = 0; i < 3; ++i)
102 drawable->surfaces_dest[i] = -1;
103
104 if (rect)
105 drawable->bbox = *rect;
106
107 drawable->mm_time = qdev->rom->mm_clock;
108 qxl_release_unmap(qdev, release, &drawable->release_info);
109 return 0;
110}
111
112
113
114
115
116
117
118
119void qxl_draw_dirty_fb(struct qxl_device *qdev,
120 struct drm_framebuffer *fb,
121 struct qxl_bo *bo,
122 unsigned int flags, unsigned int color,
123 struct drm_clip_rect *clips,
124 unsigned int num_clips, int inc,
125 uint32_t dumb_shadow_offset)
126{
127
128
129
130
131
132
133 struct drm_clip_rect *clips_ptr;
134 int i;
135 int left, right, top, bottom;
136 int width, height;
137 struct qxl_drawable *drawable;
138 struct qxl_rect drawable_rect;
139 struct qxl_rect *rects;
140 int stride = fb->pitches[0];
141
142 int depth = fb->format->cpp[0] * 8;
143 uint8_t *surface_base;
144 struct qxl_release *release;
145 struct qxl_bo *clips_bo;
146 struct qxl_drm_image *dimage;
147 int ret;
148
149 ret = alloc_drawable(qdev, &release);
150 if (ret)
151 return;
152
153 clips->x1 += dumb_shadow_offset;
154 clips->x2 += dumb_shadow_offset;
155
156 left = clips->x1;
157 right = clips->x2;
158 top = clips->y1;
159 bottom = clips->y2;
160
161
162 for (i = 1, clips_ptr = clips + inc;
163 i < num_clips; i++, clips_ptr += inc) {
164 left = min_t(int, left, (int)clips_ptr->x1);
165 right = max_t(int, right, (int)clips_ptr->x2);
166 top = min_t(int, top, (int)clips_ptr->y1);
167 bottom = max_t(int, bottom, (int)clips_ptr->y2);
168 }
169
170 width = right - left;
171 height = bottom - top;
172
173 ret = alloc_clips(qdev, release, num_clips, &clips_bo);
174 if (ret)
175 goto out_free_drawable;
176
177 ret = qxl_image_alloc_objects(qdev, release,
178 &dimage,
179 height, stride);
180 if (ret)
181 goto out_free_clips;
182
183
184 ret = qxl_release_reserve_list(release, true);
185 if (ret)
186 goto out_free_image;
187
188 drawable_rect.left = left;
189 drawable_rect.right = right;
190 drawable_rect.top = top;
191 drawable_rect.bottom = bottom;
192
193 ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &drawable_rect,
194 release);
195 if (ret)
196 goto out_release_backoff;
197
198 ret = qxl_bo_kmap(bo, (void **)&surface_base);
199 if (ret)
200 goto out_release_backoff;
201
202 ret = qxl_image_init(qdev, release, dimage, surface_base,
203 left - dumb_shadow_offset,
204 top, width, height, depth, stride);
205 qxl_bo_kunmap(bo);
206 if (ret)
207 goto out_release_backoff;
208
209 rects = drawable_set_clipping(qdev, num_clips, clips_bo);
210 if (!rects)
211 goto out_release_backoff;
212
213 drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
214
215 drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
216 drawable->clip.data = qxl_bo_physical_address(qdev,
217 clips_bo, 0);
218
219 drawable->u.copy.src_area.top = 0;
220 drawable->u.copy.src_area.bottom = height;
221 drawable->u.copy.src_area.left = 0;
222 drawable->u.copy.src_area.right = width;
223
224 drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
225 drawable->u.copy.scale_mode = 0;
226 drawable->u.copy.mask.flags = 0;
227 drawable->u.copy.mask.pos.x = 0;
228 drawable->u.copy.mask.pos.y = 0;
229 drawable->u.copy.mask.bitmap = 0;
230
231 drawable->u.copy.src_bitmap = qxl_bo_physical_address(qdev, dimage->bo, 0);
232 qxl_release_unmap(qdev, release, &drawable->release_info);
233
234 clips_ptr = clips;
235 for (i = 0; i < num_clips; i++, clips_ptr += inc) {
236 rects[i].left = clips_ptr->x1;
237 rects[i].right = clips_ptr->x2;
238 rects[i].top = clips_ptr->y1;
239 rects[i].bottom = clips_ptr->y2;
240 }
241 qxl_bo_kunmap(clips_bo);
242
243 qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
244 qxl_release_fence_buffer_objects(release);
245
246out_release_backoff:
247 if (ret)
248 qxl_release_backoff_reserve_list(release);
249out_free_image:
250 qxl_image_free_objects(qdev, dimage);
251out_free_clips:
252 qxl_bo_unref(&clips_bo);
253out_free_drawable:
254
255 if (ret)
256 free_drawable(qdev, release);
257
258}
259