Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6865 | serge | 1 | #include |
2 | #include |
||
3 | #include "pxdraw.h" |
||
4 | #include "internal.h" |
||
5 | |||
6 | ctx_t* create_context(int x, int y, int width, int height) |
||
7 | { |
||
8 | ctx_t *ctx; |
||
9 | |||
10 | ctx = malloc(sizeof(ctx_t)); |
||
11 | if (ctx == NULL) |
||
12 | goto err_0; |
||
13 | |||
14 | ctx->pitch = ALIGN(width * sizeof(color_t), 16); |
||
15 | ctx->size = ALIGN(ctx->pitch * height, 4096); |
||
16 | |||
17 | ctx->buffer = user_alloc(ctx->size+4096); |
||
18 | if (ctx->buffer == NULL) |
||
19 | goto err_1; |
||
20 | |||
21 | ctx->x = x; |
||
22 | ctx->y = y; |
||
23 | ctx->width = width; |
||
24 | ctx->height = height; |
||
25 | |||
26 | ctx->rc.l = 0; |
||
27 | ctx->rc.t = 0; |
||
28 | ctx->rc.r = width; |
||
29 | ctx->rc.b = height; |
||
30 | |||
31 | ctx->rcu.l = 0; |
||
32 | ctx->rcu.t = 0; |
||
33 | ctx->rcu.r = ctx->width; |
||
34 | ctx->rcu.b = ctx->height; |
||
35 | ctx->dirty = 1; |
||
36 | |||
37 | __builtin_cpu_init (); |
||
38 | if (__builtin_cpu_supports ("sse2")) |
||
39 | ctx->px_rect_simd = px_rect_xmm; |
||
40 | else if (__builtin_cpu_supports ("mmx")) |
||
41 | ctx->px_rect_simd = px_rect_mmx; |
||
42 | else |
||
43 | ctx->px_rect_simd = px_rect_alu; |
||
44 | |||
45 | if (__builtin_cpu_supports ("sse2")) |
||
46 | ctx->px_glyph = px_glyph_sse; |
||
47 | else |
||
48 | ctx->px_glyph = px_glyph_alu; |
||
49 | |||
50 | return ctx; |
||
51 | |||
52 | err_1: |
||
53 | free(ctx); |
||
54 | err_0: |
||
55 | return NULL; |
||
56 | }; |
||
57 | |||
58 | int resize_context(ctx_t *ctx, int width, int height) |
||
59 | { |
||
60 | int size; |
||
61 | int pitch; |
||
62 | |||
63 | pitch = ALIGN(width * sizeof(color_t), 16); |
||
64 | size = ALIGN(pitch * height, 4096); |
||
65 | |||
66 | if (size > ctx->size) |
||
67 | { |
||
68 | ctx->buffer = user_realloc(ctx->buffer, size); /* grow buffer */ |
||
69 | if (ctx->buffer == NULL) |
||
70 | return -1; |
||
71 | |||
72 | ctx->size = size; |
||
73 | } |
||
74 | else if (size < ctx->size) |
||
75 | user_unmap(ctx->buffer, size, ctx->size - size); /* unmap unused pages */ |
||
76 | |||
77 | ctx->width = width; |
||
78 | ctx->height = height; |
||
79 | ctx->pitch = pitch; |
||
80 | |||
81 | ctx->rc.l = 0; |
||
82 | ctx->rc.t = 0; |
||
83 | ctx->rc.r = width; |
||
84 | ctx->rc.b = height; |
||
85 | |||
86 | ctx->rcu.l = ctx->rcu.t = 0; |
||
87 | ctx->rcu.r = ctx->rcu.b = 0; |
||
88 | |||
89 | return 0; |
||
90 | }; |
||
91 | |||
92 | void clear_context(ctx_t *ctx, color_t color) |
||
93 | { |
||
94 | size_t size; |
||
95 | |||
96 | size = ctx->pitch * ctx->height; |
||
97 | |||
98 | if (size >= 1024) |
||
99 | ctx->px_rect_simd(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color); |
||
100 | else |
||
101 | px_rect_alu(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color); |
||
102 | |||
103 | ctx->rcu.l = 0; |
||
104 | ctx->rcu.t = 0; |
||
105 | ctx->rcu.r = ctx->width; |
||
106 | ctx->rcu.b = ctx->height; |
||
107 | ctx->dirty = 1; |
||
108 | }; |
||
109 | |||
110 | void show_context(ctx_t *ctx) |
||
111 | { |
||
112 | struct blit_call bc; |
||
113 | int ret; |
||
114 | |||
115 | bc.dstx = ctx->x; |
||
116 | bc.dsty = ctx->y; |
||
117 | bc.w = ctx->width; |
||
118 | bc.h = ctx->height; |
||
119 | bc.srcx = 0; |
||
120 | bc.srcy = 0; |
||
121 | bc.srcw = ctx->width; |
||
122 | bc.srch = ctx->height; |
||
123 | bc.stride = ctx->pitch; |
||
124 | bc.bitmap = ctx->buffer; |
||
125 | |||
126 | __asm__ __volatile__( |
||
127 | "int $0x40":"=a"(ret):"a"(73), "b"(0x00), |
||
128 | "c"(&bc):"memory"); |
||
129 | |||
130 | ctx->dirty = 0; |
||
131 | }; |
||
132 | |||
133 | void scroll_context(ctx_t *ctx, int dst_y, int src_y, int rows) |
||
134 | { |
||
135 | char *dst; |
||
136 | char *src; |
||
137 | |||
138 | dst = ctx->buffer + dst_y * ctx->pitch; |
||
139 | src = ctx->buffer + src_y * ctx->pitch; |
||
140 | |||
141 | __builtin_memmove(dst, src, rows * ctx->pitch); |
||
142 | ctx->dirty = 1; |
||
143 | } |
||
144 | |||
145 | static int clip_rect(const rect_t *clip, rect_t *rc) |
||
146 | { |
||
147 | if (rc->l > rc->r) |
||
148 | return 1; |
||
149 | if (rc->t > rc->b) |
||
150 | return 1; |
||
151 | |||
152 | if (rc->l < clip->l) |
||
153 | rc->l = clip->l; |
||
154 | else if (rc->l >= clip->r) |
||
155 | return 1; |
||
156 | |||
157 | if (rc->t < clip->t) |
||
158 | rc->t = clip->t; |
||
159 | else if (rc->t >= clip->b) |
||
160 | return 1; |
||
161 | |||
162 | if (rc->r < clip->l) |
||
163 | return 1; |
||
164 | else if (rc->r > clip->r) |
||
165 | rc->r = clip->r; |
||
166 | |||
167 | if (rc->b < clip->t) |
||
168 | return 1; |
||
169 | else if (rc->b > clip->b) |
||
170 | rc->b = clip->b; |
||
171 | |||
172 | if ((rc->l == rc->r) || |
||
173 | (rc->t == rc->b)) |
||
174 | return 1; |
||
175 | return 0; |
||
176 | } |
||
177 | |||
178 | int px_hline(ctx_t*ctx, int x, int y, int width, color_t color) |
||
179 | { |
||
180 | char *dst_addr; |
||
181 | |||
182 | int xr = x + width; |
||
183 | |||
184 | if(y < ctx->rc.t) |
||
185 | return 0; |
||
186 | else if(y >= ctx->rc.b) |
||
187 | return 0; |
||
188 | |||
189 | if(x < ctx->rc.l) |
||
190 | x = ctx->rc.l; |
||
191 | else if(x >= ctx->rc.r) |
||
192 | return 0; |
||
193 | |||
194 | if(xr <= ctx->rc.l) |
||
195 | return 0; |
||
196 | else if(xr > ctx->rc.r) |
||
197 | xr = ctx->rc.r; |
||
198 | |||
199 | dst_addr = ctx->buffer; |
||
200 | dst_addr+= ctx->pitch * y + x * sizeof(color_t); |
||
201 | |||
202 | __asm__ __volatile__ |
||
203 | (" cld; rep stosl\n\t" |
||
204 | :: "D" (dst_addr),"c" (xr-x), "a" (color) |
||
205 | : "flags"); |
||
206 | }; |
||
207 | |||
208 | void px_vline(ctx_t*ctx, int x, int y, int height, color_t color) |
||
209 | { |
||
210 | char *dst_addr; |
||
211 | |||
212 | int yb = y + height; |
||
213 | |||
214 | if(x < ctx->rc.l) |
||
215 | return; |
||
216 | else if(x >= ctx->rc.r) |
||
217 | return; |
||
218 | |||
219 | if(y < ctx->rc.t) |
||
220 | y = ctx->rc.t; |
||
221 | else if(y >= ctx->rc.b) |
||
222 | return; |
||
223 | |||
224 | if(yb <= ctx->rc.t) |
||
225 | return; |
||
226 | else if(yb > ctx->rc.b) |
||
227 | yb = ctx->rc.b; |
||
228 | |||
229 | dst_addr = ctx->buffer; |
||
230 | dst_addr+= ctx->pitch * y + x * sizeof(color_t); |
||
231 | |||
232 | while(y < yb) |
||
233 | { |
||
234 | color_t *t = (color_t*)dst_addr; |
||
235 | *t = color; |
||
236 | y++; |
||
237 | dst_addr+= ctx->pitch; |
||
238 | }; |
||
239 | }; |
||
240 | |||
241 | static int do_fill_rect(ctx_t *ctx, rect_t *rc, color_t color) |
||
242 | { |
||
243 | if (!clip_rect(&ctx->rc, rc)) |
||
244 | { |
||
245 | int w, h; |
||
246 | char *dst_addr; |
||
247 | |||
248 | w = rc->r - rc->l; |
||
249 | h = rc->b - rc->t; |
||
250 | |||
251 | dst_addr = ctx->buffer; |
||
252 | dst_addr += ctx->pitch * rc->t + rc->l * sizeof(color_t); |
||
253 | if (w * h >= 256) |
||
254 | ctx->px_rect_simd(dst_addr, ctx->pitch, w, h, color); |
||
255 | else |
||
256 | px_rect_alu(dst_addr, ctx->pitch, w, h, color); |
||
257 | return 1; |
||
258 | }; |
||
259 | return 0; |
||
260 | }; |
||
261 | |||
262 | void px_fill_rect(ctx_t *ctx, const rect_t *src, color_t color) |
||
263 | { |
||
264 | rect_t rc = *src; |
||
265 | int update; |
||
266 | |||
267 | update = do_fill_rect(ctx, &rc, color); |
||
268 | |||
269 | if(update) |
||
270 | { |
||
271 | if (rc.l < ctx->rcu.l) |
||
272 | ctx->rcu.l = rc.l; |
||
273 | if (rc.t < ctx->rcu.t) |
||
274 | ctx->rcu.t = rc.t; |
||
275 | if (rc.r > ctx->rcu.r) |
||
276 | ctx->rcu.r = rc.r; |
||
277 | if (rc.b > ctx->rcu.b) |
||
278 | ctx->rcu.b = rc.b; |
||
279 | ctx->dirty = 1; |
||
280 | }; |
||
281 | } |
||
282 | |||
283 | void px_fill_region(ctx_t *ctx, const rgn_t *rgn, color_t color) |
||
284 | { |
||
285 | int update = 0; |
||
286 | |||
287 | for (int i = 0; i < rgn->num_rects; i++) |
||
288 | { |
||
289 | rect_t rc = rgn->rects[i]; |
||
290 | update |= do_fill_rect(ctx, &rc, color); |
||
291 | } |
||
292 | |||
293 | if (update) |
||
294 | { |
||
295 | if (rgn->extents.l < ctx->rcu.l) |
||
296 | ctx->rcu.l = rgn->extents.l; |
||
297 | if (rgn->extents.t < ctx->rcu.t) |
||
298 | ctx->rcu.t = rgn->extents.t; |
||
299 | if (rgn->extents.r > ctx->rcu.r) |
||
300 | ctx->rcu.r = rgn->extents.r; |
||
301 | if (rgn->extents.b > ctx->rcu.b) |
||
302 | ctx->rcu.b = rgn->extents.b; |
||
303 | ctx->dirty = 1; |
||
304 | }; |
||
305 | } |
||
306 | |||
307 | void px_draw_glyph(ctx_t *ctx, const void *buffer, int pitch, const rect_t *rc, color_t color) |
||
308 | { |
||
309 | rect_t rc_dst = *rc; |
||
310 | int srcx, srcy; |
||
311 | |||
312 | if (!clip_rect(&ctx->rc, &rc_dst)) |
||
313 | { |
||
314 | int width; |
||
315 | int height; |
||
316 | unsigned char *dst = ctx->buffer; |
||
317 | const unsigned char *src = buffer; |
||
318 | |||
319 | width = rc_dst.r - rc_dst.l; |
||
320 | height = rc_dst.b - rc_dst.t; |
||
321 | |||
322 | srcx = rc_dst.l - rc->l; |
||
323 | srcy = rc_dst.t - rc->t; |
||
324 | dst += ctx->pitch * rc_dst.t + rc_dst.l * sizeof(color_t); |
||
325 | src += pitch * srcy + srcx; |
||
326 | ctx->px_glyph(dst, ctx->pitch, src, pitch, width, height, color); |
||
327 | |||
328 | if (rc_dst.l < ctx->rcu.l) |
||
329 | ctx->rcu.l = rc_dst.l; |
||
330 | if (rc_dst.t < ctx->rcu.t) |
||
331 | ctx->rcu.t = rc_dst.t; |
||
332 | if (rc_dst.r > ctx->rcu.r) |
||
333 | ctx->rcu.r = rc_dst.r; |
||
334 | if (rc_dst.b > ctx->rcu.b) |
||
335 | ctx->rcu.b = rc_dst.b; |
||
336 | |||
337 | ctx->dirty = 1; |
||
338 | }; |
||
339 | };>>>>>>>>=>>>=>>>>>>>> |