• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Quickest Drawing Method
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


References: 
 >Re: Quickest Drawing Method (From: spiderlama <email@hidden>)
 >Re: Quickest Drawing Method (From: arri <email@hidden>)

  • Prev by Date: Re: Quickest Drawing Method
  • Next by Date: Re: Filling bezier path with the image
  • Previous by thread: Re: Quickest Drawing Method
  • Next by thread: Re: Quickest Drawing Method
  • Index(es):
    • Date
    • Thread