source: trunk/third/libart_lgpl/art_render_svp.c @ 18256

Revision 18256, 9.8 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18255, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * art_render_gradient.c: SVP mask source for modular rendering.
3 *
4 * Libart_LGPL - library of basic graphic primitives
5 * Copyright (C) 2000 Raph Levien
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 *
22 * Authors: Raph Levien <raph@acm.org>
23 */
24
25#include "art_render_svp.h"
26#include "art_svp_render_aa.h"
27
28typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
29
30struct _ArtMaskSourceSVP {
31  ArtMaskSource super;
32  ArtRender *render;
33  const ArtSVP *svp;
34  art_u8 *dest_ptr;
35};
36
37static void
38art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
39{
40  art_free (self);
41}
42
43static int
44art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
45{
46  return 10;
47}
48
49/* The basic art_render_svp_callback function is repeated four times,
50   for all combinations of non-unit opacity and generating spans. In
51   general, I'd consider this bad style, but in this case I plead
52   a measurable performance improvement. */
53
54static void
55art_render_svp_callback (void *callback_data, int y,
56                         int start, ArtSVPRenderAAStep *steps, int n_steps)
57{
58  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
59  ArtRender *render = z->render;
60  int n_run = 0;
61  int i;
62  int running_sum = start;
63  int x0 = render->x0;
64  int x1 = render->x1;
65  int run_x0, run_x1;
66  ArtRenderMaskRun *run = render->run;
67
68  if (n_steps > 0)
69    {
70      run_x1 = steps[0].x;
71      if (run_x1 > x0 && running_sum > 0x80ff)
72        {
73          run[0].x = x0;
74          run[0].alpha = running_sum;
75          n_run++;
76        }
77
78      for (i = 0; i < n_steps - 1; i++)
79        {
80          running_sum += steps[i].delta;
81          run_x0 = run_x1;
82          run_x1 = steps[i + 1].x;
83          if (run_x1 > run_x0)
84            {
85              run[n_run].x = run_x0;
86              run[n_run].alpha = running_sum;
87              n_run++;
88            }
89        }
90      if (x1 > run_x1)
91        {
92          running_sum += steps[n_steps - 1].delta;
93          run[n_run].x = run_x1;
94          run[n_run].alpha = running_sum;
95          n_run++;
96        }
97      if (running_sum > 0x80ff)
98        {
99          run[n_run].x = x1;
100          run[n_run].alpha = 0x8000;
101          n_run++;
102        }
103    }
104  else if ((running_sum >> 16) > 0)
105    {
106      run[0].x = x0;
107      run[0].alpha = running_sum;
108      run[1].x = x1;
109      run[1].alpha = running_sum;
110      n_run = 2;
111    }
112
113  render->n_run = n_run;
114
115  art_render_invoke_callbacks (render, z->dest_ptr, y);
116
117  z->dest_ptr += render->rowstride;
118}
119
120static void
121art_render_svp_callback_span (void *callback_data, int y,
122                              int start, ArtSVPRenderAAStep *steps, int n_steps)
123{
124  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
125  ArtRender *render = z->render;
126  int n_run = 0;
127  int n_span = 0;
128  int i;
129  int running_sum = start;
130  int x0 = render->x0;
131  int x1 = render->x1;
132  int run_x0, run_x1;
133  ArtRenderMaskRun *run = render->run;
134  int *span_x = render->span_x;
135
136  if (n_steps > 0)
137    {
138      run_x1 = steps[0].x;
139      if (run_x1 > x0 && running_sum > 0x80ff)
140        {
141          run[0].x = x0;
142          run[0].alpha = running_sum;
143          n_run++;
144          span_x[0] = x0;
145          n_span++;
146        }
147
148      for (i = 0; i < n_steps - 1; i++)
149        {
150          running_sum += steps[i].delta;
151          run_x0 = run_x1;
152          run_x1 = steps[i + 1].x;
153          if (run_x1 > run_x0)
154            {
155              run[n_run].x = run_x0;
156              run[n_run].alpha = running_sum;
157              n_run++;
158              if ((n_span & 1) != (running_sum > 0x80ff))
159                span_x[n_span++] = run_x0;
160            }
161        }
162      if (x1 > run_x1)
163        {
164          running_sum += steps[n_steps - 1].delta;
165          run[n_run].x = run_x1;
166          run[n_run].alpha = running_sum;
167          n_run++;
168          if ((n_span & 1) != (running_sum > 0x80ff))
169            span_x[n_span++] = run_x1;
170        }
171      if (running_sum > 0x80ff)
172        {
173          run[n_run].x = x1;
174          run[n_run].alpha = 0x8000;
175          n_run++;
176          span_x[n_span++] = x1;
177        }
178    }
179  else if ((running_sum >> 16) > 0)
180    {
181      run[0].x = x0;
182      run[0].alpha = running_sum;
183      run[1].x = x1;
184      run[1].alpha = running_sum;
185      n_run = 2;
186      span_x[0] = x0;
187      span_x[1] = x1;
188      n_span = 2;
189    }
190
191  render->n_run = n_run;
192  render->n_span = n_span;
193
194  art_render_invoke_callbacks (render, z->dest_ptr, y);
195
196  z->dest_ptr += render->rowstride;
197}
198
199static void
200art_render_svp_callback_opacity (void *callback_data, int y,
201                                 int start, ArtSVPRenderAAStep *steps, int n_steps)
202{
203  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
204  ArtRender *render = z->render;
205  int n_run = 0;
206  int i;
207  art_u32 running_sum;
208  int x0 = render->x0;
209  int x1 = render->x1;
210  int run_x0, run_x1;
211  ArtRenderMaskRun *run = render->run;
212  art_u32 opacity = render->opacity;
213  art_u32 alpha;
214
215  running_sum = start - 0x7f80;
216
217  if (n_steps > 0)
218    {
219      run_x1 = steps[0].x;
220      alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
221      if (run_x1 > x0 && alpha > 0x80ff)
222        {
223          run[0].x = x0;
224          run[0].alpha = alpha;
225          n_run++;
226        }
227
228      for (i = 0; i < n_steps - 1; i++)
229        {
230          running_sum += steps[i].delta;
231          run_x0 = run_x1;
232          run_x1 = steps[i + 1].x;
233          if (run_x1 > run_x0)
234            {
235              run[n_run].x = run_x0;
236              alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
237              run[n_run].alpha = alpha;
238              n_run++;
239            }
240        }
241      if (x1 > run_x1)
242        {
243          running_sum += steps[n_steps - 1].delta;
244          run[n_run].x = run_x1;
245          alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
246          run[n_run].alpha = alpha;
247          n_run++;
248        }
249      if (alpha > 0x80ff)
250        {
251          run[n_run].x = x1;
252          run[n_run].alpha = 0x8000;
253          n_run++;
254        }
255    }
256  else if ((running_sum >> 16) > 0)
257    {
258      run[0].x = x0;
259      run[0].alpha = running_sum;
260      run[1].x = x1;
261      run[1].alpha = running_sum;
262      n_run = 2;
263    }
264
265  render->n_run = n_run;
266
267  art_render_invoke_callbacks (render, z->dest_ptr, y);
268
269  z->dest_ptr += render->rowstride;
270}
271
272static void
273art_render_svp_callback_opacity_span (void *callback_data, int y,
274                                      int start, ArtSVPRenderAAStep *steps, int n_steps)
275{
276  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
277  ArtRender *render = z->render;
278  int n_run = 0;
279  int n_span = 0;
280  int i;
281  art_u32 running_sum;
282  int x0 = render->x0;
283  int x1 = render->x1;
284  int run_x0, run_x1;
285  ArtRenderMaskRun *run = render->run;
286  int *span_x = render->span_x;
287  art_u32 opacity = render->opacity;
288  art_u32 alpha;
289
290  running_sum = start - 0x7f80;
291
292  if (n_steps > 0)
293    {
294      run_x1 = steps[0].x;
295      alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
296      if (run_x1 > x0 && alpha > 0x80ff)
297        {
298          run[0].x = x0;
299          run[0].alpha = alpha;
300          n_run++;
301          span_x[0] = x0;
302          n_span++;
303        }
304
305      for (i = 0; i < n_steps - 1; i++)
306        {
307          running_sum += steps[i].delta;
308          run_x0 = run_x1;
309          run_x1 = steps[i + 1].x;
310          if (run_x1 > run_x0)
311            {
312              run[n_run].x = run_x0;
313              alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
314              run[n_run].alpha = alpha;
315              n_run++;
316              if ((n_span & 1) != (alpha > 0x80ff))
317                span_x[n_span++] = run_x0;
318            }
319        }
320      if (x1 > run_x1)
321        {
322          running_sum += steps[n_steps - 1].delta;
323          run[n_run].x = run_x1;
324          alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
325          run[n_run].alpha = alpha;
326          n_run++;
327          if ((n_span & 1) != (alpha > 0x80ff))
328            span_x[n_span++] = run_x1;
329        }
330      if (alpha > 0x80ff)
331        {
332          run[n_run].x = x1;
333          run[n_run].alpha = 0x8000;
334          n_run++;
335          span_x[n_span++] = x1;
336        }
337    }
338  else if ((running_sum >> 16) > 0)
339    {
340      run[0].x = x0;
341      run[0].alpha = running_sum;
342      run[1].x = x1;
343      run[1].alpha = running_sum;
344      n_run = 2;
345      span_x[0] = x0;
346      span_x[1] = x1;
347      n_span = 2;
348    }
349
350  render->n_run = n_run;
351  render->n_span = n_span;
352
353  art_render_invoke_callbacks (render, z->dest_ptr, y);
354
355  z->dest_ptr += render->rowstride;
356}
357
358static void
359art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
360{
361  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
362  void (*callback) (void *callback_data,
363                    int y,
364                    int start,
365                    ArtSVPRenderAAStep *steps, int n_steps);
366
367  z->dest_ptr = render->pixels;
368  if (render->opacity == 0x10000)
369    {
370      if (render->need_span)
371        callback = art_render_svp_callback_span;
372      else
373        callback = art_render_svp_callback;
374    }
375  else
376    {
377      if (render->need_span)
378        callback = art_render_svp_callback_opacity_span;
379      else
380        callback = art_render_svp_callback_opacity;
381    }
382
383  art_svp_render_aa (z->svp,
384                     render->x0, render->y0,
385                     render->x1, render->y1, callback,
386                     self);
387  art_render_svp_done (&self->super, render);
388}
389
390static void
391art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
392                        art_boolean first)
393{
394  /* todo */
395  art_die ("art_render_svp non-driver mode not yet implemented.\n");
396}
397
398/**
399 * art_render_svp: Use an SVP as a render mask source.
400 * @render: Render object.
401 * @svp: SVP.
402 *
403 * Adds @svp to the render object as a mask. Note: @svp must remain
404 * allocated until art_render_invoke() is called on @render.
405 **/
406void
407art_render_svp (ArtRender *render, const ArtSVP *svp)
408{
409  ArtMaskSourceSVP *mask_source;
410  mask_source = art_new (ArtMaskSourceSVP, 1);
411
412  mask_source->super.super.render = NULL;
413  mask_source->super.super.done = art_render_svp_done;
414  mask_source->super.can_drive = art_render_svp_can_drive;
415  mask_source->super.invoke_driver = art_render_svp_invoke_driver;
416  mask_source->super.prepare = art_render_svp_prepare;
417  mask_source->render = render;
418  mask_source->svp = svp;
419
420  art_render_add_mask_source (render, &mask_source->super);
421}
Note: See TracBrowser for help on using the repository browser.