summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authortschmelcher@google.com <tschmelcher@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-08 01:30:39 +0000
committertschmelcher@google.com <tschmelcher@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-08 01:30:39 +0000
commitd35284f80eb34dd212e9370410d43aea31d20573 (patch)
treeefbbf64b2f981740c03a542ea0c201da6c3d3813 /o3d
parent33b74c951ab655b43d40c4c75d08d04c1c4f71f2 (diff)
downloadchromium_src-d35284f80eb34dd212e9370410d43aea31d20573.zip
chromium_src-d35284f80eb34dd212e9370410d43aea31d20573.tar.gz
chromium_src-d35284f80eb34dd212e9370410d43aea31d20573.tar.bz2
Add support for Core Graphics with Carbon, allowing us to use Core Graphics in Firefox (since it does not support Cocoa). This lets us use O2D in FF without porting it to Quickdraw.
Also tweak the drawing model behaviour so that we select the best possible model for the requested RenderMode. TEST=RenderMode=Auto and =2D in FF on an MBP6,2 and verified 2D avoids issues with the dynamic GPU switching feature of that hardware; RenderMode=2D in Chrome and Safari BUG=none Review URL: http://codereview.chromium.org/6626059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77223 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/core/cross/features.h9
-rw-r--r--o3d/core/cross/renderer.h2
-rw-r--r--o3d/plugin/cross/o3d_glue.h1
-rw-r--r--o3d/plugin/mac/fullscreen_window_mac.mm4
-rw-r--r--o3d/plugin/mac/main_mac.mm161
-rw-r--r--o3d/plugin/mac/plugin_mac.h2
6 files changed, 115 insertions, 64 deletions
diff --git a/o3d/core/cross/features.h b/o3d/core/cross/features.h
index 0445e30..133eb3a 100644
--- a/o3d/core/cross/features.h
+++ b/o3d/core/cross/features.h
@@ -82,10 +82,15 @@ class Features {
return init_status_;
}
- Renderer::RenderModes render_mode() const {
+ Renderer::RenderMode render_mode() const {
return render_mode_;
}
+ // For use by SuppressRenderModeAuto() in main_mac.mm.
+ void set_render_mode(Renderer::RenderMode render_mode) {
+ render_mode_ = render_mode;
+ }
+
private:
// Parses the features strings.
// Parameters:
@@ -103,7 +108,7 @@ class Features {
bool not_anti_aliased_;
bool flip_textures_;
Renderer::InitStatus init_status_;
- Renderer::RenderModes render_mode_;
+ Renderer::RenderMode render_mode_;
DISALLOW_COPY_AND_ASSIGN(Features);
};
diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h
index f198570..1970833 100644
--- a/o3d/core/cross/renderer.h
+++ b/o3d/core/cross/renderer.h
@@ -112,7 +112,7 @@ class Renderer {
DISPLAY_MODE_DEFAULT = 0
};
- enum RenderModes {
+ enum RenderMode {
RENDER_MODE_AUTO,
RENDER_MODE_3D,
RENDER_MODE_2D,
diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h
index 213687b..79cdcd9 100644
--- a/o3d/plugin/cross/o3d_glue.h
+++ b/o3d/plugin/cross/o3d_glue.h
@@ -346,6 +346,7 @@ class PluginObject: public NPObject {
void Init(int argc, char* argn[], char* argv[]);
void TearDown();
ServiceLocator* service_locator() { return &service_locator_; }
+ Features *features() { return features_; }
Client *client() { return client_; }
Renderer *renderer() { return renderer_; }
NPP npp() { return npp_; }
diff --git a/o3d/plugin/mac/fullscreen_window_mac.mm b/o3d/plugin/mac/fullscreen_window_mac.mm
index e2ba86c..cc5f26d 100644
--- a/o3d/plugin/mac/fullscreen_window_mac.mm
+++ b/o3d/plugin/mac/fullscreen_window_mac.mm
@@ -88,7 +88,7 @@ o3d::Event::Button MacOSMouseButtonNumberToO3DButton(int inButton) {
// Handles the CarbonEvents that we get sent for the fullscreen mode window.
// Most of these can be converted to EventRecord events and handled by the
-// HandleMacEvent() function in main_mac.mm, but some have no equivalent in
+// HandleCarbonEvent() function in main_mac.mm, but some have no equivalent in
// that space, scroll-wheel events for example, and so must be handled here.
static OSStatus HandleFullscreenWindow(EventHandlerCallRef inHandlerCallRef,
EventRef inEvent,
@@ -211,7 +211,7 @@ static OSStatus HandleFullscreenWindow(EventHandlerCallRef inHandlerCallRef,
EventRecord eventRecord;
if (ConvertEventRefToEventRecord(inEvent, &eventRecord)) {
- HandleMacEvent(&eventRecord, (NPP)inUserData);
+ HandleCarbonEvent(&eventRecord, (NPP)inUserData);
return noErr;
} else {
return eventNotHandledErr;
diff --git a/o3d/plugin/mac/main_mac.mm b/o3d/plugin/mac/main_mac.mm
index d06d305..eb08571 100644
--- a/o3d/plugin/mac/main_mac.mm
+++ b/o3d/plugin/mac/main_mac.mm
@@ -251,10 +251,8 @@ void DispatchMacKeyboardEvent(PluginObject* obj,
the_event->modifiers);
}
-
-
-void HandleMouseEvent(PluginObject* obj,
- EventRecord* the_event) {
+static void HandleCarbonMouseEvent(PluginObject* obj,
+ EventRecord* the_event) {
DCHECK(obj);
DCHECK(obj->client());
int screen_x = the_event->where.h;
@@ -292,11 +290,14 @@ void HandleMouseEvent(PluginObject* obj,
y = screen_y - wBounds.top;
in_plugin = true;
} else {
- Rect wBounds;
- GetWindowBounds(obj->mac_window_, kWindowGlobalPortRgn, &wBounds);
+ Rect wBounds;
+ GetWindowBounds(obj->mac_window_,
+ (obj->drawing_model_ == NPDrawingModelQuickDraw) ?
+ kWindowGlobalPortRgn : kWindowStructureRgn,
+ &wBounds);
x = screen_x - wBounds.left - obj->last_plugin_loc_.h;
y = screen_y - wBounds.top - obj->last_plugin_loc_.v;
- in_plugin = x >=0 && y >= 0 && x < obj->width() && y < obj->height();
+ in_plugin = x >= 0 && y >= 0 && x < obj->width() && y < obj->height();
}
o3d::Event event(type);
@@ -334,8 +335,8 @@ void HandleMouseEvent(PluginObject* obj,
// These events come from the new Cocoa revision of the NPAPI spec,
// currently implemented only in Safari.
// See https://wiki.mozilla.org/Mac:NPAPI_Event_Models
-void HandleCocoaMouseEvent(PluginObject* obj,
- NPCocoaEvent* the_event) {
+static void HandleCocoaMouseEvent(PluginObject* obj,
+ NPCocoaEvent* the_event) {
DCHECK(obj);
DCHECK(obj->client());
int screen_x = the_event->data.mouse.pluginX;
@@ -462,19 +463,34 @@ static bool PreferCoreAnimation() {
return (!isSafari || o3d::IsMacOSTenSixOrHigher());
}
+static void SuppressRenderModeAuto(PluginObject* obj) {
+ // If the web app specified RenderMode=Auto but the best available drawing
+ // model for 3D is one for which 2D is not implemented then we cannot
+ // provide an automatic 2D fallback because it is not legal to change drawing
+ // or event models outside of NPP_New(). To achieve a 2D fallback the web app
+ // will have to watch for initialization errors and reload the plugin with
+ // RenderMode=2D.
+ if (obj->features()->render_mode() == Renderer::RENDER_MODE_AUTO) {
+ DLOG(INFO) << "Suppressing RenderMode=Auto for incompatible drawing model";
+ obj->features()->set_render_mode(Renderer::RENDER_MODE_3D);
+ }
+}
+
// Negotiates the best plugin drawing and event model, sets the
// browser to use that, and updates the PluginObject so we can
// remember which one we chose. We prefer these combinations in the
// given order:
// - Core Animation drawing model, Cocoa event model
// - QuickDraw drawing model, Carbon event model
-// - Core Graphics drawing model, Cocoa event model
+// - Core Graphics drawing model, Cocoa or Carbon event model
// If the browser doesn't even understand the question, we use the
// QuickDraw drawing model and Carbon event model for best backward
// compatibility.
//
// This ordering provides the best forward-looking behavior while
-// still providing compatibility with older browsers.
+// still providing compatibility with older browsers. Even though Core Graphics
+// is newer than QuickDraw, we prefer QuickDraw when available because the Core
+// Graphics rendering path with OpenGL is pathologically sub-optimal.
//
// Returns NPERR_NO_ERROR (0) if successful, otherwise an NPError code.
NPError Mac_SetBestEventAndDrawingModel(NPP instance, PluginObject* obj) {
@@ -535,6 +551,8 @@ NPError Mac_SetBestEventAndDrawingModel(NPP instance, PluginObject* obj) {
// NPN_SetValue for the event or drawing models at all.
obj->drawing_model_ = NPDrawingModelQuickDraw;
obj->event_model_ = NPEventModelCarbon;
+ DLOG(INFO) << "Legacy browser, assuming QuickDraw and Carbon";
+ SuppressRenderModeAuto(obj);
return NPERR_NO_ERROR;
}
@@ -542,19 +560,29 @@ NPError Mac_SetBestEventAndDrawingModel(NPP instance, PluginObject* obj) {
NPDrawingModel drawing_model = NPDrawingModelQuickDraw;
NPEventModel event_model = NPEventModelCarbon;
- if (supportsCoreAnimation && supportsCocoaEventModel &&
+ // If the web app has requested 2D mode then we only want to select drawing
+ // models supported by RendererCairo (currently only Core Graphics).
+ bool wants_2d = obj->features()->render_mode() == Renderer::RENDER_MODE_2D;
+
+ if (!wants_2d && supportsCoreAnimation && supportsCocoaEventModel &&
PreferCoreAnimation()) {
drawing_model = NPDrawingModelCoreAnimation;
event_model = NPEventModelCocoa;
- DLOG(INFO) << "Core Animation drawing model";
- } else if (supportsQuickDraw && supportsCarbonEventModel) {
+ DLOG(INFO) << "Selecting Core Animation and Cocoa";
+ SuppressRenderModeAuto(obj);
+ } else if (!wants_2d && supportsQuickDraw && supportsCarbonEventModel) {
drawing_model = NPDrawingModelQuickDraw;
event_model = NPEventModelCarbon;
- DLOG(INFO) << "QuickDraw drawing model";
+ DLOG(INFO) << "Selecting QuickDraw and Carbon";
+ SuppressRenderModeAuto(obj);
} else if (supportsCoreGraphics && supportsCocoaEventModel) {
drawing_model = NPDrawingModelCoreGraphics;
event_model = NPEventModelCocoa;
- DLOG(INFO) << "Core Graphics drawing model";
+ DLOG(INFO) << "Selecting Core Graphics and Cocoa";
+ } else if (supportsCoreGraphics && supportsCarbonEventModel) {
+ drawing_model = NPDrawingModelCoreGraphics;
+ event_model = NPEventModelCarbon;
+ DLOG(INFO) << "Selecting Core Graphics and Carbon";
} else {
// If all of the above tests failed, we are running on a browser
// which we don't know how to handle.
@@ -671,7 +699,7 @@ NPError PlatformNPPGetValue(PluginObject *obj,
return NPERR_INVALID_PARAM;
}
-bool HandleMacEvent(EventRecord* the_event, NPP instance) {
+bool HandleCarbonEvent(EventRecord* the_event, NPP instance) {
PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
bool handled = false;
FullscreenWindowMac* fullscreen_window = obj->GetFullscreenMacWindow();
@@ -707,30 +735,36 @@ bool HandleMacEvent(EventRecord* the_event, NPP instance) {
obj->CancelFullscreenDisplay();
}
- // Send nullEvents to HandleMouseEvent so they can be used to simulate
- // mouse moved events. Not needed in fullscreen mode, where we really do
- // get mouse moved events. See the osEvt case below.
+ // Send nullEvents to HandleCarbonMouseEvent so they can be used to
+ // simulate mouse moved events. Not needed in fullscreen mode, where we
+ // really do get mouse moved events. See the osEvt case below.
if (!fullscreen_window)
- HandleMouseEvent(obj, the_event);
+ HandleCarbonMouseEvent(obj, the_event);
handled = true;
break;
case updateEvt:
- DrawPlugin(obj, false, obj->mac_cg_context_ref_);
+ // We dispatch a render callback from this point iff using Core Graphics.
+ // With CoreGraphics+Carbon this is the only source of rendering, whereas
+ // with QuickDraw+Carbon the main source of rendering is in
+ // RenderTimer::TimerCallback().
+ DrawPlugin(obj,
+ obj->drawing_model_ == NPDrawingModelCoreGraphics,
+ obj->mac_cg_context_ref_);
handled = true;
break;
case osEvt:
// These are mouse moved messages when so tagged in the high byte.
if ((the_event->message >> 24) == mouseMovedMessage) {
- HandleMouseEvent(obj, the_event);
+ HandleCarbonMouseEvent(obj, the_event);
handled = true;
}
break;
case mouseDown:
- HandleMouseEvent(obj, the_event);
+ HandleCarbonMouseEvent(obj, the_event);
break;
case mouseUp:
- HandleMouseEvent(obj, the_event);
+ HandleCarbonMouseEvent(obj, the_event);
handled = true;
break;
case keyDown:
@@ -995,40 +1029,51 @@ NPError PlatformNPPSetWindow(NPP instance,
CGLSetCurrentContext(obj->mac_cgl_context_);
}
} else if (obj->drawing_model_ == NPDrawingModelCoreGraphics) {
- // TODO(tschmelcher): We could skip this when RenderMode is 2D (though it's
- // harmless).
- if (obj->mac_cgl_pbuffer_ == NULL) {
+ // It's important to skip this when RenderMode=2D is specified because it
+ // can make OSX on an MBP6,2 flip between the Intel and NVIDIA GPUs multiple
+ // times in FF, which significantly delays our start-up.
+ if (obj->features()->render_mode() != Renderer::RENDER_MODE_2D &&
+ obj->mac_cgl_pbuffer_ == NULL) {
// We initialize things with a CGL context rendering to a 1x1
// pbuffer. Later we use the O3D RenderSurface APIs to set up the
// framebuffer object which is used for rendering.
CGLContextObj share_context = obj->GetFullscreenShareContext();
CGLPixelFormatObj pixel_format = obj->GetFullscreenCGLPixelFormatObj();
- DCHECK(share_context);
- CGLError result;
- CGLContextObj context;
- result = CGLCreateContext(pixel_format, share_context, &context);
- if (result != kCGLNoError) {
- DLOG(ERROR) << "Error " << result << " creating context.";
- return NPERR_GENERIC_ERROR;
- }
- CGLPBufferObj pbuffer;
- if ((result = CGLCreatePBuffer(1, 1,
- GL_TEXTURE_2D, GL_RGBA,
- 0, &pbuffer)) != kCGLNoError) {
- CGLDestroyContext(context);
- DLOG(ERROR) << "Error " << result << " creating pbuffer.";
- return NPERR_GENERIC_ERROR;
- }
- if ((result = CGLSetPBuffer(context, pbuffer, 0, 0, 0)) != kCGLNoError) {
- CGLDestroyContext(context);
- CGLDestroyPBuffer(pbuffer);
- DLOG(ERROR) << "Error " << result << " attaching pbuffer to context.";
- return NPERR_GENERIC_ERROR;
+ if (!share_context || !pixel_format) {
+ // This can happen in FF when using Core Graphics, though curiously
+ // only on certain websites.
+ LOG(ERROR) << "Failed to create share context and/or pixel format";
+ // We continue initializing, though without a CGLContextObj RendererGL
+ // will fail to initialize. If the web app is using RenderMode=Auto
+ // though then Cairo will work.
+ } else {
+ CGLError result;
+ CGLContextObj context;
+ result = CGLCreateContext(pixel_format, share_context, &context);
+ if (result != kCGLNoError) {
+ DLOG(ERROR) << "Error " << result << " creating context.";
+ return NPERR_GENERIC_ERROR;
+ }
+ CGLPBufferObj pbuffer;
+ if ((result = CGLCreatePBuffer(1, 1,
+ GL_TEXTURE_2D, GL_RGBA,
+ 0, &pbuffer)) != kCGLNoError) {
+ CGLDestroyContext(context);
+ DLOG(ERROR) << "Error " << result << " creating pbuffer.";
+ return NPERR_GENERIC_ERROR;
+ }
+ if ((result = CGLSetPBuffer(context, pbuffer, 0, 0, 0)) !=
+ kCGLNoError) {
+ CGLDestroyContext(context);
+ CGLDestroyPBuffer(pbuffer);
+ DLOG(ERROR) << "Error " << result << " attaching pbuffer to context.";
+ return NPERR_GENERIC_ERROR;
+ }
+ // Must make the context current for renderer creation to succeed
+ CGLSetCurrentContext(context);
+ obj->mac_cgl_context_ = context;
+ obj->mac_cgl_pbuffer_ = pbuffer;
}
- // Must make the context current for renderer creation to succeed
- CGLSetCurrentContext(context);
- obj->mac_cgl_context_ = context;
- obj->mac_cgl_pbuffer_ = pbuffer;
}
} else if (!had_a_window && obj->mac_agl_context_ == NULL) {
// setup AGL context
@@ -1172,10 +1217,10 @@ NPError PlatformNPPSetWindow(NPP instance,
aglSetCurrentContext(obj->mac_agl_context_);
Rect windowRect = {0, 0, 0, 0};
- if (obj->drawing_model_ == NPDrawingModelQuickDraw)
- GetWindowBounds(obj->mac_window_, kWindowContentRgn, &windowRect);
- else
- GetWindowBounds(obj->mac_window_, kWindowStructureRgn, &windowRect);
+ GetWindowBounds(obj->mac_window_,
+ (obj->drawing_model_ == NPDrawingModelQuickDraw) ?
+ kWindowContentRgn : kWindowStructureRgn,
+ &windowRect);
int windowHeight = windowRect.bottom - windowRect.top;
@@ -1278,7 +1323,7 @@ void PlatformNPPStreamAsFile(StreamManager *stream_manager,
int16 PlatformNPPHandleEvent(NPP instance, PluginObject *obj, void *event) {
if (obj->event_model_ == NPEventModelCarbon) {
EventRecord* theEvent = static_cast<EventRecord*>(event);
- return HandleMacEvent(theEvent, instance) ? 1 : 0;
+ return HandleCarbonEvent(theEvent, instance) ? 1 : 0;
} else if (obj->event_model_ == NPEventModelCocoa){
return HandleCocoaEvent(instance, (NPCocoaEvent*)event, true) ? 1 : 0;
}
diff --git a/o3d/plugin/mac/plugin_mac.h b/o3d/plugin/mac/plugin_mac.h
index f5196de..a6cc30a 100644
--- a/o3d/plugin/mac/plugin_mac.h
+++ b/o3d/plugin/mac/plugin_mac.h
@@ -95,7 +95,7 @@ void CFReleaseIfNotNull(CFTypeRef cf);
// Returns NULL in the event of an error.
char* CreatePosixFilePathFromHFSFilePath(const char* hfsPath);
-bool HandleMacEvent(EventRecord* the_event, NPP instance);
+bool HandleCarbonEvent(EventRecord* the_event, NPP instance);
// initiated_from_browser indicates whether the event came from the
// browser's window. It will be false if the event originated from the