massive performance improvements. On my ancient 2xPII 350, the DisplayDriverPainter with the ViewHWInteface is pretty much usable now. It could be even better if app_server culmulated update requests more.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12180 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-03-31 10:46:02 +00:00
parent b785ce8d6f
commit a356096dba
5 changed files with 171 additions and 112 deletions

View File

@ -64,11 +64,11 @@ class Painter {
// painting functions
// lines
void StrokeLine( BPoint a,
BRect StrokeLine( BPoint a,
BPoint b,
const pattern& p = B_SOLID_HIGH);
void StrokeLine( BPoint b,
BRect StrokeLine( BPoint b,
const pattern& p = B_SOLID_HIGH);
// return true if the line was either vertical or horizontal
@ -115,14 +115,14 @@ class Painter {
// rects
void StrokeRect( const BRect& r,
BRect StrokeRect( const BRect& r,
const pattern& p = B_SOLID_HIGH) const;
// strokes a one pixel wide solid rect, no blending
void StrokeRect( const BRect& r,
const rgb_color& c) const;
void FillRect( const BRect& r,
BRect FillRect( const BRect& r,
const pattern& p = B_SOLID_HIGH) const;
// fills a solid rect with color c, no blending
@ -207,6 +207,9 @@ class Painter {
uint32 length,
const BPoint& baseLine) const;
inline BRect ClipRect(const BRect& rect) const
{ return _Clipped(rect); }
private:
void _MakeEmpty();
@ -218,6 +221,7 @@ class Painter {
float _Transform(const float& width) const;
void _Transform(BRect* rect) const;
BRect _Transform(const BRect& rect) const;
BRect _Clipped(const BRect& rect) const;
void _RebuildClipping();
@ -258,10 +262,14 @@ class Painter {
template<class VertexSource>
void _StrokePath(VertexSource& path,
BRect _BoundingBox(VertexSource& path) const;
template<class VertexSource>
BRect _StrokePath(VertexSource& path,
const pattern& p) const;
template<class VertexSource>
void _FillPath(VertexSource& path,
BRect _FillPath(VertexSource& path,
const pattern& p) const;
void _SetPattern(const pattern& p) const;

View File

@ -460,7 +460,6 @@ printf("region: %ld, rect: %ld, offset(%ld, %ld)\n", i, j, xOffset, yOffset);
if (void* rectCopy = rectList.ItemAt(i))
free(rectCopy);
}
//printf("CopyRegionList(): %lld\n", system_time() - now);
fGraphicsCard->Invalidate(updateRect);
@ -549,9 +548,9 @@ DisplayDriverPainter::FillRect(const BRect &r, const RGBColor &color)
if (Lock()) {
fPainter->SetHighColor(color);
fPainter->FillRect(r);
BRect touched = fPainter->FillRect(r);
fGraphicsCard->Invalidate(r);
fGraphicsCard->Invalidate(touched);
Unlock();
}
@ -564,9 +563,9 @@ DisplayDriverPainter::FillRect(const BRect &r, const DrawData *d)
if (Lock()) {
fPainter->SetDrawData(d);
fPainter->FillRect(r);
BRect touched = fPainter->FillRect(r);
fGraphicsCard->Invalidate(r);
fGraphicsCard->Invalidate(touched);
Unlock();
}
@ -706,10 +705,17 @@ DisplayDriverPainter::StrokeEllipse(const BRect &r, const DrawData *d)
void
DisplayDriverPainter::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color)
{
DrawData d;
d.highcolor = color;
d.draw_mode = B_OP_COPY;
StrokeLine(start, end, &d);
if (Lock()) {
if (!fPainter->StraightLine(start, end, color.GetColor32())) {
DrawData d;
d.highcolor = color;
d.draw_mode = B_OP_COPY;
StrokeLine(start, end, &d);
} else {
fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(start, end)));
}
Unlock();
}
}
// StrokeLine
@ -719,10 +725,9 @@ DisplayDriverPainter::StrokeLine(const BPoint &start, const BPoint &end, const D
if (Lock()) {
fPainter->SetDrawData(d);
fPainter->StrokeLine(start, end);
BRect touched = fPainter->StrokeLine(start, end);
BRect r(start, end);
fGraphicsCard->Invalidate(r);
fGraphicsCard->Invalidate(touched);
Unlock();
}
@ -768,7 +773,6 @@ void
DisplayDriverPainter::StrokeRect(const BRect &r, const RGBColor &color)
{
if (Lock()) {
fPainter->StrokeRect(r, color.GetColor32());
fGraphicsCard->Invalidate(BRect(r.left, r.top, r.right, r.top));
@ -787,9 +791,9 @@ DisplayDriverPainter::StrokeRect(const BRect &r, const DrawData *d)
if (Lock()) {
fPainter->SetDrawData(d);
fPainter->StrokeRect(r);
BRect touched = fPainter->StrokeRect(r);
fGraphicsCard->Invalidate(r);
fGraphicsCard->Invalidate(touched);
Unlock();
}
@ -803,13 +807,11 @@ DisplayDriverPainter::StrokeRegion(BRegion& r, const DrawData *d)
fPainter->SetDrawData(d);
BRect invalid = r.RectAt(0);
fPainter->StrokeRect(invalid);
BRect invalid = fPainter->StrokeRect(r.RectAt(0));
int32 count = r.CountRects();
for (int32 i = 1; i < count; i++) {
fPainter->StrokeRect(r.RectAt(i));
invalid = invalid | r.RectAt(i);
invalid = invalid | fPainter->StrokeRect(r.RectAt(i));
}
fGraphicsCard->Invalidate(invalid);
@ -885,6 +887,7 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length,
const BPoint &pt, DrawData *d)
{
if (Lock()) {
fPainter->SetDrawData(d);
BRect boundingBox = fPainter->DrawString(string, length, pt);

View File

@ -4,9 +4,11 @@
#include <string.h>
#include <Bitmap.h>
#include <GraphicsDefs.h>
#include <Region.h>
#include <agg_bezier_arc.h>
#include <agg_bounding_rect.h>
#include <agg_conv_curve.h>
#include <agg_conv_stroke.h>
#include <agg_ellipse.h>
@ -199,17 +201,21 @@ Painter::SetLowColor(const rgb_color& color)
void
Painter::SetScale(float scale)
{
fScale = scale;
_RebuildClipping();
_UpdateLineWidth();
if (fScale != scale) {
fScale = scale;
_RebuildClipping();
_UpdateLineWidth();
}
}
// SetPenSize
void
Painter::SetPenSize(float size)
{
fPenSize = size;
_UpdateLineWidth();
if (fPenSize != size) {
fPenSize = size;
_UpdateLineWidth();
}
}
// SetOrigin
@ -245,6 +251,8 @@ void
Painter::SetBlendingMode(source_alpha alphaSrcMode, alpha_function alphaFncMode)
{
if (fAlphaSrcMode != alphaSrcMode || fAlphaFncMode != alphaFncMode) {
fAlphaSrcMode = alphaSrcMode;
fAlphaFncMode = alphaFncMode;
if (fDrawingMode == B_OP_ALPHA && fPixelFormat) {
fPixelFormat->set_drawing_mode(DrawingModeFactory::DrawingModeFor(fDrawingMode,
fAlphaSrcMode,
@ -284,12 +292,14 @@ Painter::SetFont(const ServerFont& font)
// #pragma mark -
// StrokeLine
void
BRect
Painter::StrokeLine(BPoint a, BPoint b, const pattern& p)
{
_Transform(&a);
_Transform(&b);
BRect touched(a, b);
// first, try an optimized version
float penSize = _Transform(fPenSize);
if (penSize == 1.0 &&
@ -298,30 +308,31 @@ Painter::StrokeLine(BPoint a, BPoint b, const pattern& p)
if (pat == B_SOLID_HIGH &&
StraightLine(a, b, fPatternHandler->HighColor().GetColor32())) {
SetPenLocation(b);
return;
return _Clipped(touched);
} else if (pat == B_SOLID_LOW &&
StraightLine(a, b, fPatternHandler->LowColor().GetColor32())) {
SetPenLocation(b);
return;
return _Clipped(touched);
}
}
agg::path_storage path;
path.move_to(a.x, a.y);
path.line_to(b.x, b.y);
_StrokePath(path, p);
touched = _StrokePath(path, p);
SetPenLocation(b);
return _Clipped(touched);
}
// StrokeLine
void
BRect
Painter::StrokeLine(BPoint b, const pattern& p)
{
// TODO: move this function elsewhere
StrokeLine(fPenLocation, b);
return StrokeLine(fPenLocation, b);
}
// StraightLine
@ -486,7 +497,7 @@ Painter::FillShape(/*const */BShape* shape, const pattern& p) const
}
// StrokeRect
void
BRect
Painter::StrokeRect(const BRect& r, const pattern& p) const
{
BPoint a(r.left, r.top);
@ -501,13 +512,15 @@ Painter::StrokeRect(const BRect& r, const pattern& p) const
// TODO: fix me
// pattern p = *fPatternHandler->GetR5Pattern();
if (p == B_SOLID_HIGH) {
StrokeRect(BRect(a, b),
BRect rect(a, b);
StrokeRect(rect,
fPatternHandler->HighColor().GetColor32());
return;
return _Clipped(rect);
} else if (p == B_SOLID_LOW) {
StrokeRect(BRect(a, b),
BRect rect(a, b);
StrokeRect(rect,
fPatternHandler->LowColor().GetColor32());
return;
return _Clipped(rect);
}
}
@ -518,7 +531,7 @@ Painter::StrokeRect(const BRect& r, const pattern& p) const
path.line_to(a.x, b.y);
path.close_polygon();
_StrokePath(path, p);
return _StrokePath(path, p);
}
// StrokeRect
@ -536,7 +549,7 @@ Painter::StrokeRect(const BRect& r, const rgb_color& c) const
}
// FillRect
void
BRect
Painter::FillRect(const BRect& r, const pattern& p) const
{
BPoint a(r.left, r.top);
@ -548,11 +561,13 @@ Painter::FillRect(const BRect& r, const pattern& p) const
if (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER) {
pattern pat = *fPatternHandler->GetR5Pattern();
if (pat == B_SOLID_HIGH) {
FillRect(BRect(a, b), fPatternHandler->HighColor().GetColor32());
return;
BRect rect(a, b);
FillRect(rect, fPatternHandler->HighColor().GetColor32());
return _Clipped(rect);
} else if (pat == B_SOLID_LOW) {
FillRect(BRect(a, b), fPatternHandler->LowColor().GetColor32());
return;
BRect rect(a, b);
FillRect(rect, fPatternHandler->LowColor().GetColor32());
return _Clipped(rect);
}
}
@ -569,7 +584,7 @@ Painter::FillRect(const BRect& r, const pattern& p) const
path.line_to(a.x, b.y);
path.close_polygon();
_FillPath(path, p);
return _FillPath(path, p);
}
// FillRect
@ -770,12 +785,18 @@ Painter::DrawString(const char* utf8String, uint32 length,
transform.TranslateBy(baseLine);
transform.ScaleBy(B_ORIGIN, fScale, fScale);
transform.TranslateBy(fOrigin);
BRect clippingFrame;
if (fClippingRegion)
clippingFrame = _Transform(fClippingRegion->Frame());
bounds = fTextRenderer->RenderString(utf8String,
length,
fFontRendererSolid,
fFontRendererBin,
transform, false,
transform,
clippingFrame,
false,
&fPenLocation);
// pen location is not transformed in quite the same way,
// or transformations would add up
@ -784,9 +805,7 @@ Painter::DrawString(const char* utf8String, uint32 length,
transform.TranslateBy(baseLine);
transform.Transform(&fPenLocation);
}
if (bounds.IsValid() && fClippingRegion)
bounds = bounds & _Transform(fClippingRegion->Frame());
return bounds;
return _Clipped(bounds);
}
// DrawString
@ -885,11 +904,12 @@ Painter::BoundingBox(const char* utf8String, uint32 length,
Transformable transform;
transform.TranslateBy(baseLine);
BRect dummy;
return fTextRenderer->RenderString(utf8String,
length,
fFontRendererSolid,
fFontRendererBin,
transform, true);
transform, dummy, true);
}
// #pragma mark -
@ -1008,6 +1028,17 @@ Painter::_Transform(const BRect& rect) const
return ret;
}
// _Clipped
BRect
Painter::_Clipped(const BRect& rect) const
{
if (rect.IsValid() && fClippingRegion)
return rect & _Transform(fClippingRegion->Frame());
return rect;
}
// #pragma mark -
// _RebuildClipping
void
Painter::_RebuildClipping()
@ -1320,9 +1351,24 @@ Painter::_InvertRect32(BRect r) const
// #pragma mark -
template<class VertexSource>
BRect
Painter::_BoundingBox(VertexSource& path) const
{
double left = 0.0;
double top = 0.0;
double right = -1.0;
double bottom = -1.0;
uint32 pathID[1];
pathID[0] = 0;
agg::bounding_rect(path, pathID, 0, 1, &left, &top, &right, &bottom);
return BRect(left, top, right, bottom);
}
// _StrokePath
template<class VertexSource>
void
BRect
Painter::_StrokePath(VertexSource& path, const pattern& p) const
{
// We're now used by app_server and SetDrawData() was called prior to
@ -1345,11 +1391,13 @@ Painter::_StrokePath(VertexSource& path, const pattern& p) const
#else
fOutlineRasterizer->add_path(path);
#endif
return _Clipped(_BoundingBox(path));
}
// _FillPath
template<class VertexSource>
void
BRect
Painter::_FillPath(VertexSource& path, const pattern& p) const
{
// We're now used by app_server and SetDrawData() was called prior to
@ -1359,24 +1407,25 @@ Painter::_FillPath(VertexSource& path, const pattern& p) const
fRasterizer->add_path(path);
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
return _Clipped(_BoundingBox(path));
}
// _SetPattern
void
Painter::_SetPattern(const pattern& p) const
{
if (memcmp(&p, fPatternHandler->GetR5Pattern(), sizeof(pattern)) != 0) {
// if ((uint64)p != (uint64)*fPatternHandler->GetR5Pattern()) {
if (!(p == *fPatternHandler->GetR5Pattern())) {
printf("Painter::_SetPattern()\n");
fPatternHandler->SetPattern(p);
DrawingMode* mode = NULL;
if (memcmp(&p, &B_SOLID_HIGH, sizeof(pattern)) == 0) {
if (p == B_SOLID_HIGH) {
_SetRendererColor(fPatternHandler->HighColor().GetColor32());
mode = DrawingModeFactory::DrawingModeFor(fDrawingMode,
fAlphaSrcMode,
fAlphaFncMode,
true);
} else if (memcmp(&p, &B_SOLID_LOW, sizeof(pattern)) == 0) {
} else if (p == B_SOLID_LOW) {
_SetRendererColor(fPatternHandler->LowColor().GetColor32());
mode = DrawingModeFactory::DrawingModeFor(fDrawingMode,
fAlphaSrcMode,

View File

@ -113,8 +113,8 @@ AGGTextRenderer::Archive(BMessage* into, bool deep) const
bool
AGGTextRenderer::SetFont(const ServerFont &font)
{
// if (fFontEngine.load_font(font, agg::glyph_ren_native_gray8)) {
if (fFontEngine.load_font(font, agg::glyph_ren_outline)) {
if (fFontEngine.load_font(font, agg::glyph_ren_native_gray8)) {
// if (fFontEngine.load_font(font, agg::glyph_ren_outline)) {
return TextRenderer::SetFont(font);
} else {
fprintf(stderr, "font could not be loaded\n");
@ -189,10 +189,11 @@ AGGTextRenderer::RenderString(const char* string,
font_renderer_solid_type* solidRenderer,
font_renderer_bin_type* binRenderer,
const Transformable& transform,
BRect clippingFrame,
bool dryRun,
BPoint* nextCharPos)
{
fFontEngine.hinting(fHinted);
fFontEngine.hinting(false);
fFontEngine.height((int32)(fPtSize));
fFontEngine.width((int32)(fPtSize));
@ -237,6 +238,10 @@ AGGTextRenderer::RenderString(const char* string,
double advanceX = 0.0;
double advanceY = 0.0;
// for when we bypass the transformation pipeline
BPoint transformOffset(0.0, 0.0);
transform.Transform(&transformOffset);
for (int32 i = 0; i < dstLength / 2; i++) {
// line break
@ -264,75 +269,68 @@ AGGTextRenderer::RenderString(const char* string,
x += (fAdvanceScale - 1.0) * fFontEngine.height();
y += advanceY;
fFontManager.init_embedded_adaptors(glyph, x, y);
// calculate bounds
const agg::rect& r = glyph->bounds;
BRect glyphBounds(r.x1 + x, r.y1 + y, r.x2 + x, r.y2 + y);
double left = 0.0;
double top = 0.0;
double right = -1.0;
double bottom = -1.0;
uint32 pathID[1];
pathID[0] = 0;
// init the fontmanager and transform glyph bounds
if (glyph->data_type != agg::glyph_data_outline) {
// we cannot use the transformation pipeline
double transformedX = x + transformOffset.x;
double transformedY = y + transformOffset.y;
fFontManager.init_embedded_adaptors(glyph,
transformedX,
transformedY);
glyphBounds.OffsetBy(transformOffset);
} else {
fFontManager.init_embedded_adaptors(glyph, x, y);
glyphBounds = transform.TransformBounds(glyphBounds);
}
const agg::rect& r = fFontEngine.bounds();
switch(glyph->data_type) {
case agg::glyph_data_mono:
left = r.x1 + x;
right = r.x2 + x;
top = r.y1 + y;
bottom = r.y2 + y;
if (!dryRun) {
// render glyph and update touched area
if (!dryRun && clippingFrame.Intersects(glyphBounds)) {
switch(glyph->data_type) {
case agg::glyph_data_mono:
agg::render_scanlines(fFontManager.mono_adaptor(),
fFontManager.mono_scanline(),
*binRenderer);
}
break;
case agg::glyph_data_gray8:
left = r.x1 + x;
right = r.x2 + x;
top = r.y1 + y;
bottom = r.y2 + y;
if (!dryRun) {
break;
case agg::glyph_data_gray8:
agg::render_scanlines(fFontManager.gray8_adaptor(),
fFontManager.gray8_scanline(),
*solidRenderer);
}
break;
case agg::glyph_data_outline:
ras.reset();
if(fabs(0.0) <= 0.01) {
break;
case agg::glyph_data_outline:
ras.reset();
// NOTE: this function can be easily extended to handle
// conversion to contours, to that's why there is a lot of
// commented out code, I leave here because I think it
// will be needed again.
// if(fabs(0.0) <= 0.01) {
// For the sake of efficiency skip the
// contour converter if the weight is about zero.
//-----------------------
agg::bounding_rect(ftrans, pathID, 0, 1,
&left, &top, &right, &bottom);
if (!dryRun)
// ras.add_path(fCurves);
ras.add_path(ftrans);
} else {
if (!dryRun)
/* } else {
// ras.add_path(fContour);
ras.add_path(ftrans);
agg::bounding_rect(ftrans, pathID, 0, 1,
&left, &top, &right, &bottom);
}
if (!dryRun) {
}*/
if (fAntialias) {
agg::render_scanlines(ras, sl, *solidRenderer);
} else {
agg::render_scanlines(ras, sl, *binRenderer);
}
}
break;
default:
break;
break;
default:
break;
}
}
// calculate bounds
BRect t(left, top, right, bottom);
if (t.IsValid())
bounds = bounds.IsValid() ? bounds | t : t;
if (glyphBounds.IsValid())
bounds = bounds.IsValid() ? bounds | glyphBounds : glyphBounds;
// increment pen position
advanceX = fHinted ? floorf(glyph->advance_x + 0.5) : glyph->advance_x;

View File

@ -36,6 +36,7 @@ class AGGTextRenderer : public TextRenderer {
font_renderer_solid_type* solidRenderer,
font_renderer_bin_type* binRenderer,
const Transformable& transform,
BRect clippingFrame,
bool dryRun = false,
BPoint* nextCharPos = NULL);