зеркало из https://github.com/mozilla/gecko-dev.git
Backing out changes. My changes did not support building with libxul disabled.
This commit is contained in:
Коммит
058dcfdea9
|
@ -83,9 +83,6 @@ child:
|
|||
// special cases where we need to a shared memory buffer
|
||||
rpc NPP_HandleEvent_Shmem(NPRemoteEvent event, Shmem buffer)
|
||||
returns (int16_t handled, Shmem rtnbuffer);
|
||||
// special cases where we need an iosurface
|
||||
rpc NPP_HandleEvent_IOSurface(NPRemoteEvent event, uint32_t surfaceid)
|
||||
returns (int16_t handled);
|
||||
// special cases of HandleEvent to make mediating races simpler
|
||||
rpc Paint(NPRemoteEvent event)
|
||||
returns (int16_t handled);
|
||||
|
|
|
@ -80,6 +80,7 @@ using mozilla::gfx::SharedDIB;
|
|||
#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
|
||||
#elif defined(XP_MACOSX)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include "nsPluginUtilsOSX.h"
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
||||
|
@ -100,9 +101,8 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
|||
#endif // OS_WIN
|
||||
, mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex")
|
||||
#if defined(OS_MACOSX)
|
||||
, mShColorSpace(nsnull)
|
||||
, mShContext(nsnull)
|
||||
, mDrawingModel(NPDrawingModelCoreGraphics)
|
||||
, mShColorSpace(NULL)
|
||||
, mShContext(NULL)
|
||||
#endif
|
||||
{
|
||||
memset(&mWindow, 0, sizeof(mWindow));
|
||||
|
@ -344,7 +344,7 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
|
|||
}
|
||||
|
||||
case NPNVsupportsCoreAnimationBool: {
|
||||
*((NPBool*)aValue) = true;
|
||||
*((NPBool*)aValue) = false;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,6 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
|
|||
|
||||
if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &rv))
|
||||
return NPERR_GENERIC_ERROR;
|
||||
mDrawingModel = drawingModel;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -590,7 +589,6 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
|
|||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
|
||||
Shmem& mem,
|
||||
|
@ -660,65 +658,6 @@ PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
|
||||
const uint32_t &surfaceid,
|
||||
int16_t* handled)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
AssertPluginThread();
|
||||
|
||||
NPCocoaEvent evcopy = event.event;
|
||||
nsIOSurface* surf = nsIOSurface::LookupSurface(surfaceid);
|
||||
if (!surf) {
|
||||
NS_ERROR("Invalid IOSurface.\n");
|
||||
*handled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (evcopy.type == NPCocoaEventDrawRect) {
|
||||
mCARenderer.AttachIOSurface(surf);
|
||||
if (!mCARenderer.isInit()) {
|
||||
void *caLayer = nsnull;
|
||||
NPError result = mPluginIface->getvalue(GetNPP(),
|
||||
NPPVpluginCoreAnimationLayer,
|
||||
&caLayer);
|
||||
if (result != NPERR_NO_ERROR || !caLayer) {
|
||||
PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
|
||||
"provide CALayer."));
|
||||
*handled = false;
|
||||
return false;
|
||||
}
|
||||
mCARenderer.SetupRenderer(caLayer, mWindow.width, mWindow.height);
|
||||
// Flash needs to have the window set again after this step
|
||||
if (mPluginIface->setwindow)
|
||||
(void) mPluginIface->setwindow(&mData, &mWindow);
|
||||
}
|
||||
} else {
|
||||
PLUGIN_LOG_DEBUG(("Invalid event type for "
|
||||
"AnswerNNP_HandleEvent_IOSurface."));
|
||||
*handled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
mCARenderer.Render(mWindow.width, mWindow.height, nsnull);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
|
||||
const uint32_t &surfaceid,
|
||||
int16_t* handled)
|
||||
{
|
||||
NS_RUNTIMEABORT("NPP_HandleEvent_IOSurface is a OSX-only message");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
|
||||
{
|
||||
|
@ -860,7 +799,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
|||
// Release the shared context so that it is reallocated
|
||||
// with the new size.
|
||||
::CGContextRelease(mShContext);
|
||||
mShContext = nsnull;
|
||||
mShContext = NULL;
|
||||
}
|
||||
|
||||
if (mPluginIface->setwindow)
|
||||
|
|
|
@ -44,9 +44,6 @@
|
|||
#include "mozilla/plugins/StreamNotifyChild.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "mozilla/gfx/SharedDIBWin.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "nsCoreAnimationSupport.h"
|
||||
#include "base/timer.h"
|
||||
#endif
|
||||
|
||||
#include "npfunctions.h"
|
||||
|
@ -93,8 +90,6 @@ protected:
|
|||
AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled);
|
||||
virtual bool
|
||||
AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, Shmem& mem, int16_t* handled, Shmem* rtnmem);
|
||||
virtual bool
|
||||
AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event, const uint32_t& surface, int16_t* handled);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual bool
|
||||
|
@ -328,9 +323,7 @@ private:
|
|||
#if defined(OS_MACOSX)
|
||||
private:
|
||||
CGColorSpaceRef mShColorSpace;
|
||||
CGContextRef mShContext;
|
||||
int16_t mDrawingModel;
|
||||
nsCARenderer mCARenderer;
|
||||
CGContextRef mShContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -61,13 +61,13 @@ UINT gOOPPStopNativeLoopEvent =
|
|||
#include <gdk/gdk.h>
|
||||
#elif defined(XP_MACOSX)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include "nsPluginUtilsOSX.h"
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
using namespace mozilla::plugins;
|
||||
|
||||
PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
||||
NPP npp,
|
||||
const nsCString& aMimeType,
|
||||
const NPNetscapeFuncs* npniface)
|
||||
: mParent(parent)
|
||||
, mNPP(npp)
|
||||
|
@ -78,29 +78,12 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
|||
, mPluginWndProc(NULL)
|
||||
, mNestedEventState(false)
|
||||
#endif // defined(XP_WIN)
|
||||
, mQuirks(0)
|
||||
#if defined(XP_MACOSX)
|
||||
, mShWidth(0)
|
||||
, mShHeight(0)
|
||||
, mShColorSpace(nsnull)
|
||||
, mDrawingModel(NPDrawingModelCoreGraphics)
|
||||
, mIOSurface(nsnull)
|
||||
, mShColorSpace(NULL)
|
||||
#endif
|
||||
{
|
||||
InitQuirksModes(aMimeType);
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceParent::InitQuirksModes(const nsCString& aMimeType)
|
||||
{
|
||||
#ifdef OS_MACOSX
|
||||
NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
|
||||
// Flash sends us Invalidate events so we will use those
|
||||
// instead of the refresh timer.
|
||||
if (!FindInReadable(flash, aMimeType)) {
|
||||
mQuirks |= COREANIMATION_REFRESH_TIMER;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PluginInstanceParent::~PluginInstanceParent()
|
||||
|
@ -113,13 +96,7 @@ PluginInstanceParent::~PluginInstanceParent()
|
|||
"Subclass was not reset correctly before the dtor was reached!");
|
||||
#endif
|
||||
#if defined(OS_MACOSX)
|
||||
if (mShColorSpace)
|
||||
::CGColorSpaceRelease(mShColorSpace);
|
||||
if (mIOSurface)
|
||||
delete mIOSurface;
|
||||
if (mDrawingModel == NPDrawingModelCoreAnimation) {
|
||||
mParent->RemoveFromRefreshTimer(this);
|
||||
}
|
||||
::CGColorSpaceRelease(mShColorSpace);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -352,22 +329,8 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel(
|
|||
const int& drawingModel, NPError* result)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
if (drawingModel == NPDrawingModelCoreAnimation) {
|
||||
// We need to request CoreGraphics otherwise
|
||||
// the nsObjectFrame will try to draw a CALayer
|
||||
// that can not be shared across process.
|
||||
mDrawingModel = NPDrawingModelCoreAnimation;
|
||||
*result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
|
||||
(void*)NPDrawingModelCoreGraphics);
|
||||
if (mQuirks & COREANIMATION_REFRESH_TIMER) {
|
||||
abort();
|
||||
mParent->AddToRefreshTimer(this);
|
||||
}
|
||||
} else {
|
||||
mDrawingModel = drawingModel;
|
||||
*result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
|
||||
*result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
|
||||
(void*)drawingModel);
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
*result = NPERR_GENERIC_ERROR;
|
||||
|
@ -513,24 +476,14 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
|||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
if (mShWidth != window.width || mShHeight != window.height) {
|
||||
if (mDrawingModel == NPDrawingModelCoreAnimation) {
|
||||
if (mIOSurface) {
|
||||
delete mIOSurface;
|
||||
}
|
||||
mIOSurface = nsIOSurface::CreateIOSurface(window.width, window.height);
|
||||
} else if (mShWidth * mShHeight != window.width * window.height) {
|
||||
// Uncomment me when DeallocShmem lands.
|
||||
//if (mShWidth != 0 && mShHeight != 0) {
|
||||
// DeallocShmem(&mShSurface);
|
||||
//}
|
||||
if (window.width != 0 && window.height != 0) {
|
||||
if (!AllocShmem(window.width * window.height*4,
|
||||
SharedMemory::TYPE_BASIC, &mShSurface)) {
|
||||
PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
if (mShWidth * mShHeight != window.width * window.height) {
|
||||
// XXX: benwa: OMG MEMORY LEAK!
|
||||
// There is currently no way dealloc the shmem
|
||||
// so for now we will leak the memory and will fix this ASAP!
|
||||
if (!AllocShmem(window.width * window.height * 4, SharedMemory::TYPE_BASIC,
|
||||
&mShSurface)) {
|
||||
PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
mShWidth = window.width;
|
||||
mShHeight = window.height;
|
||||
|
@ -727,85 +680,48 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
|
|||
|
||||
#ifdef XP_MACOSX
|
||||
if (npevent->type == NPCocoaEventDrawRect) {
|
||||
if (mDrawingModel == NPDrawingModelCoreAnimation) {
|
||||
if (!mIOSurface) {
|
||||
NS_ERROR("No IOSurface allocated.");
|
||||
return false;
|
||||
}
|
||||
if (!CallNPP_HandleEvent_IOSurface(npremoteevent,
|
||||
mIOSurface->GetIOSurfaceID(),
|
||||
&handled))
|
||||
return false; // no good way to handle errors here...
|
||||
|
||||
CGContextRef cgContext = npevent->data.draw.context;
|
||||
if (!mShColorSpace) {
|
||||
mShColorSpace = CreateSystemColorSpace();
|
||||
}
|
||||
if (!mShColorSpace) {
|
||||
PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
|
||||
return false;
|
||||
}
|
||||
nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface,
|
||||
mShColorSpace,
|
||||
npevent->data.draw.x,
|
||||
npevent->data.draw.y,
|
||||
npevent->data.draw.width,
|
||||
npevent->data.draw.height);
|
||||
if (mShWidth == 0 && mShHeight == 0) {
|
||||
PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0."));
|
||||
return false;
|
||||
} else {
|
||||
if (mShWidth == 0 && mShHeight == 0) {
|
||||
PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0."));
|
||||
return false;
|
||||
}
|
||||
if (!mShSurface.IsReadable()) {
|
||||
PLUGIN_LOG_DEBUG(("Shmem is not readable."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!mShSurface.IsReadable()) {
|
||||
PLUGIN_LOG_DEBUG(("Shmem is not readable."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface,
|
||||
&handled, &mShSurface))
|
||||
return false; // no good way to handle errors here...
|
||||
if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface, &handled, &mShSurface))
|
||||
return false; // no good way to handle errors here...
|
||||
|
||||
if (!mShSurface.IsReadable()) {
|
||||
PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed "
|
||||
"or we have a bug."));
|
||||
return false;
|
||||
}
|
||||
if (!mShSurface.IsReadable()) {
|
||||
PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed or we have a bug."));
|
||||
return false;
|
||||
}
|
||||
|
||||
char* shContextByte = mShSurface.get<char>();
|
||||
char* shContextByte = mShSurface.get<char>();
|
||||
|
||||
if (!mShColorSpace) {
|
||||
mShColorSpace = CreateSystemColorSpace();
|
||||
}
|
||||
if (!mShColorSpace) {
|
||||
PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
|
||||
return false;
|
||||
}
|
||||
CGContextRef shContext = ::CGBitmapContextCreate(shContextByte,
|
||||
mShWidth, mShHeight, 8,
|
||||
mShWidth*4, mShColorSpace,
|
||||
kCGImageAlphaPremultipliedFirst |
|
||||
kCGBitmapByteOrder32Host);
|
||||
if (!shContext) {
|
||||
PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
|
||||
return false;
|
||||
}
|
||||
|
||||
CGImageRef shImage = ::CGBitmapContextCreateImage(shContext);
|
||||
if (shImage) {
|
||||
CGContextRef cgContext = npevent->data.draw.context;
|
||||
|
||||
::CGContextDrawImage(cgContext,
|
||||
CGRectMake(0,0,mShWidth,mShHeight),
|
||||
shImage);
|
||||
::CGImageRelease(shImage);
|
||||
} else {
|
||||
::CGContextRelease(shContext);
|
||||
return false;
|
||||
}
|
||||
::CGContextRelease(shContext);
|
||||
if (!mShColorSpace) {
|
||||
mShColorSpace = CreateSystemColorSpace();
|
||||
}
|
||||
if (!mShColorSpace) {
|
||||
PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
|
||||
return true;
|
||||
}
|
||||
CGContextRef shContext = ::CGBitmapContextCreate(shContextByte,
|
||||
mShWidth, mShHeight, 8, mShWidth*4, mShColorSpace,
|
||||
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
|
||||
if (!shContext) {
|
||||
PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
|
||||
return true;
|
||||
}
|
||||
|
||||
CGImageRef shImage = ::CGBitmapContextCreateImage(shContext);
|
||||
if (shImage) {
|
||||
CGContextRef cgContext = npevent->data.draw.context;
|
||||
::CGContextDrawImage(cgContext, CGRectMake(0,0,mShWidth,mShHeight), shImage);
|
||||
::CGImageRelease(shImage);
|
||||
}
|
||||
::CGContextRelease(shContext);
|
||||
return handled;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1341,12 +1257,3 @@ PluginInstanceParent::RecvSetNestedEventState(const bool& aState)
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
void
|
||||
PluginInstanceParent::Invalidate()
|
||||
{
|
||||
NPRect windowRect = {0, 0, mShWidth, mShHeight};
|
||||
RecvNPN_InvalidateRect(windowRect);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
#include "mozilla/plugins/PluginScriptableObjectParent.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "mozilla/gfx/SharedDIBWin.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "nsCoreAnimationSupport.h"
|
||||
#endif
|
||||
|
||||
#include "npfunctions.h"
|
||||
|
@ -68,7 +66,6 @@ class PluginInstanceParent : public PPluginInstanceParent
|
|||
public:
|
||||
PluginInstanceParent(PluginModuleParent* parent,
|
||||
NPP npp,
|
||||
const nsCString& mimeType,
|
||||
const NPNetscapeFuncs* npniface);
|
||||
|
||||
virtual ~PluginInstanceParent();
|
||||
|
@ -249,21 +246,7 @@ public:
|
|||
virtual bool
|
||||
RecvSetNestedEventState(const bool& aState);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void Invalidate();
|
||||
#endif // definied(OS_MACOSX)
|
||||
|
||||
private:
|
||||
// Quirks mode support for various plugin mime types
|
||||
enum PluginQuirks {
|
||||
// OSX: Don't use the refresh timer for plug-ins
|
||||
// using this quirk. These plug-in most have another
|
||||
// way to refresh the window.
|
||||
COREANIMATION_REFRESH_TIMER = 1,
|
||||
};
|
||||
|
||||
void InitQuirksModes(const nsCString& aMimeType);
|
||||
|
||||
bool InternalGetValueForNPObject(NPNVariable aVariable,
|
||||
PPluginScriptableObjectParent** aValue,
|
||||
NPError* aResult);
|
||||
|
@ -273,7 +256,6 @@ private:
|
|||
NPP mNPP;
|
||||
const NPNetscapeFuncs* mNPNIface;
|
||||
NPWindowType mWindowType;
|
||||
int mQuirks;
|
||||
|
||||
nsDataHashtable<nsVoidPtrHashKey, PluginScriptableObjectParent*> mScriptableObjects;
|
||||
|
||||
|
@ -300,12 +282,10 @@ private:
|
|||
#endif // defined(XP_WIN)
|
||||
#if defined(OS_MACOSX)
|
||||
private:
|
||||
Shmem mShSurface;
|
||||
size_t mShWidth;
|
||||
size_t mShHeight;
|
||||
CGColorSpaceRef mShColorSpace;
|
||||
int16_t mDrawingModel;
|
||||
nsIOSurface *mIOSurface;
|
||||
Shmem mShSurface;
|
||||
size_t mShWidth;
|
||||
size_t mShHeight;
|
||||
CGColorSpaceRef mShColorSpace;
|
||||
#endif // definied(OS_MACOSX)
|
||||
};
|
||||
|
||||
|
|
|
@ -87,8 +87,6 @@ MediateRace(const RPCChannel::Message& parent,
|
|||
switch (parent.type()) {
|
||||
case PPluginInstance::Msg_Paint__ID:
|
||||
case PPluginInstance::Msg_NPP_SetWindow__ID:
|
||||
case PPluginInstance::Msg_NPP_HandleEvent_Shmem__ID:
|
||||
case PPluginInstance::Msg_NPP_HandleEvent_IOSurface__ID:
|
||||
// our code relies on the frame list not changing during paints and
|
||||
// reflows
|
||||
return RPCChannel::RRPParentWins;
|
||||
|
|
|
@ -715,8 +715,7 @@ PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
|
|||
}
|
||||
|
||||
PluginInstanceParent* parentInstance =
|
||||
new PluginInstanceParent(this, instance,
|
||||
nsDependentCString(pluginType), mNPNIface);
|
||||
new PluginInstanceParent(this, instance, mNPNIface);
|
||||
|
||||
if (!parentInstance->Init()) {
|
||||
delete parentInstance;
|
||||
|
@ -783,35 +782,3 @@ PluginModuleParent::AnswerProcessSomeEvents()
|
|||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
#define DEFAULT_REFRESH_MS 20 // CoreAnimation: 50 FPS
|
||||
void
|
||||
PluginModuleParent::AddToRefreshTimer(PluginInstanceParent *aInstance) {
|
||||
if (mCATimerTargets.Contains(aInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCATimerTargets.AppendElement(aInstance);
|
||||
if (mCATimerTargets.Length() == 1) {
|
||||
mCATimer.Start(base::TimeDelta::FromMilliseconds(DEFAULT_REFRESH_MS),
|
||||
this, &PluginModuleParent::CAUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::RemoveFromRefreshTimer(PluginInstanceParent *aInstance) {
|
||||
PRBool visibleRemoved = mCATimerTargets.RemoveElement(aInstance);
|
||||
if (visibleRemoved && mCATimerTargets.IsEmpty()) {
|
||||
mCATimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleParent::CAUpdate() {
|
||||
nsTObserverArray<PluginInstanceParent*>::ForwardIterator iter(mCATimerTargets);
|
||||
while (iter.HasMore()) {
|
||||
iter.GetNext()->Invalidate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsTObserverArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
@ -135,11 +134,6 @@ public:
|
|||
PPluginIdentifierParent*
|
||||
GetIdentifierForNPIdentifier(NPIdentifier aIdentifier);
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
void AddToRefreshTimer(PluginInstanceParent *aInstance);
|
||||
void RemoveFromRefreshTimer(PluginInstanceParent *aInstance);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual mozilla::ipc::RPCChannel::RacyRPCPolicy
|
||||
|
@ -246,12 +240,6 @@ private:
|
|||
nsString mPluginDumpID;
|
||||
nsString mBrowserDumpID;
|
||||
nsString mHangID;
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
void CAUpdate();
|
||||
base::RepeatingTimer<PluginModuleParent> mCATimer;
|
||||
nsTObserverArray<PluginInstanceParent*> mCATimerTargets;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -69,6 +69,7 @@ EXPORTS = \
|
|||
nsIScrollableFrame.h \
|
||||
nsIStatefulFrame.h \
|
||||
nsFrameSelection.h \
|
||||
nsPluginUtilsOSX.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef IBMBIDI
|
||||
|
|
|
@ -164,7 +164,6 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
|||
#ifdef XP_MACOSX
|
||||
#include "gfxQuartzNativeDrawing.h"
|
||||
#include "nsPluginUtilsOSX.h"
|
||||
#include "nsCoreAnimationSupport.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_X11
|
||||
|
@ -3592,24 +3591,13 @@ void nsPluginInstanceOwner::SetupCARenderer(int aWidth, int aHeight)
|
|||
if (!caLayer) {
|
||||
return;
|
||||
}
|
||||
nsresult rt = mCARenderer.SetupRenderer(caLayer, aWidth, aHeight);
|
||||
if (rt != NS_OK)
|
||||
return;
|
||||
mCARenderer.SetupRenderer(caLayer, aWidth, aHeight);
|
||||
AddToCARefreshTimer(this);
|
||||
}
|
||||
|
||||
void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight)
|
||||
{
|
||||
CGImageRef caImage = NULL;
|
||||
nsresult rt = mCARenderer.Render(aWidth, aHeight, &caImage);
|
||||
if (rt == NS_OK && caImage != NULL) {
|
||||
// Significant speed up by resetting the scaling
|
||||
::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone );
|
||||
::CGContextTranslateCTM(aCGContext, 0, aHeight);
|
||||
::CGContextScaleCTM(aCGContext, 1.0, -1.0);
|
||||
|
||||
::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage);
|
||||
}
|
||||
mCARenderer.Render(aCGContext, aWidth, aHeight);
|
||||
}
|
||||
|
||||
void* nsPluginInstanceOwner::GetPluginPortCopy()
|
||||
|
|
|
@ -64,3 +64,25 @@ NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
|
|||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace);
|
||||
|
||||
// Get the system color space.
|
||||
CGColorSpaceRef CreateSystemColorSpace();
|
||||
|
||||
// Manages a CARenderer
|
||||
struct _CGLPBufferObject;
|
||||
struct _CGLContextObject;
|
||||
class nsCARenderer {
|
||||
public:
|
||||
nsCARenderer() : mCARenderer(NULL), mPixelBuffer(NULL), mOpenGLContext(NULL),
|
||||
mCGImage(NULL), mCGData(NULL) {}
|
||||
~nsCARenderer();
|
||||
nsresult SetupRenderer(void* aCALayer, int aWidth, int aHeight);
|
||||
nsresult Render(CGContextRef aCGContext, int aWidth, int aHeight);
|
||||
private:
|
||||
void Destroy();
|
||||
|
||||
void *mCARenderer;
|
||||
_CGLPBufferObject *mPixelBuffer;
|
||||
_CGLContextObject *mOpenGLContext;
|
||||
CGImageRef mCGImage;
|
||||
void *mCGData;
|
||||
};
|
||||
|
|
|
@ -217,3 +217,196 @@ NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsCARenderer::~nsCARenderer() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
CGColorSpaceRef CreateSystemColorSpace() {
|
||||
CMProfileRef system_profile = NULL;
|
||||
CGColorSpaceRef cspace = NULL;
|
||||
|
||||
if (::CMGetSystemProfile(&system_profile) == noErr) {
|
||||
// Create a colorspace with the systems profile
|
||||
cspace = ::CGColorSpaceCreateWithPlatformColorSpace(system_profile);
|
||||
::CMCloseProfile(system_profile);
|
||||
} else {
|
||||
// Default to generic
|
||||
cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
||||
}
|
||||
|
||||
return cspace;
|
||||
}
|
||||
|
||||
void cgdata_release_callback(void *aCGData, const void *data, size_t size) {
|
||||
if (aCGData) {
|
||||
free(aCGData);
|
||||
}
|
||||
}
|
||||
|
||||
void nsCARenderer::Destroy() {
|
||||
if (mCARenderer) {
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
// Bug 556453:
|
||||
// Explicitly remove the layer from the renderer
|
||||
// otherwise it does not always happen right away.
|
||||
caRenderer.layer = NULL;
|
||||
[caRenderer release];
|
||||
}
|
||||
if (mPixelBuffer) {
|
||||
::CGLDestroyPBuffer((CGLPBufferObj)mPixelBuffer);
|
||||
}
|
||||
if (mOpenGLContext) {
|
||||
::CGLDestroyContext((CGLContextObj)mOpenGLContext);
|
||||
}
|
||||
if (mCGImage) {
|
||||
::CGImageRelease(mCGImage);
|
||||
}
|
||||
// mCGData is deallocated by cgdata_release_callback
|
||||
|
||||
mCARenderer = nil;
|
||||
mPixelBuffer = NULL;
|
||||
mOpenGLContext = NULL;
|
||||
mCGImage = NULL;
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight) {
|
||||
CALayer* layer = (CALayer*)aCALayer;
|
||||
CARenderer* caRenderer = NULL;
|
||||
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
kCGLPFANoRecovery,
|
||||
kCGLPFAAccelerated,
|
||||
kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
|
||||
(CGLPixelFormatAttribute)0
|
||||
};
|
||||
|
||||
CGLError result = ::CGLCreatePBuffer(aWidth, aHeight,
|
||||
GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, &mPixelBuffer);
|
||||
if (result != kCGLNoError) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
GLint screen;
|
||||
CGLPixelFormatObj format;
|
||||
if (::CGLChoosePixelFormat(attributes, &format, &screen) != kCGLNoError) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (::CGLCreateContext(format, NULL, &mOpenGLContext) != kCGLNoError) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
::CGLDestroyPixelFormat(format);
|
||||
|
||||
caRenderer = [[CARenderer rendererWithCGLContext:mOpenGLContext options:NULL] retain];
|
||||
mCARenderer = caRenderer;
|
||||
if (caRenderer == nil) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
[layer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[layer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)];
|
||||
caRenderer.layer = layer;
|
||||
caRenderer.bounds = CGRectMake(0, 0, aWidth, aHeight);
|
||||
|
||||
mCGData = malloc(aWidth*aHeight*4);
|
||||
if (!mCGData) {
|
||||
Destroy();
|
||||
}
|
||||
CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(mCGData,
|
||||
mCGData, aHeight*aWidth*4, cgdata_release_callback);
|
||||
if (!dataProvider) {
|
||||
cgdata_release_callback(mCGData, mCGData, aHeight*aWidth*4);
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CGColorSpaceRef colorSpace = CreateSystemColorSpace();
|
||||
|
||||
mCGImage = ::CGImageCreate(aWidth, aHeight, 8, 32, aWidth * 4,
|
||||
colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, NULL, true, kCGRenderingIntentDefault);
|
||||
|
||||
::CGDataProviderRelease(dataProvider);
|
||||
if (colorSpace) {
|
||||
::CGColorSpaceRelease(colorSpace);
|
||||
}
|
||||
|
||||
if (!mCGImage) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::Render(CGContextRef aCGContext, int aWidth, int aHeight) {
|
||||
|
||||
if (!mCARenderer)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
int renderer_width = caRenderer.bounds.size.width;
|
||||
int renderer_height = caRenderer.bounds.size.height;
|
||||
|
||||
if (renderer_width != aWidth || renderer_height != aHeight) {
|
||||
// XXX: This should be optimized to not rescale the buffer
|
||||
// if we are resizing down.
|
||||
CALayer* caLayer = [caRenderer layer];
|
||||
Destroy();
|
||||
if (SetupRenderer(caLayer, aWidth, aHeight) != NPERR_NO_ERROR) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
caRenderer = (CARenderer*)mCARenderer;
|
||||
}
|
||||
GLint screen;
|
||||
CGLContextObj oldContext = ::CGLGetCurrentContext();
|
||||
::CGLSetCurrentContext(mOpenGLContext);
|
||||
::CGLGetVirtualScreen(mOpenGLContext, &screen);
|
||||
::CGLSetPBuffer(mOpenGLContext, mPixelBuffer, 0, 0, screen);
|
||||
|
||||
::glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
::glViewport(0.0, 0.0, aWidth, aHeight);
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
::glLoadIdentity();
|
||||
::glOrtho (0.0, aWidth, 0.0, aHeight, -1, 1);
|
||||
::glClear(GL_COLOR_BUFFER_BIT);
|
||||
// Render upside down to speed up CGContextDrawImage
|
||||
::glTranslatef(0.0f, aHeight, 0.0);
|
||||
::glScalef(1.0, -1.0, 1.0);
|
||||
|
||||
double caTime = ::CACurrentMediaTime();
|
||||
[caRenderer beginFrameAtTime:caTime timeStamp:NULL];
|
||||
[caRenderer addUpdateRect:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[caRenderer render];
|
||||
[caRenderer endFrame];
|
||||
|
||||
::glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
::glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
::glPixelStorei(GL_PACK_SKIP_ROWS, 0);
|
||||
::glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
|
||||
|
||||
::glReadPixels(0.0f, 0.0f, aWidth, aHeight,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
mCGData);
|
||||
|
||||
if (oldContext) {
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
}
|
||||
|
||||
// Significant speed up by reseting the scaling
|
||||
::CGContextSetInterpolationQuality( aCGContext, kCGInterpolationNone );
|
||||
::CGContextTranslateCTM( aCGContext, 0, aHeight);
|
||||
::CGContextScaleCTM( aCGContext, 1.0, -1.0);
|
||||
|
||||
CGRect drawRect;
|
||||
drawRect.origin.x = 0;
|
||||
drawRect.origin.y = 0;
|
||||
drawRect.size.width = aWidth;
|
||||
drawRect.size.height = aHeight;
|
||||
::CGContextDrawImage( aCGContext, drawRect, mCGImage );
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,10 +57,6 @@ EXPORTS_mozilla = \
|
|||
PluginPRLibrary.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsCoreAnimationSupport.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsNPAPIPlugin.cpp \
|
||||
nsNPAPIPluginInstance.cpp \
|
||||
|
@ -87,7 +83,6 @@ else
|
|||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += nsPluginsDirDarwin.cpp
|
||||
CPPSRCS += nsPluginNativeWindow.cpp
|
||||
CMMSRCS += nsCoreAnimationSupport.mm
|
||||
else
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||
CPPSRCS += nsPluginsDirUnix.cpp
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:set ts=2 sts=2 sw=2 et cin:
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* bgirard <b56girard@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsCoreAnimationSupport_h__
|
||||
#define nsCoreAnimationSupport_h__
|
||||
#ifdef XP_MACOSX
|
||||
|
||||
#import "ApplicationServices/ApplicationServices.h"
|
||||
#include "nscore.h"
|
||||
|
||||
// Get the system color space.
|
||||
CGColorSpaceRef CreateSystemColorSpace();
|
||||
|
||||
// Manages a CARenderer
|
||||
struct _CGLPBufferObject;
|
||||
struct _CGLContextObject;
|
||||
class nsIOSurface;
|
||||
|
||||
class nsCARenderer {
|
||||
public:
|
||||
nsCARenderer() : mCARenderer(nsnull), mPixelBuffer(nsnull), mOpenGLContext(nsnull),
|
||||
mCGImage(nsnull), mCGData(nsnull), mIOSurface(nsnull), mFBO(nsnull),
|
||||
mIOTexture(nsnull) {}
|
||||
~nsCARenderer();
|
||||
nsresult SetupRenderer(void* aCALayer, int aWidth, int aHeight);
|
||||
nsresult Render(int aWidth, int aHeight, CGImageRef *aOutCAImage);
|
||||
bool isInit() { return mCARenderer != nsnull; }
|
||||
/*
|
||||
* Render the CALayer to an IOSurface. If no IOSurface
|
||||
* is attached then an internal pixel buffer will be
|
||||
* used.
|
||||
*/
|
||||
void AttachIOSurface(nsIOSurface *aSurface);
|
||||
static nsresult DrawSurfaceToCGContext(CGContextRef aContext,
|
||||
nsIOSurface *surf,
|
||||
CGColorSpaceRef aColorSpace,
|
||||
int aX, int aY,
|
||||
int aWidth, int aHeight);
|
||||
private:
|
||||
void Destroy();
|
||||
|
||||
void *mCARenderer;
|
||||
_CGLPBufferObject *mPixelBuffer;
|
||||
_CGLContextObject *mOpenGLContext;
|
||||
CGImageRef mCGImage;
|
||||
void *mCGData;
|
||||
nsIOSurface *mIOSurface;
|
||||
uint32_t mFBO;
|
||||
uint32_t mIOTexture;
|
||||
};
|
||||
|
||||
typedef uint32_t IOSurfaceID;
|
||||
|
||||
class nsIOSurface {
|
||||
public:
|
||||
static nsIOSurface *CreateIOSurface(int aWidth, int aHeight);
|
||||
static void ReleaseIOSurface(nsIOSurface *aIOSurface);
|
||||
static nsIOSurface *LookupSurface(IOSurfaceID aSurfaceID);
|
||||
|
||||
nsIOSurface(CFTypeRef aIOSurfacePtr) : mIOSurfacePtr(aIOSurfacePtr) {}
|
||||
~nsIOSurface() { CFRelease(mIOSurfacePtr); }
|
||||
IOSurfaceID GetIOSurfaceID();
|
||||
void *GetBaseAddress();
|
||||
size_t GetWidth();
|
||||
size_t GetHeight();
|
||||
size_t GetBytesPerRow();
|
||||
void Lock();
|
||||
void Unlock();
|
||||
private:
|
||||
friend class nsCARenderer;
|
||||
CFTypeRef mIOSurfacePtr;
|
||||
};
|
||||
|
||||
#endif // XP_MACOSX
|
||||
#endif // nsCoreAnimationSupport_h__
|
||||
|
|
@ -1,722 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:set ts=2 sts=2 sw=2 et cin:
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <b56girard@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsCoreAnimationSupport.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define IOSURFACE_FRAMEWORK_PATH \
|
||||
"/System/Library/Frameworks/IOSurface.framework/IOSurface"
|
||||
#define OPENGL_FRAMEWORK_PATH \
|
||||
"/System/Library/Frameworks/OpenGL.framework/OpenGL"
|
||||
|
||||
|
||||
// IOSurface signatures
|
||||
typedef CFTypeRef IOSurfacePtr;
|
||||
typedef IOSurfacePtr (*IOSurfaceCreateFunc) (CFDictionaryRef properties);
|
||||
typedef IOSurfacePtr (*IOSurfaceLookupFunc) (uint32_t io_surface_id);
|
||||
typedef IOSurfaceID (*IOSurfaceGetIDFunc) (CFTypeRef io_surface);
|
||||
typedef IOReturn (*IOSurfaceLockFunc) (CFTypeRef io_surface,
|
||||
uint32_t options,
|
||||
uint32_t *seed);
|
||||
typedef IOReturn (*IOSurfaceUnlockFunc) (CFTypeRef io_surface,
|
||||
uint32_t options,
|
||||
uint32_t *seed);
|
||||
typedef void* (*IOSurfaceGetBaseAddressFunc) (CFTypeRef io_surface);
|
||||
typedef size_t (*IOSurfaceGetWidthFunc) (IOSurfacePtr io_surface);
|
||||
typedef size_t (*IOSurfaceGetHeightFunc) (IOSurfacePtr io_surface);
|
||||
typedef size_t (*IOSurfaceGetBytesPerRowFunc) (IOSurfacePtr io_surface);
|
||||
typedef CGLError (*CGLTexImageIOSurface2DFunc) (CGLContextObj ctxt,
|
||||
GLenum target, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
IOSurfacePtr ioSurface, GLuint plane);
|
||||
|
||||
#define GET_CONST(const_name) \
|
||||
((CFStringRef*) dlsym(sIOSurfaceFramework, const_name))
|
||||
#define GET_IOSYM(dest,sym_name) \
|
||||
(typeof(dest)) dlsym(sIOSurfaceFramework, sym_name)
|
||||
#define GET_CGLSYM(dest,sym_name) \
|
||||
(typeof(dest)) dlsym(sOpenGLFramework, sym_name)
|
||||
|
||||
class nsIOSurfaceLib: public nsIOSurface {
|
||||
public:
|
||||
static void *sIOSurfaceFramework;
|
||||
static void *sOpenGLFramework;
|
||||
static bool isLoaded;
|
||||
static IOSurfaceCreateFunc sCreate;
|
||||
static IOSurfaceGetIDFunc sGetID;
|
||||
static IOSurfaceLookupFunc sLookup;
|
||||
static IOSurfaceGetBaseAddressFunc sGetBaseAddress;
|
||||
static IOSurfaceLockFunc sLock;
|
||||
static IOSurfaceUnlockFunc sUnlock;
|
||||
static IOSurfaceGetWidthFunc sWidth;
|
||||
static IOSurfaceGetHeightFunc sHeight;
|
||||
static IOSurfaceGetBytesPerRowFunc sBytesPerRow;
|
||||
static CGLTexImageIOSurface2DFunc sTexImage;
|
||||
static CFStringRef kPropWidth;
|
||||
static CFStringRef kPropHeight;
|
||||
static CFStringRef kPropBytesPerElem;
|
||||
static CFStringRef kPropBytesPerRow;
|
||||
static CFStringRef kPropIsGlobal;
|
||||
|
||||
static bool isInit();
|
||||
static CFStringRef GetIOConst(const char* symbole);
|
||||
static IOSurfacePtr IOSurfaceCreate(CFDictionaryRef properties);
|
||||
static IOSurfacePtr IOSurfaceLookup(IOSurfaceID aIOSurfaceID);
|
||||
static IOSurfaceID IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr);
|
||||
static void *IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr);
|
||||
static size_t IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr);
|
||||
static size_t IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr);
|
||||
static size_t IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr);
|
||||
static IOReturn IOSurfaceLock(IOSurfacePtr aIOSurfacePtr,
|
||||
uint32_t options, uint32_t *seed);
|
||||
static IOReturn IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr,
|
||||
uint32_t options, uint32_t *seed);
|
||||
static CGLError CGLTexImageIOSurface2D(CGLContextObj ctxt,
|
||||
GLenum target, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
IOSurfacePtr ioSurface, GLuint plane);
|
||||
static void LoadLibrary();
|
||||
static void CloseLibrary();
|
||||
|
||||
// Static deconstructor
|
||||
static class LibraryUnloader {
|
||||
public:
|
||||
~LibraryUnloader() {
|
||||
CloseLibrary();
|
||||
}
|
||||
} sLibraryUnloader;
|
||||
};
|
||||
|
||||
nsIOSurfaceLib::LibraryUnloader nsIOSurfaceLib::sLibraryUnloader;
|
||||
bool nsIOSurfaceLib::isLoaded = false;
|
||||
void* nsIOSurfaceLib::sIOSurfaceFramework;
|
||||
void* nsIOSurfaceLib::sOpenGLFramework;
|
||||
IOSurfaceCreateFunc nsIOSurfaceLib::sCreate;
|
||||
IOSurfaceGetIDFunc nsIOSurfaceLib::sGetID;
|
||||
IOSurfaceLookupFunc nsIOSurfaceLib::sLookup;
|
||||
IOSurfaceGetBaseAddressFunc nsIOSurfaceLib::sGetBaseAddress;
|
||||
IOSurfaceGetHeightFunc nsIOSurfaceLib::sWidth;
|
||||
IOSurfaceGetWidthFunc nsIOSurfaceLib::sHeight;
|
||||
IOSurfaceGetBytesPerRowFunc nsIOSurfaceLib::sBytesPerRow;
|
||||
IOSurfaceLockFunc nsIOSurfaceLib::sLock;
|
||||
IOSurfaceUnlockFunc nsIOSurfaceLib::sUnlock;
|
||||
CGLTexImageIOSurface2DFunc nsIOSurfaceLib::sTexImage;
|
||||
CFStringRef nsIOSurfaceLib::kPropWidth;
|
||||
CFStringRef nsIOSurfaceLib::kPropHeight;
|
||||
CFStringRef nsIOSurfaceLib::kPropBytesPerElem;
|
||||
CFStringRef nsIOSurfaceLib::kPropBytesPerRow;
|
||||
CFStringRef nsIOSurfaceLib::kPropIsGlobal;
|
||||
|
||||
bool nsIOSurfaceLib::isInit() {
|
||||
// Guard against trying to reload the library
|
||||
// if it is not available.
|
||||
if (!isLoaded)
|
||||
LoadLibrary();
|
||||
if (!sIOSurfaceFramework) {
|
||||
NS_ERROR("nsIOSurfaceLib failed to initialize");
|
||||
}
|
||||
return sIOSurfaceFramework;
|
||||
}
|
||||
|
||||
IOSurfacePtr nsIOSurfaceLib::IOSurfaceCreate(CFDictionaryRef properties) {
|
||||
return sCreate(properties);
|
||||
}
|
||||
|
||||
IOSurfacePtr nsIOSurfaceLib::IOSurfaceLookup(IOSurfaceID aIOSurfaceID) {
|
||||
return sLookup(aIOSurfaceID);
|
||||
}
|
||||
|
||||
IOSurfaceID nsIOSurfaceLib::IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr) {
|
||||
return sGetID(aIOSurfacePtr);
|
||||
}
|
||||
|
||||
void* nsIOSurfaceLib::IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr) {
|
||||
return sGetBaseAddress(aIOSurfacePtr);
|
||||
}
|
||||
|
||||
size_t nsIOSurfaceLib::IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr) {
|
||||
return sWidth(aIOSurfacePtr);
|
||||
}
|
||||
|
||||
size_t nsIOSurfaceLib::IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr) {
|
||||
return sHeight(aIOSurfacePtr);
|
||||
}
|
||||
|
||||
size_t nsIOSurfaceLib::IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr) {
|
||||
return sBytesPerRow(aIOSurfacePtr);
|
||||
}
|
||||
|
||||
IOReturn nsIOSurfaceLib::IOSurfaceLock(IOSurfacePtr aIOSurfacePtr,
|
||||
uint32_t options, uint32_t *seed) {
|
||||
return sLock(aIOSurfacePtr, options, seed);
|
||||
}
|
||||
|
||||
IOReturn nsIOSurfaceLib::IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr,
|
||||
uint32_t options, uint32_t *seed) {
|
||||
return sUnlock(aIOSurfacePtr, options, seed);
|
||||
}
|
||||
|
||||
CGLError nsIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt,
|
||||
GLenum target, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
IOSurfacePtr ioSurface, GLuint plane) {
|
||||
return sTexImage(ctxt, target, internalFormat, width, height,
|
||||
format, type, ioSurface, plane);
|
||||
}
|
||||
|
||||
CFStringRef nsIOSurfaceLib::GetIOConst(const char* symbole) {
|
||||
CFStringRef *address = (CFStringRef*)dlsym(sIOSurfaceFramework, symbole);
|
||||
if (!address)
|
||||
return nsnull;
|
||||
|
||||
return *address;
|
||||
}
|
||||
|
||||
void nsIOSurfaceLib::LoadLibrary() {
|
||||
if (isLoaded) {
|
||||
return;
|
||||
}
|
||||
isLoaded = true;
|
||||
sIOSurfaceFramework = dlopen(IOSURFACE_FRAMEWORK_PATH,
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
sOpenGLFramework = dlopen(OPENGL_FRAMEWORK_PATH,
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!sIOSurfaceFramework) {
|
||||
return;
|
||||
}
|
||||
if (!sOpenGLFramework) {
|
||||
dlclose(sIOSurfaceFramework);
|
||||
sIOSurfaceFramework = nsnull;
|
||||
return;
|
||||
}
|
||||
|
||||
kPropWidth = GetIOConst("kIOSurfaceWidth");
|
||||
kPropHeight = GetIOConst("kIOSurfaceHeight");
|
||||
kPropBytesPerElem = GetIOConst("kIOSurfaceBytesPerElement");
|
||||
kPropBytesPerRow = GetIOConst("kIOSurfaceBytesPerRow");
|
||||
kPropIsGlobal = GetIOConst("kIOSurfaceIsGlobal");
|
||||
sCreate = GET_IOSYM(sCreate, "IOSurfaceCreate");
|
||||
sGetID = GET_IOSYM(sGetID, "IOSurfaceGetID");
|
||||
sWidth = GET_IOSYM(sWidth, "IOSurfaceGetWidth");
|
||||
sHeight = GET_IOSYM(sHeight, "IOSurfaceGetHeight");
|
||||
sBytesPerRow = GET_IOSYM(sBytesPerRow, "IOSurfaceGetBytesPerRow");
|
||||
sLookup = GET_IOSYM(sLookup, "IOSurfaceLookup");
|
||||
sLock = GET_IOSYM(sLock, "IOSurfaceLock");
|
||||
sUnlock = GET_IOSYM(sUnlock, "IOSurfaceUnlock");
|
||||
sGetBaseAddress = GET_IOSYM(sGetBaseAddress, "IOSurfaceGetBaseAddress");
|
||||
sTexImage = GET_CGLSYM(sTexImage, "CGLTexImageIOSurface2D");
|
||||
|
||||
if (!sCreate || !sGetID || !sLookup || !sTexImage || !sGetBaseAddress ||
|
||||
!kPropWidth || !kPropHeight || !kPropBytesPerElem || !kPropIsGlobal ||
|
||||
!sLock || !sUnlock || !sWidth || !sHeight || !kPropBytesPerRow ||
|
||||
!sBytesPerRow) {
|
||||
CloseLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
void nsIOSurfaceLib::CloseLibrary() {
|
||||
if (sIOSurfaceFramework) {
|
||||
dlclose(sIOSurfaceFramework);
|
||||
}
|
||||
if (sOpenGLFramework) {
|
||||
dlclose(sOpenGLFramework);
|
||||
}
|
||||
sIOSurfaceFramework = nsnull;
|
||||
sOpenGLFramework = nsnull;
|
||||
}
|
||||
|
||||
nsIOSurface* nsIOSurface::CreateIOSurface(int aWidth, int aHeight) {
|
||||
if (!nsIOSurfaceLib::isInit())
|
||||
return nsnull;
|
||||
|
||||
CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
|
||||
kCFAllocatorDefault, 4,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
if (!props)
|
||||
return nsnull;
|
||||
|
||||
int32_t bytesPerElem = 4;
|
||||
CFNumberRef cfWidth = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &aWidth);
|
||||
CFNumberRef cfHeight = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &aHeight);
|
||||
CFNumberRef cfBytesPerElem = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &bytesPerElem);
|
||||
::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropWidth,
|
||||
cfWidth);
|
||||
::CFRelease(cfWidth);
|
||||
::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropHeight,
|
||||
cfHeight);
|
||||
::CFRelease(cfHeight);
|
||||
::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropBytesPerElem,
|
||||
cfBytesPerElem);
|
||||
::CFRelease(cfBytesPerElem);
|
||||
::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropIsGlobal,
|
||||
kCFBooleanTrue);
|
||||
|
||||
IOSurfacePtr surfaceRef = nsIOSurfaceLib::IOSurfaceCreate(props);
|
||||
::CFRelease(props);
|
||||
|
||||
if (!surfaceRef)
|
||||
return nsnull;
|
||||
|
||||
nsIOSurface* ioSurface = new nsIOSurface(surfaceRef);
|
||||
if (!ioSurface) {
|
||||
::CFRelease(surfaceRef);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return ioSurface;
|
||||
}
|
||||
|
||||
nsIOSurface* nsIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID) {
|
||||
if (!nsIOSurfaceLib::isInit())
|
||||
return nsnull;
|
||||
|
||||
IOSurfacePtr surfaceRef = nsIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID);
|
||||
if (!surfaceRef)
|
||||
return nsnull;
|
||||
// IOSurfaceLookup does not retain the object for us,
|
||||
// we want IOSurfacePtr to remain for the lifetime of
|
||||
// nsIOSurface.
|
||||
CFRetain(surfaceRef);
|
||||
|
||||
nsIOSurface* ioSurface = new nsIOSurface(surfaceRef);
|
||||
if (!ioSurface) {
|
||||
::CFRelease(ioSurface);
|
||||
return nsnull;
|
||||
}
|
||||
return ioSurface;
|
||||
}
|
||||
|
||||
IOSurfaceID nsIOSurface::GetIOSurfaceID() {
|
||||
return nsIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr);
|
||||
}
|
||||
|
||||
void* nsIOSurface::GetBaseAddress() {
|
||||
return nsIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr);
|
||||
}
|
||||
|
||||
size_t nsIOSurface::GetWidth() {
|
||||
return nsIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr);
|
||||
}
|
||||
|
||||
size_t nsIOSurface::GetHeight() {
|
||||
return nsIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr);
|
||||
}
|
||||
|
||||
size_t nsIOSurface::GetBytesPerRow() {
|
||||
return nsIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr);
|
||||
}
|
||||
|
||||
#define READ_ONLY 0x1
|
||||
void nsIOSurface::Lock() {
|
||||
nsIOSurfaceLib::IOSurfaceLock(mIOSurfacePtr, READ_ONLY, NULL);
|
||||
}
|
||||
|
||||
void nsIOSurface::Unlock() {
|
||||
nsIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, NULL);
|
||||
}
|
||||
|
||||
nsCARenderer::~nsCARenderer() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
CGColorSpaceRef CreateSystemColorSpace() {
|
||||
CMProfileRef system_profile = nsnull;
|
||||
CGColorSpaceRef cspace = nsnull;
|
||||
|
||||
if (::CMGetSystemProfile(&system_profile) == noErr) {
|
||||
// Create a colorspace with the systems profile
|
||||
cspace = ::CGColorSpaceCreateWithPlatformColorSpace(system_profile);
|
||||
::CMCloseProfile(system_profile);
|
||||
} else {
|
||||
// Default to generic
|
||||
cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
||||
}
|
||||
|
||||
return cspace;
|
||||
}
|
||||
|
||||
void cgdata_release_callback(void *aCGData, const void *data, size_t size) {
|
||||
if (aCGData) {
|
||||
free(aCGData);
|
||||
}
|
||||
}
|
||||
|
||||
void nsCARenderer::Destroy() {
|
||||
if (mCARenderer) {
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
// Bug 556453:
|
||||
// Explicitly remove the layer from the renderer
|
||||
// otherwise it does not always happen right away.
|
||||
caRenderer.layer = nsnull;
|
||||
[caRenderer release];
|
||||
}
|
||||
if (mPixelBuffer) {
|
||||
::CGLDestroyPBuffer((CGLPBufferObj)mPixelBuffer);
|
||||
}
|
||||
if (mOpenGLContext) {
|
||||
if (mFBO || mIOTexture) {
|
||||
// Release these resources with the context that allocated them
|
||||
CGLContextObj oldContext = ::CGLGetCurrentContext();
|
||||
::CGLSetCurrentContext(mOpenGLContext);
|
||||
|
||||
if (mIOTexture) {
|
||||
::glDeleteTextures(1, &mIOTexture);
|
||||
}
|
||||
if (mFBO) {
|
||||
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
::glDeleteFramebuffersEXT(1, &mFBO);
|
||||
}
|
||||
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
}
|
||||
::CGLDestroyContext((CGLContextObj)mOpenGLContext);
|
||||
}
|
||||
if (mCGImage) {
|
||||
::CGImageRelease(mCGImage);
|
||||
}
|
||||
if (mIOSurface) {
|
||||
delete mIOSurface;
|
||||
}
|
||||
// mCGData is deallocated by cgdata_release_callback
|
||||
|
||||
mCARenderer = nil;
|
||||
mPixelBuffer = nsnull;
|
||||
mOpenGLContext = nsnull;
|
||||
mCGImage = nsnull;
|
||||
mIOSurface = nsnull;
|
||||
mFBO = nsnull;
|
||||
mIOTexture = nsnull;
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight) {
|
||||
CALayer* layer = (CALayer*)aCALayer;
|
||||
CARenderer* caRenderer = nsnull;
|
||||
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
kCGLPFANoRecovery,
|
||||
kCGLPFAAccelerated,
|
||||
kCGLPFAPBuffer,
|
||||
kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
|
||||
(CGLPixelFormatAttribute)0
|
||||
};
|
||||
|
||||
if (!mIOSurface) {
|
||||
CGLError result = ::CGLCreatePBuffer(aWidth, aHeight,
|
||||
GL_TEXTURE_2D, GL_RGBA, 0, &mPixelBuffer);
|
||||
if (result != kCGLNoError) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
GLint screen;
|
||||
CGLPixelFormatObj format;
|
||||
if (::CGLChoosePixelFormat(attributes, &format, &screen) != kCGLNoError) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (::CGLCreateContext(format, nsnull, &mOpenGLContext) != kCGLNoError) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
::CGLDestroyPixelFormat(format);
|
||||
|
||||
caRenderer = [[CARenderer rendererWithCGLContext:mOpenGLContext
|
||||
options:nil] retain];
|
||||
mCARenderer = caRenderer;
|
||||
if (caRenderer == nil) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
[layer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[layer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)];
|
||||
caRenderer.layer = layer;
|
||||
caRenderer.bounds = CGRectMake(0, 0, aWidth, aHeight);
|
||||
|
||||
if (aWidth == 0 || aHeight == 0) {
|
||||
// No need to allocate if size is 0
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We either target rendering to a CGImage or IOSurface.
|
||||
if (!mIOSurface) {
|
||||
mCGData = malloc(aWidth*aHeight*4);
|
||||
if (!mCGData) {
|
||||
Destroy();
|
||||
}
|
||||
memset(mCGData, 0, aWidth*aHeight*4);
|
||||
|
||||
CGDataProviderRef dataProvider = nsnull;
|
||||
dataProvider = ::CGDataProviderCreateWithData(mCGData,
|
||||
mCGData, aHeight*aWidth*4,
|
||||
cgdata_release_callback);
|
||||
if (!dataProvider) {
|
||||
cgdata_release_callback(mCGData, mCGData, aHeight*aWidth*4);
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CGColorSpaceRef colorSpace = CreateSystemColorSpace();
|
||||
|
||||
mCGImage = ::CGImageCreate(aWidth, aHeight, 8, 32, aWidth * 4, colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, NULL, true, kCGRenderingIntentDefault);
|
||||
|
||||
::CGDataProviderRelease(dataProvider);
|
||||
if (colorSpace) {
|
||||
::CGColorSpaceRelease(colorSpace);
|
||||
}
|
||||
if (!mCGImage) {
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
CGLContextObj oldContext = ::CGLGetCurrentContext();
|
||||
::CGLSetCurrentContext(mOpenGLContext);
|
||||
|
||||
// Create the IOSurface mapped texture.
|
||||
::glGenTextures(1, &mIOTexture);
|
||||
::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
|
||||
::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
nsIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
|
||||
GL_RGBA, aWidth, aHeight,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
mIOSurface->mIOSurfacePtr, 0);
|
||||
::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
// Create the fbo
|
||||
::glGenFramebuffersEXT(1, &mFBO);
|
||||
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
|
||||
::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_RECTANGLE_ARB, mIOTexture, 0);
|
||||
|
||||
// Make sure that the Framebuffer configuration is supported on the client machine
|
||||
GLenum fboStatus;
|
||||
fboStatus = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
NS_ERROR("FBO not supported\n");
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
}
|
||||
|
||||
CGLContextObj oldContext = ::CGLGetCurrentContext();
|
||||
::CGLSetCurrentContext(mOpenGLContext);
|
||||
|
||||
::glViewport(0.0, 0.0, aWidth, aHeight);
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
::glLoadIdentity();
|
||||
::glOrtho (0.0, aWidth, 0.0, aHeight, -1, 1);
|
||||
|
||||
// Render upside down to speed up CGContextDrawImage
|
||||
::glTranslatef(0.0f, aHeight, 0.0);
|
||||
::glScalef(1.0, -1.0, 1.0);
|
||||
|
||||
GLenum result = ::glGetError();
|
||||
if (result != GL_NO_ERROR) {
|
||||
NS_ERROR("Unexpected OpenGL Error\n");
|
||||
Destroy();
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsCARenderer::AttachIOSurface(nsIOSurface *aSurface) {
|
||||
if (mIOSurface &&
|
||||
aSurface->GetIOSurfaceID() == mIOSurface->GetIOSurfaceID()) {
|
||||
delete aSurface;
|
||||
return;
|
||||
}
|
||||
if (mCARenderer) {
|
||||
// We are attaching a larger IOSurface, we need to
|
||||
// resize our elements.
|
||||
Destroy();
|
||||
}
|
||||
if (mIOSurface)
|
||||
delete mIOSurface;
|
||||
|
||||
mIOSurface = aSurface;
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
||||
CGImageRef *aOutCGImage) {
|
||||
if (aOutCGImage && mIOSurface) {
|
||||
NS_WARNING("CGImageRef should not be passed if we are "
|
||||
"drawing to an IOSurface");
|
||||
} else if (aOutCGImage) {
|
||||
// We are expected to return a CGImageRef, we will set
|
||||
// it to NULL in case we fail before the image is ready.
|
||||
*aOutCGImage = NULL;
|
||||
}
|
||||
|
||||
if (aWidth == 0 || aHeight == 0)
|
||||
return NS_OK;
|
||||
|
||||
if (!mCARenderer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
int renderer_width = caRenderer.bounds.size.width;
|
||||
int renderer_height = caRenderer.bounds.size.height;
|
||||
|
||||
if (renderer_width != aWidth || renderer_height != aHeight) {
|
||||
// XXX: This should be optimized to not rescale the buffer
|
||||
// if we are resizing down.
|
||||
CALayer* caLayer = [caRenderer layer];
|
||||
Destroy();
|
||||
if (SetupRenderer(caLayer, aWidth, aHeight) != NS_OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
caRenderer = (CARenderer*)mCARenderer;
|
||||
}
|
||||
|
||||
CGLContextObj oldContext = ::CGLGetCurrentContext();
|
||||
::CGLSetCurrentContext(mOpenGLContext);
|
||||
if (!mIOSurface) {
|
||||
::CGLSetPBuffer(mOpenGLContext, mPixelBuffer, 0, 0, 0);
|
||||
}
|
||||
|
||||
GLenum result = ::glGetError();
|
||||
if (result != GL_NO_ERROR) {
|
||||
NS_ERROR("Unexpected OpenGL Error\n");
|
||||
Destroy();
|
||||
if (oldContext)
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
::glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
::glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
double caTime = ::CACurrentMediaTime();
|
||||
[caRenderer beginFrameAtTime:caTime timeStamp:NULL];
|
||||
[caRenderer addUpdateRect:CGRectMake(0,0, aWidth, aHeight)];
|
||||
[caRenderer render];
|
||||
[caRenderer endFrame];
|
||||
|
||||
// Read the data back either to the IOSurface or mCGImage.
|
||||
if (mIOSurface) {
|
||||
::glFlush();
|
||||
} else {
|
||||
::glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
::glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
::glPixelStorei(GL_PACK_SKIP_ROWS, 0);
|
||||
::glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
|
||||
|
||||
::glReadPixels(0.0f, 0.0f, aWidth, aHeight,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
mCGData);
|
||||
|
||||
*aOutCGImage = mCGImage;
|
||||
}
|
||||
|
||||
if (oldContext) {
|
||||
::CGLSetCurrentContext(oldContext);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
||||
nsIOSurface *surf,
|
||||
CGColorSpaceRef aColorSpace,
|
||||
int aX, int aY,
|
||||
int aWidth, int aHeight) {
|
||||
surf->Lock();
|
||||
size_t bytesPerRow = surf->GetBytesPerRow();
|
||||
size_t ioWidth = surf->GetWidth();
|
||||
size_t ioHeight = surf->GetHeight();
|
||||
void* ioData = surf->GetBaseAddress();
|
||||
CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
|
||||
ioData, ioHeight*(bytesPerRow)*4,
|
||||
NULL); //No release callback
|
||||
if (!dataProvider) {
|
||||
surf->Unlock();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow,
|
||||
aColorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
|
||||
dataProvider, NULL, true, kCGRenderingIntentDefault);
|
||||
::CGDataProviderRelease(dataProvider);
|
||||
if (!cgImage) {
|
||||
surf->Unlock();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
CGImageRef subImage = ::CGImageCreateWithImageInRect(cgImage,
|
||||
::CGRectMake(aX, aY, aWidth, aHeight));
|
||||
if (!subImage) {
|
||||
::CGImageRelease(cgImage);
|
||||
surf->Unlock();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
::CGContextTranslateCTM(aContext, 0.0f, float(aHeight));
|
||||
::CGContextScaleCTM(aContext, 1.0f, -1.0f);
|
||||
::CGContextTranslateCTM(aContext, aX, -aY);
|
||||
CGContextDrawImage(aContext, CGRectMake(0, 0, aWidth, aHeight), subImage);
|
||||
|
||||
::CGImageRelease(subImage);
|
||||
::CGImageRelease(cgImage);
|
||||
surf->Unlock();
|
||||
return NS_OK;
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче