• 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: NSView drawRect: QuickDraw, CoreGraphics, OpenGL ? DP.2
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSView drawRect: QuickDraw, CoreGraphics, OpenGL ? DP.2


  • Subject: Re: NSView drawRect: QuickDraw, CoreGraphics, OpenGL ? DP.2
  • From: Nat! <email@hidden>
  • Date: Thu, 31 Oct 2002 01:04:39 +0100

<continuing from part 1>

Well, back to your question...

You should keep the following things in mind whenever you want to draw a
bitmap as fast as possible with Quartz:

1) Be absolutely sure that your bitmap data is in one of the formats which
Quartz understands natively. I.e. use 32bit true color with the alpha
channel in the _highest_ 8bits (ARGB / XRGB). Don't use RGBA or RGBX as this
will easily cut your drawing performance by half because Quartz has to spend
extra time in converting from your "wrong" format into one of its native
formats. You specify the relative location of the alpha channel and whether
your data contains an alpha channel at all with the CGImageAlphaInfo
enumeration. However, never use kCGImageAlphaNone for a bitmap without an
alpha channel because it maps to kCGImageAlphaNoneSkipLast which is one of
the inefficient bitmap formats...

2) Use a direct access data provider for your bitmap data on MacOS X 10.2. A
direct access data provider can simply return a pointer to the bitmap data,
thus it avoids the otherwise necessary copy step.

3) In case your CTM contains scaling, rotation or skew (I'm not sure about
sub-pixel translations) either create your CGImage with interpolation turned
off, or select a low interpolation quality in your CGContext (i.e.
kCGInterpolationLow). Image interpolation can be a very expensive process
depending on the type of pixel filter which the context implementation uses.

4) Create your CGImage with the same color space than the output device has.
You may need to use ColorSync directly in order to convert your pixels from
the source color space to the device color space.

5) In case your bitmap is fully opaque, switch the alpha composition
function to NSCompositeCopy by adding the following call to your code before
you draw the CGImage:

CGContextSetCompositeOperation(ctx, NSCompositeCopy);

The prototype is:

void CGContextSetCompositeOperation(CGContextRef, int);

WARNING: The above call is currently (still) a privat Quartz call. It may
stop to work in the future, although is has been available since at least
MacOS X 10.0. And yes, I have _absolutely_ no understanding for the fact
that _basic_ and _fundamental_ functions like this one are still private.


A possible Quartz bitmap drawing example code might look like the following
(works only on MacOS X 10.2 'cause of the direct access provider stuff):

static const void *get_byte_pointer(void *bitmap)
{
return bitmap;
}

CGDataProviderDirectAccessCallbacks gProviderCallbacks = {
get_byte_pointer,
NULL,
NULL,
NULL
};

- (void)drawRect: (NSRect)rect
{
CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];

if(_bitmap == NULL) {
size_t numBytes = kBitmapWidth * kBitmapHeight * 4;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();

_bitmap = malloc(numBytes);
_provider = CGDataProviderCreateDirectAccess(_bitmap,
numBytes, &gProviderCallbacks);
_cgImage = CGImageCreate(kBitmapWidth, kBitmapHeight,
8, 32, kBitmapWidth * 4, cs,
kCGImageAlphaNoneSkipFirst, _provider, NULL,
FALSE, kCGRenderingIntentAbsoluteColormetric);
CGColorSpaceRelease(cs);

// fill bitmap by either loading an image into it or by
// wrapping a CGBitmapContext around it and using that
// for drawing into it with Quartz calls
}

CGContextDrawImage(ctx,
CGRectMake(0.0, 0.0, kBitmapWidth, kBitmapHeight},
_cgImage);
}

Caution: Don't work with bitmaps which are too small because Quartz has a
relatively high base overhead. Thats due to things like locking/unlocking
the window backbuffer or checking whether the pixels must be format or color
converted. The overhead is neglectable for bitmap sizes > 32x32.

If your code already takes all the above points into account and in fact
Sampler.app tells you that the vast majority of blitting time is spent in
one of the XXX_image_mark Quartz routines, but you're still not satisfied
with drawing performance, then its time to think about moving to OpenGL.

The first step in this case should be the clarification into which of the
following categories your blitting needs fall:

A) You need to draw a _static_ bitmap very often per second.

The important aspect here is that the bitmap stays as it is for a very long
time and just needs to be drawn in various different places many times per
second.
The ideal solution to this problem is that we move the bitmap data after its
creation as close as possible to the GPU. This can be accomplished in OGL by
uploading the bitmap as a texture into VRAM. The bitmap is then displayed by
drawing an OGL quad with texture mapping turned on.

B) You need to draw a _dynamic_ bitmap often per second.

Contrary to above, the bitmap changes very often, in the extreme case once
per frame. Here, the goal should be to get the bitmap as fast as possible to
the GPU. This can be done in OGL by taking advantage of Apple's special
texture range extension which allows you to texture from RAM via AGP.
Documentation about the APPLE_texture_range extension can be found on
Apple's OGL home page. The "OpenGL Image" example from Apple uses this
technique in order to display large bitmaps via OGL and to allow the
rotation, zooming and translation of the bitmap in real-time.


Regards,

Dietmar Planitzer

------------------------------------------------------
Certainly there is no hunting like the hunting of man,
and those who have hunted armed men long enough and
like it, never really care for anything else
thereafter. -- Hemingway
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

  • Prev by Date: Re: NSView drawRect: QuickDraw, CoreGraphics, OpenGL ? DP.1
  • Next by Date: Better random screensaver
  • Previous by thread: NSDocuments without window associations
  • Next by thread: Better random screensaver
  • Index(es):
    • Date
    • Thread