|
View:
New views
7 Messages
—
Rating Filter:
Alert me
|
|
|
Rasterizer clippingHi devs,
is there way to set clipping to rasterizer in pixel based coordinates? I'm working with agg::rasterizer_scanline_aa and there is method void clip_box(double x1, double y1, double x2, double y2), if I use for example clip_box(1.0, 1.0, 4.0, 4.0) is there chance that there will be some content in scanlines outside these bounds (I mean something with 0 cover) ? Note: I'm using this rasterizer instead of other classes that's using it to render real content. Thanks for ideas - Petr ------------------------------------------------------------------------------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ Vector-agg-general mailing list Vector-agg-general@... https://lists.sourceforge.net/lists/listinfo/vector-agg-general |
|
|
Re: Rasterizer clippingPetr Kobalíček schrieb:
> is there way to set clipping to rasterizer in pixel based coordinates? > > I'm working with agg::rasterizer_scanline_aa and there is method void > clip_box(double x1, double y1, double x2, double y2), > if I use for example clip_box(1.0, 1.0, 4.0, 4.0) is there chance that > there will be some content in scanlines outside these bounds (I mean > something with 0 cover) ? AFAIK, there should not be any pixels rendered outside these bounds. > Note: I'm using this rasterizer instead of other classes that's using > it to render real content. What is the actual problem that you observe? Best regards, -Stephan ------------------------------------------------------------------------------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ Vector-agg-general mailing list Vector-agg-general@... https://lists.sourceforge.net/lists/listinfo/vector-agg-general |
|
|
Re: Rasterizer clippingHi stefan,
thanks for reply. To give you basic understanding what I'm doing I will show you snippet of code: template<int BytesPerPixel, class Rasterizer, class Scanline> static void FOG_OPTIMIZEDCALL AggRenderScanlines(RasterPainterDevice* d, Rasterizer& ras, Scanline& sl) { if (!ras.rewind_scanlines()) return; uint8_t* pBase = d->_workRaster; uint8_t* pRas; uint8_t* pCur; sysint_t stride = d->_stride; sl.reset(ras.min_x(), ras.max_x()); // TODO: Not needed ? // int extx1 = painter_d->_realRegion.extents().x1(); // int exty1 = d->_clipBox.y1(); // int extx2 = painter_d->_realRegion.extents().x2(); // int exty2 = d->_clipBox.y2(); FillSpan fillSpan = d->_fillFuncs.fillSpan; FillSpanM fillSpanM_A8 = d->_fillFuncs.fillSpanM_A8; // solid source if (1) { while (ras.sweep_scanline(sl)) { unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); sysint_t y = sl.y(); // TODO: Not needed ? // Vertical clipping to extents. // if (y < exty1) continue; // if (y >= exty2) break; pRas = pBase + y * stride; for (;;) { int x = span->x; int len = span->len; pCur = pRas + Raster::mul<int, BytesPerPixel>(x); if (len > 0) { fillSpanM_A8(pCur, &d->_source, span->covers, (unsigned)len); } else { len = -len; FOG_ASSERT(len > 0); uint32_t cover = (uint32_t)*(span->covers); if (cover == 0xFF) { fillSpan(pCur, &d->_source, len); } else { uint32_t t = Raster::bytemul(d->_source.i, cover); fillSpan(pCur, &t, len); } } if (--num_spans == 0) break; ++span; } } } } This is function that renders content using antigrain rasterizer and BlitJit jit optimized fillers/blitters. I will probably create own rasterizer class and I will try some optimizations (I have some ideas), but currently I'm finding bug in my code that causes sometimes invalid writes (I'm using valgrind to profile it) so I wondered if this can happen through clipping. Btw: the posted function is called from this: void RasterPainterDevice::_renderPath(const Path& path, bool stroke) { AggPath aggPath(path); ConvCurve curvesPath(aggPath); _ras.reset(); _ras.filling_rule(static_cast<agg::filling_rule_e>(_fillMode)); _ras.clip_box( (double)_clipBox.x1(), (double)_clipBox.y1(), (double)_clipBox.x2()-0.000001, (double)_clipBox.y2()-0.000001); // This can be a bit messy, but it's here to increase performance. We will // not calculate using transformations if they are not used. Also we add // stroke and line dash pipeline only if it's needed. This is goal of // AntiGrain to be able to setup only pipelines what are really need. if (_transformationsUsed) { if (stroke) { ConvStroke strokePath(curvesPath); ConvStrokeTransform strokeTransform( strokePath, *((agg::trans_affine *)&_transformations)); strokePath.width(_lineWidth); strokePath.line_join(static_cast<agg::line_join_e>(_lineJoin)); strokePath.line_cap(static_cast<agg::line_cap_e>(_lineCap)); strokePath.miter_limit(_miterLimit); _ras.add_path(strokeTransform); } else { ConvCurveTransform curvesTransform( curvesPath, *((agg::trans_affine *)&_transformations)); _ras.add_path(curvesTransform); } } else { if (stroke) { ConvStroke strokePath(curvesPath); strokePath.width(_lineWidth); strokePath.line_join(static_cast<agg::line_join_e>(_lineJoin)); strokePath.line_cap(static_cast<agg::line_cap_e>(_lineCap)); strokePath.miter_limit(_miterLimit); _ras.add_path(strokePath); } else { _ras.add_path(curvesPath); } } AggRenderScanlines<4, Rasterizer, ScanlineP8>(this, _ras, _slP8); } I only think that there should be way how to clip to pixel units, because windowing systems and painters usually contains pixel based clipping (my painter too) and converting this to double to convert it back to pixels in rasterizer seems to be a bit hacky :) But antigrain is nice library to play with, I really think it's powerful, because if I need I can replace any part to fit my needs:) - Petr 2009/4/30 Stephan Aßmus <superstippi@...>: > Petr Kobalíček schrieb: >> is there way to set clipping to rasterizer in pixel based coordinates? >> >> I'm working with agg::rasterizer_scanline_aa and there is method void >> clip_box(double x1, double y1, double x2, double y2), >> if I use for example clip_box(1.0, 1.0, 4.0, 4.0) is there chance that >> there will be some content in scanlines outside these bounds (I mean >> something with 0 cover) ? > > AFAIK, there should not be any pixels rendered outside these bounds. > >> Note: I'm using this rasterizer instead of other classes that's using >> it to render real content. > > What is the actual problem that you observe? > > Best regards, > -Stephan > > ------------------------------------------------------------------------------ > Register Now & Save for Velocity, the Web Performance & Operations > Conference from O'Reilly Media. Velocity features a full day of > expert-led, hands-on workshops and two days of sessions from industry > leaders in dedicated Performance & Operations tracks. Use code vel09scf > and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf > _______________________________________________ > Vector-agg-general mailing list > Vector-agg-general@... > https://lists.sourceforge.net/lists/listinfo/vector-agg-general > ------------------------------------------------------------------------------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ Vector-agg-general mailing list Vector-agg-general@... https://lists.sourceforge.net/lists/listinfo/vector-agg-general |
|
|
Re: Rasterizer clippingHi Petr,
I flipped your functions, because I need to discuss them in reverted order... :-) > void RasterPainterDevice::_renderPath(const Path& path, bool stroke) { > AggPath aggPath(path); > ConvCurve curvesPath(aggPath); > > _ras.reset(); > _ras.filling_rule(static_cast<agg::filling_rule_e>(_fillMode)); > _ras.clip_box( > (double)_clipBox.x1(), > (double)_clipBox.y1(), > (double)_clipBox.x2()-0.000001, > (double)_clipBox.y2()-0.000001); If your _clipBox is in pixel indices, ie. x1() refers to the index of the left pixel and x2() refers to the index of the right pixel, then it needs to be like this: _ras.clip_box( (double)_clipBox.x1(), (double)_clipBox.y1(), (double)_clipBox.x2() + 1, (double)_clipBox.y2() + 1); That's because the rasterizer clipping is still at a "geometry level". If your clipBox can be non-integer, but you still want pixel based clipping, then it needs to be like this: _ras.clip_box( floor(_clipBox.x1()), floor(_clipBox.y1(), ceil(_clipBox.x2()), ceil(_clipBox.y2())); In any case, you need to include the pixels at the last colum/row by rounding up or adding "+ 1" for integer based pixel indices clipping boxen. > template<int BytesPerPixel, class Rasterizer, class Scanline> static void > FOG_OPTIMIZEDCALL AggRenderScanlines(RasterPainterDevice* d, Rasterizer& > ras, Scanline& sl) > { > if (!ras.rewind_scanlines()) return; > > uint8_t* pBase = d->_workRaster; > uint8_t* pRas; > uint8_t* pCur; > sysint_t stride = d->_stride; > > sl.reset(ras.min_x(), ras.max_x()); > > // TODO: Not needed ? > // int extx1 = painter_d->_realRegion.extents().x1(); > // int exty1 = d->_clipBox.y1(); > // int extx2 = painter_d->_realRegion.extents().x2(); > // int exty2 = d->_clipBox.y2(); > > FillSpan fillSpan = d->_fillFuncs.fillSpan; > FillSpanM fillSpanM_A8 = d->_fillFuncs.fillSpanM_A8; > > // solid source > if (1) > { > while (ras.sweep_scanline(sl)) > { > unsigned num_spans = sl.num_spans(); > typename Scanline::const_iterator span = sl.begin(); > > sysint_t y = sl.y(); > > // TODO: Not needed ? > // Vertical clipping to extents. > // if (y < exty1) continue; > // if (y >= exty2) break; > > pRas = pBase + y * stride; > > for (;;) > { > int x = span->x; > int len = span->len; > > pCur = pRas + Raster::mul<int, BytesPerPixel>(x); > > if (len > 0) > { > fillSpanM_A8(pCur, &d->_source, span->covers, (unsigned)len); > } > else > { > len = -len; > FOG_ASSERT(len > 0); > > uint32_t cover = (uint32_t)*(span->covers); > if (cover == 0xFF) > { > fillSpan(pCur, &d->_source, len); > } > else > { > uint32_t t = Raster::bytemul(d->_source.i, cover); > fillSpan(pCur, &t, len); > } > } > > if (--num_spans == 0) break; > ++span; > } > } > } > } Since you are doing your own rendering, I suspect that the error is somewhere there. I am not 100% sure that if you setup rasterizer clipping, that it will never render outside that box. I think it doesn't, but it would be thinkable that it still touches outside pixels with cover of 0. But I find that highly unlikely. At least I have never seen any problems in this regard, but I also usually setup clipping on the renderer as well. In your place, I would simply add the necessary debugging facilities to make sure of this. My first suspicion would be that the out of bounds access happens somewhere in your code. Possibly the fillSpan routines. Best regards, -Stephan ------------------------------------------------------------------------------ The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com _______________________________________________ Vector-agg-general mailing list Vector-agg-general@... https://lists.sourceforge.net/lists/listinfo/vector-agg-general |
|
|
Re: Rasterizer clippingHi Stephan,
thanks for detailed reply:) I think that my code is right, because my geometry model is quite different. The x1,y1 positions are first and x2,y2 positions are last, but they are not in region. I think that RECT structure and HREGION from WinAPI should explain this: width = x2 - x1; height = y2 - y1; x2/y2 are not part of rect. Only code I'm not sure is -0.000001, I think that after your explanations it's not necessary, thank you. Currently my problem is different. Part of my thesis is multithreading and I don't know how to access scanlines from multiple threads, to be hones I don't know how AGG rasterizer exactly works. My current idea is to sweep_scanlines() from different threads, but this can't be done without locking, so my second idea is rasterizer for each thread and set different clipping for each. This will isolate and optimize access, but the path will be computed in all threads. BTW: The out of bounds problem is probably gone. I think I fixed it in BlitJit, but I'm not sure where exactly:) Cheers - Petr 2009/5/9 Stephan Assmus <superstippi@...>: > Hi Petr, > > I flipped your functions, because I need to discuss them in reverted > order... :-) > >> void RasterPainterDevice::_renderPath(const Path& path, bool stroke) { >> AggPath aggPath(path); >> ConvCurve curvesPath(aggPath); >> >> _ras.reset(); >> _ras.filling_rule(static_cast<agg::filling_rule_e>(_fillMode)); >> _ras.clip_box( >> (double)_clipBox.x1(), >> (double)_clipBox.y1(), >> (double)_clipBox.x2()-0.000001, >> (double)_clipBox.y2()-0.000001); > [...] > > If your _clipBox is in pixel indices, ie. x1() refers to the index of the > left pixel and x2() refers to the index of the right pixel, then it needs > to be like this: > > _ras.clip_box( > (double)_clipBox.x1(), > (double)_clipBox.y1(), > (double)_clipBox.x2() + 1, > (double)_clipBox.y2() + 1); > > That's because the rasterizer clipping is still at a "geometry level". If > your clipBox can be non-integer, but you still want pixel based clipping, > then it needs to be like this: > > _ras.clip_box( > floor(_clipBox.x1()), > floor(_clipBox.y1(), > ceil(_clipBox.x2()), > ceil(_clipBox.y2())); > > In any case, you need to include the pixels at the last colum/row by > rounding up or adding "+ 1" for integer based pixel indices clipping boxen. > > > >> template<int BytesPerPixel, class Rasterizer, class Scanline> static void >> FOG_OPTIMIZEDCALL AggRenderScanlines(RasterPainterDevice* d, Rasterizer& >> ras, Scanline& sl) >> { >> if (!ras.rewind_scanlines()) return; >> >> uint8_t* pBase = d->_workRaster; >> uint8_t* pRas; >> uint8_t* pCur; >> sysint_t stride = d->_stride; >> >> sl.reset(ras.min_x(), ras.max_x()); >> >> // TODO: Not needed ? >> // int extx1 = painter_d->_realRegion.extents().x1(); >> // int exty1 = d->_clipBox.y1(); >> // int extx2 = painter_d->_realRegion.extents().x2(); >> // int exty2 = d->_clipBox.y2(); >> >> FillSpan fillSpan = d->_fillFuncs.fillSpan; >> FillSpanM fillSpanM_A8 = d->_fillFuncs.fillSpanM_A8; >> >> // solid source >> if (1) >> { >> while (ras.sweep_scanline(sl)) >> { >> unsigned num_spans = sl.num_spans(); >> typename Scanline::const_iterator span = sl.begin(); >> >> sysint_t y = sl.y(); >> >> // TODO: Not needed ? >> // Vertical clipping to extents. >> // if (y < exty1) continue; >> // if (y >= exty2) break; >> >> pRas = pBase + y * stride; >> >> for (;;) >> { >> int x = span->x; >> int len = span->len; >> >> pCur = pRas + Raster::mul<int, BytesPerPixel>(x); >> >> if (len > 0) >> { >> fillSpanM_A8(pCur, &d->_source, span->covers, (unsigned)len); >> } >> else >> { >> len = -len; >> FOG_ASSERT(len > 0); >> >> uint32_t cover = (uint32_t)*(span->covers); >> if (cover == 0xFF) >> { >> fillSpan(pCur, &d->_source, len); >> } >> else >> { >> uint32_t t = Raster::bytemul(d->_source.i, cover); >> fillSpan(pCur, &t, len); >> } >> } >> >> if (--num_spans == 0) break; >> ++span; >> } >> } >> } >> } > > Since you are doing your own rendering, I suspect that the error is > somewhere there. I am not 100% sure that if you setup rasterizer clipping, > that it will never render outside that box. I think it doesn't, but it > would be thinkable that it still touches outside pixels with cover of 0. > But I find that highly unlikely. At least I have never seen any problems in > this regard, but I also usually setup clipping on the renderer as well. In > your place, I would simply add the necessary debugging facilities to make > sure of this. My first suspicion would be that the out of bounds access > happens somewhere in your code. Possibly the fillSpan routines. > > Best regards, > -Stephan > > ------------------------------------------------------------------------------ > The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your > production scanning environment may not be a perfect world - but thanks to > Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 > Series Scanner you'll get full speed at 300 dpi even with all image > processing features enabled. http://p.sf.net/sfu/kodak-com > _______________________________________________ > Vector-agg-general mailing list > Vector-agg-general@... > https://lists.sourceforge.net/lists/listinfo/vector-agg-general > ------------------------------------------------------------------------------ The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com _______________________________________________ Vector-agg-general mailing list Vector-agg-general@... https://lists.sourceforge.net/lists/listinfo/vector-agg-general |
|
|
Re: Rasterizer clippingHi Petr,
On 2009-05-09 at 12:00:45 [+0200], Petr Kobalíček <kobalicek.petr@...> wrote: > thanks for detailed reply:) I think that my code is right, because my > geometry model is quite different. The x1,y1 positions are first and > x2,y2 positions are last, but they are not in region. I think that RECT > structure and HREGION from WinAPI should explain this: > > width = x2 - x1; > height = y2 - y1; > > x2/y2 are not part of rect. Only code I'm not sure is -0.000001, I think > that after your explanations it's not necessary, thank you. Perfect, that's clear then. > Currently my problem is different. Part of my thesis is multithreading > and I don't know how to access scanlines from multiple threads, to be > hones I don't know how AGG rasterizer exactly works. My current idea is > to sweep_scanlines() from different threads, but this can't be done > without locking, so my second idea is rasterizer for each thread and set > different clipping for each. This will isolate and optimize access, but > the path will be computed in all threads. I think the best approach depends on your framework. Ie, do you render a complete scene and want this to be multi-threaded? Or do you provide a graphics API and render one path at a time or whatever the client code that uses your lib can trigger to be rendered in one call into your lib? From what I understand of what you are doing, it's the later. Then you have the following problem: There is of course a slight overhead to managing the threads, preparing jobs and triggering the threads to run. If the work to be done falls below a certain threshold, it could be beneficial to switch between single threaded rendering and multi-threaded rendering depending on estimated penalty. However, this again could pose a problem. Assume client code uses your library to render text, and enters your library for each glyph in a text run. The glyphs are small and each time you may estimate that it's better to stay single threaded, and effectively the whole glyph run is rendered in a single thread as a result. To work around this, your library could encourage "bulk rendering", where the client code schedules more data to be rendered in one API call. Anyways, in the background, I believe one "pipeline" per thread would be best, ie including rasterizer, renderer, scanline storage, everything that changes during rendering. And you need to be careful! For example, the agg::path_storage has the iterator implementation built-in, IAW iterating over a path storage is _not_ a read-only operation! So you should extract that from the actual path storage, so that you can have one instance of a path storage, but one iterator instance in each thread to iterate the same path data. Finally I would estimate that alternating scanlines based rendering should yield the best balanceing effect. As you have already your own renderer code where you iterate over scanlines, I would extend the AGG rasterizer interface to be able to provide a "skip" value, ie the increment to be used when iterating over scanlines during rasterizing. And the same for your rendering implementation. > BTW: The out of bounds problem is probably gone. I think I fixed it in > BlitJit, but I'm not sure where exactly:) Cool. Best regards, -Stephan ------------------------------------------------------------------------------ The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com _______________________________________________ Vector-agg-general mailing list Vector-agg-general@... https://lists.sourceforge.net/lists/listinfo/vector-agg-general |
|
|
Re: Rasterizer clippingHi Stephan,
your comment is really great! I think you understand what I'm are doing. Your guess about API is right (API like cairo to render one primitive per function call). I solved some problems you talked about. For example I'm not using agg::path_storage, but I'm created own Path that is not changed during iteration and with antigrain it's used through wrapper (antigrain architecture is really good in wrapping everythin). For example the path wrapper looks like this: // Wraps Fog::Path to antigrain like vertex storage. struct FOG_HIDDEN AggPath { FOG_INLINE AggPath(const Path& path) { d = path._d; rewind(0); } FOG_INLINE ~AggPath() { } FOG_INLINE void rewind(unsigned index) { vCur = d->data + index; vEnd = d->data + d->length; } FOG_INLINE unsigned vertex(double* x, double* y) { if (vCur == vEnd) return Path::CmdStop; *x = vCur->x; *y = vCur->y; uint command = vCur->cmd.cmd(); vCur++; return command; } private: const Path::Data* d; const Path::Vertex* vCur; const Path::Vertex* vEnd; }; It's nothing special, but allows to share path with multiple threads without problems and removes "changing" problem during iteration. The Fog API uses implicit sharing and copy-on-write, so I can share one path or image (or pattern, ...) in multiple threads without copying them. So this problem is solved ;-) --- Ideas... While implementing rendering across multiple threads I'm considering this idea (nothing finished, just idea). You have painter (vector context) and painter operations are not flushed directly, but each job will be queued to different thread that will prepare it for blitting. Painter currently contains method flush() and end() that must be used to finish rendering or to access attached image buffer. For example this code: // Create image and painter context Image i(320, 200, Image::FormatPRGB32); Painter p(i); // Serialize commands p.clear(Rgba(0, 0, 0, 0)); p.fillRect(Rgba(10, 10, 300, 300)); p.drawText(Point(10, 10), StubAscii8("ABCDEF"), Font()); // here some things can be drawn or not, flush() ensures it p.flush() should not paint things immediately, but can paint it from different thread while main thread is serializing work to it. I can elaborate with it, because all painting methods will serialize paint commands only into four virtual methods. BTW: How is easiest way to implement "alternating scanlines" rendering. I must go to lower layer than rasterizer ? I think that replacement for function sweep_scanlines() can do the job. For example here is sweep_scanlines(): //-------------------------------------------------------------------- template<class Scanline> bool sweep_scanline(Scanline& sl) { for(;;) { if(m_scan_y > m_outline.max_y()) return false; sl.reset_spans(); unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); int cover = 0; while(num_cells) { const cell_aa* cur_cell = *cells; int x = cur_cell->x; int area = cur_cell->area; unsigned alpha; cover += cur_cell->cover; //accumulate all cells with the same X while(--num_cells) { cur_cell = *++cells; if(cur_cell->x != x) break; area += cur_cell->area; cover += cur_cell->cover; } if(area) { alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); if(alpha) { sl.add_cell(x, alpha); } x++; } if(num_cells && cur_cell->x > x) { alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); if(alpha) { sl.add_span(x, cur_cell->x - x, alpha); } } } if(sl.num_spans()) break; ++m_scan_y; } sl.finalize(m_scan_y); ++m_scan_y; return true; } I must debug it, but it seems that this function is not modifying anything except some working variables (m_scan_y) and Scanline& sl instance that will be unique to each thread, so it seems that there is perfect way how to share rasterizer across threads without any synchronization (and i think that sharing rasterizer means better performance) So, thanks for tips and good comment. On success I will inform here about my results:) Cheers - Petr 2009/5/9 Stephan Assmus <superstippi@...>: > Hi Petr, > > On 2009-05-09 at 12:00:45 [+0200], Petr Kobalíček > <kobalicek.petr@...> wrote: >> thanks for detailed reply:) I think that my code is right, because my >> geometry model is quite different. The x1,y1 positions are first and >> x2,y2 positions are last, but they are not in region. I think that RECT >> structure and HREGION from WinAPI should explain this: >> >> width = x2 - x1; >> height = y2 - y1; >> >> x2/y2 are not part of rect. Only code I'm not sure is -0.000001, I think >> that after your explanations it's not necessary, thank you. > > Perfect, that's clear then. > >> Currently my problem is different. Part of my thesis is multithreading >> and I don't know how to access scanlines from multiple threads, to be >> hones I don't know how AGG rasterizer exactly works. My current idea is >> to sweep_scanlines() from different threads, but this can't be done >> without locking, so my second idea is rasterizer for each thread and set >> different clipping for each. This will isolate and optimize access, but >> the path will be computed in all threads. > > I think the best approach depends on your framework. Ie, do you render a > complete scene and want this to be multi-threaded? Or do you provide a > graphics API and render one path at a time or whatever the client code that > uses your lib can trigger to be rendered in one call into your lib? From > what I understand of what you are doing, it's the later. Then you have the > following problem: There is of course a slight overhead to managing the > threads, preparing jobs and triggering the threads to run. If the work to > be done falls below a certain threshold, it could be beneficial to switch > between single threaded rendering and multi-threaded rendering depending on > estimated penalty. However, this again could pose a problem. Assume client > code uses your library to render text, and enters your library for each > glyph in a text run. The glyphs are small and each time you may estimate > that it's better to stay single threaded, and effectively the whole glyph > run is rendered in a single thread as a result. To work around this, your > library could encourage "bulk rendering", where the client code schedules > more data to be rendered in one API call. > > Anyways, in the background, I believe one "pipeline" per thread would be > best, ie including rasterizer, renderer, scanline storage, everything that > changes during rendering. And you need to be careful! For example, the > agg::path_storage has the iterator implementation built-in, IAW iterating > over a path storage is _not_ a read-only operation! So you should extract > that from the actual path storage, so that you can have one instance of a > path storage, but one iterator instance in each thread to iterate the same > path data. > > Finally I would estimate that alternating scanlines based rendering should > yield the best balanceing effect. As you have already your own renderer > code where you iterate over scanlines, I would extend the AGG rasterizer > interface to be able to provide a "skip" value, ie the increment to be used > when iterating over scanlines during rasterizing. And the same for your > rendering implementation. > > >> BTW: The out of bounds problem is probably gone. I think I fixed it in >> BlitJit, but I'm not sure where exactly:) > > Cool. > > Best regards, > -Stephan > > ------------------------------------------------------------------------------ > The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your > production scanning environment may not be a perfect world - but thanks to > Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 > Series Scanner you'll get full speed at 300 dpi even with all image > processing features enabled. http://p.sf.net/sfu/kodak-com > _______________________________________________ > Vector-agg-general mailing list > Vector-agg-general@... > https://lists.sourceforge.net/lists/listinfo/vector-agg-general > ------------------------------------------------------------------------------ The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com _______________________________________________ Vector-agg-general mailing list Vector-agg-general@... https://lists.sourceforge.net/lists/listinfo/vector-agg-general |
| Free embeddable forum powered by Nabble | Forum Help |