From da08bdd09dfc14f8a3374ea01a782a96e306cc8f Mon Sep 17 00:00:00 2001 From: DarkWyrm Date: Fri, 16 Apr 2004 17:52:31 +0000 Subject: [PATCH] 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 --- src/servers/app/server/DisplayDriver.cpp | 359 +++++++++++++++++++++++ src/servers/app/server/ServerApp.cpp | 5 +- src/servers/app/server/ServerApp.h | 1 + src/servers/app/server/ServerWindow.cpp | 89 +++++- 4 files changed, 451 insertions(+), 3 deletions(-) diff --git a/src/servers/app/server/DisplayDriver.cpp b/src/servers/app/server/DisplayDriver.cpp index c1e7f2e1c2..ff8d713458 100644 --- a/src/servers/app/server/DisplayDriver.cpp +++ b/src/servers/app/server/DisplayDriver.cpp @@ -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) diff --git a/src/servers/app/server/ServerApp.cpp b/src/servers/app/server/ServerApp.cpp index 2721f5774f..ee4b4686ef 100644 --- a/src/servers/app/server/ServerApp.cpp +++ b/src/servers/app/server/ServerApp.cpp @@ -574,6 +574,7 @@ void ServerApp::_DispatchMessage(PortMessage *msg) if(sbmp) { + fBitmapList->AddItem(sbmp); PortLink replylink(replyport); replylink.SetOpCode(SERVER_TRUE); replylink.Attach(sbmp->Token()); @@ -607,7 +608,7 @@ void ServerApp::_DispatchMessage(PortMessage *msg) msg->Read(&bmp_id); msg->Read(&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; iCountItems();i++) diff --git a/src/servers/app/server/ServerApp.h b/src/servers/app/server/ServerApp.h index 53249e5dff..69f2352eb2 100644 --- a/src/servers/app/server/ServerApp.h +++ b/src/servers/app/server/ServerApp.h @@ -72,6 +72,7 @@ public: void SendMessageToClient( const BMessage* msg ) const; void SetAppCursor(void); + ServerBitmap *FindBitmap(int32 token); team_id ClientTeamID(); diff --git a/src/servers/app/server/ServerWindow.cpp b/src/servers/app/server/ServerWindow.cpp index 321b7f1e51..4fb6449f32 100644 --- a/src/servers/app/server/ServerWindow.cpp +++ b/src/servers/app/server/ServerWindow.cpp @@ -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(®ion, 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(®ion, 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(®ion, 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(®ion, 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; }