summaryrefslogtreecommitdiffstats
path: root/o3d/core
diff options
context:
space:
mode:
authorkbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-11 01:26:00 +0000
committerkbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-11 01:26:00 +0000
commit8a304130d6d53bae89ae6023e64b261624ed5ddf (patch)
tree1b58beab34926aa5eab2f5b2ce866d9a31a6925a /o3d/core
parentb93cc8295f42e55bb2bec5e444918a8cd20da069 (diff)
downloadchromium_src-8a304130d6d53bae89ae6023e64b261624ed5ddf.zip
chromium_src-8a304130d6d53bae89ae6023e64b261624ed5ddf.tar.gz
chromium_src-8a304130d6d53bae89ae6023e64b261624ed5ddf.tar.bz2
Added support for O3D in Chrome on Mac OS X using CoreGraphics drawing
model by rendering offscreen, reading back the frame buffer, and drawing the rendering results into the CGContextRef. This code path is currently Chrome-specific, but could be used for any browser with similar characteristics. This will require refactoring of the drawing and event model selection code, which may be done in a subsequent bug. Changed the RenderSurface APIs to allow the Bitmap for readback to be passed in. Added Client::SetOffscreenRenderingSurfaces so that the entry point Client::RenderClient() can be used unchanged. Fixed problem with plugin_enable_fullscreen_msg gyp variable which needs to be in top-level gypi so #define is consistent throughout project. Fixed minor issue in Cocoa key event handling. Fixed log message causing crashes when render target attachment fails. Chrome currently blacklists the O3D plugin's MIME type, so to enable support for O3D this blacklist entry needs to be removed from Chrome. Ran nearly all O3D samples in Chrome on Mac OS X. There are a couple of failures which will be fixed in subsequent bugs. Also ran samples in Safari and Firefox on Mac and verified no performance regressions. BUG=http://code.google.com/p/o3d/issues/detail?id=215 TEST=ran O3D samples in Chrome, Safari and Firefox Review URL: http://codereview.chromium.org/669220 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41233 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/core')
-rw-r--r--o3d/core/cross/client.cc27
-rw-r--r--o3d/core/cross/client.h12
-rw-r--r--o3d/core/cross/gl/render_surface_gl.cc12
-rw-r--r--o3d/core/cross/gl/render_surface_gl.h4
-rw-r--r--o3d/core/cross/gl/renderer_gl.cc3
-rw-r--r--o3d/core/cross/gl/texture_gl.cc1
-rw-r--r--o3d/core/cross/param_test.cc2
-rw-r--r--o3d/core/cross/render_surface.cc24
-rw-r--r--o3d/core/cross/render_surface.h11
-rw-r--r--o3d/core/win/d3d9/render_surface_d3d9.cc26
-rw-r--r--o3d/core/win/d3d9/render_surface_d3d9.h4
11 files changed, 96 insertions, 30 deletions
diff --git a/o3d/core/cross/client.cc b/o3d/core/cross/client.cc
index a7f5924..c63c940 100644
--- a/o3d/core/cross/client.cc
+++ b/o3d/core/cross/client.cc
@@ -304,7 +304,25 @@ void Client::RenderClient(bool send_callback) {
if (!renderer_.IsAvailable())
return;
- RenderClientInner(true, send_callback);
+ bool have_offscreen_surfaces =
+ !(offscreen_render_surface_.IsNull() ||
+ offscreen_depth_render_surface_.IsNull());
+
+ if (have_offscreen_surfaces) {
+ if (!renderer_->StartRendering()) {
+ return;
+ }
+ renderer_->SetRenderSurfaces(offscreen_render_surface_,
+ offscreen_depth_render_surface_,
+ true);
+ }
+
+ RenderClientInner(!have_offscreen_surfaces, send_callback);
+
+ if (have_offscreen_surfaces) {
+ renderer_->SetRenderSurfaces(NULL, NULL, false);
+ renderer_->FinishRendering();
+ }
}
// Executes draw calls for all visible shapes in a subtree
@@ -503,6 +521,13 @@ String Client::GetMessageQueueAddress() const {
}
}
+void Client::SetOffscreenRenderingSurfaces(
+ RenderSurface::Ref surface,
+ RenderDepthStencilSurface::Ref depth_surface) {
+ offscreen_render_surface_ = surface;
+ offscreen_depth_render_surface_ = depth_surface;
+}
+
// Error Related methods -------------------------------------------------------
void Client::SetErrorCallback(ErrorCallback* callback) {
diff --git a/o3d/core/cross/client.h b/o3d/core/cross/client.h
index 7347af4..003c6de 100644
--- a/o3d/core/cross/client.h
+++ b/o3d/core/cross/client.h
@@ -59,6 +59,7 @@
#include "core/cross/event_manager.h"
#include "core/cross/lost_resource_callback.h"
#include "core/cross/render_event.h"
+#include "core/cross/render_surface.h"
#include "core/cross/tick_event.h"
#include "core/cross/timer.h"
#include "core/cross/timingtable.h"
@@ -429,6 +430,14 @@ class Client {
DISALLOW_COPY_AND_ASSIGN(ScopedIncrement);
};
+ // Offscreen rendering methods -------------------
+
+ // Sets up this Client so that RenderClient will cause the rendering
+ // results to go into the given surfaces.
+ void SetOffscreenRenderingSurfaces(
+ RenderSurface::Ref surface,
+ RenderDepthStencilSurface::Ref depth_surface);
+
private:
// Renders the client.
void RenderClientInner(bool present, bool send_callback);
@@ -499,6 +508,9 @@ class Client {
int calls_; // Used to check reentrancy along with ScopedIncrement.
+ RenderSurface::Ref offscreen_render_surface_;
+ RenderDepthStencilSurface::Ref offscreen_depth_render_surface_;
+
DISALLOW_COPY_AND_ASSIGN(Client);
}; // Client
diff --git a/o3d/core/cross/gl/render_surface_gl.cc b/o3d/core/cross/gl/render_surface_gl.cc
index 6570baa..f12718c 100644
--- a/o3d/core/cross/gl/render_surface_gl.cc
+++ b/o3d/core/cross/gl/render_surface_gl.cc
@@ -54,13 +54,13 @@ RenderSurfaceGL::RenderSurfaceGL(ServiceLocator *service_locator,
RenderSurfaceGL::~RenderSurfaceGL() {
}
-Bitmap::Ref RenderSurfaceGL::PlatformSpecificGetBitmap() const {
+bool RenderSurfaceGL::PlatformSpecificGetIntoBitmap(Bitmap::Ref bitmap) const {
Renderer* renderer = service_locator()->GetService<Renderer>();
DCHECK(renderer);
-
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->Allocate(
- Texture::ARGB8, clip_width(), clip_height(), 1, Bitmap::IMAGE);
+ DCHECK(bitmap->width() == static_cast<unsigned int>(clip_width()) &&
+ bitmap->height() == static_cast<unsigned int>(clip_height()) &&
+ bitmap->num_mipmaps() == 1 &&
+ bitmap->format() == Texture::ARGB8);
const RenderSurface* old_render_surface;
const RenderDepthStencilSurface* old_depth_surface;
@@ -76,7 +76,7 @@ Bitmap::Ref RenderSurfaceGL::PlatformSpecificGetBitmap() const {
renderer->SetRenderSurfaces(old_render_surface, old_depth_surface,
old_is_back_buffer);
- return bitmap;
+ return true;
}
RenderDepthStencilSurfaceGL::RenderDepthStencilSurfaceGL(
diff --git a/o3d/core/cross/gl/render_surface_gl.h b/o3d/core/cross/gl/render_surface_gl.h
index 593b7994..254a142 100644
--- a/o3d/core/cross/gl/render_surface_gl.h
+++ b/o3d/core/cross/gl/render_surface_gl.h
@@ -73,8 +73,8 @@ class RenderSurfaceGL : public RenderSurface {
}
protected:
- // The platform specific part of GetBitmap.
- virtual Bitmap::Ref PlatformSpecificGetBitmap() const;
+ // The platform specific part of GetIntoBitmap.
+ virtual bool PlatformSpecificGetIntoBitmap(Bitmap::Ref bitmap) const;
private:
GLenum cube_face_;
diff --git a/o3d/core/cross/gl/renderer_gl.cc b/o3d/core/cross/gl/renderer_gl.cc
index e4de52f..378c74e 100644
--- a/o3d/core/cross/gl/renderer_gl.cc
+++ b/o3d/core/cross/gl/renderer_gl.cc
@@ -1317,7 +1317,8 @@ void RendererGL::SetRenderSurfacesPlatformSpecific(
if (!InstallFramebufferObjects(surface, surface_depth)) {
O3D_ERROR(service_locator())
<< "Failed to bind OpenGL render target objects:"
- << surface->name() <<", "<< surface_depth->name();
+ << (surface ? surface->name() : "(no surface)") << ", "
+ << (surface_depth ? surface_depth->name() : "(no depth surface)");
}
// RenderSurface rendering is performed with an inverted Y, so the front
// face winding must be changed to clock-wise. See comments for
diff --git a/o3d/core/cross/gl/texture_gl.cc b/o3d/core/cross/gl/texture_gl.cc
index c168f41..f9a11e0 100644
--- a/o3d/core/cross/gl/texture_gl.cc
+++ b/o3d/core/cross/gl/texture_gl.cc
@@ -278,6 +278,7 @@ Texture2DGL* Texture2DGL::Create(ServiceLocator* service_locator,
bool enable_render_surfaces) {
DLOG(INFO) << "Texture2DGL Create";
DCHECK_NE(format, Texture::UNKNOWN_FORMAT);
+ DCHECK_GE(levels, 0);
RendererGL *renderer = static_cast<RendererGL *>(
service_locator->GetService<Renderer>());
renderer->MakeCurrentLazy();
diff --git a/o3d/core/cross/param_test.cc b/o3d/core/cross/param_test.cc
index 82daa16..f4e7299 100644
--- a/o3d/core/cross/param_test.cc
+++ b/o3d/core/cross/param_test.cc
@@ -78,7 +78,7 @@ class TestRenderSurface : public RenderSurface {
explicit TestRenderSurface(ServiceLocator* service_locator)
: RenderSurface(service_locator, 1, 1, NULL) {}
void* GetSurfaceHandle() const { return NULL; }
- Bitmap::Ref PlatformSpecificGetBitmap() const { return Bitmap::Ref(); }
+ bool PlatformSpecificGetIntoBitmap(Bitmap::Ref bitmap) const { return true; }
};
// TestSampler derives from o3d::Sampler and provides a public
diff --git a/o3d/core/cross/render_surface.cc b/o3d/core/cross/render_surface.cc
index 0e6a85a..8db8f01 100644
--- a/o3d/core/cross/render_surface.cc
+++ b/o3d/core/cross/render_surface.cc
@@ -72,7 +72,29 @@ RenderSurface::RenderSurface(ServiceLocator* service_locator,
}
Bitmap::Ref RenderSurface::GetBitmap() const {
- return PlatformSpecificGetBitmap();
+ Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
+ bitmap->Allocate(Texture::ARGB8,
+ clip_width(),
+ clip_height(),
+ 1,
+ Bitmap::IMAGE);
+ if (!GetIntoBitmap(bitmap)) {
+ Bitmap::Ref empty;
+ return empty;
+ }
+ return bitmap;
+}
+
+bool RenderSurface::GetIntoBitmap(Bitmap::Ref bitmap) const {
+ if (bitmap.IsNull() ||
+ bitmap->width() != static_cast<unsigned int>(clip_width()) ||
+ bitmap->height() != static_cast<unsigned int>(clip_height()) ||
+ bitmap->num_mipmaps() != 1 ||
+ bitmap->format() != Texture::ARGB8) {
+ return false;
+ }
+
+ return PlatformSpecificGetIntoBitmap(bitmap);
}
RenderDepthStencilSurface::RenderDepthStencilSurface(
diff --git a/o3d/core/cross/render_surface.h b/o3d/core/cross/render_surface.h
index ba6db69..8ee3f01 100644
--- a/o3d/core/cross/render_surface.h
+++ b/o3d/core/cross/render_surface.h
@@ -138,9 +138,16 @@ class RenderSurface : public RenderSurfaceBase {
// Only gets the clip_width/clip_height area.
Bitmap::Ref GetBitmap() const;
+ // Gets a copy of the contents of the render surface into the given
+ // Bitmap. Only gets the clip_width/clip_height area. Returns true
+ // if the bitmap was appropriately sized, false if not or if an
+ // error occurred.
+ bool GetIntoBitmap(Bitmap::Ref bitmap) const;
+
protected:
- // The platform specific part of GetBitmap.
- virtual Bitmap::Ref PlatformSpecificGetBitmap() const = 0;
+ // The platform specific part of GetIntoBitmap.
+ virtual bool PlatformSpecificGetIntoBitmap(
+ Bitmap::Ref bitmap) const = 0;
private:
// Texture parameter of the texture in which this render surface is contained.
diff --git a/o3d/core/win/d3d9/render_surface_d3d9.cc b/o3d/core/win/d3d9/render_surface_d3d9.cc
index 5b7c9e4..c291887 100644
--- a/o3d/core/win/d3d9/render_surface_d3d9.cc
+++ b/o3d/core/win/d3d9/render_surface_d3d9.cc
@@ -75,11 +75,15 @@ void RenderSurfaceD3D9::Clear() {
}
}
-Bitmap::Ref RenderSurfaceD3D9::PlatformSpecificGetBitmap() const {
- Bitmap::Ref empty;
+bool RenderSurfaceD3D9::PlatformSpecificGetIntoBitmap(
+ Bitmap::Ref bitmap) const {
+ DCHECK(bitmap->width() == static_cast<unsigned int>(clip_width()) &&
+ bitmap->height() == static_cast<unsigned int>(clip_height()) &&
+ bitmap->num_mipmaps() == 1 &&
+ bitmap->format() == Texture::ARGB8);
if (!direct3d_surface_) {
- return empty;
+ return false;
}
RendererD3D9* renderer =
@@ -89,7 +93,7 @@ Bitmap::Ref RenderSurfaceD3D9::PlatformSpecificGetBitmap() const {
D3DSURFACE_DESC surface_description;
if (!HR(direct3d_surface_->GetDesc(&surface_description))) {
- return empty;
+ return false;
}
if (!HR(device->CreateOffscreenPlainSurface(surface_description.Width,
@@ -98,25 +102,19 @@ Bitmap::Ref RenderSurfaceD3D9::PlatformSpecificGetBitmap() const {
D3DPOOL_SYSTEMMEM,
&system_surface,
NULL))) {
- return empty;
+ return false;
}
if (!HR(device->GetRenderTargetData(direct3d_surface_, system_surface)))
- return empty;
+ return false;
RECT rect = { 0, 0, clip_width(), clip_height() };
D3DLOCKED_RECT out_rect = {0};
if (!HR(system_surface->LockRect(&out_rect, &rect, D3DLOCK_READONLY))) {
O3D_ERROR(service_locator()) << "Failed to Lock Surface (D3D9)";
- return empty;
+ return false;
}
- Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
- bitmap->Allocate(Texture::ARGB8,
- clip_width(),
- clip_height(),
- 1,
- Bitmap::IMAGE);
bitmap->SetRect(0, 0, 0,
clip_width(),
clip_height(),
@@ -125,7 +123,7 @@ Bitmap::Ref RenderSurfaceD3D9::PlatformSpecificGetBitmap() const {
system_surface->UnlockRect();
- return bitmap;
+ return true;
}
RenderDepthStencilSurfaceD3D9::RenderDepthStencilSurfaceD3D9(
diff --git a/o3d/core/win/d3d9/render_surface_d3d9.h b/o3d/core/win/d3d9/render_surface_d3d9.h
index c708dab..f541e6f 100644
--- a/o3d/core/win/d3d9/render_surface_d3d9.h
+++ b/o3d/core/win/d3d9/render_surface_d3d9.h
@@ -79,8 +79,8 @@ class RenderSurfaceD3D9 : public RenderSurface {
void Clear();
protected:
- // The platform specific part of GetBitmap.
- virtual Bitmap::Ref PlatformSpecificGetBitmap() const;
+ // The platform specific part of GetIntoBitmap.
+ virtual bool PlatformSpecificGetIntoBitmap(Bitmap::Ref bitmap) const;
private:
CComPtr<IDirect3DSurface9> direct3d_surface_;