summaryrefslogtreecommitdiffstats
path: root/o3d/core
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-17 21:42:54 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-17 21:42:54 +0000
commit9149cdc6f2acf0db263281ce2d4bb40112847582 (patch)
treef2749b3565b65aad5ed076201a3eacdbc496f95e /o3d/core
parent0cbacf170644b4efce6c98b6637bba942b9110a5 (diff)
downloadchromium_src-9149cdc6f2acf0db263281ce2d4bb40112847582.zip
chromium_src-9149cdc6f2acf0db263281ce2d4bb40112847582.tar.gz
chromium_src-9149cdc6f2acf0db263281ce2d4bb40112847582.tar.bz2
Rewrote full-screen support on Windows. O3D now always creates its own
window in which to render, rather than rendering into either the browser's window or a separate full-screen window. The O3D window is removed from the browser's hierarchy and made top-level in order to go to full-screen mode via Direct3D. This solves fundamental focus fighting problems seen on Windows Vista. This change allowed the event forwarding code in the plugin's window message loop to be deleted, but a new workaround for a flicker upon the first mouse click in O3D in Firefox was required. Split the Renderer's fullscreen API into GoFullscreen and CancelFullscreen to solve chicken-and-egg problems with coming out of full-screen mode. Changed how the plugin detects resize events. Rather than responding to WM_SIZE messages, NPP_SetWindow is now responsible for propagating resize events to the client. Changed the ActiveX host control to call NPP_SetWindow in response to SetObjectRects. Fixed RendererGL::IsCurrent() on non-Mac platforms. Removed the bogus current_renderer_ static variable. Tested the following scenarios in IE and Firefox on Windows: - Full-screen involving display mode change, Escape to exit. - Full-screen involving display mode change, Alt-Tab to exit. - Full-screen involving display mode change, Alt-F4 to exit. - Full-screen involving display mode change, timeout to exit. - Full-screen with no display mode change, Escape to exit. - Full-screen with no display mode change, Alt-Tab to exit. - Full-screen with no display mode change, Alt-F4 to exit. - Full-screen with no display mode change, timeout to exit. - Beach demo, particle demo, other tests. Tested the following scenarios on the Mac in Safari (for which the code path didn't change): - Full-screen, escape to exit. - Full-screen, Alt-Tab to exit. - Full-screen, timeout to exit. When http://crbug.com/21921 is fixed, full-screen mode will work on Windows Vista with Aero on in Chrome. Review URL: http://codereview.chromium.org/210005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26489 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/core')
-rw-r--r--o3d/core/cross/gl/renderer_gl.cc22
-rw-r--r--o3d/core/cross/gl/renderer_gl.h51
-rw-r--r--o3d/core/cross/renderer.cc4
-rw-r--r--o3d/core/cross/renderer.h33
-rw-r--r--o3d/core/win/d3d9/renderer_d3d9.cc80
-rw-r--r--o3d/core/win/d3d9/renderer_d3d9.h16
6 files changed, 124 insertions, 82 deletions
diff --git a/o3d/core/cross/gl/renderer_gl.cc b/o3d/core/cross/gl/renderer_gl.cc
index b52e324..9f0955c 100644
--- a/o3d/core/cross/gl/renderer_gl.cc
+++ b/o3d/core/cross/gl/renderer_gl.cc
@@ -651,8 +651,6 @@ RendererGL::RendererGL(ServiceLocator* service_locator)
new BlendEquationHandler(&blend_equation_[ALPHA]));
}
-RendererGL *RendererGL::current_renderer_ = NULL;
-
RendererGL::~RendererGL() {
Destroy();
}
@@ -1101,7 +1099,6 @@ void RendererGL::Destroy() {
DestroyCommonGL();
if (display_) {
::glXMakeCurrent(display_, 0, 0);
- current_renderer_ = NULL;
if (context_) {
::glXDestroyContext(display_, context_);
context_ = 0;
@@ -1117,17 +1114,14 @@ bool RendererGL::MakeCurrent() {
#ifdef OS_WIN
if (!device_context_ || !gl_context_) return false;
bool result = ::wglMakeCurrent(device_context_, gl_context_) != 0;
- if (result) current_renderer_ = this;
return result;
#endif
#ifdef OS_MACOSX
if (mac_cgl_context_ != NULL) {
::CGLSetCurrentContext(mac_cgl_context_);
- current_renderer_ = this;
return true;
} else if (mac_agl_context_ != NULL) {
::aglSetCurrentContext(mac_agl_context_);
- current_renderer_ = this;
return true;
} else {
return false;
@@ -1136,7 +1130,6 @@ bool RendererGL::MakeCurrent() {
#ifdef OS_LINUX
if (context_ != NULL) {
bool result = ::glXMakeCurrent(display_, window_, context_) == True;
- if (result) current_renderer_ = this;
return result;
} else {
return false;
@@ -1219,12 +1212,15 @@ void RendererGL::Resize(int width, int height) {
CHECK_GL_ERROR();
}
-bool RendererGL::SetFullscreen(bool fullscreen,
- const DisplayWindow& display,
- int mode_id) {
- if (fullscreen != fullscreen_) {
- fullscreen_ = fullscreen;
- }
+bool RendererGL::GoFullscreen(const DisplayWindow& display,
+ int mode_id) {
+ fullscreen_ = true;
+ return true;
+}
+
+bool RendererGL::CancelFullscreen(const DisplayWindow& display,
+ int width, int height) {
+ fullscreen_ = false;
return true;
}
diff --git a/o3d/core/cross/gl/renderer_gl.h b/o3d/core/cross/gl/renderer_gl.h
index 92aaca8..722e29e2 100644
--- a/o3d/core/cross/gl/renderer_gl.h
+++ b/o3d/core/cross/gl/renderer_gl.h
@@ -65,16 +65,13 @@ class RendererGL : public Renderer {
// Released all hardware resources.
virtual void Destroy();
- // Turns fullscreen display on or off.
- // Parameters:
- // fullscreen: true for fullscreen, false for in-browser display
- // display: a platform-specific display identifier
- // mode_id: a mode returned by GetDisplayModes, for fullscreen use.
- // (Ignored in non-fullscreen mode.)
- // Returns true on success, false on failure.
- virtual bool SetFullscreen(bool fullscreen,
- const DisplayWindow& display,
- int mode_id);
+ // Overridden from Renderer.
+ virtual bool GoFullscreen(const DisplayWindow& display,
+ int mode_id);
+
+ // Overridden from Renderer.
+ virtual bool CancelFullscreen(const DisplayWindow& display,
+ int width, int height);
// Tells whether we're currently displayed fullscreen or not.
virtual bool fullscreen() const {
@@ -118,23 +115,35 @@ class RendererGL : public Renderer {
// Makes this renderer active on the current thread if it is not active
// already.
void MakeCurrentLazy() {
- if (!IsCurrent()) MakeCurrent();
+ if (!IsCurrent())
+ MakeCurrent();
}
// Returns whether or not this renderer is active on the current thread.
- // In the Mac case, also requires the correct GL context to be active.
// Don't worry, the "get" calls are el cheapo.
bool IsCurrent() {
-#ifdef OS_MACOSX
+#if defined(OS_MACOSX)
if ((mac_agl_context_ != NULL) &&
- (mac_agl_context_ != aglGetCurrentContext())) {
- return false;
+ (mac_agl_context_ == aglGetCurrentContext())) {
+ return true;
} else if ((mac_cgl_context_ != NULL) &&
- (mac_cgl_context_ != CGLGetCurrentContext())) {
- return false;
+ (mac_cgl_context_ == CGLGetCurrentContext())) {
+ return true;
}
+#elif defined(OS_WIN)
+ if ((gl_context_ != NULL) &&
+ (gl_context_ == wglGetCurrentContext())) {
+ return true;
+ }
+#elif defined(OS_LINUX)
+ if ((context_ != NULL) &&
+ (context_ == glXGetCurrentContext())) {
+ return true;
+ }
+#else
+ Error: must port RendererGL::IsCurrent() to your platform.
#endif
- return this == current_renderer_;
+ return false;
}
// Makes this renderer active on the current thread.
@@ -221,12 +230,6 @@ class RendererGL : public Renderer {
ServiceDependency<SemanticManager> semantic_manager_;
- // Current renderer, tracking which renderer has last called wglMakeCurrent
- // (or equivalent on other platforms).
- // NOTE: this should really be thread-local, but since we don't handle
- // multiple threads currently, this is enough.
- static RendererGL *current_renderer_;
-
// Indicates we're rendering fullscreen rather than in the plugin region.
bool fullscreen_;
diff --git a/o3d/core/cross/renderer.cc b/o3d/core/cross/renderer.cc
index ff640b7..1310376 100644
--- a/o3d/core/cross/renderer.cc
+++ b/o3d/core/cross/renderer.cc
@@ -127,7 +127,8 @@ Renderer::Renderer(ServiceLocator* service_locator)
dest_x_offset_(0),
dest_y_offset_(0),
supports_npot_(false),
- back_buffer_cleared_(false) {
+ back_buffer_cleared_(false),
+ presented_once_(false) {
}
Renderer::~Renderer() {
@@ -321,6 +322,7 @@ void Renderer::Present() {
DCHECK(!rendering_);
DCHECK(!drawing_);
PlatformSpecificPresent();
+ presented_once_ = true;
}
void Renderer::Clear(const Float4 &color,
diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h
index df5bbd2..c372bca 100644
--- a/o3d/core/cross/renderer.h
+++ b/o3d/core/cross/renderer.h
@@ -213,16 +213,27 @@ class Renderer {
// Handles the plugin resize event.
virtual void Resize(int width, int height) = 0;
- // Turns fullscreen display on or off.
+ // Turns fullscreen display on.
// Parameters:
- // fullscreen: true for fullscreen, false for in-plugin display
// display: a platform-specific display identifier
- // mode_id: a mode returned by GetDisplayModes, for fullscreen use. Ignored
- // in non-fullscreen mode.
+ // mode_id: a mode returned by GetDisplayModes
// Returns true on success, false on failure.
- // TODO: Make this pure virtual once it's implemented everywhere.
- virtual bool SetFullscreen(bool fullscreen, const DisplayWindow& display,
- int mode_id) {
+ // TODO(o3d): Make this pure virtual once it's implemented everywhere.
+ virtual bool GoFullscreen(const DisplayWindow& display,
+ int mode_id) {
+ return false;
+ }
+
+ // Cancels fullscreen display. Restores rendering to windowed mode
+ // with the given width and height.
+ // Parameters:
+ // display: a platform-specific display identifier
+ // width: the width to which to restore windowed rendering
+ // height: the height to which to restore windowed rendering
+ // Returns true on success, false on failure.
+ // TODO(o3d): Make this pure virtual once it's implemented everywhere.
+ virtual bool CancelFullscreen(const DisplayWindow& display,
+ int width, int height) {
return false;
}
@@ -532,6 +543,11 @@ class Renderer {
write_mask_ = mask & 0xF;
}
+ // Indicates whether this Renderer has yet presented to the screen.
+ bool presented_once() {
+ return presented_once_;
+ }
+
protected:
typedef vector_map<String, StateHandler*> StateHandlerMap;
typedef std::vector<ParamVector> ParamVectorArray;
@@ -748,6 +764,9 @@ class Renderer {
// Whether the backbuffer has been cleared this frame.
bool back_buffer_cleared_;
+ // Whether we have ever completed a call to Present().
+ bool presented_once_;
+
DISALLOW_COPY_AND_ASSIGN(Renderer);
};
diff --git a/o3d/core/win/d3d9/renderer_d3d9.cc b/o3d/core/win/d3d9/renderer_d3d9.cc
index 3c56994..f667ee4 100644
--- a/o3d/core/win/d3d9/renderer_d3d9.cc
+++ b/o3d/core/win/d3d9/renderer_d3d9.cc
@@ -422,6 +422,7 @@ Renderer::InitStatus InitializeD3D9Context(
// Note: SwapEffect=DISCARD is req. for multisample to function
ZeroMemory(d3d_present_parameters, sizeof(*d3d_present_parameters));
d3d_present_parameters->Windowed = !fullscreen;
+ d3d_present_parameters->hDeviceWindow = window;
d3d_present_parameters->SwapEffect = D3DSWAPEFFECT_DISCARD;
d3d_present_parameters->BackBufferFormat = D3DFMT_A8R8G8B8;
d3d_present_parameters->EnableAutoDepthStencil = FALSE;
@@ -1331,52 +1332,75 @@ bool RendererD3D9::GetDisplayMode(int id, DisplayMode *mode) {
return success;
}
-bool RendererD3D9::SetFullscreen(bool fullscreen,
- const DisplayWindow& display,
- int mode_id) {
- if (fullscreen != fullscreen_) {
+bool RendererD3D9::GoFullscreen(const DisplayWindow& display,
+ int mode_id) {
+ if (!fullscreen_) {
if (d3d_device_) { // Have we been initialized yet?
const DisplayWindowWindows& platform_display =
static_cast<const DisplayWindowWindows&>(display);
HWND window = platform_display.hwnd();
int refresh_rate = 0;
bool windowed = true;
- if (fullscreen) {
- // If fullscreen is requested but the mode is set to
- // DISPLAY_MODE_DEFAULT then create a non-full-screen window at the
- // current display resolution. If any other mode is chosen then the
- // windows will change mode and create a true full-screen window.
- if (mode_id != DISPLAY_MODE_DEFAULT) {
- // Look up the refresh rate.
- DisplayMode mode;
- if (!GetDisplayMode(mode_id, &mode)) {
- LOG(ERROR) << "Failed to GetDisplayMode";
- return false;
- }
- refresh_rate = mode.refresh_rate();
- windowed = false;
- }
- showing_fullscreen_message_ = true;
- fullscreen_message_timer_.GetElapsedTimeAndReset(); // Reset the timer.
- } else {
- showing_fullscreen_message_ = false;
+
+ // Look up the refresh rate, width and height.
+ DisplayMode mode;
+ if (!GetDisplayMode(mode_id, &mode)) {
+ LOG(ERROR) << "Failed to GetDisplayMode";
+ return false;
+ }
+
+ int width = mode.width();
+ int height = mode.height();
+
+ // If fullscreen is requested but the mode is set to
+ // DISPLAY_MODE_DEFAULT then create a non-full-screen window at the
+ // current display resolution. If any other mode is chosen then the
+ // windows will change mode and create a true full-screen window.
+ if (mode_id != DISPLAY_MODE_DEFAULT) {
+ refresh_rate = mode.refresh_rate();
+ windowed = false;
}
+
+ showing_fullscreen_message_ = true;
+ fullscreen_message_timer_.GetElapsedTimeAndReset(); // Reset the timer.
+
d3d_present_parameters_.FullScreen_RefreshRateInHz = refresh_rate;
d3d_present_parameters_.hDeviceWindow = window;
d3d_present_parameters_.Windowed = windowed;
// Check if the window size is zero. Some drivers will fail because of
// that so we'll force a small size in that case.
- RECT windowRect;
- ::GetWindowRect(window, &windowRect);
- int width = windowRect.right - windowRect.left;
- int height = windowRect.bottom - windowRect.top;
+ if (width == 0 || height == 0) {
+ width = 16;
+ height = 16;
+ }
+ fullscreen_ = true;
+ Resize(width, height);
+ }
+ }
+ return true;
+}
+bool RendererD3D9::CancelFullscreen(const DisplayWindow& display,
+ int width,
+ int height) {
+ if (fullscreen_) {
+ if (d3d_device_) { // Have we been initialized yet?
+ const DisplayWindowWindows& platform_display =
+ static_cast<const DisplayWindowWindows&>(display);
+ HWND window = platform_display.hwnd();
+ showing_fullscreen_message_ = false;
+ d3d_present_parameters_.FullScreen_RefreshRateInHz = 0;
+ d3d_present_parameters_.hDeviceWindow = window;
+ d3d_present_parameters_.Windowed = true;
+
+ // Check if the window size is zero. Some drivers will fail because of
+ // that so we'll force a small size in that case.
if (width == 0 || height == 0) {
width = 16;
height = 16;
}
- fullscreen_ = fullscreen;
+ fullscreen_ = false;
Resize(width, height);
}
}
diff --git a/o3d/core/win/d3d9/renderer_d3d9.h b/o3d/core/win/d3d9/renderer_d3d9.h
index e4a567c..4a7221b 100644
--- a/o3d/core/win/d3d9/renderer_d3d9.h
+++ b/o3d/core/win/d3d9/renderer_d3d9.h
@@ -77,15 +77,13 @@ class RendererD3D9 : public Renderer {
// Attempts to reset the back buffer to its new dimensions.
virtual void Resize(int width, int height);
- // Turns fullscreen display on or off.
- // Parameters:
- // fullscreen: true for fullscreen, false for in-plugin display
- // display: a platform-specific display identifier
- // mode_id: a mode returned by GetDisplayModes, for fullscreen use. Ignored
- // in non-fullscreen mode.
- // Returns true on success, false on failure.
- virtual bool SetFullscreen(bool fullscreen, const DisplayWindow& display,
- int mode_id);
+ // Overridden from Renderer.
+ virtual bool GoFullscreen(const DisplayWindow& display,
+ int mode_id);
+
+ // Overridden from Renderer.
+ virtual bool CancelFullscreen(const DisplayWindow& display,
+ int width, int height);
// Tells whether we're currently displayed fullscreen or not.
virtual bool fullscreen() const {