* extracted the frame buffer memcpy routine from HWInterface.cpp
into a new frame_buffer_support.h * added blend32 routine for blending a certain color with a scanline in the frame buffer * added "solid" versions of B_OP_ALPHA drawing with B_ALPHA_OVERLAY alha function (blending on top of a non-transparent background such as the frame buffer) * implemented an optimized shortcut for alpha blended FillRect() in Painter * used the "packed" version of scanlines for shapes with an outline thicker than 4 pixels (and filled shapes anyways), this improves drawing speed when there are a few anti-aliased pixels at the beginning of a scanline, then a solid fill and some anti-aliased pixels at the end of the scanline. Such as large letters. To summarize: The alpha blending in Painter seems to be about 1.45 times faster than on BeOS R5 which benefits drawing large shapes. For example, drawing a large alpha blended rounded rect is 1.28 times faster on the Haiku app_server. On the other hand, B_OP_COPY is quite tough to beat. It is currently 10 times faster on R5. But a great deal seems to be caused by the Painter rasterization algorithm itself, since commenting out the actual drawing doesn't gain any speed. The other useful experience I collected was that reading and writing and over the PCI bus in the same loop really hurts performance. It is actually faster (like 1.8 times!!) to allocate a second buffer, read from frame buffer into that, doing the blending at the same time, then writing the buffer back to the screen. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15698 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,8 +1,15 @@
|
|||||||
// HWInterface.cpp
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright 2005, Haiku, Inc. All rights reserved.
|
||||||
|
// Distributed under the terms of the MIT License.
|
||||||
|
//
|
||||||
|
// Author: Stephan Aßmus, <[email protected]>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "frame_buffer_support.h"
|
||||||
|
|
||||||
#include "RenderingBuffer.h"
|
#include "RenderingBuffer.h"
|
||||||
#include "ServerCursor.h"
|
#include "ServerCursor.h"
|
||||||
#include "SystemPalette.h"
|
#include "SystemPalette.h"
|
||||||
@@ -388,86 +395,6 @@ HWInterface::_DrawCursor(BRect area) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// gfxcpy
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
gfxcpy(uint8* dst, uint8* src, int32 numBytes)
|
|
||||||
{
|
|
||||||
uint64* d64 = (uint64*)dst;
|
|
||||||
uint64* s64 = (uint64*)src;
|
|
||||||
int32 numBytesBegin = numBytes;
|
|
||||||
while (numBytes >= 32) {
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
numBytes -= 32;
|
|
||||||
}
|
|
||||||
while (numBytes >= 16) {
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
numBytes -= 16;
|
|
||||||
}
|
|
||||||
while (numBytes >= 8) {
|
|
||||||
*d64++ = *s64++;
|
|
||||||
numBytes -= 8;
|
|
||||||
}
|
|
||||||
if (numBytes > 0) {
|
|
||||||
// update original pointers
|
|
||||||
dst += numBytesBegin - numBytes;
|
|
||||||
src += numBytesBegin - numBytes;
|
|
||||||
numBytesBegin = numBytes;
|
|
||||||
|
|
||||||
uint32* d32 = (uint32*)dst;
|
|
||||||
uint32* s32 = (uint32*)src;
|
|
||||||
while (numBytes >= 4) {
|
|
||||||
*d32++ = *s32++;
|
|
||||||
numBytes -= 4;
|
|
||||||
}
|
|
||||||
// update original pointers
|
|
||||||
dst += numBytesBegin - numBytes;
|
|
||||||
src += numBytesBegin - numBytes;
|
|
||||||
|
|
||||||
while (numBytes > 0) {
|
|
||||||
*dst++ = *src++;
|
|
||||||
numBytes--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// gfxcpy32
|
|
||||||
// * numBytes is expected to be a multiple of 4
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
gfxcpy32(uint8* dst, uint8* src, int32 numBytes)
|
|
||||||
{
|
|
||||||
uint64* d64 = (uint64*)dst;
|
|
||||||
uint64* s64 = (uint64*)src;
|
|
||||||
int32 numBytesStart = numBytes;
|
|
||||||
while (numBytes >= 32) {
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
numBytes -= 32;
|
|
||||||
}
|
|
||||||
if (numBytes >= 16) {
|
|
||||||
*d64++ = *s64++;
|
|
||||||
*d64++ = *s64++;
|
|
||||||
numBytes -= 16;
|
|
||||||
}
|
|
||||||
if (numBytes >= 8) {
|
|
||||||
*d64++ = *s64++;
|
|
||||||
numBytes -= 8;
|
|
||||||
}
|
|
||||||
if (numBytes == 4) {
|
|
||||||
uint32* d32 = (uint32*)(dst + numBytesStart - numBytes);
|
|
||||||
uint32* s32 = (uint32*)(src + numBytesStart - numBytes);
|
|
||||||
*d32 = *s32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// _CopyToFront
|
// _CopyToFront
|
||||||
//
|
//
|
||||||
// * source is assumed to be already at the right offset
|
// * source is assumed to be already at the right offset
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ AddSubDirSupportedPlatforms libbe_test ;
|
|||||||
|
|
||||||
UseLibraryHeaders agg ;
|
UseLibraryHeaders agg ;
|
||||||
UsePrivateHeaders app interface shared [ FDirName servers app ] ;
|
UsePrivateHeaders app interface shared [ FDirName servers app ] ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
|
||||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ;
|
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ;
|
||||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter font_support ] ;
|
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter font_support ] ;
|
||||||
UseFreeTypeHeaders ;
|
UseFreeTypeHeaders ;
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#include <agg_span_image_filter_rgba32.h>
|
#include <agg_span_image_filter_rgba32.h>
|
||||||
#include <agg_span_interpolator_linear.h>
|
#include <agg_span_interpolator_linear.h>
|
||||||
|
|
||||||
|
#include "frame_buffer_support.h"
|
||||||
|
|
||||||
#include "DrawState.h"
|
#include "DrawState.h"
|
||||||
|
|
||||||
#include "AGGTextRenderer.h"
|
#include "AGGTextRenderer.h"
|
||||||
@@ -63,7 +65,8 @@ Painter::Painter()
|
|||||||
fBaseRenderer(NULL),
|
fBaseRenderer(NULL),
|
||||||
fOutlineRenderer(NULL),
|
fOutlineRenderer(NULL),
|
||||||
fOutlineRasterizer(NULL),
|
fOutlineRasterizer(NULL),
|
||||||
fScanline(NULL),
|
fUnpackedScanline(NULL),
|
||||||
|
fPackedScanline(NULL),
|
||||||
fRasterizer(NULL),
|
fRasterizer(NULL),
|
||||||
fRenderer(NULL),
|
fRenderer(NULL),
|
||||||
fFontRendererSolid(NULL),
|
fFontRendererSolid(NULL),
|
||||||
@@ -76,7 +79,6 @@ Painter::Painter()
|
|||||||
fValidClipping(false),
|
fValidClipping(false),
|
||||||
fDrawingMode(B_OP_COPY),
|
fDrawingMode(B_OP_COPY),
|
||||||
fAlphaSrcMode(B_PIXEL_ALPHA),
|
fAlphaSrcMode(B_PIXEL_ALPHA),
|
||||||
// fAlphaSrcMode(B_CONSTANT_ALPHA),
|
|
||||||
fAlphaFncMode(B_ALPHA_OVERLAY),
|
fAlphaFncMode(B_ALPHA_OVERLAY),
|
||||||
fPenLocation(0.0, 0.0),
|
fPenLocation(0.0, 0.0),
|
||||||
fLineCapMode(B_BUTT_CAP),
|
fLineCapMode(B_BUTT_CAP),
|
||||||
@@ -149,7 +151,8 @@ Painter::AttachToBuffer(RenderingBuffer* buffer)
|
|||||||
// the renderer used for filling paths
|
// the renderer used for filling paths
|
||||||
fRenderer = new renderer_type(*fBaseRenderer);
|
fRenderer = new renderer_type(*fBaseRenderer);
|
||||||
fRasterizer = new rasterizer_type();
|
fRasterizer = new rasterizer_type();
|
||||||
fScanline = new scanline_type();
|
fUnpackedScanline = new scanline_unpacked_type();
|
||||||
|
fPackedScanline = new scanline_packed_type();
|
||||||
|
|
||||||
#if ALIASED_DRAWING
|
#if ALIASED_DRAWING
|
||||||
fRasterizer->gamma(agg::gamma_threshold(0.5));
|
fRasterizer->gamma(agg::gamma_threshold(0.5));
|
||||||
@@ -665,6 +668,22 @@ Painter::FillRect(const BRect& r) const
|
|||||||
return _Clipped(rect);
|
return _Clipped(rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fDrawingMode == B_OP_ALPHA && fAlphaFncMode == B_ALPHA_OVERLAY) {
|
||||||
|
pattern p = *fPatternHandler->GetR5Pattern();
|
||||||
|
if (p == B_SOLID_HIGH) {
|
||||||
|
BRect rect(a, b);
|
||||||
|
_BlendRect32(rect, fPatternHandler->HighColor().GetColor32());
|
||||||
|
return _Clipped(rect);
|
||||||
|
} else if (p == B_SOLID_LOW) {
|
||||||
|
rgb_color c = fPatternHandler->LowColor().GetColor32();
|
||||||
|
if (fAlphaSrcMode == B_CONSTANT_ALPHA)
|
||||||
|
c.alpha = fPatternHandler->HighColor().GetColor32().alpha;
|
||||||
|
BRect rect(a, b);
|
||||||
|
_BlendRect32(rect, c);
|
||||||
|
return _Clipped(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// account for stricter interpretation of coordinates in AGG
|
// account for stricter interpretation of coordinates in AGG
|
||||||
// the rectangle ranges from the top-left (.0, .0)
|
// the rectangle ranges from the top-left (.0, .0)
|
||||||
@@ -769,8 +788,11 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
|
|||||||
|
|
||||||
// make the inner rect work as a hole
|
// make the inner rect work as a hole
|
||||||
fRasterizer->filling_rule(agg::fill_even_odd);
|
fRasterizer->filling_rule(agg::fill_even_odd);
|
||||||
|
|
||||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
if (fPenSize > 4)
|
||||||
|
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer);
|
||||||
|
else
|
||||||
|
agg::render_scanlines(*fRasterizer, *fUnpackedScanline, *fRenderer);
|
||||||
|
|
||||||
// reset to default
|
// reset to default
|
||||||
fRasterizer->filling_rule(agg::fill_non_zero);
|
fRasterizer->filling_rule(agg::fill_non_zero);
|
||||||
@@ -1007,8 +1029,10 @@ Painter::_MakeEmpty()
|
|||||||
fOutlineRasterizer = NULL;
|
fOutlineRasterizer = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
delete fScanline;
|
delete fUnpackedScanline;
|
||||||
fScanline = NULL;
|
fUnpackedScanline = NULL;
|
||||||
|
delete fPackedScanline;
|
||||||
|
fPackedScanline = NULL;
|
||||||
|
|
||||||
delete fRasterizer;
|
delete fRasterizer;
|
||||||
fRasterizer = NULL;
|
fRasterizer = NULL;
|
||||||
@@ -1199,7 +1223,10 @@ Painter::_DrawEllipse(BPoint center, float xRadius, float yRadius,
|
|||||||
// make the inner ellipse work as a hole
|
// make the inner ellipse work as a hole
|
||||||
fRasterizer->filling_rule(agg::fill_even_odd);
|
fRasterizer->filling_rule(agg::fill_even_odd);
|
||||||
|
|
||||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
if (fPenSize > 4)
|
||||||
|
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer);
|
||||||
|
else
|
||||||
|
agg::render_scanlines(*fRasterizer, *fUnpackedScanline, *fRenderer);
|
||||||
|
|
||||||
// reset to default
|
// reset to default
|
||||||
fRasterizer->filling_rule(agg::fill_non_zero);
|
fRasterizer->filling_rule(agg::fill_non_zero);
|
||||||
@@ -1390,6 +1417,38 @@ Painter::_InvertRect32(BRect r) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _BlendRect32
|
||||||
|
void
|
||||||
|
Painter::_BlendRect32(const BRect& r, const rgb_color& c) const
|
||||||
|
{
|
||||||
|
if (fBuffer && fValidClipping) {
|
||||||
|
uint8* dst = fBuffer->row(0);
|
||||||
|
uint32 bpr = fBuffer->stride();
|
||||||
|
|
||||||
|
int32 left = (int32)r.left;
|
||||||
|
int32 top = (int32)r.top;
|
||||||
|
int32 right = (int32)r.right;
|
||||||
|
int32 bottom = (int32)r.bottom;
|
||||||
|
|
||||||
|
// fill rects, iterate over clipping boxes
|
||||||
|
fBaseRenderer->first_clip_box();
|
||||||
|
do {
|
||||||
|
int32 x1 = max_c(fBaseRenderer->xmin(), left);
|
||||||
|
int32 x2 = min_c(fBaseRenderer->xmax(), right);
|
||||||
|
if (x1 <= x2) {
|
||||||
|
int32 y1 = max_c(fBaseRenderer->ymin(), top);
|
||||||
|
int32 y2 = min_c(fBaseRenderer->ymax(), bottom);
|
||||||
|
|
||||||
|
uint8* offset = dst + x1 * 4 + y1 * bpr;
|
||||||
|
for (; y1 <= y2; y1++) {
|
||||||
|
blend_line32(offset, x2 - x1 + 1, c.red, c.green, c.blue, c.alpha);
|
||||||
|
offset += bpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (fBaseRenderer->next_clip_box());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
template<class VertexSource>
|
template<class VertexSource>
|
||||||
@@ -1465,7 +1524,11 @@ Painter::_StrokePath(VertexSource& path) const
|
|||||||
agg::conv_clip_polygon<agg::conv_stroke<VertexSource> > clippedPath(stroke);
|
agg::conv_clip_polygon<agg::conv_stroke<VertexSource> > clippedPath(stroke);
|
||||||
clippedPath.clip_box(-500, -500, fBuffer->width() + 500, fBuffer->height() + 500);
|
clippedPath.clip_box(-500, -500, fBuffer->width() + 500, fBuffer->height() + 500);
|
||||||
fRasterizer->add_path(clippedPath);
|
fRasterizer->add_path(clippedPath);
|
||||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
|
||||||
|
if (fPenSize > 4)
|
||||||
|
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer);
|
||||||
|
else
|
||||||
|
agg::render_scanlines(*fRasterizer, *fUnpackedScanline, *fRenderer);
|
||||||
// } else {
|
// } else {
|
||||||
// TODO: update to AGG 2.3 to get rid of the remaining problems:
|
// TODO: update to AGG 2.3 to get rid of the remaining problems:
|
||||||
// rects which are 2 or 1 pixel high/wide don't render at all.
|
// rects which are 2 or 1 pixel high/wide don't render at all.
|
||||||
@@ -1489,7 +1552,7 @@ Painter::_FillPath(VertexSource& path) const
|
|||||||
agg::conv_clip_polygon<VertexSource> clippedPath(path);
|
agg::conv_clip_polygon<VertexSource> clippedPath(path);
|
||||||
clippedPath.clip_box(-500, -500, fBuffer->width() + 500, fBuffer->height() + 500);
|
clippedPath.clip_box(-500, -500, fBuffer->width() + 500, fBuffer->height() + 500);
|
||||||
fRasterizer->add_path(clippedPath);
|
fRasterizer->add_path(clippedPath);
|
||||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer);
|
||||||
|
|
||||||
return _Clipped(_BoundingBox(clippedPath));
|
return _Clipped(_BoundingBox(clippedPath));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,9 @@ class Painter {
|
|||||||
BRect bitmapRect,
|
BRect bitmapRect,
|
||||||
BRect viewRect) const;
|
BRect viewRect) const;
|
||||||
|
|
||||||
void _InvertRect32(BRect r) const;
|
void _InvertRect32( BRect r) const;
|
||||||
|
void _BlendRect32( const BRect& r,
|
||||||
|
const rgb_color& c) const;
|
||||||
|
|
||||||
|
|
||||||
template<class VertexSource>
|
template<class VertexSource>
|
||||||
@@ -256,7 +258,8 @@ class Painter {
|
|||||||
outline_renderer_type* fOutlineRenderer;
|
outline_renderer_type* fOutlineRenderer;
|
||||||
outline_rasterizer_type* fOutlineRasterizer;
|
outline_rasterizer_type* fOutlineRasterizer;
|
||||||
|
|
||||||
scanline_type* fScanline;
|
scanline_unpacked_type* fUnpackedScanline;
|
||||||
|
scanline_packed_type* fPackedScanline;
|
||||||
rasterizer_type* fRasterizer;
|
rasterizer_type* fRasterizer;
|
||||||
renderer_type* fRenderer;
|
renderer_type* fRenderer;
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,11 @@
|
|||||||
#include <agg_rasterizer_outline.h>
|
#include <agg_rasterizer_outline.h>
|
||||||
#include <agg_rasterizer_outline_aa.h>
|
#include <agg_rasterizer_outline_aa.h>
|
||||||
#include <agg_rasterizer_scanline_aa.h>
|
#include <agg_rasterizer_scanline_aa.h>
|
||||||
//#include <agg_renderer_mclip.h>
|
|
||||||
#include <agg_renderer_outline_aa.h>
|
#include <agg_renderer_outline_aa.h>
|
||||||
#include <agg_renderer_primitives.h>
|
#include <agg_renderer_primitives.h>
|
||||||
#include <agg_renderer_scanline.h>
|
#include <agg_renderer_scanline.h>
|
||||||
#include <agg_scanline_bin.h>
|
#include <agg_scanline_bin.h>
|
||||||
//#include <agg_scanline_p.h>
|
#include <agg_scanline_p.h>
|
||||||
#include <agg_scanline_u.h>
|
#include <agg_scanline_u.h>
|
||||||
#include <agg_rendering_buffer.h>
|
#include <agg_rendering_buffer.h>
|
||||||
|
|
||||||
@@ -35,14 +34,16 @@
|
|||||||
typedef agg::renderer_primitives<renderer_base> outline_renderer_type;
|
typedef agg::renderer_primitives<renderer_base> outline_renderer_type;
|
||||||
typedef agg::rasterizer_outline<outline_renderer_type> outline_rasterizer_type;
|
typedef agg::rasterizer_outline<outline_renderer_type> outline_rasterizer_type;
|
||||||
|
|
||||||
typedef agg::scanline_bin scanline_type;
|
typedef agg::scanline_bin scanline_unpacked_type;
|
||||||
|
typedef agg::scanline_bin scanline_packed_type;
|
||||||
typedef agg::rasterizer_scanline_aa<> rasterizer_type;
|
typedef agg::rasterizer_scanline_aa<> rasterizer_type;
|
||||||
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_type;
|
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_type;
|
||||||
#else
|
#else
|
||||||
typedef agg::renderer_outline_aa<renderer_base> outline_renderer_type;
|
typedef agg::renderer_outline_aa<renderer_base> outline_renderer_type;
|
||||||
typedef agg::rasterizer_outline_aa<outline_renderer_type> outline_rasterizer_type;
|
typedef agg::rasterizer_outline_aa<outline_renderer_type> outline_rasterizer_type;
|
||||||
|
|
||||||
typedef agg::scanline_u8 scanline_type;
|
typedef agg::scanline_u8 scanline_unpacked_type;
|
||||||
|
typedef agg::scanline_p8 scanline_packed_type;
|
||||||
typedef agg::rasterizer_scanline_aa<> rasterizer_type;
|
typedef agg::rasterizer_scanline_aa<> rasterizer_type;
|
||||||
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
|
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#ifndef DRAWING_MODE_H
|
#ifndef DRAWING_MODE_H
|
||||||
#define DRAWING_MODE_H
|
#define DRAWING_MODE_H
|
||||||
|
|
||||||
|
#include "frame_buffer_support.h"
|
||||||
|
|
||||||
#include "PatternHandler.h"
|
#include "PatternHandler.h"
|
||||||
#include "PixelFormat.h"
|
#include "PixelFormat.h"
|
||||||
|
|
||||||
@@ -17,11 +19,6 @@ class PatternHandler;
|
|||||||
typedef PixelFormat::color_type color_type;
|
typedef PixelFormat::color_type color_type;
|
||||||
typedef PixelFormat::agg_buffer agg_buffer;
|
typedef PixelFormat::agg_buffer agg_buffer;
|
||||||
|
|
||||||
union pixel32 {
|
|
||||||
uint32 data32;
|
|
||||||
uint8 data8[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
// BLEND
|
// BLEND
|
||||||
//
|
//
|
||||||
// This macro assumes source alpha in range 0..255 and
|
// This macro assumes source alpha in range 0..255 and
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRAWING_MODE_ALPHA_CO_SOLID_H
|
||||||
|
#define DRAWING_MODE_ALPHA_CO_SOLID_H
|
||||||
|
|
||||||
|
#include "DrawingModeAlphaCO.h"
|
||||||
|
|
||||||
|
// blend_pixel_alpha_co_solid
|
||||||
|
void
|
||||||
|
blend_pixel_alpha_co_solid(int x, int y, const color_type& c, uint8 cover,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
uint16 alpha = pattern->HighColor().GetColor32().alpha * cover;
|
||||||
|
if (alpha == 255 * 255) {
|
||||||
|
ASSIGN_ALPHA_CO(p, c.r, c.g, c.b);
|
||||||
|
} else {
|
||||||
|
BLEND_ALPHA_CO(p, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// blend_hline_alpha_co_solid
|
||||||
|
void
|
||||||
|
blend_hline_alpha_co_solid(int x, int y, unsigned len,
|
||||||
|
const color_type& c, uint8 cover,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint16 alpha = pattern->HighColor().GetColor32().alpha * cover;
|
||||||
|
if (alpha == 255 * 255) {
|
||||||
|
// cache the color as 32bit values
|
||||||
|
uint32 v;
|
||||||
|
uint8* p8 = (uint8*)&v;
|
||||||
|
p8[0] = c.b;
|
||||||
|
p8[1] = c.g;
|
||||||
|
p8[2] = c.r;
|
||||||
|
p8[3] = 255;
|
||||||
|
// row offset as 32bit pointer
|
||||||
|
uint32* p32 = (uint32*)(buffer->row(y)) + x;
|
||||||
|
do {
|
||||||
|
*p32 = v;
|
||||||
|
p32++;
|
||||||
|
x++;
|
||||||
|
} while(--len);
|
||||||
|
} else {
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
if (len < 4) {
|
||||||
|
do {
|
||||||
|
BLEND_ALPHA_CO(p, c.r, c.g, c.b, alpha);
|
||||||
|
x++;
|
||||||
|
p += 4;
|
||||||
|
} while(--len);
|
||||||
|
} else {
|
||||||
|
alpha = alpha >> 8;
|
||||||
|
blend_line32(p, len, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// blend_solid_hspan_alpha_co_solid
|
||||||
|
void
|
||||||
|
blend_solid_hspan_alpha_co_solid(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const uint8* covers,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
uint8 hAlpha = pattern->HighColor().GetColor32().alpha;
|
||||||
|
do {
|
||||||
|
uint16 alpha = hAlpha * *covers;
|
||||||
|
if (alpha) {
|
||||||
|
if (alpha == 255 * 255) {
|
||||||
|
ASSIGN_ALPHA_CO(p, c.r, c.g, c.b);
|
||||||
|
} else {
|
||||||
|
BLEND_ALPHA_CO(p, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
covers++;
|
||||||
|
p += 4;
|
||||||
|
x++;
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// blend_solid_vspan_alpha_co_solid
|
||||||
|
void
|
||||||
|
blend_solid_vspan_alpha_co_solid(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const uint8* covers,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
uint8 hAlpha = pattern->HighColor().GetColor32().alpha;
|
||||||
|
do {
|
||||||
|
uint16 alpha = hAlpha * *covers;
|
||||||
|
if (alpha) {
|
||||||
|
if (alpha == 255 * 255) {
|
||||||
|
ASSIGN_ALPHA_CO(p, c.r, c.g, c.b);
|
||||||
|
} else {
|
||||||
|
BLEND_ALPHA_CO(p, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
covers++;
|
||||||
|
p += buffer->stride();
|
||||||
|
y++;
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DRAWING_MODE_ALPHA_CO_SOLID_H
|
||||||
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRAWING_MODE_ALPHA_PO_SOLID_H
|
||||||
|
#define DRAWING_MODE_ALPHA_PO_SOLID_H
|
||||||
|
|
||||||
|
#include "DrawingModeAlphaPO.h"
|
||||||
|
|
||||||
|
// blend_pixel_alpha_po_solid
|
||||||
|
void
|
||||||
|
blend_pixel_alpha_po_solid(int x, int y, const color_type& c, uint8 cover,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
uint16 alpha = c.a * cover;
|
||||||
|
if (alpha == 255 * 255) {
|
||||||
|
ASSIGN_ALPHA_PO(p, c.r, c.g, c.b);
|
||||||
|
} else {
|
||||||
|
BLEND_ALPHA_PO(p, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// blend_hline_alpha_po_solid
|
||||||
|
void
|
||||||
|
blend_hline_alpha_po_solid(int x, int y, unsigned len,
|
||||||
|
const color_type& c, uint8 cover,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint16 alpha = c.a * cover;
|
||||||
|
if (alpha == 255 * 255) {
|
||||||
|
// cache the color as 32bit values
|
||||||
|
uint32 v;
|
||||||
|
uint8* p8 = (uint8*)&v;
|
||||||
|
p8[0] = c.b;
|
||||||
|
p8[1] = c.g;
|
||||||
|
p8[2] = c.r;
|
||||||
|
p8[3] = 255;
|
||||||
|
// row offset as 32bit pointer
|
||||||
|
uint32* p32 = (uint32*)(buffer->row(y)) + x;
|
||||||
|
do {
|
||||||
|
*p32 = v;
|
||||||
|
p32++;
|
||||||
|
x++;
|
||||||
|
} while(--len);
|
||||||
|
} else {
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
if (len < 4) {
|
||||||
|
do {
|
||||||
|
BLEND_ALPHA_CO(p, c.r, c.g, c.b, alpha);
|
||||||
|
x++;
|
||||||
|
p += 4;
|
||||||
|
} while(--len);
|
||||||
|
} else {
|
||||||
|
alpha = alpha >> 8;
|
||||||
|
blend_line32(p, len, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// blend_solid_hspan_alpha_po_solid
|
||||||
|
void
|
||||||
|
blend_solid_hspan_alpha_po_solid(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const uint8* covers,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
do {
|
||||||
|
uint16 alpha = c.a * *covers;
|
||||||
|
if (alpha) {
|
||||||
|
if(alpha == 255 * 255) {
|
||||||
|
ASSIGN_ALPHA_PO(p, c.r, c.g, c.b);
|
||||||
|
} else {
|
||||||
|
BLEND_ALPHA_PO(p, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
covers++;
|
||||||
|
p += 4;
|
||||||
|
x++;
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// blend_solid_vspan_alpha_po_solid
|
||||||
|
void
|
||||||
|
blend_solid_vspan_alpha_po_solid(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const uint8* covers,
|
||||||
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
uint8* p = buffer->row(y) + (x << 2);
|
||||||
|
do {
|
||||||
|
uint16 alpha = c.a * *covers;
|
||||||
|
if (alpha) {
|
||||||
|
if (alpha == 255 * 255) {
|
||||||
|
ASSIGN_ALPHA_PO(p, c.r, c.g, c.b);
|
||||||
|
} else {
|
||||||
|
BLEND_ALPHA_PO(p, c.r, c.g, c.b, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
covers++;
|
||||||
|
p += buffer->stride();
|
||||||
|
y++;
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DRAWING_MODE_ALPHA_PO_SOLID_H
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ blend_hline_copy_solid(int x, int y, unsigned len,
|
|||||||
const color_type& c, uint8 cover,
|
const color_type& c, uint8 cover,
|
||||||
agg_buffer* buffer, const PatternHandler* pattern)
|
agg_buffer* buffer, const PatternHandler* pattern)
|
||||||
{
|
{
|
||||||
if(cover == 255) {
|
if (cover == 255) {
|
||||||
// cache the color as 32bit value
|
// cache the color as 32bit value
|
||||||
uint32 v;
|
uint32 v;
|
||||||
uint8* p8 = (uint8*)&v;
|
uint8* p8 = (uint8*)&v;
|
||||||
|
|||||||
@@ -17,8 +17,10 @@
|
|||||||
#include "DrawingModeAdd.h"
|
#include "DrawingModeAdd.h"
|
||||||
#include "DrawingModeAlphaCC.h"
|
#include "DrawingModeAlphaCC.h"
|
||||||
#include "DrawingModeAlphaCO.h"
|
#include "DrawingModeAlphaCO.h"
|
||||||
|
#include "DrawingModeAlphaCOSolid.h"
|
||||||
#include "DrawingModeAlphaPC.h"
|
#include "DrawingModeAlphaPC.h"
|
||||||
#include "DrawingModeAlphaPO.h"
|
#include "DrawingModeAlphaPO.h"
|
||||||
|
#include "DrawingModeAlphaPOSolid.h"
|
||||||
#include "DrawingModeBlend.h"
|
#include "DrawingModeBlend.h"
|
||||||
#include "DrawingModeCopy.h"
|
#include "DrawingModeCopy.h"
|
||||||
#include "DrawingModeCopySolid.h"
|
#include "DrawingModeCopySolid.h"
|
||||||
@@ -230,10 +232,17 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
|
|||||||
case B_OP_ALPHA:
|
case B_OP_ALPHA:
|
||||||
if (alphaSrcMode == B_CONSTANT_ALPHA) {
|
if (alphaSrcMode == B_CONSTANT_ALPHA) {
|
||||||
if (alphaFncMode == B_ALPHA_OVERLAY) {
|
if (alphaFncMode == B_ALPHA_OVERLAY) {
|
||||||
fBlendPixel = blend_pixel_alpha_co;
|
if (fPatternHandler->IsSolid()) {
|
||||||
fBlendHLine = blend_hline_alpha_co;
|
fBlendPixel = blend_pixel_alpha_co_solid;
|
||||||
fBlendSolidHSpan = blend_solid_hspan_alpha_co;
|
fBlendHLine = blend_hline_alpha_co_solid;
|
||||||
fBlendSolidVSpan = blend_solid_vspan_alpha_co;
|
fBlendSolidHSpan = blend_solid_hspan_alpha_co_solid;
|
||||||
|
fBlendSolidVSpan = blend_solid_vspan_alpha_co_solid;
|
||||||
|
} else {
|
||||||
|
fBlendPixel = blend_pixel_alpha_co;
|
||||||
|
fBlendHLine = blend_hline_alpha_co;
|
||||||
|
fBlendSolidHSpan = blend_solid_hspan_alpha_co;
|
||||||
|
fBlendSolidVSpan = blend_solid_vspan_alpha_co;
|
||||||
|
}
|
||||||
fBlendColorHSpan = blend_color_hspan_alpha_co;
|
fBlendColorHSpan = blend_color_hspan_alpha_co;
|
||||||
} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
|
||||||
fBlendPixel = blend_pixel_alpha_cc;
|
fBlendPixel = blend_pixel_alpha_cc;
|
||||||
@@ -244,10 +253,17 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
|
|||||||
}
|
}
|
||||||
} else if (alphaSrcMode == B_PIXEL_ALPHA){
|
} else if (alphaSrcMode == B_PIXEL_ALPHA){
|
||||||
if (alphaFncMode == B_ALPHA_OVERLAY) {
|
if (alphaFncMode == B_ALPHA_OVERLAY) {
|
||||||
fBlendPixel = blend_pixel_alpha_po;
|
if (fPatternHandler->IsSolid()) {
|
||||||
fBlendHLine = blend_hline_alpha_po;
|
fBlendPixel = blend_pixel_alpha_po_solid;
|
||||||
fBlendSolidHSpan = blend_solid_hspan_alpha_po;
|
fBlendHLine = blend_hline_alpha_po_solid;
|
||||||
fBlendSolidVSpan = blend_solid_vspan_alpha_po;
|
fBlendSolidHSpan = blend_solid_hspan_alpha_po_solid;
|
||||||
|
fBlendSolidVSpan = blend_solid_vspan_alpha_po_solid;
|
||||||
|
} else {
|
||||||
|
fBlendPixel = blend_pixel_alpha_po;
|
||||||
|
fBlendHLine = blend_hline_alpha_po;
|
||||||
|
fBlendSolidHSpan = blend_solid_hspan_alpha_po;
|
||||||
|
fBlendSolidVSpan = blend_solid_vspan_alpha_po;
|
||||||
|
}
|
||||||
fBlendColorHSpan = blend_color_hspan_alpha_po;
|
fBlendColorHSpan = blend_color_hspan_alpha_po;
|
||||||
} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
|
||||||
fBlendPixel = blend_pixel_alpha_pc;
|
fBlendPixel = blend_pixel_alpha_pc;
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright 2005, Haiku, Inc. All rights reserved.
|
||||||
|
// Distributed under the terms of the MIT License.
|
||||||
|
//
|
||||||
|
// Author: Stephan Aßmus, <[email protected]>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef SUPPORT_H
|
||||||
|
#define SUPPORT_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
// gfxcpy
|
||||||
|
static inline void
|
||||||
|
gfxcpy(uint8* dst, uint8* src, int32 numBytes)
|
||||||
|
{
|
||||||
|
uint64* d64 = (uint64*)dst;
|
||||||
|
uint64* s64 = (uint64*)src;
|
||||||
|
int32 numBytesBegin = numBytes;
|
||||||
|
while (numBytes >= 32) {
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
numBytes -= 32;
|
||||||
|
}
|
||||||
|
while (numBytes >= 16) {
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
numBytes -= 16;
|
||||||
|
}
|
||||||
|
while (numBytes >= 8) {
|
||||||
|
*d64++ = *s64++;
|
||||||
|
numBytes -= 8;
|
||||||
|
}
|
||||||
|
if (numBytes > 0) {
|
||||||
|
// update original pointers
|
||||||
|
dst += numBytesBegin - numBytes;
|
||||||
|
src += numBytesBegin - numBytes;
|
||||||
|
numBytesBegin = numBytes;
|
||||||
|
|
||||||
|
uint32* d32 = (uint32*)dst;
|
||||||
|
uint32* s32 = (uint32*)src;
|
||||||
|
while (numBytes >= 4) {
|
||||||
|
*d32++ = *s32++;
|
||||||
|
numBytes -= 4;
|
||||||
|
}
|
||||||
|
// update original pointers
|
||||||
|
dst += numBytesBegin - numBytes;
|
||||||
|
src += numBytesBegin - numBytes;
|
||||||
|
|
||||||
|
while (numBytes > 0) {
|
||||||
|
*dst++ = *src++;
|
||||||
|
numBytes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// gfxcpy32
|
||||||
|
// * numBytes is expected to be a multiple of 4
|
||||||
|
static inline void
|
||||||
|
gfxcpy32(uint8* dst, uint8* src, int32 numBytes)
|
||||||
|
{
|
||||||
|
uint64* d64 = (uint64*)dst;
|
||||||
|
uint64* s64 = (uint64*)src;
|
||||||
|
int32 numBytesStart = numBytes;
|
||||||
|
while (numBytes >= 32) {
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
numBytes -= 32;
|
||||||
|
}
|
||||||
|
if (numBytes >= 16) {
|
||||||
|
*d64++ = *s64++;
|
||||||
|
*d64++ = *s64++;
|
||||||
|
numBytes -= 16;
|
||||||
|
}
|
||||||
|
if (numBytes >= 8) {
|
||||||
|
*d64++ = *s64++;
|
||||||
|
numBytes -= 8;
|
||||||
|
}
|
||||||
|
if (numBytes == 4) {
|
||||||
|
uint32* d32 = (uint32*)(dst + numBytesStart - numBytes);
|
||||||
|
uint32* s32 = (uint32*)(src + numBytesStart - numBytes);
|
||||||
|
*d32 = *s32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
union pixel32 {
|
||||||
|
uint32 data32;
|
||||||
|
uint8 data8[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
// blend_line32
|
||||||
|
static inline void
|
||||||
|
blend_line32(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b, uint8 a)
|
||||||
|
{
|
||||||
|
pixel32 p;
|
||||||
|
|
||||||
|
r = (r * a) >> 8;
|
||||||
|
g = (g * a) >> 8;
|
||||||
|
b = (b * a) >> 8;
|
||||||
|
a = 255 - a;
|
||||||
|
|
||||||
|
uint8 tempBuffer[pixels * 4];
|
||||||
|
|
||||||
|
uint8* t = tempBuffer;
|
||||||
|
uint8* s = buffer;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < pixels; i++) {
|
||||||
|
p.data32 = *(uint32*)s;
|
||||||
|
|
||||||
|
t[0] = ((p.data8[0] * a) >> 8) + b;
|
||||||
|
t[1] = ((p.data8[1] * a) >> 8) + g;
|
||||||
|
t[2] = ((p.data8[2] * a) >> 8) + r;
|
||||||
|
|
||||||
|
t += 4;
|
||||||
|
s += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxcpy32(buffer, tempBuffer, pixels * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SUPPORT_H
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user