Implement a new RP_DRAW_BITMAP_RECTS which splits up bitmaps to be sent into the
relevant parts (i.e. removes clipped or out of bounds parts) and does local scaling in case the view rect is smaller than the bitmap rect. This avoids sending the full blown bitmaps across when they are in the end scaled to a much smaller representation. It's nowhere near perfect yet, but it's useable and improves the network traffic heaviness quite a bit depending on the application. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40014 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Haiku, Inc.
|
* Copyright 2009-2010, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "RemoteDrawingEngine.h"
|
#include "RemoteDrawingEngine.h"
|
||||||
#include "RemoteMessage.h"
|
#include "RemoteMessage.h"
|
||||||
|
|
||||||
|
#include "BitmapDrawingEngine.h"
|
||||||
#include "DrawState.h"
|
#include "DrawState.h"
|
||||||
|
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
@@ -24,7 +25,8 @@ RemoteDrawingEngine::RemoteDrawingEngine(RemoteHWInterface* interface)
|
|||||||
fToken((uint32)this), // TODO: need to redo that for 64 bit
|
fToken((uint32)this), // TODO: need to redo that for 64 bit
|
||||||
fExtendWidth(0),
|
fExtendWidth(0),
|
||||||
fCallbackAdded(false),
|
fCallbackAdded(false),
|
||||||
fResultNotify(-1)
|
fResultNotify(-1),
|
||||||
|
fBitmapDrawingEngine(NULL)
|
||||||
{
|
{
|
||||||
RemoteMessage message(NULL, fHWInterface->SendBuffer());
|
RemoteMessage message(NULL, fHWInterface->SendBuffer());
|
||||||
message.Start(RP_CREATE_STATE);
|
message.Start(RP_CREATE_STATE);
|
||||||
@@ -39,6 +41,8 @@ RemoteDrawingEngine::~RemoteDrawingEngine()
|
|||||||
message.Add(fToken);
|
message.Add(fToken);
|
||||||
message.Flush();
|
message.Flush();
|
||||||
|
|
||||||
|
delete fBitmapDrawingEngine;
|
||||||
|
|
||||||
if (fCallbackAdded)
|
if (fCallbackAdded)
|
||||||
fHWInterface->RemoveCallback(fToken);
|
fHWInterface->RemoveCallback(fToken);
|
||||||
if (fResultNotify >= 0)
|
if (fResultNotify >= 0)
|
||||||
@@ -288,47 +292,67 @@ void
|
|||||||
RemoteDrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& _bitmapRect,
|
RemoteDrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& _bitmapRect,
|
||||||
const BRect& _viewRect, uint32 options)
|
const BRect& _viewRect, uint32 options)
|
||||||
{
|
{
|
||||||
if (!fClippingRegion.Intersects(_viewRect))
|
|
||||||
return;
|
|
||||||
|
|
||||||
BRect viewRect = _viewRect;
|
|
||||||
BRect bitmapRect = _bitmapRect;
|
BRect bitmapRect = _bitmapRect;
|
||||||
if (bitmapRect.IntegerWidth() == viewRect.IntegerWidth()
|
BRect viewRect = _viewRect;
|
||||||
&& bitmapRect.IntegerHeight() == viewRect.IntegerHeight()) {
|
double xScale = (bitmapRect.Width() + 1) / (viewRect.Width() + 1);
|
||||||
// unscaled bitmap we can chop off stuff we don't need
|
double yScale = (bitmapRect.Height() + 1) / (viewRect.Height() + 1);
|
||||||
BRegion target(viewRect);
|
|
||||||
target.IntersectWith(&fClippingRegion);
|
|
||||||
BRect frame = target.Frame();
|
|
||||||
|
|
||||||
if (frame != viewRect) {
|
// constrain rect to passed bitmap bounds
|
||||||
BPoint offset = frame.LeftTop() - viewRect.LeftTop();
|
// and transfer the changes to the viewRect with the right scale
|
||||||
viewRect = frame;
|
BRect actualBitmapRect = bitmap->Bounds();
|
||||||
bitmapRect = viewRect.OffsetToCopy(bitmapRect.LeftTop() + offset);
|
if (bitmapRect.left < actualBitmapRect.left) {
|
||||||
}
|
float diff = actualBitmapRect.left - bitmapRect.left;
|
||||||
|
viewRect.left += diff / xScale;
|
||||||
|
bitmapRect.left = actualBitmapRect.left;
|
||||||
|
}
|
||||||
|
if (bitmapRect.top < actualBitmapRect.top) {
|
||||||
|
float diff = actualBitmapRect.top - bitmapRect.top;
|
||||||
|
viewRect.top += diff / yScale;
|
||||||
|
bitmapRect.top = actualBitmapRect.top;
|
||||||
|
}
|
||||||
|
if (bitmapRect.right > actualBitmapRect.right) {
|
||||||
|
float diff = bitmapRect.right - actualBitmapRect.right;
|
||||||
|
viewRect.right -= diff / xScale;
|
||||||
|
bitmapRect.right = actualBitmapRect.right;
|
||||||
|
}
|
||||||
|
if (bitmapRect.bottom > actualBitmapRect.bottom) {
|
||||||
|
float diff = bitmapRect.bottom - actualBitmapRect.bottom;
|
||||||
|
viewRect.bottom -= diff / yScale;
|
||||||
|
bitmapRect.bottom = actualBitmapRect.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
UtilityBitmap* other = NULL;
|
BRegion clippedRegion(viewRect);
|
||||||
BRect bounds = bitmap->Bounds();
|
clippedRegion.IntersectWith(&fClippingRegion);
|
||||||
BRect newBounds;
|
|
||||||
newBounds.right
|
|
||||||
= min_c(bounds.IntegerWidth(), bitmapRect.IntegerWidth());
|
|
||||||
newBounds.bottom
|
|
||||||
= min_c(bounds.IntegerHeight(), bitmapRect.IntegerHeight());
|
|
||||||
|
|
||||||
if (newBounds.IntegerWidth() < bounds.IntegerWidth()
|
int32 rectCount = clippedRegion.CountRects();
|
||||||
|| newBounds.IntegerHeight() < bounds.IntegerHeight()) {
|
if (rectCount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
other = new(std::nothrow) UtilityBitmap(newBounds, bitmap->ColorSpace(),
|
if (rectCount > 1 || (rectCount == 1 && clippedRegion.RectAt(0) != viewRect)
|
||||||
bitmap->Flags());
|
|| viewRect.Width() < bitmapRect.Width()
|
||||||
|
|| viewRect.Height() < bitmapRect.Height()) {
|
||||||
if (other != NULL && other->ImportBits(bitmap->Bits(),
|
UtilityBitmap** bitmaps;
|
||||||
bitmap->BitsLength(), bitmap->BytesPerRow(),
|
if (_ExtractBitmapRegions(*bitmap, options, bitmapRect, viewRect,
|
||||||
bitmap->ColorSpace(), bitmapRect.LeftTop(), BPoint(0, 0),
|
xScale, yScale, clippedRegion, bitmaps) != B_OK) {
|
||||||
newBounds.IntegerWidth() + 1,
|
return;
|
||||||
newBounds.IntegerHeight() + 1) == B_OK) {
|
|
||||||
bitmapRect.OffsetTo(0, 0);
|
|
||||||
bitmap = other;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemoteMessage message(NULL, fHWInterface->SendBuffer());
|
||||||
|
message.Start(RP_DRAW_BITMAP_RECTS);
|
||||||
|
message.Add(fToken);
|
||||||
|
message.Add(options);
|
||||||
|
message.Add(bitmap->ColorSpace());
|
||||||
|
message.Add(bitmap->Flags());
|
||||||
|
message.Add(rectCount);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < rectCount; i++) {
|
||||||
|
message.Add(clippedRegion.RectAt(i));
|
||||||
|
message.AddBitmap(*bitmaps[i], true);
|
||||||
|
delete bitmaps[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(bitmaps);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we may want to cache/checksum bitmaps
|
// TODO: we may want to cache/checksum bitmaps
|
||||||
@@ -339,9 +363,6 @@ RemoteDrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& _bitmapRect,
|
|||||||
message.Add(viewRect);
|
message.Add(viewRect);
|
||||||
message.Add(options);
|
message.Add(options);
|
||||||
message.AddBitmap(*bitmap);
|
message.AddBitmap(*bitmap);
|
||||||
|
|
||||||
if (other != NULL)
|
|
||||||
delete other;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -972,3 +993,120 @@ RemoteDrawingEngine::_BuildBounds(BPoint* points, int32 pointCount)
|
|||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RemoteDrawingEngine::_ExtractBitmapRegions(ServerBitmap& bitmap, uint32 options,
|
||||||
|
const BRect& bitmapRect, const BRect& viewRect, double xScale,
|
||||||
|
double yScale, BRegion& region, UtilityBitmap**& bitmaps)
|
||||||
|
{
|
||||||
|
int32 rectCount = region.CountRects();
|
||||||
|
bitmaps = (UtilityBitmap**)malloc(rectCount * sizeof(UtilityBitmap*));
|
||||||
|
if (bitmaps == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < rectCount; i++) {
|
||||||
|
BRect sourceRect = region.RectAt(i).OffsetByCopy(-viewRect.LeftTop());
|
||||||
|
int32 targetWidth = (int32)(sourceRect.Width() + 1.5);
|
||||||
|
int32 targetHeight = (int32)(sourceRect.Height() + 1.5);
|
||||||
|
|
||||||
|
if (xScale != 1.0) {
|
||||||
|
sourceRect.left = (int32)(sourceRect.left * xScale + 0.5);
|
||||||
|
sourceRect.right = (int32)(sourceRect.right * xScale + 0.5);
|
||||||
|
if (xScale < 1.0)
|
||||||
|
targetWidth = (int32)(sourceRect.Width() + 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yScale != 1.0) {
|
||||||
|
sourceRect.top = (int32)(sourceRect.top * yScale + 0.5);
|
||||||
|
sourceRect.bottom = (int32)(sourceRect.bottom * yScale + 0.5);
|
||||||
|
if (yScale < 1.0)
|
||||||
|
targetHeight = (int32)(sourceRect.Height() + 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceRect.OffsetBy(bitmapRect.LeftTop());
|
||||||
|
// sourceRect is now the part of the bitmap we want copied
|
||||||
|
|
||||||
|
status_t result = B_OK;
|
||||||
|
if ((xScale > 1.0 || yScale > 1.0)
|
||||||
|
&& (targetWidth * targetHeight < (int32)(sourceRect.Width() + 1.5)
|
||||||
|
* (int32)(sourceRect.Height() + 1.5))) {
|
||||||
|
// the target bitmap is smaller than the source, scale it locally
|
||||||
|
// and send over the smaller version to avoid sending any extra data
|
||||||
|
if (fBitmapDrawingEngine == NULL) {
|
||||||
|
fBitmapDrawingEngine
|
||||||
|
= new(std::nothrow) BitmapDrawingEngine(B_RGBA32);
|
||||||
|
if (fBitmapDrawingEngine == NULL)
|
||||||
|
result = B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == B_OK) {
|
||||||
|
result = fBitmapDrawingEngine->SetSize(targetWidth,
|
||||||
|
targetHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == B_OK) {
|
||||||
|
fBitmapDrawingEngine->SetDrawingMode(B_OP_COPY);
|
||||||
|
|
||||||
|
switch (bitmap.ColorSpace()) {
|
||||||
|
case B_RGBA32:
|
||||||
|
case B_RGBA32_BIG:
|
||||||
|
case B_RGBA15:
|
||||||
|
case B_RGBA15_BIG:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// we need to clear the background if there may be
|
||||||
|
// transparency through transparent magic (we use
|
||||||
|
// B_OP_COPY when we draw alpha enabled bitmaps, so we
|
||||||
|
// don't need to clear there)
|
||||||
|
// TODO: this is not actually correct, as we're going to
|
||||||
|
// loose the transparency with the conversion to the
|
||||||
|
// original non-alpha colorspace happening in
|
||||||
|
// ExportToBitmap
|
||||||
|
rgb_color background = { 0, 0, 0, 0 };
|
||||||
|
fBitmapDrawingEngine->FillRect(
|
||||||
|
BRect(0, 0, targetWidth - 1, targetHeight -1),
|
||||||
|
background);
|
||||||
|
fBitmapDrawingEngine->SetDrawingMode(B_OP_OVER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fBitmapDrawingEngine->DrawBitmap(&bitmap, sourceRect,
|
||||||
|
BRect(0, 0, targetWidth - 1, targetHeight - 1), options);
|
||||||
|
bitmaps[i] = fBitmapDrawingEngine->ExportToBitmap(targetWidth,
|
||||||
|
targetHeight, bitmap.ColorSpace());
|
||||||
|
if (bitmaps[i] == NULL)
|
||||||
|
result = B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// source is smaller or equal target, extract the relevant rects
|
||||||
|
// directly without any scaling and conversion
|
||||||
|
targetWidth = (int32)(sourceRect.Width() + 1.5);
|
||||||
|
targetHeight = (int32)(sourceRect.Height() + 1.5);
|
||||||
|
|
||||||
|
bitmaps[i] = new(std::nothrow) UtilityBitmap(
|
||||||
|
BRect(0, 0, targetWidth - 1, targetHeight - 1),
|
||||||
|
bitmap.ColorSpace(), 0);
|
||||||
|
if (bitmaps[i] == NULL)
|
||||||
|
result = B_NO_MEMORY;
|
||||||
|
|
||||||
|
result = bitmaps[i]->ImportBits(bitmap.Bits(), bitmap.BitsLength(),
|
||||||
|
bitmap.BytesPerRow(), bitmap.ColorSpace(), sourceRect.LeftTop(),
|
||||||
|
BPoint(0, 0), targetWidth, targetHeight);
|
||||||
|
if (result != B_OK)
|
||||||
|
delete bitmaps[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != B_OK) {
|
||||||
|
for (int32 j = 0; j < i; j++)
|
||||||
|
delete bitmaps[j];
|
||||||
|
free(bitmaps);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,13 @@
|
|||||||
#include "RemoteHWInterface.h"
|
#include "RemoteHWInterface.h"
|
||||||
#include "ServerFont.h"
|
#include "ServerFont.h"
|
||||||
|
|
||||||
|
class BPoint;
|
||||||
|
class BRect;
|
||||||
|
class BRegion;
|
||||||
|
|
||||||
|
class BitmapDrawingEngine;
|
||||||
|
class ServerBitmap;
|
||||||
|
|
||||||
class RemoteDrawingEngine : public DrawingEngine {
|
class RemoteDrawingEngine : public DrawingEngine {
|
||||||
public:
|
public:
|
||||||
RemoteDrawingEngine(
|
RemoteDrawingEngine(
|
||||||
@@ -99,18 +106,18 @@ public:
|
|||||||
float yRadius, const BGradient& gradient);
|
float yRadius, const BGradient& gradient);
|
||||||
|
|
||||||
virtual void DrawShape(const BRect& bounds,
|
virtual void DrawShape(const BRect& bounds,
|
||||||
int32 opCount, const uint32* opList,
|
int32 opCount, const uint32* opList,
|
||||||
int32 pointCount, const BPoint* pointList,
|
int32 pointCount, const BPoint* pointList,
|
||||||
bool filled,
|
bool filled,
|
||||||
const BPoint& viewToScreenOffset,
|
const BPoint& viewToScreenOffset,
|
||||||
float viewScale);
|
float viewScale);
|
||||||
virtual void FillShape(const BRect& bounds,
|
virtual void FillShape(const BRect& bounds,
|
||||||
int32 opCount, const uint32* opList,
|
int32 opCount, const uint32* opList,
|
||||||
int32 pointCount, const BPoint* pointList,
|
int32 pointCount, const BPoint* pointList,
|
||||||
const BGradient& gradient,
|
const BGradient& gradient,
|
||||||
const BPoint& viewToScreenOffset,
|
const BPoint& viewToScreenOffset,
|
||||||
float viewScale);
|
float viewScale);
|
||||||
|
|
||||||
virtual void DrawTriangle(BPoint* points,
|
virtual void DrawTriangle(BPoint* points,
|
||||||
const BRect& bounds, bool filled);
|
const BRect& bounds, bool filled);
|
||||||
virtual void FillTriangle(BPoint* points,
|
virtual void FillTriangle(BPoint* points,
|
||||||
@@ -147,6 +154,11 @@ private:
|
|||||||
RemoteMessage& message);
|
RemoteMessage& message);
|
||||||
|
|
||||||
BRect _BuildBounds(BPoint* points, int32 pointCount);
|
BRect _BuildBounds(BPoint* points, int32 pointCount);
|
||||||
|
status_t _ExtractBitmapRegions(ServerBitmap& bitmap,
|
||||||
|
uint32 options, const BRect& bitmapRect,
|
||||||
|
const BRect& viewRect, double xScale,
|
||||||
|
double yScale, BRegion& region,
|
||||||
|
UtilityBitmap**& bitmaps);
|
||||||
|
|
||||||
RemoteHWInterface* fHWInterface;
|
RemoteHWInterface* fHWInterface;
|
||||||
uint32 fToken;
|
uint32 fToken;
|
||||||
@@ -160,6 +172,8 @@ private:
|
|||||||
BPoint fDrawStringResult;
|
BPoint fDrawStringResult;
|
||||||
float fStringWidthResult;
|
float fStringWidthResult;
|
||||||
BBitmap* fReadBitmapResult;
|
BBitmap* fReadBitmapResult;
|
||||||
|
|
||||||
|
BitmapDrawingEngine* fBitmapDrawingEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // REMOTE_DRAWING_ENGINE_H
|
#endif // REMOTE_DRAWING_ENGINE_H
|
||||||
|
|||||||
Reference in New Issue
Block a user