From 62b965a65f1c2e5898e0ec2c294b3d5a24f7761e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sat, 10 Dec 2005 21:45:41 +0000 Subject: [PATCH] * got the "cloned accelerant" based DWindowHWInterface to work, though without using the clipping info from a BDirectWindow... I made it so that the window used stays on top always, until I can think of something better. The other problem is that you should not move the window, since Painter doesn't update it's pointer into the frame buffer. * Now the test environment is running at pretty much the same speed as it would under Haiku, completely by-passing the BeOS app_server. It shows that Painter needs to be optimized for writing to graphics memory, and also that we need to figure out a way to distribute update sessions more equally. What happens is this: The first invalidation of a window triggers an update on the client side... the client cannot keep up with drawing, since it is pretty much blocked all the time because the desktop thread moves a window and because the clipping constantly changes. In the meantime, new update request are added to the pending session because the client has still not finished with the current session. Only when things settle a bit, the next update session can be startet. On the bright side of things, the earlier problems with scrolling seem to be fixed for good. * some documentation updates on Painter git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15478 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/ScreenManager.cpp | 4 +- src/servers/app/drawing/DWindowBuffer.cpp | 21 ++- src/servers/app/drawing/DWindowBuffer.h | 6 + .../app/drawing/DWindowHWInterface.cpp | 145 ++++++++++++------ src/servers/app/drawing/DWindowHWInterface.h | 8 + src/servers/app/drawing/HWInterface.cpp | 2 +- src/servers/app/drawing/Painter/README | 14 +- src/servers/app/drawing/Painter/TODO | 14 -- .../font_support/agg_font_freetype.cpp | 1 + src/tests/servers/app/Jamfile | 6 +- 10 files changed, 138 insertions(+), 83 deletions(-) diff --git a/src/servers/app/ScreenManager.cpp b/src/servers/app/ScreenManager.cpp index 5d08bc6702..a36db9bc5e 100644 --- a/src/servers/app/ScreenManager.cpp +++ b/src/servers/app/ScreenManager.cpp @@ -31,6 +31,7 @@ using std::nothrow; # include "AccelerantHWInterface.h" #else # include "ViewHWInterface.h" +# include "DWindowHWInterface.h" #endif @@ -144,7 +145,8 @@ ScreenManager::_ScanDrivers() #if USE_ACCELERANT interface = new AccelerantHWInterface(); #else - interface = new ViewHWInterface(); + interface = new DWindowHWInterface(); +// interface = new ViewHWInterface(); #endif _AddHWInterface(interface); diff --git a/src/servers/app/drawing/DWindowBuffer.cpp b/src/servers/app/drawing/DWindowBuffer.cpp index 27510f6404..9a930fe5b4 100644 --- a/src/servers/app/drawing/DWindowBuffer.cpp +++ b/src/servers/app/drawing/DWindowBuffer.cpp @@ -1,5 +1,6 @@ #include +#include #include #include "DWindowBuffer.h" @@ -69,7 +70,6 @@ DWindowBuffer::Height() const void DWindowBuffer::SetTo(direct_buffer_info* info) { -printf("DWindowBuffer::SetTo(%p)\n", info); fWindowClipping.MakeEmpty(); if (info) { @@ -86,9 +86,8 @@ printf("DWindowBuffer::SetTo(%p)\n", info); fFormat = info->pixel_format; fWidth = info->window_bounds.right - info->window_bounds.left + 1; fHeight = info->window_bounds.bottom - info->window_bounds.top + 1; -printf(" width: %ld, height: %ld\n", fWidth, fHeight); -// offset bits to left top corner of window -fBits += xOffset * 4 + yOffset * fBytesPerRow; + // offset bits to left top corner of window + fBits += xOffset * 4 + yOffset * fBytesPerRow; } else { fBits = NULL; fWidth = 0; @@ -98,3 +97,17 @@ fBits += xOffset * 4 + yOffset * fBytesPerRow; } } +// SetTo +void +DWindowBuffer::SetTo(frame_buffer_config* config, + uint32 x, uint32 y, + uint32 width, uint32 height, + color_space format) +{ + fBits = (uint8*)config->frame_buffer; + fBytesPerRow = config->bytes_per_row; + fBits += x * 4 + y * fBytesPerRow; + fWidth = width; + fHeight = height; + fFormat = format; +} diff --git a/src/servers/app/drawing/DWindowBuffer.h b/src/servers/app/drawing/DWindowBuffer.h index 475b89a449..b094d1fe5b 100644 --- a/src/servers/app/drawing/DWindowBuffer.h +++ b/src/servers/app/drawing/DWindowBuffer.h @@ -4,6 +4,7 @@ #include "RenderingBuffer.h" struct direct_buffer_info; +struct frame_buffer_config; class DWindowBuffer : public RenderingBuffer { public: @@ -20,6 +21,11 @@ class DWindowBuffer : public RenderingBuffer { void SetTo(direct_buffer_info* info); + void SetTo(frame_buffer_config* config, + uint32 x, uint32 y, + uint32 width, uint32 height, + color_space format); + BRegion& WindowClipping() { return fWindowClipping; } private: diff --git a/src/servers/app/drawing/DWindowHWInterface.cpp b/src/servers/app/drawing/DWindowHWInterface.cpp index 8e4896a756..f1573c4eb2 100644 --- a/src/servers/app/drawing/DWindowHWInterface.cpp +++ b/src/servers/app/drawing/DWindowHWInterface.cpp @@ -79,8 +79,6 @@ class DView : public BView { DView(BRect bounds); virtual ~DView(); -// virtual void AttachedToWindow(); - // DView void ForwardMessage(BMessage* message = NULL); @@ -88,19 +86,22 @@ private: port_id fInputPort; }; -class DWindow : public BDirectWindow { +class DWindow : public BWindow { public: DWindow(BRect frame, + DWindowHWInterface* interface, DWindowBuffer* buffer); virtual ~DWindow(); -// virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); - virtual void DirectConnected(direct_buffer_info* info); +// virtual void DirectConnected(direct_buffer_info* info); - private: - DWindowBuffer* fBuffer; + virtual void FrameMoved(BPoint newOffset); + + private: + DWindowHWInterface* fHWInterface; + DWindowBuffer* fBuffer; }; class DirectMessageFilter : public BMessageFilter { @@ -119,6 +120,7 @@ class DirectMessageFilter : public BMessageFilter { DView::DView(BRect bounds) : BView(bounds, "graphics card view", B_FOLLOW_ALL, 0) { + SetViewColor(B_TRANSPARENT_COLOR); #ifndef INPUTSERVER_TEST_MODE fInputPort = create_port(200, SERVER_INPUT_PORT); #else @@ -209,9 +211,10 @@ DirectMessageFilter::Filter(BMessage *message, BHandler **target) // #pragma mark - -DWindow::DWindow(BRect frame, DWindowBuffer* buffer) - : BDirectWindow(frame, "Haiku App Server", B_TITLED_WINDOW, - B_NOT_ZOOMABLE | B_NOT_RESIZABLE), +DWindow::DWindow(BRect frame, DWindowHWInterface* interface, DWindowBuffer* buffer) + : BWindow(frame, "Haiku App Server", B_TITLED_WINDOW_LOOK, + B_FLOATING_ALL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_NOT_RESIZABLE), + fHWInterface(interface), fBuffer(buffer) { DView* view = new DView(Bounds()); @@ -242,7 +245,7 @@ DWindow::QuitRequested() // we don't quit on ourself, we let us be Quit()! return false; } - +/* // DirectConnected void DWindow::DirectConnected(direct_buffer_info* info) @@ -268,6 +271,14 @@ DWindow::DirectConnected(direct_buffer_info* info) // // fDesktop->UnlockClipping(); } +*/ + +// FrameMoved +void +DWindow::FrameMoved(BPoint newOffset) +{ + fHWInterface->SetOffset((int32)newOffset.x, (int32)newOffset.y); +} // #pragma mark - @@ -277,6 +288,9 @@ DWindowHWInterface::DWindowHWInterface() fFrontBuffer(new DWindowBuffer()), fWindow(NULL), + fXOffset(50), + fYOffset(50), + fCardFD(-1), fAccelerantImage(-1), fAccelerantHook(NULL), @@ -304,8 +318,8 @@ DWindowHWInterface::DWindowHWInterface() fAccMoveCursor(NULL), fAccShowCursor(NULL) { - fDisplayMode.virtual_width = 640; - fDisplayMode.virtual_height = 480; + fDisplayMode.virtual_width = 800; + fDisplayMode.virtual_height = 600; fDisplayMode.space = B_RGBA32; memset(&fSyncToken, 0, sizeof(sync_token)); @@ -511,6 +525,8 @@ sprintf((char*)cloneInfoData, "graphics/%s", fCardNameInDevFS.String()); unload_add_on(fAccelerantImage); return B_ERROR; + } else { + _UpdateFrameBufferConfig(); } return B_OK; @@ -555,10 +571,29 @@ fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT, return B_OK; } +// _UpdateFrameBufferConfig +status_t +DWindowHWInterface::_UpdateFrameBufferConfig() +{ + frame_buffer_config config; + if (fAccGetFrameBufferConfig(&config) != B_OK) { + STRACE(("unable to get frame buffer config\n")); + return B_ERROR; + } + + fFrontBuffer->SetTo(&config, fXOffset, fYOffset, + fDisplayMode.virtual_width, + fDisplayMode.virtual_height, + (color_space)fDisplayMode.space); + return B_OK; +} + + // Shutdown status_t DWindowHWInterface::Shutdown() { +printf("DWindowHWInterface::Shutdown()\n"); if (fAccelerantHook) { uninit_accelerant UninitAccelerant = (uninit_accelerant)fAccelerantHook(B_UNINIT_ACCELERANT, NULL); if (UninitAccelerant) @@ -633,8 +668,8 @@ DWindowHWInterface::SetMode(const display_mode &mode) if (ret < B_OK) return ret; - - fWindow = new DWindow(frame.OffsetToCopy(BPoint(50.0, 50.0)), fFrontBuffer); + + fWindow = new DWindow(frame.OffsetByCopy(fXOffset, fYOffset), this, fFrontBuffer); // fire up the window thread but don't show it on screen yet fWindow->Hide(); @@ -646,10 +681,6 @@ DWindowHWInterface::SetMode(const display_mode &mode) // so that the view does not accidentally draw a freed bitmap if (ret >= B_OK) { - // clear out buffers, alpha is 255 this way - // TODO: maybe this should handle different color spaces in different ways -// memset(fFrontBuffer->Bits(), 255, fFrontBuffer->BitsLength()); - // change the window size and update the bitmap used for drawing fWindow->ResizeTo(frame.Width(), frame.Height()); } @@ -662,6 +693,9 @@ DWindowHWInterface::SetMode(const display_mode &mode) } else { ret = B_ERROR; } + + _UpdateFrameBufferConfig(); + return ret; } @@ -722,8 +756,8 @@ DWindowHWInterface::GetModeList(display_mode **_modes, uint32 *_count) {1280, 1024}, {1400, 1050}, {1600, 1200} }; uint32 resolutionCount = sizeof(resolutions) / sizeof(resolutions[0]); - const uint32 colors[] = {B_CMAP8, B_RGB15, B_RGB16, B_RGB32}; - uint32 count = resolutionCount * 4; +// const uint32 colors[] = {B_CMAP8, B_RGB15, B_RGB16, B_RGB32}; + uint32 count = resolutionCount/* * 4*/; display_mode *modes = new(nothrow) display_mode[count]; if (modes == NULL) @@ -734,31 +768,29 @@ DWindowHWInterface::GetModeList(display_mode **_modes, uint32 *_count) int32 index = 0; for (uint32 i = 0; i < resolutionCount; i++) { - for (uint32 c = 0; c < 4; c++) { - modes[index].virtual_width = resolutions[i].width; - modes[index].virtual_height = resolutions[i].height; - modes[index].space = colors[c]; + modes[index].virtual_width = resolutions[i].width; + modes[index].virtual_height = resolutions[i].height; + modes[index].space = B_RGB32; - modes[index].h_display_start = 0; - modes[index].v_display_start = 0; - modes[index].timing.h_display = resolutions[i].width; - modes[index].timing.v_display = resolutions[i].height; - modes[index].timing.h_total = 22000; - modes[index].timing.v_total = 22000; - modes[index].timing.pixel_clock = ((uint32)modes[index].timing.h_total - * modes[index].timing.v_total * 60) / 1000; - modes[index].flags = B_PARALLEL_ACCESS; + modes[index].h_display_start = 0; + modes[index].v_display_start = 0; + modes[index].timing.h_display = resolutions[i].width; + modes[index].timing.v_display = resolutions[i].height; + modes[index].timing.h_total = 22000; + modes[index].timing.v_total = 22000; + modes[index].timing.pixel_clock = ((uint32)modes[index].timing.h_total + * modes[index].timing.v_total * 60) / 1000; + modes[index].flags = B_PARALLEL_ACCESS; - index++; - } + index++; } #else // support only a single mode, useful // for testing a specific mode display_mode *modes = new(nothrow) display_mode[1]; - modes[0].virtual_width = 640; - modes[0].virtual_height = 480; - modes[0].space = B_CMAP8; + modes[0].virtual_width = 800; + modes[0].virtual_height = 600; + modes[0].space = B_BRGB32; *_modes = modes; *_count = 1; @@ -860,11 +892,11 @@ DWindowHWInterface::CopyRegion(const clipping_rect* sortedRectList, // convert the rects blit_params* params = new blit_params[count]; for (uint32 i = 0; i < count; i++) { - params[i].src_left = (uint16)sortedRectList[i].left; - params[i].src_top = (uint16)sortedRectList[i].top; + params[i].src_left = (uint16)sortedRectList[i].left + fXOffset; + params[i].src_top = (uint16)sortedRectList[i].top + fYOffset; - params[i].dest_left = (uint16)sortedRectList[i].left + xOffset; - params[i].dest_top = (uint16)sortedRectList[i].top + yOffset; + params[i].dest_left = (uint16)sortedRectList[i].left + xOffset + fXOffset; + params[i].dest_top = (uint16)sortedRectList[i].top + yOffset + fYOffset; // NOTE: width and height are expressed as distance, not pixel count! params[i].width = (uint16)(sortedRectList[i].right - sortedRectList[i].left); @@ -958,7 +990,7 @@ DWindowHWInterface::FrontBuffer() const RenderingBuffer* DWindowHWInterface::BackBuffer() const { - return NULL; + return fFrontBuffer; } // IsDoubleBuffered @@ -975,6 +1007,23 @@ DWindowHWInterface::Invalidate(const BRect& frame) return HWInterface::Invalidate(frame); } +// SetOffset +void +DWindowHWInterface::SetOffset(int32 left, int32 top) +{ + if (!WriteLock()) + return; + + fXOffset = left; + fYOffset = top; + + _UpdateFrameBufferConfig(); + + // TODO: someone would have to call DrawingEngine::Update() now! + + WriteUnlock(); +} + // _RegionToRectParams void DWindowHWInterface::_RegionToRectParams(/*const*/ BRegion* region, @@ -986,10 +1035,10 @@ DWindowHWInterface::_RegionToRectParams(/*const*/ BRegion* region, for (uint32 i = 0; i < *count; i++) { clipping_rect r = region->RectAtInt(i); - (*params)[i].left = (uint16)r.left; - (*params)[i].top = (uint16)r.top; - (*params)[i].right = (uint16)r.right; - (*params)[i].bottom = (uint16)r.bottom; + (*params)[i].left = (uint16)(r.left + fXOffset); + (*params)[i].top = (uint16)(r.top + fYOffset); + (*params)[i].right = (uint16)(r.right + fXOffset); + (*params)[i].bottom = (uint16)(r.bottom + fYOffset); } } diff --git a/src/servers/app/drawing/DWindowHWInterface.h b/src/servers/app/drawing/DWindowHWInterface.h index 0d48bf4fc1..fdc9827d23 100644 --- a/src/servers/app/drawing/DWindowHWInterface.h +++ b/src/servers/app/drawing/DWindowHWInterface.h @@ -69,17 +69,23 @@ class DWindowHWInterface : public HWInterface { virtual status_t Invalidate(const BRect& frame); + // DWindowHWInterface + void SetOffset(int32 left, int32 top); + private: DWindowBuffer* fFrontBuffer; DWindow* fWindow; display_mode fDisplayMode; + int32 fXOffset; + int32 fYOffset; // accelerant stuff int _OpenGraphicsDevice(int deviceNumber); status_t _OpenAccelerant(int device); status_t _SetupDefaultHooks(); + status_t _UpdateFrameBufferConfig(); void _RegionToRectParams(/*const*/ BRegion* region, fill_rect_params** params, @@ -115,6 +121,8 @@ class DWindowHWInterface : public HWInterface { move_cursor fAccMoveCursor; show_cursor fAccShowCursor; + frame_buffer_config fFrameBufferConfig; + BString fCardNameInDevFS; }; diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 98f9e5f953..f90fce9842 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -589,7 +589,7 @@ printf("nothing to copy\n"); break; } default: - fprintf(stderr, "ViewHWInterface::CopyBackToFront() - unsupported front buffer format!\n"); + fprintf(stderr, "HWInterface::CopyBackToFront() - unsupported front buffer format!\n"); break; } } diff --git a/src/servers/app/drawing/Painter/README b/src/servers/app/drawing/Painter/README index c62e27a438..22d493ab94 100644 --- a/src/servers/app/drawing/Painter/README +++ b/src/servers/app/drawing/Painter/README @@ -6,10 +6,6 @@ Painter is a class implementing the BView drawing functions with the Anti-Grain Status: -1) Most of the drawing modes are unimplemented. - -I want to work out the effects of the drawing_mode together with the source_alpha and alpha_func. Currently, Painter supports B_OP_COPY, B_OP_OVER and B_OP_INVERT with patterns. It is kind of ignorant towards the orginal app_servers treatment of alpha in the high and low color. I think it acts for the most part as if the BView was SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE), especially for drawing bitmaps, which will of course be fixed, but should be no obstacle in integrating Painter right now. - 2) Only 32 bit frame buffers are support yet. Most of the work in supporting other color spaces is only in the drawing_mode classes. It makes no sense to start work on these before I have even nailed the details once on the 32 bit case. @@ -20,11 +16,7 @@ There is some work involved when trying to make this fast. The conversion should 4) Most of the BView behaviour for DrawString() is missing. -Putting the current pen at the position of the virtual next char is now handled, but I have to figure out the escapment_delta stuff. - -5) Font handling is somewhat weird. - -There is a FontManager class that is supposed to be an interface between font family/style names and font files on disk loadable by Freetype. There is a TextRenderer interface class and AGGTextRenderer implementation that can be used to get the job done, but this is of course very open for discussion. I didn't really look at what was already available in the Haiku repository, but just took from WonderBrush what I already had. The biggest problem when testing Painter on R5 is the sometimes slightly different naming of font families in Freetype and R5. Sometimes, FontManager is not able to match up the correct file for the given family and style. For the "default" "Swiss911 BT", it works. If the be_plain_font can not be "loaded" by FontManager, it might look like font rendering is not working at all, you might have to tweak this, or maybe hardcode a font that works. Of course, on a "true Haiku system", once such a thing exists, this problem will be non-existent. Fonts will just be named as Freetype suggests, and everything will match up fine. +Putting the current pen at the position of the virtual next char is now handled, but I have to figure out the escapment_delta stuff. Glyph spacing modes need to be supported. 6) The framework is still developing. @@ -32,6 +24,4 @@ I'm still working on many ends of Painter and I might refactor things. The basic 7) Article -I have written a Newsletter article, that explains the concepts of AGG, how Painter is therefor designed and how it can be improved with the knowledge of AGG inner workings. I don't know when this article will appear, but email me if you're interested in the current version. - - +I have written a Newsletter article, that explains the concepts of AGG, how Painter is therefor designed and how it can be improved with the knowledge of AGG inner workings. diff --git a/src/servers/app/drawing/Painter/TODO b/src/servers/app/drawing/Painter/TODO index a7efd2b114..48cc178ee1 100644 --- a/src/servers/app/drawing/Painter/TODO +++ b/src/servers/app/drawing/Painter/TODO @@ -2,32 +2,18 @@ Test: * "composite" alpha blending modes -* BShape conversion and rendering - -* Bezier curve rendering - -* other color spaces (currently uses BBitmap::ImportBits(), - which is only available on Haiku) - Implement: * "escapment_delta" text rendering -* font shearing - (* handling of other BBitmap colorspaces) Improve: -* make special case versions of some functions: - -- horizontal/vertical lines -- horizonzal text rendering, using scanline cache - * make special verions of DrawingModes for B_SOLID_* patterns * get rid of virtual function use in DrawingMode framework diff --git a/src/servers/app/drawing/Painter/font_support/agg_font_freetype.cpp b/src/servers/app/drawing/Painter/font_support/agg_font_freetype.cpp index 5e62f2f103..e4106367b3 100644 --- a/src/servers/app/drawing/Painter/font_support/agg_font_freetype.cpp +++ b/src/servers/app/drawing/Painter/font_support/agg_font_freetype.cpp @@ -565,6 +565,7 @@ namespace agg } update_transform(); +// update_char_size(); } return ret; } diff --git a/src/tests/servers/app/Jamfile b/src/tests/servers/app/Jamfile index 71d2fe169c..f78fb66ea0 100644 --- a/src/tests/servers/app/Jamfile +++ b/src/tests/servers/app/Jamfile @@ -46,7 +46,7 @@ SharedLibrary libhwinterfaceimpl.so : ViewHWInterface.cpp DWindowHWInterface.cpp - : be game libhwinterface.so + : be libhwinterface.so ; SharedLibrary libhaikuappserver.so : @@ -71,7 +71,7 @@ SharedLibrary libhaikuappserver.so : # libraries : - be game libtextencoding.so libfreetype.so + be libtextencoding.so libfreetype.so ; AddResources haiku_app_server : app_server.rdef ; @@ -123,7 +123,7 @@ Server haiku_app_server : # libraries : z libpng.so libhaikuappserver.so - libpainter.a be game + libpainter.a be libhwinterface.so libhwinterfaceimpl.so libagg.a libfreetype.so libtextencoding.so ;