diff options
author | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-03 23:53:29 +0000 |
---|---|---|
committer | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-03 23:53:29 +0000 |
commit | b49b27f504501ecafee601985176dcbad9540f56 (patch) | |
tree | ae6fabf2751a23dffb977c7c6ad7016b21f672ce /o3d | |
parent | d2135bbf2b6f78584499302506e94f2a7d4c0364 (diff) | |
download | chromium_src-b49b27f504501ecafee601985176dcbad9540f56.zip chromium_src-b49b27f504501ecafee601985176dcbad9540f56.tar.gz chromium_src-b49b27f504501ecafee601985176dcbad9540f56.tar.bz2 |
Port O2D to Mac, currently just for Core Graphics (the drawing model used in Chrome on 10.5). Unfortunately the performance is not yet good enough to prefer it over the CGL + GPU readback + CoreGraphics re-render code path currently in use, so some optimization work will be necessary.
TEST=loaded O3D on OSX with RenderMode=Auto and RenderMode=2D in Chrome 9 on 10.5 and 10.6, Safari 4 on 10.5, Safari 5 on 10.6, and FF 3.6 on 10.5 and 10.6 and verified that Auto works everywhere, 2D works in Chrome on 10.5, and 2D fails without crashing in the remaining cases; unit tests
BUG=none
Review URL: http://codereview.chromium.org/6614005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76839 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/DEPS | 2 | ||||
-rw-r--r-- | o3d/build/cairo.gyp | 11 | ||||
-rw-r--r-- | o3d/build/common.gypi | 18 | ||||
-rw-r--r-- | o3d/build/libs.gyp | 76 | ||||
-rw-r--r-- | o3d/build/pixman.gyp | 4 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.cc | 95 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.h | 14 | ||||
-rw-r--r-- | o3d/core/cross/renderer.cc | 4 | ||||
-rw-r--r-- | o3d/core/cross/renderer.h | 15 | ||||
-rw-r--r-- | o3d/core/mac/display_window_mac.h | 15 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.cc | 2 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.h | 6 | ||||
-rw-r--r-- | o3d/plugin/mac/config_mac.mm | 4 | ||||
-rw-r--r-- | o3d/plugin/mac/main_mac.mm | 77 | ||||
-rw-r--r-- | o3d/plugin/mac/plugin_mac.mm | 16 |
15 files changed, 265 insertions, 94 deletions
@@ -7,7 +7,7 @@ vars = { "chromium_breakpad_rev": "47985", "o3d_code_rev": "232", "skia_rev": "586", - "gyp_rev": "820", + "gyp_rev": "899", "gtest_rev": "408", "gflags_rev": "30", "breakpad_rev": "604", diff --git a/o3d/build/cairo.gyp b/o3d/build/cairo.gyp index edeb6e4..2bcdf53 100644 --- a/o3d/build/cairo.gyp +++ b/o3d/build/cairo.gyp @@ -58,11 +58,12 @@ # Put our pkg-config binary into the PATH so cairo's build can # find it. 'PATH=<(pkgconfigroot)/usr/bin:$PATH && ' - # Configure it. We disable png and svg because we don't need - # them and they require additional external dependencies to - # build. - './configure --prefix=<(pkgconfigroot)/usr --disable-shared ' - '--disable-png --disable-svg && ' + # Configure it. + 'CFLAGS="-arch <(mac_gcc_arch)" ./configure ' + '--prefix=<(pkgconfigroot)/usr --disable-shared ' + # Disable things we don't need that have additional + # external dependencies. + '--disable-png --disable-svg --disable-ft && ' # Build. 'make && ' # "Install" to pkgconfigroot. diff --git a/o3d/build/common.gypi b/o3d/build/common.gypi index 2e848fd..796d493 100644 --- a/o3d/build/common.gypi +++ b/o3d/build/common.gypi @@ -51,7 +51,7 @@ 'cgdir': 'third_party/cg/files/mac', 'renderer%': 'gl', 'swiftshaderdir': '', - 'support_cairo%' : 0, + 'support_cairo%' : 1, }, ], ['OS == "linux"', @@ -189,6 +189,22 @@ ], ['OS == "mac"', { + 'conditions': [ + ['target_arch == "ia32"', + { + 'variables': { + 'mac_gcc_arch': 'i386', + }, + } + ], + ['target_arch == "x64"', + { + 'variables': { + 'mac_gcc_arch': 'x86_64', + }, + } + ], + ], 'target_defaults': { 'defines': [ 'OS_MACOSX', diff --git a/o3d/build/libs.gyp b/o3d/build/libs.gyp index 8a3f2f9..0f31c25 100644 --- a/o3d/build/libs.gyp +++ b/o3d/build/libs.gyp @@ -21,24 +21,54 @@ 'target_name': 'cairo_libs', 'type': 'none', 'conditions': [ - [ 'OS=="linux"', + ['OS=="linux"', { 'all_dependent_settings': { 'cflags': [ '<!@(pkg-config --cflags cairo)', ], + 'ldflags': [ + '<!@(pkg-config --libs-only-L --libs-only-other cairo)', + ], 'libraries': [ - '-lcairo', + '<!@(pkg-config --libs-only-l cairo)', ], }, }, ], - [ 'OS=="mac"', + ['OS=="mac"', { - #TODO(fransiskusx): Link to Cairo on Win/Mac as a static library + 'dependencies': [ + 'pixman.gyp:pixman', + 'cairo.gyp:cairo', + ], + # Ideally we would just call our pkg-config build here to query the + # right settings, but there are multiple problems with GYP/Xcode + # that prevent that from working, so we hard-code the values. + 'all_dependent_settings': { + 'include_dirs': [ + '<(pkgconfigroot)/usr/include/cairo', + '<(pkgconfigroot)/usr/include/pixman-1', + ], + # GYP/Xcode also has problems with adding libraries to all + # dependents, so we have to put them in this target_conditions + # section to restrict them to just the target types that we care + # about. + 'target_conditions': [ + ['_type=="executable" or _type=="shared_library" ' + 'or _type=="loadable_module"', + { + 'libraries': [ + '<(pkgconfigroot)/usr/lib/libcairo.a', + '<(pkgconfigroot)/usr/lib/libpixman-1.a', + ] + }, + ], + ], + }, }, ], - [ 'OS=="win"', + ['OS=="win"', { 'all_dependent_settings': { 'defines': [ @@ -66,14 +96,14 @@ ], }, 'conditions': [ - [ 'OS=="linux"', + ['OS=="linux"', { 'all_dependent_settings': { 'defines': [ 'GL_GLEXT_PROTOTYPES', ], 'conditions': [ - [ 'target_arch=="x64"', + ['target_arch=="x64"', { 'variables': { 'libdir': 'lib64' } }, { @@ -93,7 +123,7 @@ }, }, ], - [ 'OS=="mac"', + ['OS=="mac"', { 'direct_dependent_settings': { 'libraries': [ @@ -102,7 +132,7 @@ }, }, ], - [ 'OS=="win"', + ['OS=="win"', { 'all_dependent_settings': { 'libraries': [ @@ -134,14 +164,14 @@ ], }, 'conditions': [ - [ 'OS=="linux"', + ['OS=="linux"', { 'all_dependent_settings': { 'defines': [ 'GL_GLEXT_PROTOTYPES', ], 'conditions': [ - [ 'target_arch=="x64"', + ['target_arch=="x64"', { 'variables': { 'libdir': 'lib64' } }, { @@ -161,7 +191,7 @@ }, }, ], - [ 'OS=="mac"', + ['OS=="mac"', { 'direct_dependent_settings': { 'libraries': [ @@ -170,7 +200,7 @@ }, }, ], - [ 'OS=="win"', + ['OS=="win"', { 'all_dependent_settings': { 'libraries': [ @@ -217,7 +247,7 @@ ], }, 'conditions': [ - [ 'OS=="linux"', + ['OS=="linux"', { 'all_dependent_settings': { 'ldflags': [ @@ -230,7 +260,7 @@ }, }, ], - [ 'OS=="win"', + ['OS=="win"', { 'all_dependent_settings': { 'libraries': [ @@ -242,7 +272,7 @@ }, }, ], - [ 'OS=="mac"', + ['OS=="mac"', { 'direct_dependent_settings': { 'mac_framework_dirs': [ @@ -258,11 +288,11 @@ 'copies': [ { 'conditions' : [ - [ 'OS=="linux"', + ['OS=="linux"', { 'destination': '<(PRODUCT_DIR)', 'conditions': [ - [ 'target_arch=="x64"', + ['target_arch=="x64"', { 'variables': { 'libdir': 'lib64' } }, { @@ -277,7 +307,7 @@ ], }, ], - [ 'OS=="win"', + ['OS=="win"', { 'destination': '<(PRODUCT_DIR)', 'files': [ @@ -289,7 +319,7 @@ ], }, ], - [ 'OS=="mac"', + ['OS=="mac"', { 'destination': '<(PRODUCT_DIR)/Library/Frameworks', 'files': [ @@ -301,7 +331,7 @@ }, { 'conditions' : [ - [ 'OS=="linux"', + ['OS=="linux"', { 'destination': '<(SHARED_LIB_DIR)', 'files': [ @@ -310,7 +340,7 @@ ], }, ], - [ 'OS=="mac"', + ['OS=="mac"', { # Dummy copy, because the xcode generator in gyp fails when it # has an empty copy entry. @@ -365,7 +395,7 @@ ], }, ], - } + }, ], ], } diff --git a/o3d/build/pixman.gyp b/o3d/build/pixman.gyp index ae4278f..a6e9457 100644 --- a/o3d/build/pixman.gyp +++ b/o3d/build/pixman.gyp @@ -38,8 +38,8 @@ # Go there! 'cd <(pixmanbuilddir) && ' # Configure it. - './configure --prefix=<(pkgconfigroot)/usr --disable-shared ' - '&& ' + 'CFLAGS="-arch <(mac_gcc_arch)" ./configure ' + '--prefix=<(pkgconfigroot)/usr --disable-shared && ' # Build. 'make && ' # "Install" to pkgconfigroot. diff --git a/o3d/core/cross/cairo/renderer_cairo.cc b/o3d/core/cross/cairo/renderer_cairo.cc index 885d477..66e1c83 100644 --- a/o3d/core/cross/cairo/renderer_cairo.cc +++ b/o3d/core/cross/cairo/renderer_cairo.cc @@ -32,10 +32,16 @@ // Renderer that is using 2D Library Cairo. #include "core/cross/cairo/renderer_cairo.h" + +#if defined(OS_LINUX) #include <cairo-xlib.h> +#elif defined(OS_MACOSX) +#include <cairo-quartz.h> +#endif #include <stdio.h> #include <stdlib.h> #include <string.h> + #include "core/cross/cairo/layer.h" #include "core/cross/cairo/texture_cairo.h" @@ -49,7 +55,14 @@ Renderer* Renderer::Create2DRenderer(ServiceLocator* service_locator) { namespace o2d { RendererCairo::RendererCairo(ServiceLocator* service_locator) - : Renderer(service_locator), display_(NULL), main_surface_(NULL) { + : Renderer(service_locator), +#if defined(OS_LINUX) + display_(NULL), + window_(0), +#elif defined(OS_MACOSX) + mac_cg_context_ref_(0), +#endif + main_surface_(NULL) { // Don't need to do anything. } @@ -65,12 +78,14 @@ RendererCairo* RendererCairo::CreateDefault(ServiceLocator* service_locator) { void RendererCairo::Destroy() { DLOG(INFO) << "To Destroy"; - if (main_surface_ != NULL) { - cairo_surface_destroy(main_surface_); - main_surface_= NULL; - } + DestroyCairoSurface(); +#if defined(OS_LINUX) display_ = NULL; + window_ = 0; +#elif defined(OS_MACOSX) + mac_cg_context_ref_ = 0; +#endif } // Comparison predicate for STL sort. @@ -79,6 +94,11 @@ bool LayerZValueLessThan(const Layer* first, const Layer* second) { } void RendererCairo::Paint() { + if (!main_surface_) { + DLOG(INFO) << "No target surface, cannot paint"; + return; + } + // TODO(tschmelcher): Don't keep creating and destroying the drawing context. cairo_t* current_drawing = cairo_create(main_surface_); @@ -201,9 +221,48 @@ void RendererCairo::RemoveLayer(Layer* image) { } void RendererCairo::InitCommon() { - main_surface_ = cairo_xlib_surface_create(display_, window_, + CreateCairoSurface(); +} + +void RendererCairo::CreateCairoSurface() { +#if defined(OS_LINUX) + main_surface_ = cairo_xlib_surface_create(display_, + window_, XDefaultVisual(display_, 0), - display_width(), display_height()); + display_width(), + display_height()); +#elif defined(OS_MACOSX) + if (!mac_cg_context_ref_) { + // Can't create the surface until we get a valid CGContextRef. If we don't + // have one it may be because we haven't yet gotten one from + // HandleCocoaEvent() in main_mac.mm, or we may have initialized with a + // drawing model other than Core Graphics (in which case we are never going + // to get one and rendering won't work). + // TODO(tschmelcher): Support the other drawing models too. + DLOG(INFO) << "No CGContextRef, cannot initialize yet"; + return; + } + // Save a pristine CG graphics state. + CGContextSaveGState(mac_cg_context_ref_); + // Transform the coordinate space to match Cairo's conventions. + CGContextTranslateCTM(mac_cg_context_ref_, 0.0, display_height()); + CGContextScaleCTM(mac_cg_context_ref_, 1.0, -1.0); + main_surface_ = cairo_quartz_surface_create_for_cg_context( + mac_cg_context_ref_, + display_width(), + display_height()); +#endif +} + +void RendererCairo::DestroyCairoSurface() { + if (main_surface_ != NULL) { + cairo_surface_destroy(main_surface_); + main_surface_= NULL; +#ifdef OS_MACOSX + // Get back the pristine CG state. + CGContextRestoreGState(mac_cg_context_ref_); +#endif + } } void RendererCairo::UninitCommon() { @@ -213,21 +272,41 @@ void RendererCairo::UninitCommon() { Renderer::InitStatus RendererCairo::InitPlatformSpecific( const DisplayWindow& display_window, bool off_screen) { +#if defined(OS_LINUX) const DisplayWindowLinux &display_platform = static_cast<const DisplayWindowLinux&>(display_window); display_ = display_platform.display(); window_ = display_platform.window(); - +#elif defined(OS_MACOSX) + const DisplayWindowMac &display_platform = + static_cast<const DisplayWindowMac&>(display_window); + mac_cg_context_ref_ = display_platform.cg_context_ref(); +#endif return SUCCESS; } +#ifdef OS_MACOSX +bool RendererCairo::ChangeDisplayWindow(const DisplayWindow& display_window) { + const DisplayWindowMac &display_platform = + static_cast<const DisplayWindowMac&>(display_window); + DestroyCairoSurface(); + mac_cg_context_ref_ = display_platform.cg_context_ref(); + CreateCairoSurface(); +} +#endif + // Handles the plugin resize event. void RendererCairo::Resize(int width, int height) { DLOG(INFO) << "To Resize " << width << " x " << height; SetClientSize(width, height); +#if defined(OS_LINUX) // Resize the mainSurface and buffer cairo_xlib_surface_set_size(main_surface_, width, height); +#elif defined(OS_MACOSX) + DestroyCairoSurface(); + CreateCairoSurface(); +#endif } // The platform specific part of BeginDraw. diff --git a/o3d/core/cross/cairo/renderer_cairo.h b/o3d/core/cross/cairo/renderer_cairo.h index d3c8e94..b80d246 100644 --- a/o3d/core/cross/cairo/renderer_cairo.h +++ b/o3d/core/cross/cairo/renderer_cairo.h @@ -62,6 +62,12 @@ class RendererCairo : public Renderer { virtual InitStatus InitPlatformSpecific(const DisplayWindow& display, bool off_screen); +#ifdef OS_MACOSX + virtual bool ChangeDisplayWindow(const DisplayWindow& display); + + virtual bool SupportsCoreGraphics() const { return true; } +#endif + // Released all hardware resources. virtual void Destroy(); @@ -221,10 +227,18 @@ class RendererCairo : public Renderer { // Clip the area of the current layer that will collide with other images. void ClipArea(cairo_t* cr, LayerList::iterator it); + private: + void CreateCairoSurface(); + void DestroyCairoSurface(); + +#if defined(OS_LINUX) // Linux Client Display Display* display_; // Linux Client Window Window window_; +#elif defined(OS_MACOSX) + CGContextRef mac_cg_context_ref_; +#endif // Main surface to render cairo cairo_surface_t* main_surface_; diff --git a/o3d/core/cross/renderer.cc b/o3d/core/cross/renderer.cc index 3a71722..a1d50f1 100644 --- a/o3d/core/cross/renderer.cc +++ b/o3d/core/cross/renderer.cc @@ -150,6 +150,10 @@ Renderer::InitStatus Renderer::Init( return InitPlatformSpecific(display, off_screen); } +bool Renderer::ChangeDisplayWindow(const DisplayWindow& display) { + return false; +} + void Renderer::InitCommon() { AddDefaultStates(); SetInitialStates(); diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h index 311fb6d..f198570 100644 --- a/o3d/core/cross/renderer.h +++ b/o3d/core/cross/renderer.h @@ -158,7 +158,6 @@ class Renderer { // needed by the application. static Renderer* Create2DRenderer(ServiceLocator* service_locator); - // Gets whether or not the renderer should attempt to use the software // renderer. static bool IsForceSoftwareRenderer(); @@ -166,9 +165,9 @@ class Renderer { // Initialises the renderer for use, claiming hardware resources. InitStatus Init(const DisplayWindow& display, bool off_screen); - // The platform specific part of initalization. - virtual InitStatus InitPlatformSpecific(const DisplayWindow& display, - bool off_screen) = 0; + // Switch rendering to a different window after initialization (if supported + // by the implementation). + virtual bool ChangeDisplayWindow(const DisplayWindow& display); // Initializes stuff that has to happen after Init virtual void InitCommon(); @@ -406,6 +405,10 @@ class Renderer { int width, int height) = 0; +#ifdef OS_MACOSX + virtual bool SupportsCoreGraphics() const { return false; } +#endif + ServiceLocator* service_locator() const { return service_locator_; } // Returns the type of Param needed for a particular state. @@ -677,6 +680,10 @@ class Renderer { } private: + // The platform specific part of initalization. + virtual InitStatus InitPlatformSpecific(const DisplayWindow& display, + bool off_screen) = 0; + // Adds the default states to their respective stacks. void AddDefaultStates(); diff --git a/o3d/core/mac/display_window_mac.h b/o3d/core/mac/display_window_mac.h index 29eeec6..6390617 100644 --- a/o3d/core/mac/display_window_mac.h +++ b/o3d/core/mac/display_window_mac.h @@ -35,6 +35,7 @@ #include <OpenGL/OpenGL.h> #include <AGL/agl.h> +#include <CoreGraphics/CGContext.h> #include "core/cross/display_window.h" @@ -48,11 +49,17 @@ namespace o3d { class DisplayWindowMac : public DisplayWindow { public: - DisplayWindowMac() : agl_context_(NULL), cgl_context_(NULL) {} + DisplayWindowMac() + : agl_context_(NULL), + cgl_context_(NULL), + cg_context_ref_(NULL) { + } + virtual ~DisplayWindowMac() {} AGLContext agl_context() const { return agl_context_; } CGLContextObj cgl_context() const { return cgl_context_; } + CGContextRef cg_context_ref() const { return cg_context_ref_; } void set_agl_context(const AGLContext& agl_context) { agl_context_ = agl_context; @@ -61,9 +68,15 @@ class DisplayWindowMac : public DisplayWindow { void set_cgl_context(const CGLContextObj& cgl_context) { cgl_context_ = cgl_context; } + + void set_cg_context_ref(const CGContextRef& cg_context_ref) { + cg_context_ref_ = cg_context_ref; + } + private: AGLContext agl_context_; CGLContextObj cgl_context_; + CGContextRef cg_context_ref_; DISALLOW_COPY_AND_ASSIGN(DisplayWindowMac); }; diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc index d3da84d..ea64a84 100644 --- a/o3d/plugin/cross/o3d_glue.cc +++ b/o3d/plugin/cross/o3d_glue.cc @@ -133,7 +133,7 @@ PluginObject::PluginObject(NPP npp) mac_window_selected_tab_(0), mac_cocoa_window_(0), mac_surface_hidden_(0), - mac_2d_context_(0), + mac_cg_context_ref_(0), mac_agl_context_(0), mac_cgl_context_(0), mac_cgl_pbuffer_(0), diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h index 9af13dd..213687b 100644 --- a/o3d/plugin/cross/o3d_glue.h +++ b/o3d/plugin/cross/o3d_glue.h @@ -38,6 +38,7 @@ #ifdef OS_MACOSX #include <OpenGL/OpenGL.h> #include <AGL/agl.h> +#include <CoreGraphics/CGContext.h> #endif #ifdef OS_LINUX @@ -285,9 +286,8 @@ class PluginObject: public NPObject { // end of Safari tab detection vars GLint last_buffer_rect_[4]; Point last_plugin_loc_; - // can be a CGrafPtr, a CGContextRef or NULL depending on drawing_model - void* mac_2d_context_; - // either can be NULL depending on drawing_model + // each of these three can be NULL depending on drawing_model + CGContextRef mac_cg_context_ref_; AGLContext mac_agl_context_; CGLContextObj mac_cgl_context_; void *gl_layer_; diff --git a/o3d/plugin/mac/config_mac.mm b/o3d/plugin/mac/config_mac.mm index c85f8c8..df5673c 100644 --- a/o3d/plugin/mac/config_mac.mm +++ b/o3d/plugin/mac/config_mac.mm @@ -330,10 +330,10 @@ bool GetUserAgentMetrics(NPP npp) { // The Chrome user_agent string also contains Safari. Search for Chrome first. if (std::string::npos != user_agent.find("Chrome")) { o3d::metric_browser_type = o3d::BROWSER_NAME_CHROME; - // The OmniWeb user_agent also contains Safari. Search for OminWeb first. + // The OmniWeb user_agent also contains Safari. Search for OmniWeb first. } else if (std::string::npos != user_agent.find("OmniWeb")) { o3d::metric_browser_type = o3d::BROWSER_NAME_OMNIWEB; - // now we can safely look for Safari + // Now we can safely look for Safari. } else if (std::string::npos != user_agent.find("Safari")) { o3d::metric_browser_type = o3d::BROWSER_NAME_SAFARI; } else if (std::string::npos != user_agent.find("Opera")) { diff --git a/o3d/plugin/mac/main_mac.mm b/o3d/plugin/mac/main_mac.mm index e3daf86..d06d305 100644 --- a/o3d/plugin/mac/main_mac.mm +++ b/o3d/plugin/mac/main_mac.mm @@ -691,9 +691,7 @@ bool HandleMacEvent(EventRecord* the_event, NPP instance) { GLUE_PROFILE_STOP(instance, "forceredraw"); #elif defined(CFTIMER) #else - DrawPlugin(obj, true, - (obj->drawing_model_ == NPDrawingModelCoreGraphics) ? - reinterpret_cast<CGContextRef>(obj->mac_2d_context_) : NULL); + DrawPlugin(obj, true, obj->mac_cg_context_ref_); #endif // Safari tab switching recovery code. if (obj->mac_surface_hidden_) { @@ -718,9 +716,7 @@ bool HandleMacEvent(EventRecord* the_event, NPP instance) { handled = true; break; case updateEvt: - DrawPlugin(obj, false, - (obj->drawing_model_ == NPDrawingModelCoreGraphics) ? - reinterpret_cast<CGContextRef>(obj->mac_2d_context_) : NULL); + DrawPlugin(obj, false, obj->mac_cg_context_ref_); handled = true; break; case osEvt: @@ -780,17 +776,26 @@ bool HandleCocoaEvent(NPP instance, NPCocoaEvent* the_event, obj->MacEventReceived(!lostFocus); switch (the_event->type) { case NPCocoaEventDrawRect: - // We need to call the render callback from here if we are rendering - // off-screen because it doesn't get called anywhere else. if (obj->drawing_model_ == NPDrawingModelCoreAnimation) { O3DLayer* layer = ObjO3DLayer(obj); if (layer) { [layer setNeedsDisplay]; } } else { - DrawPlugin(obj, - obj->IsOffscreenRenderingEnabled(), - the_event->data.draw.context); + // We need to call the render callback from here if we are using + // Core Graphics because it doesn't get called anywhere else. + CGContextRef new_mac_cg_context_ref = the_event->data.draw.context; + if (new_mac_cg_context_ref != obj->mac_cg_context_ref_) { + obj->mac_cg_context_ref_ = new_mac_cg_context_ref; + // Update the Renderer's CGContextRef (only RendererCairo actually + // uses it). + o3d::DisplayWindowMac display; + display.set_agl_context(obj->mac_agl_context_); + display.set_cgl_context(obj->mac_cgl_context_); + display.set_cg_context_ref(obj->mac_cg_context_ref_); + obj->renderer()->ChangeDisplayWindow(display); + } + DrawPlugin(obj, true, obj->mac_cg_context_ref_); } handled = true; break; @@ -931,7 +936,7 @@ NPError PlatformNPPSetWindow(NPP instance, if (window->window == NULL && obj->drawing_model_ != NPDrawingModelCoreGraphics && - obj->drawing_model_!= NPDrawingModelCoreAnimation) { + obj->drawing_model_ != NPDrawingModelCoreAnimation) { return NPERR_NO_ERROR; } @@ -945,7 +950,9 @@ NPError PlatformNPPSetWindow(NPP instance, return NPERR_NO_ERROR; } case NPDrawingModelCoreGraphics: { - // Safari 4 sets window->window to NULL when in Cocoa event mode. + // In some browsers (Safari 4 on 10.5, Chrome on 10.5), window->window is + // NULL when using the Cocoa event model. In that situation we get our + // CGContextRef in HandleCocoaEvent() instead. if (window->window != NULL) { NP_CGContext* np_cg = reinterpret_cast<NP_CGContext*>(window->window); if (obj->event_model_ == NPEventModelCocoa) { @@ -954,13 +961,12 @@ NPError PlatformNPPSetWindow(NPP instance, } else { new_window = static_cast<OpaqueWindowPtr*>(np_cg->window); } - obj->mac_2d_context_ = np_cg->context; + obj->mac_cg_context_ref_ = np_cg->context; } break; } case NPDrawingModelQuickDraw: { NP_Port* np_qd = reinterpret_cast<NP_Port*>(window->window); - obj->mac_2d_context_ = np_qd->port; if (np_qd->port) new_window = GetWindowFromPort(np_qd->port); // Safari 4 on Snow Leopard is sending us a spurious @@ -982,9 +988,6 @@ NPError PlatformNPPSetWindow(NPP instance, // Whether we already had a window before this call. bool had_a_window = obj->mac_window_ != NULL; - // Whether we already had a pbuffer before this call. - bool had_a_pbuffer = obj->mac_cgl_pbuffer_ != NULL; - obj->mac_window_ = new_window; if (obj->drawing_model_ == NPDrawingModelCoreAnimation) { @@ -992,6 +995,8 @@ 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) { // We initialize things with a CGL context rendering to a 1x1 // pbuffer. Later we use the O3D RenderSurface APIs to set up the @@ -1195,31 +1200,28 @@ NPError PlatformNPPSetWindow(NPP instance, aglEnable(obj->mac_agl_context_, AGL_BUFFER_RECT); } - if (had_a_pbuffer) { - // CoreGraphics drawing model when we have no on-screen window (Chrome, - // specifically). - obj->EnableOffscreenRendering(); - obj->Resize(window->width, window->height); - return NPERR_NO_ERROR; - } - - // Renderer is already initialized from a previous call to this function, - // just update size and position and return. - if (had_a_window) { - if (obj->renderer()) { + if (obj->renderer()) { + // Renderer is already initialized from a previous call to this function, + // just update size and position and return. + if (obj->drawing_model_ == NPDrawingModelCoreGraphics) { + if (!obj->renderer()->SupportsCoreGraphics()) { + obj->EnableOffscreenRendering(); + } + obj->Resize(window->width, window->height); + } else if (had_a_window) { obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin); obj->Resize(window->width, window->height); } return NPERR_NO_ERROR; } - if (obj->renderer()) - return NPERR_NO_ERROR; + // Else this is the first call. // Create and assign the graphics context. o3d::DisplayWindowMac default_display; default_display.set_agl_context(obj->mac_agl_context_); default_display.set_cgl_context(obj->mac_cgl_context_); + default_display.set_cg_context_ref(obj->mac_cg_context_ref_); obj->CreateRenderer(default_display); @@ -1235,15 +1237,20 @@ NPError PlatformNPPSetWindow(NPP instance, obj->client()->Init(); if (obj->renderer()) { - if (obj->mac_cgl_pbuffer_) { - obj->EnableOffscreenRendering(); + if (obj->drawing_model_ == NPDrawingModelCoreGraphics) { + if (!obj->renderer()->SupportsCoreGraphics()) { + // Browser is using Core Graphics but renderer doesn't support it, so we + // must render off-screen and then read back into software to re-render + // with Core Graphics. + obj->EnableOffscreenRendering(); + } } else { obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin); } obj->Resize(window->width, window->height); #ifdef CFTIMER - // now that the grahics context is setup, add this instance to the timer + // now that the graphics context is setup, add this instance to the timer // list so it gets drawn repeatedly gRenderTimer.AddInstance(instance); #endif // CFTIMER diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm index 9fb57a5..199a061 100644 --- a/o3d/plugin/mac/plugin_mac.mm +++ b/o3d/plugin/mac/plugin_mac.mm @@ -270,22 +270,22 @@ void RenderTimer::TimerCallback(CFRunLoopTimerRef timer, void* info) { obj->GetFullscreenMacWindow()->IdleCallback(); } - // We're visible if (a) we are in fullscreen mode, (b) our cliprect - // height and width are both a sensible size, ie > 1 pixel, or (c) if - // we are rendering to render surfaces (CoreGraphics drawing model, - // essentially offscreen rendering). + // We're visible if (a) we are in fullscreen mode, (b) we are using + // QuickDraw and our cliprect height and width are both a sensible size, ie + // > 1 pixel, or (c) we are using Core Graphics. // // We don't check for 0 as we have to size to 1 x 1 on occasion rather than // 0 x 0 to avoid crashing the Apple software renderer, but do not want to // actually draw to a 1 x 1 pixel area. bool plugin_visible = in_fullscreen || - (obj->last_buffer_rect_[2] > 1 && obj->last_buffer_rect_[3] > 1) || - obj->IsOffscreenRenderingEnabled(); + (obj->drawing_model_ == NPDrawingModelQuickDraw && + obj->last_buffer_rect_[2] > 1 && obj->last_buffer_rect_[3] > 1) || + obj->drawing_model_ == NPDrawingModelCoreGraphics; if (plugin_visible && obj->renderer()) { if (obj->client()->NeedsRender()) { // Force a sync to the VBL (once per timer callback) - // to avoid tearing + // to avoid tearing, if using GL. GLint sync = (i == 0); if (obj->mac_cgl_context_) { CGLSetParameter(obj->mac_cgl_context_, kCGLCPSwapInterval, &sync); @@ -293,7 +293,7 @@ void RenderTimer::TimerCallback(CFRunLoopTimerRef timer, void* info) { aglSetInteger(obj->mac_agl_context_, AGL_SWAP_INTERVAL, &sync); } - if (obj->IsOffscreenRenderingEnabled()) { + if (obj->drawing_model_ == NPDrawingModelCoreGraphics) { NPRect rect = { 0 }; rect.bottom = obj->height(); rect.right = obj->width(); |