From 02ec6ae825ace4dce1c18433455e1936cbadb43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 28 Mar 2005 13:38:11 +0000 Subject: [PATCH] Implemented and tested the color spaces B_RGB16, B_RGB15, B_CMAP8 and B_GRAY8. The trick is this: The Painter based implementation will most likely always use a double buffered approach. I simply made the back buffer, into which Painter draws, always B_RGBA32, while the front buffer can have any other format the drawing backend is supposed to support. In CopyBackToFront, the format conversion is handled. This gets us pretty far without actually doing very much, and I am not even sure if there should/can be a better implementation. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12091 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/drawing/ViewHWInterface.cpp | 191 +++++++++++++++++++- 1 file changed, 189 insertions(+), 2 deletions(-) diff --git a/src/servers/app/drawing/ViewHWInterface.cpp b/src/servers/app/drawing/ViewHWInterface.cpp index 2d8aaf3da0..842c2690e2 100644 --- a/src/servers/app/drawing/ViewHWInterface.cpp +++ b/src/servers/app/drawing/ViewHWInterface.cpp @@ -51,6 +51,45 @@ enum { MSG_UPDATE = 'updt', }; +// string_for_color_space +const char* +string_for_color_space(color_space format) +{ + const char* name = ""; + switch (format) { + case B_RGB32: + name = "B_RGB32"; + break; + case B_RGBA32: + name = "B_RGBA32"; + break; + case B_RGB32_BIG: + name = "B_RGB32_BIG"; + break; + case B_RGBA32_BIG: + name = "B_RGBA32_BIG"; + break; + case B_RGB24: + name = "B_RGB24"; + break; + case B_RGB24_BIG: + name = "B_RGB24_BIG"; + break; + case B_CMAP8: + name = "B_CMAP8"; + break; + case B_GRAY8: + name = "B_GRAY8"; + break; + case B_GRAY1: + name = "B_GRAY1"; + break; + default: + break; + } + return name; +} + class CardView : public BView { public: CardView(BRect bounds); @@ -365,7 +404,8 @@ ViewHWInterface::SetMode(const display_mode &mode) { status_t ret = B_OK; // prevent from doing the unnecessary - if (fDisplayMode.virtual_width == mode.virtual_width && + if (fBackBuffer && fFrontBuffer && + fDisplayMode.virtual_width == mode.virtual_width && fDisplayMode.virtual_height == mode.virtual_height && fDisplayMode.space == mode.space) { return ret; @@ -378,6 +418,8 @@ ViewHWInterface::SetMode(const display_mode &mode) fDisplayMode.virtual_height = mode.virtual_height; fDisplayMode.space = mode.space; +printf("ViewHWInterface::SetMode(%s)\n", string_for_color_space((color_space)fDisplayMode.space)); + // left over code // hide_cursor=0; @@ -403,7 +445,10 @@ ViewHWInterface::SetMode(const display_mode &mode) delete fBackBuffer; delete fFrontBuffer; - BBitmap* backBitmap = new BBitmap(frame, 0, (color_space)fDisplayMode.space); + // NOTE: backbuffer is always B_RGBA32, this simplifies the + // drawing backend implementation tremendously for the time + // being. The color space conversion is handled in CopyBackToFront() + BBitmap* backBitmap = new BBitmap(frame, 0, B_RGBA32); BBitmap* frontBitmap = new BBitmap(frame, 0, (color_space)fDisplayMode.space); fBackBuffer = new BitmapBuffer(backBitmap); @@ -647,6 +692,148 @@ ViewHWInterface::CopyBackToFront(const BRect& frame) int32 right = (int32)ceilf(area.right); int32 bottom = (int32)ceilf(area.bottom); + // offset to left top pixel in source buffer (always B_RGBA32) + src += y * srcBPR + x * 4; + + // transfer, handle colorspace conversion + switch (into->ColorSpace()) { + case B_RGB32: + case B_RGBA32: { + int32 bytes = (right - x + 1) * 4; + + if (bytes > 0) { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 4; + // copy + for (; y <= bottom; y++) { + memcpy(dst, src, bytes); + dst += dstBPR; + src += srcBPR; + } + } + break; + } + // NOTE: on R5, B_RGB24 bitmaps are not supported by DrawBitmap() + case B_RGB24: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 3; + int32 left = x; + // copy + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint8* dstHandle = dst; + x = left; + for (; x <= right; x++) { + dstHandle[0] = srcHandle[0]; + dstHandle[1] = srcHandle[1]; + dstHandle[2] = srcHandle[2]; + dstHandle += 3; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_RGB16: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 2; + int32 left = x; + // copy + // TODO: assumes BGR order, does this work on big endian as well? + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint16* dstHandle = (uint16*)dst; + x = left; + for (; x <= right; x++) { + *dstHandle = (uint16)(((srcHandle[2] & 0xf8) << 8) | + ((srcHandle[1] & 0xfc) << 3) | + (srcHandle[0] >> 3)); + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_RGB15: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x * 2; + int32 left = x; + // copy + // TODO: assumes BGR order, does this work on big endian as well? + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint16* dstHandle = (uint16*)dst; + x = left; + for (; x <= right; x++) { + *dstHandle = (uint16)(((srcHandle[2] & 0xf8) << 7) | + ((srcHandle[1] & 0xf8) << 2) | + (srcHandle[0] >> 3)); + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_CMAP8: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x; + int32 left = x; + // copy + // TODO: using BScreen will not be an option in the + // final implementation, will it? The BBitmap implementation + // has a class that handles this, something so useful + // should be moved to a more public place. + // TODO: assumes BGR order again + BScreen screen; + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint8* dstHandle = dst; + x = left; + for (; x <= right; x++) { + *dstHandle = screen.IndexForColor(srcHandle[2], + srcHandle[1], + srcHandle[0]); + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + case B_GRAY8: { + // offset to left top pixel in dest buffer + dst += y * dstBPR + x; + int32 left = x; + // copy + // TODO: assumes BGR order, does this work on big endian as well? + for (; y <= bottom; y++) { + uint8* srcHandle = src; + uint8* dstHandle = dst; + x = left; + for (; x <= right; x++) { + *dstHandle = (308 * srcHandle[2] + 600 * srcHandle[1] + 116 * srcHandle[0]) / 1024; + dstHandle ++; + srcHandle += 4; + } + dst += dstBPR; + src += srcBPR; + } + break; + } + default: + fprintf(stderr, "ViewHWInterface::CopyBackToFront() - unsupported front buffer format!\n"); + break; + } + + + + int32 pixelSize = 0; color_space dstFormat = into->ColorSpace(); // NOTE: there is no check if the bitmaps