Re: Quickest Drawing Method
Re: Quickest Drawing Method
- Subject: Re: Quickest Drawing Method
- From: arri <email@hidden>
- Date: Fri, 27 Jul 2007 03:48:30 +0200
sorry, forgot the secret (no, it's not a leapard Dock..)
below;
.a
On Jul 27, 2007, at 3:38 AM, arri wrote:
On Jul 25, 2007, at 2:33 AM, spiderlama wrote:
...I think it can't get any faster...
it can!
i was struggling with a similair performance issue,
but after some experiments i've come to very promising results;
my approach at this point is;
- create a tiny bitmap (CGBitmapContext) that containst all
elements needed to draw the 'big image'
- from that image, create tiles (corners, borders body etc..) and
cache those as CGLayers
the docs teach us that those are actually cached on the graphics-
card where approreate/needed/possible..
- in the drawrect:-routine, check what needs to be drawn, and draw
only that.
right now i'm just using NSViews' needsToDrawRect: to check for
only 9 areas;
the corners (4), borders (4) and the body/fill.
and then i simply draw (if/as needed)
the corner-tiles on a 1:1 scale,
the border-tiles streched to fill whatever area needs to be filled,
and same for the body.
i guess this could be further improved using NSViews'
getRectsBeingDrawn:count:
but this is already blazing fast. i'm happy :)
i suspect that these CGLayers actually did the trick..
i didn't profile with shark, but my home-made fps-counter showed an
improvement of around 300%,
and memory consumption is not even worth mentioning anymore...
On Jul 22, 2007, at 4:52 PM, Alan Smith wrote:
Spider,
Instead of using images which you composite together and draw every
time I would suggest using a NSBezierPath as a clipping path and
filling it with a semi-transparent color for the dock background or,
whatever you want. That should be faster than compositing images and
drawing them, it will certainly be more memory efficient. Not to
mention being much more simple.
i might be wrong, please tell me if i am (i'm not exactly an
expert..),
but i find it a very strange idea that 'rendering' vectors (into
bitmaps),
and then using those for compositing,
would be faster than just copying exisiting bitmap-data around.
especially when that bitmap data can be cached in hardware,
and even more when this compositing, and btw. also scaling can all
be done on the GPU.
i don't believe NSBezierpaths can benefit from hardware acceleration..
€.02
.a_______________________________________________
- (void)drawRect:(NSRect)rect {
if(!didInit) [self createBackgroundImage];
NSRect srect = [self bounds];
CGRect trect; // target rectangle
float vwidth = srect.size.width; // view width
float vheight = srect.size.height; // view hight
CGContextRef context = (CGContextRef)[[NSGraphicsContext
currentContext] graphicsPort];
CGContextSetInterpolationQuality(context,kCGInterpolationNone);
trect = CGRectMake(kTileSize,kTileSize,vwidth-(2*kTileSize),vheight-
(2*kTileSize));
if([self needsToDrawRect: *(NSRect *)&trect ])
CGContextDrawLayerInRect(context,trect,players[4]);
else NSLog(@"%d", 4);
// right edge
trect = CGRectMake(vwidth-kTileSize,kTileSize,kTileSize,vheight-
(2*kTileSize));
if([self needsToDrawRect: *(NSRect *)&trect ])
CGContextDrawLayerInRect(context,trect,players[5]);
else NSLog(@"%d", 5);
// bottom edge
trect = CGRectMake(kTileSize,0,vwidth-(2*kTileSize),kTileSize);
if([self needsToDrawRect: *(NSRect *)&trect ])
CGContextDrawLayerInRect(context,trect,players[7]);
else NSLog(@"%d", 7);
// TOP edge
trect = CGRectMake(kTileSize,vheight-kTileSize,vwidth-
(kTileSize*2),kTileSize);
if([self needsToDrawRect: *(NSRect *)&trect ])
CGContextDrawLayerInRect(context,trect,players[1]);
else NSLog(@"%d", 1);
// left edge
trect = CGRectMake(0,kTileSize,kTileSize,vheight-(2*kTileSize));
if([self needsToDrawRect: *(NSRect *)&trect ])
CGContextDrawLayerInRect(context,trect,players[3]);
else NSLog(@"%d", 3);
// top-right corner
trect = CGRectMake(vwidth-kTileSize,vheight-
kTileSize,kTileSize,kTileSize);
if([self needsToDrawRect: *(NSRect *)&trect ])
CGContextDrawLayerInRect(context,trect,players[2]);
else NSLog(@"%d", 2);
// bottom-right coner
trect = CGRectMake(vwidth-kTileSize,0,kTileSize,kTileSize);
if([self needsToDrawRect: *(NSRect *)&trect ])
CGContextDrawLayerInRect(context,trect,players[8]);
else NSLog(@"%d", 8);
// bottom left
trect = CGRectMake(0,0,kTileSize,kTileSize);
if([self needsToDrawRect: *(NSRect *)&trect ] && first)
CGContextDrawLayerInRect(context,trect,players[6]);
else NSLog(@"%d", 6);
// top right
trect = CGRectMake(0,vheight-kTileSize,kTileSize,kTileSize);
if([self needsToDrawRect: *(NSRect *)&trect ]&&first)
CGContextDrawLayerInRect(context,trect,players[0]);
else NSLog(@"%d", 0);
frc++;
}
- (void)createBackgroundImage {
didInit = YES;
int i = 0;
float radius = 7;
NSRect rect = NSMakeRect( 0, 0, (3*kTileSize), (3*kTileSize) );
NSRect irect = NSMakeRect( 5, 6, (3*kTileSize)-10,
(3*kTileSize)-7 );
float rx = irect.origin.x;
float ry = irect.origin.y;
float rw = irect.size.width;
float rh = irect.size.height;
float cwidth = rect.size.width;
float cheight = rect.size.height;
const int bytesPerPixel = 4;
const int rowBytes = cwidth * bytesPerPixel;
void* imageData = malloc( (rowBytes * cheight) );
CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bmInfo = kCGBitmapByteOrder32Host |
kCGImageAlphaPremultipliedFirst;
CGContextRef context = CGBitmapContextCreate(imageData,
cwidth,
cheight,
8, // bits per component
rowBytes,
cspace,
bmInfo );
CGContextClearRect( context, CGRectMake
(0,0,rect.size.width,rect.size.height) );
assert( CGContextIsPathEmpty(context) );
CGContextSetShouldAntialias( context,1);
// path
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, rx+radius, ry+radius, radius, radians(180),
radians(270),0);
CGPathAddArc(path, NULL, rw+rx-radius, ry+radius, radius, radians
(270), radians(360),0);
CGPathAddLineToPoint(path,NULL,rw+rx,rh+ry);
CGPathAddLineToPoint(path,NULL,rx,rh+ry);
CGPathCloseSubpath(path);
// fill with dropshadow
float clr[4] = {0.0,0.0,0.0,0.5};
CGColorRef shadowColor = CGColorCreate(cspace,clr);
CGContextSetShadowWithColor(context,CGSizeMake(0.0,-2.0),
5.0,shadowColor);
CGContextAddPath(context,path);
CGContextSetRGBFillColor(context,kJAWhite,kJAWhite,kJAWhite,kJAAlpha);
CGContextFillPath(context);
// clear fill area
CGContextAddPath(context,path);
CGContextClip(context);
CGContextClearRect(context,CGRectMake
(0,0,rect.size.width,rect.size.height));
// fill again without shadow
CGContextSetShadowWithColor(context,CGSizeZero,0,NULL);
CGContextAddPath(context,path);
CGContextSetRGBFillColor
(context,kJAWhite,kJAWhite,kJAWhite,kJAAlpha-.1);
CGContextFillPath(context);
// thin outline
CGContextSetLineWidth(context, 6.0);
CGContextSetShadowWithColor(context,CGSizeMake(0,0),1,shadowColor);
CGContextAddPath(context,path);
CGContextSetRGBStrokeColor(context,1,1,1,1);
CGContextStrokePath(context);
// resize corner
float stx, enx, len;
len = (rw/5);
if (len>30.) len=30.;
stx = rx + (rw/2.) - (len/2.);
enx = rx + (rw/2.) + (len/2.);
CGContextSetShadowWithColor(context,CGSizeMake(0,0),2,shadowColor);
CGContextSetRGBStrokeColor(context,1.,1.,1.,.99);
CGContextSetLineWidth(context, 6.);
CGContextMoveToPoint(context,rx+0,ry+radius+5);
CGContextAddArc(context, rx+radius+1,ry+radius+1,radius+1,radians
(180),radians(270),0);
CGContextAddLineToPoint(context,rx+radius+5,ry+0);
CGContextStrokePath(context);
CGColorRelease(shadowColor);
CGContextFlush(context);
CGImageRef smallImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
free(imageData);
// create CGLayers
CGRect srcR;
CGImageRef tile;
CGRect tileR = CGRectMake(0,0,kTileSize,kTileSize);
CGContextRef lcontext;
for (i=0; i<9; i++) {
int ox = (i%3) * kTileSize;
int oy = (i/3) * kTileSize;
srcR = CGRectMake(ox,oy,kTileSize,kTileSize);
tile = CGImageCreateWithImageInRect(smallImage,srcR);
players[i] = CGLayerCreateWithContext(context,CGSizeMake
(kTileSize,kTileSize),NULL);
lcontext = CGLayerGetContext(players[i]);
CGContextDrawImage(lcontext,tileR,tile);
CGContextFlush(lcontext);
}
CGImageRelease(smallImage);
}_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden