Checkin for Caz (without pain, even!) which adds rudimentary DrawBitmap support

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7223 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm 2004-04-16 17:52:31 +00:00
parent 8af87c1dcc
commit da08bdd09d
4 changed files with 451 additions and 3 deletions

View File

@ -38,6 +38,210 @@
// handled by the public drawing functions.
// Add clipping and make sure public functions have Lock & Unlock.
struct integer_rect
{
int32 x;
int32 y;
int32 w;
int32 h;
};
struct integer_scaling_info
{
int32 k;
};
static inline void BRect_to_integer_rect(BRect source_rect, integer_rect &dest_rect)
{
dest_rect.x = (int32)source_rect.left;
dest_rect.y = (int32)source_rect.top;
dest_rect.w = (int32)(source_rect.right - source_rect.left) + 1;
dest_rect.h = (int32)(source_rect.bottom - source_rect.top) + 1;
}
static inline integer_rect BRect_to_integer_rect(BRect source_rect)
{
integer_rect dest_rect;
dest_rect.x = (int32)source_rect.left;
dest_rect.y = (int32)source_rect.top;
dest_rect.w = (int32)(source_rect.right - source_rect.left) + 1;
dest_rect.h = (int32)(source_rect.bottom - source_rect.top) + 1;
return dest_rect;
}
class Blitter
{
public:
Blitter();
void draw_8_to_8(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_8_to_16(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_8_to_32(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_16_to_8(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_16_to_16(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_16_to_32(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_32_to_8(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_32_to_16(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_32_to_32(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void draw_none(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor) {}
void Draw(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
void Select(int32 source_bits_per_pixel, int32 dest_bits_per_pixel);
drawing_mode GetDrawMode() const { return mode; }
void SetDrawMode(drawing_mode draw_mode) { mode = draw_mode; }
private:
void (Blitter::*DrawFunc)(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor);
drawing_mode mode;
};
static Blitter blitter;
Blitter::Blitter()
{
DrawFunc = &Blitter::draw_none;
}
void Blitter::draw_8_to_8(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint8 *s = (uint8 *)src;
uint8 *d = (uint8 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_8_to_16(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint8 *s = (uint8 *)src;
uint16 *d = (uint16 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_8_to_32(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint8 *s = (uint8 *)src;
uint32 *d = (uint32 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_16_to_8(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint16 *s = (uint16 *)src;
uint8 *d = (uint8 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_16_to_16(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint16 *s = (uint16 *)src;
uint16 *d = (uint16 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_16_to_32(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint16 *s = (uint16 *)src;
uint32 *d = (uint32 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_32_to_8(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint32 *s = (uint32 *)src;
uint8 *d = (uint8 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_32_to_16(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint32 *s = (uint32 *)src;
uint16 *d = (uint16 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::draw_32_to_32(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
uint32 *s = (uint32 *)src;
uint32 *d = (uint32 *)dst;
while(width--)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
}
void Blitter::Draw(uint8 *src, uint8 *dst, int32 width, int32 xscale_position, int32 xscale_factor)
{
(this->*DrawFunc)(src, dst, width, xscale_position, xscale_factor);
}
void Blitter::Select(int32 source_bits_per_pixel, int32 dest_bits_per_pixel)
{
if(source_bits_per_pixel == 8 && dest_bits_per_pixel == 8)
DrawFunc = &Blitter::draw_8_to_8;
else if(source_bits_per_pixel == 8 && dest_bits_per_pixel == 16)
DrawFunc = &Blitter::draw_8_to_16;
else if(source_bits_per_pixel == 8 && dest_bits_per_pixel == 32)
DrawFunc = &Blitter::draw_8_to_32;
else if(source_bits_per_pixel == 16 && dest_bits_per_pixel == 16)
DrawFunc = &Blitter::draw_16_to_16;
else if(source_bits_per_pixel == 16 && dest_bits_per_pixel == 8)
DrawFunc = &Blitter::draw_16_to_8;
else if(source_bits_per_pixel == 16 && dest_bits_per_pixel == 32)
DrawFunc = &Blitter::draw_16_to_32;
else if(source_bits_per_pixel == 32 && dest_bits_per_pixel == 32)
DrawFunc = &Blitter::draw_32_to_32;
else if(source_bits_per_pixel == 32 && dest_bits_per_pixel == 16)
DrawFunc = &Blitter::draw_32_to_16;
else if(source_bits_per_pixel == 32 && dest_bits_per_pixel == 8)
DrawFunc = &Blitter::draw_32_to_8;
else
DrawFunc = &Blitter::draw_none;
}
LineCalc::LineCalc()
{
}
@ -304,14 +508,169 @@ void DisplayDriver::CopyRegion(BRegion *src, const BPoint &lefttop)
/*!
\brief Called for all BView::DrawBitmap calls
\param region Destination rects in screen coordinates
\param bmp Bitmap to be drawn. It will always be non-NULL and valid. The color
space is not guaranteed to match.
\param src Source rectangle
\param dest Destination rectangle. Source will be scaled to fit if not the same size.
\param d Data structure containing any other data necessary for the call. Always non-NULL.
*/
void DisplayDriver::DrawBitmap(BRegion *region, ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d)
{
Lock();
FBBitmap frameBuffer;
FBBitmap *bmp = &frameBuffer;
blitter.Select(32, 32);
if(!AcquireBuffer(&frameBuffer))
{
debugger("ERROR: Couldn't acquire framebuffer in DrawBitmap()\n");
return;
}
uint8 colorspace_size = (bitmap->BitsPerPixel() + 7) / 8;
int32 count = region->CountRects();
BRect bitmaprect(bitmap->Bounds());
BRect sourcerect(source);
BRect destrect(dest);
destrect.right *= d->scale;
destrect.bottom *= d->scale;
if(sourcerect.left < 0) sourcerect.left = 0;
if(sourcerect.top < 0) sourcerect.top = 0;
if(sourcerect.Width() > bitmaprect.Width())
sourcerect.right = bitmaprect.left + bitmaprect.Width();
if(sourcerect.Height() > bitmaprect.Height())
sourcerect.bottom = bitmaprect.top + bitmaprect.Height();
int32 sourcewidth = (int32)sourcerect.Width() + 1;
int32 sourceheight = (int32)sourcerect.Height() + 1;
int32 destwidth = (int32)destrect.Width() + 1;
int32 destheight = (int32)destrect.Height() + 1;
int32 xscale_factor = (sourcewidth << 16) / destwidth;
int32 yscale_factor = (sourceheight << 16) / destheight;
uint8 *src_bits = (uint8 *)bitmap->Bits();
uint8 *dest_bits = (uint8*)bmp->Bits();
int32 src_row = bitmap->BytesPerRow();
int32 dest_row = bmp->BytesPerRow();
src_bits += uint32((sourcerect.top * src_row) + (sourcerect.left * colorspace_size));
integer_rect src_integer_rectangle = BRect_to_integer_rect(sourcerect);
integer_rect dst_integer_rectangle = BRect_to_integer_rect(destrect);
int32 xscale_position = 0, yscale_position = 0, clipped_xscale_position = 0;
for(int32 c = 0; c < count; c++)
{
integer_rect screen_integer_rect = BRect_to_integer_rect(region->RectAt(c));
integer_rect src_integer_rect = src_integer_rectangle;
integer_rect dst_integer_rect = dst_integer_rectangle;
xscale_position = 0, yscale_position = 0, clipped_xscale_position = 0;
if(dst_integer_rect.x < screen_integer_rect.x)
{
dst_integer_rect.x -= screen_integer_rect.x;
dst_integer_rect.w += dst_integer_rect.x;
src_integer_rect.x -= dst_integer_rect.x;
dst_integer_rect.x = screen_integer_rect.x;
}
if(dst_integer_rect.y < screen_integer_rect.y)
{
dst_integer_rect.y -= screen_integer_rect.y;
dst_integer_rect.h += dst_integer_rect.y;
src_integer_rect.y -= dst_integer_rect.y;
dst_integer_rect.y = screen_integer_rect.y;
}
if(dst_integer_rect.w > screen_integer_rect.w)
dst_integer_rect.w = screen_integer_rect.w;
if(dst_integer_rect.h > screen_integer_rect.h)
dst_integer_rect.h = screen_integer_rect.h;
if(src_integer_rect.x > src_integer_rectangle.x)
{
int32 x_scale_pixel_multiply = src_integer_rect.x - src_integer_rectangle.x;
clipped_xscale_position = xscale_factor * x_scale_pixel_multiply;
}
if(src_integer_rect.y > src_integer_rectangle.y)
{
int32 y_scale_pixel_multiply = src_integer_rect.y - src_integer_rectangle.y;
yscale_position = yscale_factor * y_scale_pixel_multiply;
}
if(dst_integer_rect.w > 0 && dst_integer_rect.h > 0)
{
uint8 *src_data = src_bits;
uint8 *dst_data = (uint8 *)dest_bits + dst_integer_rect.y * dest_row + dst_integer_rect.x * colorspace_size;
while(dst_integer_rect.h--)
{
xscale_position = clipped_xscale_position;
uint8 *s = (uint8 *)((uint8 *)src_data + (yscale_position >> 16) * src_row);
uint8 *d = (uint8 *)((uint8 *)dst_data);
blitter.Draw(s, d, dst_integer_rect.w, xscale_position, xscale_factor);
#if 0
for(int32 x = 0; x < dst_integer_rect.w; x++)
{
*d++ = s[xscale_position >> 16];
xscale_position += xscale_factor;
}
#endif
dst_data += dest_row;
yscale_position += yscale_factor;
}
}
}
ReleaseBuffer();
Unlock();
Invalidate(destrect);
}
/*!
\brief Called for all BView::DrawBitmap calls
\param bmp Bitmap to be drawn. It will always be non-NULL and valid. The color
space is not guaranteed to match.
\param src Source rectangle
\param dest Destination rectangle. Source will be scaled to fit if not the same size.
\param d Data structure containing any other data necessary for the call. Always non-NULL.
*/
void DisplayDriver::DrawBitmap(ServerBitmap *bmp, const BRect &src, const BRect &dest, const DrawData *d)
{
Lock();
FBBitmap frameBuffer;
FBBitmap *fbmp = &frameBuffer;
if(!AcquireBuffer(&frameBuffer))
{
debugger("ERROR: Couldn't acquire framebuffer in DrawBitmap()\n");
return;
}
ReleaseBuffer();
Unlock();
Invalidate(dest);
}
void DisplayDriver::CopyRegionList(BList* list, BList* pList, int32 rCount, BRegion* clipReg)

View File

@ -574,6 +574,7 @@ void ServerApp::_DispatchMessage(PortMessage *msg)
if(sbmp)
{
fBitmapList->AddItem(sbmp);
PortLink replylink(replyport);
replylink.SetOpCode(SERVER_TRUE);
replylink.Attach<int32>(sbmp->Token());
@ -607,7 +608,7 @@ void ServerApp::_DispatchMessage(PortMessage *msg)
msg->Read<int32>(&bmp_id);
msg->Read<int32>(&replyport);
ServerBitmap *sbmp=_FindBitmap(bmp_id);
ServerBitmap *sbmp=FindBitmap(bmp_id);
if(sbmp)
{
STRACE(("ServerApp %s: Deleting Bitmap %ld\n",fSignature.String(),bmp_id));
@ -920,7 +921,7 @@ void ServerApp::_DispatchMessage(PortMessage *msg)
\param token ID token of the bitmap to find
\return The bitmap having that ID or NULL if not found
*/
ServerBitmap *ServerApp::_FindBitmap(int32 token)
ServerBitmap *ServerApp::FindBitmap(int32 token)
{
ServerBitmap *temp;
for(int32 i=0; i<fBitmapList->CountItems();i++)

View File

@ -72,6 +72,7 @@ public:
void SendMessageToClient( const BMessage* msg ) const;
void SetAppCursor(void);
ServerBitmap *FindBitmap(int32 token);
team_id ClientTeamID();

View File

@ -705,6 +705,93 @@ void ServerWindow::DispatchMessage(int32 code)
switch(code)
{
//--------- BView Messages -----------------
case AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT:
{
int32 bitmapToken;
BPoint point;
fSession->ReadInt32(&bitmapToken);
fSession->ReadPoint(&point);
ServerBitmap *sbmp = fServerApp->FindBitmap(bitmapToken);
if(sbmp)
{
BRect src, dst;
BRegion region;
src = sbmp->Bounds();
dst = cl->_parent->ConvertFromParent(cl->_full.Frame());
region = cl->_parent->ConvertFromParent(&(cl->_full));
dst.OffsetBy(point);
cl->fDriver->DrawBitmap(&region, sbmp, src, dst, cl->_layerdata);
}
break;
}
case AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT:
{
int32 bitmapToken;
BPoint point;
fSession->ReadInt32(&bitmapToken);
fSession->ReadPoint(&point);
ServerBitmap *sbmp = fServerApp->FindBitmap(bitmapToken);
if(sbmp)
{
BRect src, dst;
BRegion region;
src = sbmp->Bounds();
dst = cl->_parent->ConvertFromParent(cl->_full.Frame());
region = cl->_parent->ConvertFromParent(&(cl->_full));
dst.OffsetBy(point);
cl->fDriver->DrawBitmap(&region, sbmp, src, dst, cl->_layerdata);
}
break;
}
case AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT:
{
int32 bitmapToken;
BRect srcRect, dstRect;
fSession->ReadInt32(&bitmapToken);
fSession->ReadRect(&dstRect);
fSession->ReadRect(&srcRect);
ServerBitmap *sbmp = fServerApp->FindBitmap(bitmapToken);
if(sbmp)
{
//cl->fDriver->DrawBitmap(&region, sbmp, srcRect, dstRect, cl->_layerdata);
}
break;
}
case AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT:
{
int32 bitmapToken;
BRect srcRect, dstRect;
fSession->ReadInt32(&bitmapToken);
fSession->ReadRect(&dstRect);
fSession->ReadRect(&srcRect);
ServerBitmap *sbmp = fServerApp->FindBitmap(bitmapToken);
if(sbmp)
{
BRegion region;
BRect dst;
region = cl->_parent->ConvertFromParent(&(cl->_full));
dst = cl->_parent->ConvertFromParent(cl->_full.Frame());
dstRect.OffsetBy(dst.left, dst.top);
cl->fDriver->DrawBitmap(&region, sbmp, srcRect, dstRect, cl->_layerdata);
//printf("%d %d %d %d %d %d %d %d %d %d\n", (int)cl->_boundsLeftTop.x, (int)cl->_boundsLeftTop.y,
// (int)cl->_frame.left, (int)cl->_frame.top, (int)cl->_frame.right, (int)cl->_frame.bottom,
// (int)cl->_parent->_frame.left, (int)cl->_parent->_frame.top, (int)cl->_parent->_frame.right, (int)cl->_parent->_frame.bottom);
}
break;
}
case AS_SET_CURRENT_LAYER:
{
int32 token;
@ -2095,7 +2182,7 @@ printf("Deleting window...\n");
}
default:
{
STRACE(("ServerWindow %s: got a message to dispatch\n",win->Title()));
//STRACE(("ServerWindow %s: got a message to dispatch\n",win->Title()));
win->DispatchMessage(code);
break;
}