From 46b4e489982de2e3ddfab11c68c714f6c1be4598 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Thu, 16 Aug 2007 09:14:03 +0000 Subject: [PATCH] Added some debug output to PicturePlayer. Since checking the table size for every op is very slow, now we do that only at the beginning, and use a custom op table if needed. The best case (which is the one used when drawing a picture with BView::DrawPicture()) is very fast since it only requires one check. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21972 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/interface/PictureProtocol.h | 4 + src/kits/interface/PictureDataWriter.cpp | 6 +- src/kits/interface/PicturePlayer.cpp | 337 ++++++++++++-------- src/servers/app/ServerPicture.cpp | 4 +- 4 files changed, 210 insertions(+), 141 deletions(-) diff --git a/headers/private/interface/PictureProtocol.h b/headers/private/interface/PictureProtocol.h index 77b132953b..08d9ca0586 100644 --- a/headers/private/interface/PictureProtocol.h +++ b/headers/private/interface/PictureProtocol.h @@ -53,5 +53,9 @@ enum { B_PIC_SET_FONT_FACE = 0x0389, }; + +const static uint32 kOpsTableSize = 48; + + #endif diff --git a/src/kits/interface/PictureDataWriter.cpp b/src/kits/interface/PictureDataWriter.cpp index ce2591c420..8d459adce9 100644 --- a/src/kits/interface/PictureDataWriter.cpp +++ b/src/kits/interface/PictureDataWriter.cpp @@ -172,15 +172,17 @@ PictureDataWriter::WriteSetClipping(/*const */BRegion ®ion) const int32 numRects = region.CountRects(); if (numRects > 0 && region.Frame().IsValid()) { BeginOp(B_PIC_SET_CLIPPING_RECTS); - Write(numRects); - for (int32 i = 0; i < numRects; i++) + Write(numRects); + for (int32 i = 0; i < numRects; i++) { Write(region.RectAt(i)); + } EndOp(); } else WriteClearClipping(); } catch (status_t &status) { return status; } + return B_OK; } diff --git a/src/kits/interface/PicturePlayer.cpp b/src/kits/interface/PicturePlayer.cpp index 54e21fcaa0..37273e97dd 100644 --- a/src/kits/interface/PicturePlayer.cpp +++ b/src/kits/interface/PicturePlayer.cpp @@ -4,11 +4,11 @@ * * Authors: * Marc Flerackers (mflerackers@androme.be) - * Stefano Ceccherini (burton666@libero.it) + * Stefano Ceccherini (stefano.ceccherini@gmail.com) * Marcus Overhagen (marcus@overhagen.de) */ -/** PicturePlayer is used to create and play picture data. */ +/** PicturePlayer is used to play picture data. */ #include @@ -17,6 +17,8 @@ #include +#define DEBUG 3 + typedef void (*fnc)(void*); typedef void (*fnc_BPoint)(void*, BPoint); typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint); @@ -42,6 +44,127 @@ typedef void (*fnc_DrawPicture)(void *, BPoint, int32); typedef void (*fnc_BShape)(void*, BShape*); +static void +nop() +{ +} + + +static void * +kDummyTable[kOpsTableSize] = { + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop, + nop +}; + + +#if DEBUG +static const char * +PictureOpToString(int op) +{ + #define RETURN_STRING(x) case x: return #x + + switch(op) { + RETURN_STRING(B_PIC_MOVE_PEN_BY); + RETURN_STRING(B_PIC_STROKE_LINE); + RETURN_STRING(B_PIC_STROKE_RECT); + RETURN_STRING(B_PIC_FILL_RECT); + RETURN_STRING(B_PIC_STROKE_ROUND_RECT); + RETURN_STRING(B_PIC_FILL_ROUND_RECT); + RETURN_STRING(B_PIC_STROKE_BEZIER); + RETURN_STRING(B_PIC_FILL_BEZIER); + RETURN_STRING(B_PIC_STROKE_POLYGON); + RETURN_STRING(B_PIC_FILL_POLYGON); + RETURN_STRING(B_PIC_STROKE_SHAPE); + RETURN_STRING(B_PIC_FILL_SHAPE); + RETURN_STRING(B_PIC_DRAW_STRING); + RETURN_STRING(B_PIC_DRAW_PIXELS); + RETURN_STRING(B_PIC_DRAW_PICTURE); + RETURN_STRING(B_PIC_STROKE_ARC); + RETURN_STRING(B_PIC_FILL_ARC); + RETURN_STRING(B_PIC_STROKE_ELLIPSE); + RETURN_STRING(B_PIC_FILL_ELLIPSE); + + RETURN_STRING(B_PIC_ENTER_STATE_CHANGE); + RETURN_STRING(B_PIC_SET_CLIPPING_RECTS); + RETURN_STRING(B_PIC_CLIP_TO_PICTURE); + RETURN_STRING(B_PIC_PUSH_STATE); + RETURN_STRING(B_PIC_POP_STATE); + RETURN_STRING(B_PIC_CLEAR_CLIPPING_RECTS); + + RETURN_STRING(B_PIC_SET_ORIGIN); + RETURN_STRING(B_PIC_SET_PEN_LOCATION); + RETURN_STRING(B_PIC_SET_DRAWING_MODE); + RETURN_STRING(B_PIC_SET_LINE_MODE); + RETURN_STRING(B_PIC_SET_PEN_SIZE); + RETURN_STRING(B_PIC_SET_SCALE); + RETURN_STRING(B_PIC_SET_FORE_COLOR); + RETURN_STRING(B_PIC_SET_BACK_COLOR); + RETURN_STRING(B_PIC_SET_STIPLE_PATTERN); + RETURN_STRING(B_PIC_ENTER_FONT_STATE); + RETURN_STRING(B_PIC_SET_BLENDING_MODE); + RETURN_STRING(B_PIC_SET_FONT_FAMILY); + RETURN_STRING(B_PIC_SET_FONT_STYLE); + RETURN_STRING(B_PIC_SET_FONT_SPACING); + RETURN_STRING(B_PIC_SET_FONT_ENCODING); + RETURN_STRING(B_PIC_SET_FONT_FLAGS); + RETURN_STRING(B_PIC_SET_FONT_SIZE); + RETURN_STRING(B_PIC_SET_FONT_ROTATE); + RETURN_STRING(B_PIC_SET_FONT_SHEAR); + RETURN_STRING(B_PIC_SET_FONT_BPP); + RETURN_STRING(B_PIC_SET_FONT_FACE); + default: return "Unknown op"; + } + #undef RETURN_STRING +} +#endif + + PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures) : fData(data), fSize(size), @@ -62,6 +185,22 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) // check the tableEntries to see if the table is big enough. // If an application supplies the wrong size or an invalid pointer, // it's its own fault. +#if DEBUG + FILE *file = fopen("/var/log/PicturePlayer.log", "a"); + fprintf(file, "Start rendering BPicture...\n"); + bigtime_t startTime = system_time(); + int32 numOps = 0; +#endif + // If the caller supplied a function table smaller than needed, + // we use our dummy table, and copy the supported ops from the supplied one. + void **functionTable = callBackTable; + if ((uint32)tableEntries < kOpsTableSize) { +#if DEBUG + fprintf(file, "A smaller than needed function table was supplied.\n"); +#endif + functionTable = kDummyTable; + memcpy(functionTable, callBackTable, (kOpsTableSize - tableEntries) * sizeof(void *)); + } const char *data = reinterpret_cast(fData); size_t pos = 0; @@ -78,21 +217,21 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) if (pos + size > fSize) debugger("PicturePlayer::Play: buffer overrun\n"); +#if DEBUG > 1 + bigtime_t startOpTime = system_time(); + fprintf(file, "Op %s ", PictureOpToString(op)); +#endif switch (op) { case B_PIC_MOVE_PEN_BY: { - if (tableEntries <= 1) - break; - ((fnc_BPoint)callBackTable[1])(userData, + ((fnc_BPoint)functionTable[1])(userData, *reinterpret_cast(data)); /* where */ break; } case B_PIC_STROKE_LINE: { - if (tableEntries <= 2) - break; - ((fnc_BPointBPoint)callBackTable[2])(userData, + ((fnc_BPointBPoint)functionTable[2])(userData, *reinterpret_cast(data), /* start */ *reinterpret_cast(data + sizeof(BPoint))); /* end */ break; @@ -100,27 +239,21 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_STROKE_RECT: { - if (tableEntries <= 3) - break; - ((fnc_BRect)callBackTable[3])(userData, + ((fnc_BRect)functionTable[3])(userData, *reinterpret_cast(data)); /* rect */ break; } case B_PIC_FILL_RECT: { - if (tableEntries <= 4) - break; - ((fnc_BRect)callBackTable[4])(userData, + ((fnc_BRect)functionTable[4])(userData, *reinterpret_cast(data)); /* rect */ break; } case B_PIC_STROKE_ROUND_RECT: { - if (tableEntries <= 5) - break; - ((fnc_BRectBPoint)callBackTable[5])(userData, + ((fnc_BRectBPoint)functionTable[5])(userData, *reinterpret_cast(data), /* rect */ *reinterpret_cast(data + sizeof(BRect))); /* radii */ break; @@ -128,9 +261,7 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_FILL_ROUND_RECT: { - if (tableEntries <= 6) - break; - ((fnc_BRectBPoint)callBackTable[6])(userData, + ((fnc_BRectBPoint)functionTable[6])(userData, *reinterpret_cast(data), /* rect */ *reinterpret_cast(data + sizeof(BRect))); /* radii */ break; @@ -138,27 +269,21 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_STROKE_BEZIER: { - if (tableEntries <= 7) - break; - ((fnc_PBPoint)callBackTable[7])(userData, + ((fnc_PBPoint)functionTable[7])(userData, reinterpret_cast(data)); break; } case B_PIC_FILL_BEZIER: { - if (tableEntries <= 8) - break; - ((fnc_PBPoint)callBackTable[8])(userData, + ((fnc_PBPoint)functionTable[8])(userData, reinterpret_cast(data)); break; } case B_PIC_STROKE_ARC: { - if (tableEntries <= 9) - break; - ((fnc_BPointBPointff)callBackTable[9])(userData, + ((fnc_BPointBPointff)functionTable[9])(userData, *reinterpret_cast(data), /* center */ *reinterpret_cast(data + sizeof(BPoint)), /* radii */ *reinterpret_cast(data + 2 * sizeof(BPoint)), /* startTheta */ @@ -168,9 +293,7 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_FILL_ARC: { - if (tableEntries <= 10) - break; - ((fnc_BPointBPointff)callBackTable[10])(userData, + ((fnc_BPointBPointff)functionTable[10])(userData, *reinterpret_cast(data), /* center */ *reinterpret_cast(data + sizeof(BPoint)), /* radii */ *reinterpret_cast(data + 2 * sizeof(BPoint)), /* startTheta */ @@ -180,32 +303,26 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_STROKE_ELLIPSE: { - if (tableEntries <= 11) - break; const BRect *rect = reinterpret_cast(data); BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f); BPoint center = rect->LeftTop() + radii; - ((fnc_BPointBPoint)callBackTable[11])(userData, center, radii); + ((fnc_BPointBPoint)functionTable[11])(userData, center, radii); break; } case B_PIC_FILL_ELLIPSE: { - if (tableEntries <= 12) - break; const BRect *rect = reinterpret_cast(data); BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f); BPoint center = rect->LeftTop() + radii; - ((fnc_BPointBPoint)callBackTable[12])(userData, center, radii); + ((fnc_BPointBPoint)functionTable[12])(userData, center, radii); break; } case B_PIC_STROKE_POLYGON: { - if (tableEntries <= 13) - break; int32 numPoints = *reinterpret_cast(data); - ((fnc_iPBPointb)callBackTable[13])(userData, + ((fnc_iPBPointb)functionTable[13])(userData, numPoints, reinterpret_cast(data + sizeof(int32)), /* points */ *reinterpret_cast(data + sizeof(int32) + numPoints * sizeof(BPoint))); /* is-closed */ @@ -214,9 +331,7 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_FILL_POLYGON: { - if (tableEntries <= 14) - break; - ((fnc_iPBPoint)callBackTable[14])(userData, + ((fnc_iPBPoint)functionTable[14])(userData, *reinterpret_cast(data), /* numPoints */ reinterpret_cast(data + sizeof(int32))); /* points */ break; @@ -226,9 +341,6 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_FILL_SHAPE: { const bool stroke = (op == B_PIC_STROKE_SHAPE); - if (tableEntries <= 16 || (stroke && tableEntries <= 15)) - break; - int32 opCount = *reinterpret_cast(data); int32 ptCount = *reinterpret_cast(data + sizeof(int32)); const uint32 *opList = reinterpret_cast(data + 2 * sizeof(int32)); @@ -239,15 +351,13 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) shape.SetData(opCount, ptCount, opList, ptList); const int32 tableIndex = stroke ? 15 : 16; - ((fnc_BShape)callBackTable[tableIndex])(userData, &shape); + ((fnc_BShape)functionTable[tableIndex])(userData, &shape); break; } case B_PIC_DRAW_STRING: { - if (tableEntries <= 17) - break; - ((fnc_Pcff)callBackTable[17])(userData, + ((fnc_Pcff)functionTable[17])(userData, reinterpret_cast(data + 2 * sizeof(float)), /* string */ *reinterpret_cast(data), /* escapement.space */ *reinterpret_cast(data + sizeof(float))); /* escapement.nonspace */ @@ -256,9 +366,7 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_DRAW_PIXELS: { - if (tableEntries <= 18) - break; - ((fnc_DrawPixels)callBackTable[18])(userData, + ((fnc_DrawPixels)functionTable[18])(userData, *reinterpret_cast(data), /* src */ *reinterpret_cast(data + 1 * sizeof(BRect)), /* dst */ *reinterpret_cast(data + 2 * sizeof(BRect)), /* width */ @@ -272,9 +380,7 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_DRAW_PICTURE: { - if (tableEntries <= 19) - break; - ((fnc_DrawPicture)callBackTable[19])(userData, + ((fnc_DrawPicture)functionTable[19])(userData, *reinterpret_cast(data), *reinterpret_cast(data + sizeof(BPoint))); break; @@ -282,10 +388,8 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_SET_CLIPPING_RECTS: { - if (tableEntries <= 20) - break; // TODO: Not sure if it's compatible with R5's BPicture version - ((fnc_PBRecti)callBackTable[20])(userData, + ((fnc_PBRecti)functionTable[20])(userData, reinterpret_cast(data + sizeof(uint32)), *reinterpret_cast(data)); break; @@ -293,84 +397,66 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_CLEAR_CLIPPING_RECTS: { - if (tableEntries <= 20) - break; - ((fnc_PBRecti)callBackTable[20])(userData, NULL, 0); + ((fnc_PBRecti)functionTable[20])(userData, NULL, 0); break; } case B_PIC_CLIP_TO_PICTURE: { - if (tableEntries <= 21) - break; // TODO: Implement break; } case B_PIC_PUSH_STATE: { - if (tableEntries <= 22) - break; - ((fnc)callBackTable[22])(userData); + ((fnc)functionTable[22])(userData); break; } case B_PIC_POP_STATE: { - if (tableEntries <= 23) - break; - ((fnc)callBackTable[23])(userData); + ((fnc)functionTable[23])(userData); break; } case B_PIC_ENTER_STATE_CHANGE: { - if (tableEntries > 24) - ((fnc)callBackTable[24])(userData); + ((fnc)functionTable[24])(userData); stateBlockSize = size; break; } case B_PIC_ENTER_FONT_STATE: { - if (tableEntries > 26) - ((fnc)callBackTable[26])(userData); + ((fnc)functionTable[26])(userData); fontStateBlockSize = size; break; } case B_PIC_SET_ORIGIN: { - if (tableEntries <= 28) - break; - ((fnc_BPoint)callBackTable[28])(userData, + ((fnc_BPoint)functionTable[28])(userData, *reinterpret_cast(data)); /* origin */ break; } case B_PIC_SET_PEN_LOCATION: { - if (tableEntries <= 29) - break; - ((fnc_BPoint)callBackTable[29])(userData, + ((fnc_BPoint)functionTable[29])(userData, *reinterpret_cast(data)); /* location */ break; } case B_PIC_SET_DRAWING_MODE: { - if (tableEntries <= 30) - break; - ((fnc_s)callBackTable[30])(userData, + ((fnc_s)functionTable[30])(userData, *reinterpret_cast(data)); /* mode */ break; } case B_PIC_SET_LINE_MODE: { - if (tableEntries <= 31) - break; - ((fnc_ssf)callBackTable[31])(userData, + ((fnc_ssf)functionTable[31])(userData, *reinterpret_cast(data), /* cap-mode */ *reinterpret_cast(data + 1 * sizeof(int16)), /* join-mode */ *reinterpret_cast(data + 2 * sizeof(int16))); /* miter-limit */ @@ -379,135 +465,105 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) case B_PIC_SET_PEN_SIZE: { - if (tableEntries <= 32) - break; - ((fnc_f)callBackTable[32])(userData, + ((fnc_f)functionTable[32])(userData, *reinterpret_cast(data)); /* size */ break; } case B_PIC_SET_FORE_COLOR: { - if (tableEntries <= 33) - break; - ((fnc_Color)callBackTable[33])(userData, + ((fnc_Color)functionTable[33])(userData, *reinterpret_cast(data)); /* color */ break; } case B_PIC_SET_BACK_COLOR: { - if (tableEntries <= 34) - break; - ((fnc_Color)callBackTable[34])(userData, + ((fnc_Color)functionTable[34])(userData, *reinterpret_cast(data)); /* color */ break; } case B_PIC_SET_STIPLE_PATTERN: { - if (tableEntries <= 35) - break; - ((fnc_Pattern)callBackTable[35])(userData, + ((fnc_Pattern)functionTable[35])(userData, *reinterpret_cast(data)); /* pattern */ break; } case B_PIC_SET_SCALE: { - if (tableEntries <= 36) - break; - ((fnc_f)callBackTable[36])(userData, + ((fnc_f)functionTable[36])(userData, *reinterpret_cast(data)); /* scale */ break; } case B_PIC_SET_FONT_FAMILY: { - if (tableEntries <= 37) - break; - ((fnc_Pc)callBackTable[37])(userData, + ((fnc_Pc)functionTable[37])(userData, reinterpret_cast(data)); /* string */ break; } case B_PIC_SET_FONT_STYLE: { - if (tableEntries <= 38) - break; - ((fnc_Pc)callBackTable[38])(userData, + ((fnc_Pc)functionTable[38])(userData, reinterpret_cast(data)); /* string */ break; } case B_PIC_SET_FONT_SPACING: { - if (tableEntries <= 39) - break; - ((fnc_i)callBackTable[39])(userData, + ((fnc_i)functionTable[39])(userData, *reinterpret_cast(data)); /* spacing */ break; } case B_PIC_SET_FONT_SIZE: { - if (tableEntries <= 40) - break; - ((fnc_f)callBackTable[40])(userData, + ((fnc_f)functionTable[40])(userData, *reinterpret_cast(data)); /* size */ break; } case B_PIC_SET_FONT_ROTATE: { - if (tableEntries <= 41) - break; - ((fnc_f)callBackTable[41])(userData, + ((fnc_f)functionTable[41])(userData, *reinterpret_cast(data)); /* rotation */ break; } case B_PIC_SET_FONT_ENCODING: { - if (tableEntries <= 42) - break; - ((fnc_i)callBackTable[42])(userData, + ((fnc_i)functionTable[42])(userData, *reinterpret_cast(data)); /* encoding */ break; } case B_PIC_SET_FONT_FLAGS: { - if (tableEntries <= 43) - break; - ((fnc_i)callBackTable[43])(userData, + ((fnc_i)functionTable[43])(userData, *reinterpret_cast(data)); /* flags */ break; } case B_PIC_SET_FONT_SHEAR: { - if (tableEntries <= 44) - break; - ((fnc_f)callBackTable[44])(userData, + ((fnc_f)functionTable[44])(userData, *reinterpret_cast(data)); /* shear */ break; } case B_PIC_SET_FONT_FACE: { - if (tableEntries <= 46) - break; - ((fnc_i)callBackTable[46])(userData, + ((fnc_i)functionTable[46])(userData, *reinterpret_cast(data)); /* flags */ break; } case B_PIC_SET_BLENDING_MODE: { - if (tableEntries <= 47) - break; - ((fnc_ss)callBackTable[47])(userData, + ((fnc_ss)functionTable[47])(userData, *reinterpret_cast(data), /* alphaSrcMode */ *reinterpret_cast(data + sizeof(int16))); /* alphaFncMode */ break; @@ -530,20 +586,27 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) // call the exit_state_change hook if needed if (stateBlockSize == 0) { - if (tableEntries > 25) - ((fnc)callBackTable[25])(userData); + ((fnc)functionTable[25])(userData); stateBlockSize = -1; } // call the exit_font_state hook if needed if (fontStateBlockSize == 0) { - if (tableEntries > 27) - ((fnc)callBackTable[27])(userData); + ((fnc)functionTable[27])(userData); fontStateBlockSize = -1; } - +#if DEBUG + numOps++; +#if DEBUG > 1 + fprintf(file, "executed in %lld usecs\n", system_time() - startOpTime); +#endif +#endif // TODO: what if too much was read, should we return B_ERROR? } +#if DEBUG + fprintf(file, "Done! %ld ops, rendering completed in %lld usecs.\n", numOps, system_time() - startTime); + fclose(file); +#endif return B_OK; } diff --git a/src/servers/app/ServerPicture.cpp b/src/servers/app/ServerPicture.cpp index 0a0978f6b6..a9587fca29 100644 --- a/src/servers/app/ServerPicture.cpp +++ b/src/servers/app/ServerPicture.cpp @@ -671,7 +671,7 @@ reserved() } -const void *tableEntries[] = { +const static void *kTableEntries[] = { (const void *)nop, (const void *)move_pen_by, (const void *)stroke_line, @@ -909,7 +909,7 @@ ServerPicture::Play(ViewLayer *view) return; PicturePlayer player(mallocIO->Buffer(), mallocIO->BufferLength(), fPictures); - player.Play(const_cast(tableEntries), sizeof(tableEntries) / sizeof(void *), view); + player.Play(const_cast(kTableEntries), sizeof(kTableEntries) / sizeof(void *), view); }