refactoring, speedup by decoupling back to front transferes from drawing and usage of special memcpy routine, minor speedups in Painter
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12437 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
300af26345
commit
74b3612ac3
@ -523,68 +523,8 @@ AccelerantHWInterface::BackBuffer() const
|
|||||||
void
|
void
|
||||||
AccelerantHWInterface::_DrawCursor(BRect area) const
|
AccelerantHWInterface::_DrawCursor(BRect area) const
|
||||||
{
|
{
|
||||||
|
// use the default implementation for now,
|
||||||
BRect cf = _CursorFrame();
|
// until we have a hardware cursor
|
||||||
if (cf.IsValid() && area.Intersects(cf)) {
|
HWInterface::_DrawCursor(area);
|
||||||
// clip to common area
|
|
||||||
area = area & cf;
|
|
||||||
|
|
||||||
int32 left = (int32)floorf(area.left);
|
|
||||||
int32 top = (int32)floorf(area.top);
|
|
||||||
int32 right = (int32)ceilf(area.right);
|
|
||||||
int32 bottom = (int32)ceilf(area.bottom);
|
|
||||||
int32 width = right - left + 1;
|
|
||||||
int32 height = bottom - top + 1;
|
|
||||||
|
|
||||||
// make a bitmap from the backbuffer
|
|
||||||
// that has the cursor blended on top of it
|
|
||||||
|
|
||||||
// blending buffer
|
|
||||||
uint8* buffer = new uint8[width * height * 4];
|
|
||||||
|
|
||||||
// offset into back buffer
|
|
||||||
uint8* src = (uint8*)fBackBuffer->Bits();
|
|
||||||
uint32 srcBPR = fBackBuffer->BytesPerRow();
|
|
||||||
src += top * srcBPR + left * 4;
|
|
||||||
|
|
||||||
// offset into cursor bitmap
|
|
||||||
uint8* crs = (uint8*)fCursor->Bits();
|
|
||||||
uint32 crsBPR = fCursor->BytesPerRow();
|
|
||||||
// since area is clipped to cf,
|
|
||||||
// the diff between top and cf.top is always positive,
|
|
||||||
// same for diff between left and cf.left
|
|
||||||
crs += (top - (int32)floorf(cf.top)) * crsBPR
|
|
||||||
+ (left - (int32)floorf(cf.left)) * 4;
|
|
||||||
|
|
||||||
uint8* dst = buffer;
|
|
||||||
|
|
||||||
// blending
|
|
||||||
for (int32 y = top; y <= bottom; y++) {
|
|
||||||
uint8* s = src;
|
|
||||||
uint8* c = crs;
|
|
||||||
uint8* d = dst;
|
|
||||||
for (int32 x = left; x <= right; x++) {
|
|
||||||
// assume backbuffer alpha = 255
|
|
||||||
// TODO: it appears alpha in cursor us upside down
|
|
||||||
uint8 a = 255 - c[3];
|
|
||||||
d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8;
|
|
||||||
d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8;
|
|
||||||
d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8;
|
|
||||||
d[3] = 255;
|
|
||||||
s += 4;
|
|
||||||
c += 4;
|
|
||||||
d += 4;
|
|
||||||
}
|
|
||||||
crs += crsBPR;
|
|
||||||
src += srcBPR;
|
|
||||||
dst += width * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy result to front buffer
|
|
||||||
_CopyToFront(buffer, width * 4, left, top, right, bottom);
|
|
||||||
|
|
||||||
delete[] buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ HWInterface::HWInterface()
|
|||||||
fCursor(NULL),
|
fCursor(NULL),
|
||||||
fCursorVisible(true),
|
fCursorVisible(true),
|
||||||
fCursorLocation(0, 0),
|
fCursorLocation(0, 0),
|
||||||
// fUpdateExecutor(new UpdateQueue(this))
|
fUpdateExecutor(new UpdateQueue(this))
|
||||||
fUpdateExecutor(NULL)
|
// fUpdateExecutor(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,14 +105,18 @@ HWInterface::GetCursorPosition()
|
|||||||
status_t
|
status_t
|
||||||
HWInterface::Invalidate(const BRect& frame)
|
HWInterface::Invalidate(const BRect& frame)
|
||||||
{
|
{
|
||||||
return CopyBackToFront(frame);;
|
// return CopyBackToFront(frame);
|
||||||
|
|
||||||
// TODO: get this working, the locking in the DisplayDriverPainter needs
|
// TODO: the remaining problem is the immediate wake up of the
|
||||||
// to be based on locking this object, which essentially means the access
|
// thread carrying out the updates, when I enable it, there
|
||||||
// to the back buffer is locked, or more precise the access to the invalid
|
// seems to be a deadlock, but I didn't figure it out yet.
|
||||||
// region scheduled to be copied to the front buffer
|
// Maybe the same bug is there without the wakeup, only, triggered
|
||||||
// fUpdateExecutor->AddRect(frame);
|
// less often.... scarry, huh?
|
||||||
// return B_OK;
|
if (frame.IsValid()) {
|
||||||
|
fUpdateExecutor->AddRect(frame);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyBackToFront
|
// CopyBackToFront
|
||||||
@ -155,6 +159,155 @@ HWInterface::CopyBackToFront(const BRect& frame)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _DrawCursor
|
||||||
|
// * default implementation, can be used as fallback or for
|
||||||
|
// software cursor
|
||||||
|
void
|
||||||
|
HWInterface::_DrawCursor(BRect area) const
|
||||||
|
{
|
||||||
|
BRect cf = _CursorFrame();
|
||||||
|
RenderingBuffer* backBuffer = BackBuffer();
|
||||||
|
if (backBuffer && cf.IsValid() && area.Intersects(cf)) {
|
||||||
|
// clip to common area
|
||||||
|
area = area & cf;
|
||||||
|
|
||||||
|
int32 left = (int32)area.left;
|
||||||
|
int32 top = (int32)area.top;
|
||||||
|
int32 right = (int32)area.right;
|
||||||
|
int32 bottom = (int32)area.bottom;
|
||||||
|
int32 width = right - left + 1;
|
||||||
|
int32 height = bottom - top + 1;
|
||||||
|
|
||||||
|
// make a bitmap from the backbuffer
|
||||||
|
// that has the cursor blended on top of it
|
||||||
|
|
||||||
|
// blending buffer
|
||||||
|
uint8* buffer = new uint8[width * height * 4];
|
||||||
|
|
||||||
|
// offset into back buffer
|
||||||
|
uint8* src = (uint8*)backBuffer->Bits();
|
||||||
|
uint32 srcBPR = backBuffer->BytesPerRow();
|
||||||
|
src += top * srcBPR + left * 4;
|
||||||
|
|
||||||
|
// offset into cursor bitmap
|
||||||
|
uint8* crs = (uint8*)fCursor->Bits();
|
||||||
|
uint32 crsBPR = fCursor->BytesPerRow();
|
||||||
|
// since area is clipped to cf,
|
||||||
|
// the diff between top and cf.top is always positive,
|
||||||
|
// same for diff between left and cf.left
|
||||||
|
crs += (top - (int32)floorf(cf.top)) * crsBPR
|
||||||
|
+ (left - (int32)floorf(cf.left)) * 4;
|
||||||
|
|
||||||
|
uint8* dst = buffer;
|
||||||
|
|
||||||
|
// blending
|
||||||
|
for (int32 y = top; y <= bottom; y++) {
|
||||||
|
uint8* s = src;
|
||||||
|
uint8* c = crs;
|
||||||
|
uint8* d = dst;
|
||||||
|
for (int32 x = left; x <= right; x++) {
|
||||||
|
// assume backbuffer alpha = 255
|
||||||
|
// TODO: it appears alpha in cursor is upside down
|
||||||
|
uint8 a = 255 - c[3];
|
||||||
|
d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8;
|
||||||
|
d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8;
|
||||||
|
d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8;
|
||||||
|
d[3] = 255;
|
||||||
|
s += 4;
|
||||||
|
c += 4;
|
||||||
|
d += 4;
|
||||||
|
}
|
||||||
|
crs += crsBPR;
|
||||||
|
src += srcBPR;
|
||||||
|
dst += width * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy result to front buffer
|
||||||
|
_CopyToFront(buffer, width * 4, left, top, right, bottom);
|
||||||
|
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// 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
|
||||||
//
|
//
|
||||||
@ -183,7 +336,12 @@ HWInterface::_CopyToFront(uint8* src, uint32 srcBPR,
|
|||||||
dst += y * dstBPR + x * 4;
|
dst += y * dstBPR + x * 4;
|
||||||
// copy
|
// copy
|
||||||
for (; y <= bottom; y++) {
|
for (; y <= bottom; y++) {
|
||||||
|
#ifndef __HAIKU__
|
||||||
memcpy(dst, src, bytes);
|
memcpy(dst, src, bytes);
|
||||||
|
#else
|
||||||
|
// bytes is guaranteed to be multiple of 4
|
||||||
|
gfxcpy32(dst, src, bytes);
|
||||||
|
#endif // __HAIKU__
|
||||||
dst += dstBPR;
|
dst += dstBPR;
|
||||||
src += srcBPR;
|
src += srcBPR;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ class HWInterface : public BLocker {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
// implement this in derived classes
|
// implement this in derived classes
|
||||||
virtual void _DrawCursor(BRect area) const = 0;
|
virtual void _DrawCursor(BRect area) const;
|
||||||
|
|
||||||
// does the actual transfer and handles color space conversion
|
// does the actual transfer and handles color space conversion
|
||||||
void _CopyToFront(uint8* src, uint32 srcBPR,
|
void _CopyToFront(uint8* src, uint32 srcBPR,
|
||||||
|
@ -363,6 +363,11 @@ Painter::StrokeLine(BPoint b, DrawData* context)
|
|||||||
return StrokeLine(context->penlocation, b, context);
|
return StrokeLine(context->penlocation, b, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint32 data32;
|
||||||
|
int8 data[4];
|
||||||
|
} color32;
|
||||||
|
|
||||||
// StraightLine
|
// StraightLine
|
||||||
bool
|
bool
|
||||||
Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
|
Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
|
||||||
@ -376,6 +381,11 @@ Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
|
|||||||
dst += x * 4;
|
dst += x * 4;
|
||||||
int32 y1 = (int32)min_c(a.y, b.y);
|
int32 y1 = (int32)min_c(a.y, b.y);
|
||||||
int32 y2 = (int32)max_c(a.y, b.y);
|
int32 y2 = (int32)max_c(a.y, b.y);
|
||||||
|
color32 color;
|
||||||
|
color.data[0] = c.blue;
|
||||||
|
color.data[1] = c.green;
|
||||||
|
color.data[2] = c.red;
|
||||||
|
color.data[3] = 255;
|
||||||
// draw a line, iterate over clipping boxes
|
// draw a line, iterate over clipping boxes
|
||||||
fBaseRenderer->first_clip_box();
|
fBaseRenderer->first_clip_box();
|
||||||
do {
|
do {
|
||||||
@ -385,9 +395,7 @@ Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
|
|||||||
int32 end = min_c(fBaseRenderer->ymax(), y2);
|
int32 end = min_c(fBaseRenderer->ymax(), y2);
|
||||||
uint8* handle = dst + i * bpr;
|
uint8* handle = dst + i * bpr;
|
||||||
for (; i <= end; i++) {
|
for (; i <= end; i++) {
|
||||||
handle[0] = c.blue;
|
*(uint32*)handle = color.data32;
|
||||||
handle[1] = c.green;
|
|
||||||
handle[2] = c.red;
|
|
||||||
handle += bpr;
|
handle += bpr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,6 +411,11 @@ Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
|
|||||||
dst += y * bpr;
|
dst += y * bpr;
|
||||||
int32 x1 = (int32)min_c(a.x, b.x);
|
int32 x1 = (int32)min_c(a.x, b.x);
|
||||||
int32 x2 = (int32)max_c(a.x, b.x);
|
int32 x2 = (int32)max_c(a.x, b.x);
|
||||||
|
color32 color;
|
||||||
|
color.data[0] = c.blue;
|
||||||
|
color.data[1] = c.green;
|
||||||
|
color.data[2] = c.red;
|
||||||
|
color.data[3] = 255;
|
||||||
// draw a line, iterate over clipping boxes
|
// draw a line, iterate over clipping boxes
|
||||||
fBaseRenderer->first_clip_box();
|
fBaseRenderer->first_clip_box();
|
||||||
do {
|
do {
|
||||||
@ -412,9 +425,7 @@ Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
|
|||||||
int32 end = min_c(fBaseRenderer->xmax(), x2);
|
int32 end = min_c(fBaseRenderer->xmax(), x2);
|
||||||
uint8* handle = dst + i * 4;
|
uint8* handle = dst + i * 4;
|
||||||
for (; i <= end; i++) {
|
for (; i <= end; i++) {
|
||||||
handle[0] = c.blue;
|
*(uint32*)handle = color.data32;
|
||||||
handle[1] = c.green;
|
|
||||||
handle[2] = c.red;
|
|
||||||
handle += 4;
|
handle += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -626,6 +637,12 @@ Painter::FillRect(const BRect& r, const rgb_color& c) const
|
|||||||
int32 top = (int32)r.top;
|
int32 top = (int32)r.top;
|
||||||
int32 right = (int32)r.right;
|
int32 right = (int32)r.right;
|
||||||
int32 bottom = (int32)r.bottom;
|
int32 bottom = (int32)r.bottom;
|
||||||
|
// get a 32 bit pixel ready with the color
|
||||||
|
color32 color;
|
||||||
|
color.data[0] = c.blue;
|
||||||
|
color.data[1] = c.green;
|
||||||
|
color.data[2] = c.red;
|
||||||
|
color.data[3] = 255;
|
||||||
// fill rects, iterate over clipping boxes
|
// fill rects, iterate over clipping boxes
|
||||||
fBaseRenderer->first_clip_box();
|
fBaseRenderer->first_clip_box();
|
||||||
do {
|
do {
|
||||||
@ -636,12 +653,9 @@ Painter::FillRect(const BRect& r, const rgb_color& c) const
|
|||||||
int32 y2 = min_c(fBaseRenderer->ymax(), bottom);
|
int32 y2 = min_c(fBaseRenderer->ymax(), bottom);
|
||||||
uint8* offset = dst + x1 * 4;
|
uint8* offset = dst + x1 * 4;
|
||||||
for (; y1 <= y2; y1++) {
|
for (; y1 <= y2; y1++) {
|
||||||
uint8* handle = offset + y1 * bpr;
|
uint32* handle = (uint32*)(offset + y1 * bpr);
|
||||||
for (int32 x = x1; x <= x2; x++) {
|
for (int32 x = x1; x <= x2; x++) {
|
||||||
handle[0] = c.blue;
|
*handle++ = color.data32;
|
||||||
handle[1] = c.green;
|
|
||||||
handle[2] = c.red;
|
|
||||||
handle += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,15 @@ UpdateQueue::AddRect(const BRect& rect)
|
|||||||
{
|
{
|
||||||
// Lock();
|
// Lock();
|
||||||
//printf("UpdateQueue::AddRect()\n");
|
//printf("UpdateQueue::AddRect()\n");
|
||||||
|
// NOTE: The access to fUpdateRegion
|
||||||
|
// is protected by the HWInterface lock.
|
||||||
|
// When trying to access the fUpdateRegion,
|
||||||
|
// our thread will first try to lock the
|
||||||
|
// HWInterface, while on the other hand
|
||||||
|
// HWInterface will always be locked when
|
||||||
|
// it calls AddRect().
|
||||||
fUpdateRegion.Include(rect);
|
fUpdateRegion.Include(rect);
|
||||||
_Reschedule();
|
// _Reschedule();
|
||||||
// Unlock();
|
// Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +87,7 @@ UpdateQueue::_ExecuteUpdates()
|
|||||||
// execute updates
|
// execute updates
|
||||||
if (fInterface->LockWithTimeout(5000) >= B_OK) {
|
if (fInterface->LockWithTimeout(5000) >= B_OK) {
|
||||||
int32 count = fUpdateRegion.CountRects();
|
int32 count = fUpdateRegion.CountRects();
|
||||||
//printf("%ld copy dirty region\n", find_thread(NULL));
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
printf("%ld rects\n", count);
|
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
fInterface->CopyBackToFront(fUpdateRegion.RectAt(i));
|
fInterface->CopyBackToFront(fUpdateRegion.RectAt(i));
|
||||||
}
|
}
|
||||||
@ -96,7 +101,7 @@ printf("%ld rects\n", count);
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("other error: %s\n", strerror(err));
|
printf("other error: %s\n", strerror(err));
|
||||||
running = false;
|
//running = false;
|
||||||
snooze(20000);
|
snooze(20000);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -110,6 +115,11 @@ running = false;
|
|||||||
void
|
void
|
||||||
UpdateQueue::_Reschedule()
|
UpdateQueue::_Reschedule()
|
||||||
{
|
{
|
||||||
|
// TODO: _Reschedule() is supposed to cause the
|
||||||
|
// immediate wake up of the update thread, but
|
||||||
|
// the HWInterface is still locked when we get here.
|
||||||
|
// Somehow this causes a deadlock, but I don't
|
||||||
|
// see why yet...
|
||||||
if (fStatus == B_OK) {
|
if (fStatus == B_OK) {
|
||||||
release_sem(fThreadControl);
|
release_sem(fThreadControl);
|
||||||
}
|
}
|
||||||
|
@ -611,74 +611,6 @@ ViewHWInterface::CopyBackToFront(const BRect& frame)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _DrawCursor
|
|
||||||
void
|
|
||||||
ViewHWInterface::_DrawCursor(BRect area) const
|
|
||||||
{
|
|
||||||
BRect cf = _CursorFrame();
|
|
||||||
if (cf.IsValid() && area.Intersects(cf)) {
|
|
||||||
// clip to common area
|
|
||||||
area = area & cf;
|
|
||||||
|
|
||||||
int32 left = (int32)floorf(area.left);
|
|
||||||
int32 top = (int32)floorf(area.top);
|
|
||||||
int32 right = (int32)ceilf(area.right);
|
|
||||||
int32 bottom = (int32)ceilf(area.bottom);
|
|
||||||
int32 width = right - left + 1;
|
|
||||||
int32 height = bottom - top + 1;
|
|
||||||
|
|
||||||
// make a bitmap from the backbuffer
|
|
||||||
// that has the cursor blended on top of it
|
|
||||||
|
|
||||||
// blending buffer
|
|
||||||
uint8* buffer = new uint8[width * height * 4];
|
|
||||||
|
|
||||||
// offset into back buffer
|
|
||||||
uint8* src = (uint8*)fBackBuffer->Bits();
|
|
||||||
uint32 srcBPR = fBackBuffer->BytesPerRow();
|
|
||||||
src += top * srcBPR + left * 4;
|
|
||||||
|
|
||||||
// offset into cursor bitmap
|
|
||||||
uint8* crs = (uint8*)fCursor->Bits();
|
|
||||||
uint32 crsBPR = fCursor->BytesPerRow();
|
|
||||||
// since area is clipped to cf,
|
|
||||||
// the diff between top and cf.top is always positive,
|
|
||||||
// same for diff between left and cf.left
|
|
||||||
crs += (top - (int32)floorf(cf.top)) * crsBPR
|
|
||||||
+ (left - (int32)floorf(cf.left)) * 4;
|
|
||||||
|
|
||||||
uint8* dst = buffer;
|
|
||||||
|
|
||||||
// blending
|
|
||||||
for (int32 y = top; y <= bottom; y++) {
|
|
||||||
uint8* s = src;
|
|
||||||
uint8* c = crs;
|
|
||||||
uint8* d = dst;
|
|
||||||
for (int32 x = left; x <= right; x++) {
|
|
||||||
// assume backbuffer alpha = 255
|
|
||||||
// TODO: it appears alpha in cursor us upside down
|
|
||||||
uint8 a = 255 - c[3];
|
|
||||||
d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8;
|
|
||||||
d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8;
|
|
||||||
d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8;
|
|
||||||
d[3] = 255;
|
|
||||||
s += 4;
|
|
||||||
c += 4;
|
|
||||||
d += 4;
|
|
||||||
}
|
|
||||||
crs += crsBPR;
|
|
||||||
src += srcBPR;
|
|
||||||
dst += width * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy result to front buffer
|
|
||||||
_CopyToFront(buffer, width * 4, left, top, right, bottom);
|
|
||||||
|
|
||||||
delete[] buffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*void ViewHWInterface::CopyBitmap(ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d)
|
/*void ViewHWInterface::CopyBitmap(ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d)
|
||||||
{
|
{
|
||||||
|
@ -55,9 +55,6 @@ class ViewHWInterface : public HWInterface {
|
|||||||
|
|
||||||
virtual status_t CopyBackToFront(const BRect& frame);
|
virtual status_t CopyBackToFront(const BRect& frame);
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void _DrawCursor(BRect area) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BitmapBuffer* fBackBuffer;
|
BitmapBuffer* fBackBuffer;
|
||||||
BitmapBuffer* fFrontBuffer;
|
BitmapBuffer* fFrontBuffer;
|
||||||
|
Loading…
Reference in New Issue
Block a user