NPAPI:CoreAnimationDrawingModel

Status

Accepted

Background

Currently, the only way for a plug-in on Mac to use OpenGL is to attach an AGL surface manually. This has a number of drawbacks:

  • The plug-in has to move the surface in response to page scrolling, window resizing, etc
  • The plug-in needs access to the browser window's WindowRef
  • AGL is a Carbon based API and does not work in 64-bit

The Core Animation drawing model aims to solve these problems (and more) by letting the plug-in hand off a Core Animation layer to the browser. It is then up to the browser to position and size the layer.

Current Proposal

Last modified: January 17, 2010 Authors: Anders Carlsson (Apple Inc), Kevin Decker (Apple Inc) Contributors: Josh Aas (Mozilla Corporation)

Querying for availability

A plug-in may, in it's NPP_New callback negotiate a drawing model. It can call NPN_GetValue with the

NPNVsupportsCoreAnimationBool = 2003

NPNVariable to query the browser for whether the Core Animation drawing model is supported. The argument is an NPBool.

The plug-in can then call NPN_SetValue to tell the browser to use the Core Animation drawing model, using the

NPNVpluginDrawingModel = 1000

NPNVariable and the

NPDrawingModelCoreAnimation = 3 

drawing model enumeration, cast to a void pointer.

The Core Animation drawing model only works together with the Cocoa Event Model. If the plug-in tries to use the Carbon Event model with the Core Animation drawing model, the browser will destroy the plug-in after it has been instantiated.

Vending a layer

When the plug-in has selected the drawing model, the browser will call NPP_GetValue with the

NPPVpluginCoreAnimationLayer = 1003

NPPVariable. The value should be treated as a CALayer * pointer, which the plug-in should fill in with a _retained_ layer. For example:

NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
    PluginObject *obj = instance->pdata;

    switch (variable) {
        case NPPVpluginCoreAnimationLayer:
            if (!obj->layer) {
                obj->layer = createLayer();
            }
            
            // Make sure to return a retained layer
            *((CALayer **)value) = [obj->layer retain];
            
            return NPERR_NO_ERROR;
            
        default:
            return NPERR_GENERIC_ERROR;
    }
}

CALayer lifecycle

The browser is not responsible for releasing retained CALayer objects it receives via the "NPPVpluginCoreAnimationLayer" variable. The browser may additionally retain layers (perhaps by attaching them to views). A plugin may release the layer for an instance during or after the instance's NPP_Destroy call.