diff options
author | mazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-11 03:58:59 +0000 |
---|---|---|
committer | mazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-11 03:58:59 +0000 |
commit | a2a1f48277a24594cecd4b90585ec95923101128 (patch) | |
tree | 394b797212f48d6ae3c00485be443e48f0463d09 /content/browser/renderer_host | |
parent | bd985a221a00d320a4fb585c3a5a920724d79621 (diff) | |
download | chromium_src-a2a1f48277a24594cecd4b90585ec95923101128.zip chromium_src-a2a1f48277a24594cecd4b90585ec95923101128.tar.gz chromium_src-a2a1f48277a24594cecd4b90585ec95923101128.tar.bz2 |
Implement RenderWidgetHostViewMac::CopyFromCompositingSurface.
This adds the support of the browser side thumbailing to Mac Chrome.
BUG=120001
TEST=Manually tested that thumbnails are properly generated on GPU composited pages with --enable-in-browser-thumbnailing.
Review URL: http://codereview.chromium.org/10022007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131710 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/renderer_host')
3 files changed, 111 insertions, 20 deletions
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h index b81b286..6f0d8da 100644 --- a/content/browser/renderer_host/compositing_iosurface_mac.h +++ b/content/browser/renderer_host/compositing_iosurface_mac.h @@ -32,6 +32,12 @@ class CompositingIOSurfaceMac { // be white. void DrawIOSurface(NSView* view); + // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef + // into |out|. The image data is transformed so that it fits in |dst_size|. + // Caller must ensure that |out| is allocated with the size no less than + // |4 * dst_size.width() * dst_size.height()| bytes. + bool CopyTo(const gfx::Size& dst_size, void* out); + // Unref the IOSurface and delete the associated GL texture. If the GPU // process is no longer referencing it, this will delete the IOSurface. void UnrefIOSurface(); @@ -66,15 +72,17 @@ class CompositingIOSurfaceMac { // Counter-clockwise verts starting from upper-left corner (0, 0). struct SurfaceQuad { - void set_size(gfx::Size size) { + void set_size(gfx::Size vertex_size, gfx::Size texcoord_size) { // Texture coordinates are flipped vertically so they can be drawn on // a projection with a flipped y-axis (origin is top left). - float w = static_cast<float>(size.width()); - float h = static_cast<float>(size.height()); - verts_[0].set(0.0f, 0.0f, 0.0f, h); - verts_[1].set(0.0f, h, 0.0f, 0.0f); - verts_[2].set(w, h, w, 0.0f); - verts_[3].set(w, 0.0f, w, h); + float vw = static_cast<float>(vertex_size.width()); + float vh = static_cast<float>(vertex_size.height()); + float tw = static_cast<float>(texcoord_size.width()); + float th = static_cast<float>(texcoord_size.height()); + verts_[0].set(0.0f, 0.0f, 0.0f, th); + verts_[1].set(0.0f, vh, 0.0f, 0.0f); + verts_[2].set(vw, vh, tw, 0.0f); + verts_[3].set(vw, 0.0f, tw, th); } SurfaceVertex verts_[4]; }; @@ -88,6 +96,8 @@ class CompositingIOSurfaceMac { void UnrefIOSurfaceWithContextCurrent(); + void DrawQuad(const SurfaceQuad& quad); + // Cached pointer to IOSurfaceSupport Singleton. IOSurfaceSupport* io_surface_support_; diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm index 6b4a53d..f1754cf 100644 --- a/content/browser/renderer_host/compositing_iosurface_mac.mm +++ b/content/browser/renderer_host/compositing_iosurface_mac.mm @@ -136,15 +136,7 @@ void CompositingIOSurfaceMac::DrawIOSurface(NSView* view) { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); CHECK_GL_ERROR(); glEnable(GL_TEXTURE_RECTANGLE_ARB); CHECK_GL_ERROR(); - glEnableClientState(GL_VERTEX_ARRAY); CHECK_GL_ERROR(); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_GL_ERROR(); - - glVertexPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad_.verts_[0].x_); - glTexCoordPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad_.verts_[0].tx_); - glDrawArrays(GL_QUADS, 0, 4); CHECK_GL_ERROR(); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + DrawQuad(quad_); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); CHECK_GL_ERROR(); } @@ -154,6 +146,77 @@ void CompositingIOSurfaceMac::DrawIOSurface(NSView* view) { CGLSetCurrentContext(0); } +bool CompositingIOSurfaceMac::CopyTo(const gfx::Size& dst_size, void* out) { + if (!MapIOSurfaceToTexture(io_surface_handle_)) + return false; + + CGLSetCurrentContext(cglContext_); + GLuint target = GL_TEXTURE_RECTANGLE_ARB; + + GLuint dst_texture = 0; + glGenTextures(1, &dst_texture); CHECK_GL_ERROR(); + glBindTexture(target, dst_texture); CHECK_GL_ERROR(); + + GLuint dst_framebuffer = 0; + glGenFramebuffersEXT(1, &dst_framebuffer); CHECK_GL_ERROR(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dst_framebuffer); CHECK_GL_ERROR(); + + glTexImage2D(target, + 0, + GL_RGBA, + dst_size.width(), + dst_size.height(), + 0, + GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, + NULL); CHECK_GL_ERROR(); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + target, + dst_texture, + 0); CHECK_GL_ERROR(); + glBindTexture(target, 0); CHECK_GL_ERROR(); + + glViewport(0, 0, dst_size.width(), dst_size.height()); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, dst_size.width(), 0, dst_size.height(), -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + // Draw only the color channels from the incoming texture. + glColorMask(true, true, true, false); + + // Draw the color channels from the incoming texture. + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); CHECK_GL_ERROR(); + glEnable(GL_TEXTURE_RECTANGLE_ARB); CHECK_GL_ERROR(); + + SurfaceQuad quad; + quad.set_size(dst_size, io_surface_size_); + DrawQuad(quad); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); CHECK_GL_ERROR(); + + CGLFlushDrawable(cglContext_); + + glReadPixels(0, 0, dst_size.width(), dst_size.height(), + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, out); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR(); + + glDeleteFramebuffersEXT(1, &dst_framebuffer); + glDeleteTextures(1, &dst_texture); + + CGLSetCurrentContext(0); + return true; +} + bool CompositingIOSurfaceMac::MapIOSurfaceToTexture( uint64 io_surface_handle) { if (io_surface_.get() && io_surface_handle == io_surface_handle_) @@ -176,7 +239,7 @@ bool CompositingIOSurfaceMac::MapIOSurfaceToTexture( io_surface_support_->IOSurfaceGetWidth(io_surface_), io_surface_support_->IOSurfaceGetHeight(io_surface_)); - quad_.set_size(io_surface_size_); + quad_.set_size(io_surface_size_, io_surface_size_); GLenum target = GL_TEXTURE_RECTANGLE_ARB; glGenTextures(1, &texture_); @@ -209,6 +272,18 @@ void CompositingIOSurfaceMac::UnrefIOSurface() { CGLSetCurrentContext(0); } +void CompositingIOSurfaceMac::DrawQuad(const SurfaceQuad& quad) { + glEnableClientState(GL_VERTEX_ARRAY); CHECK_GL_ERROR(); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_GL_ERROR(); + + glVertexPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].x_); + glTexCoordPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].tx_); + glDrawArrays(GL_QUADS, 0, 4); CHECK_GL_ERROR(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + void CompositingIOSurfaceMac::UnrefIOSurfaceWithContextCurrent() { if (texture_) { glDeleteTextures(1, &texture_); diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 6ba515f..9f5a2de 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -796,9 +796,15 @@ BackingStore* RenderWidgetHostViewMac::AllocBackingStore( bool RenderWidgetHostViewMac::CopyFromCompositingSurface( const gfx::Size& size, skia::PlatformCanvas* output) { - // TODO(mazda): Implement this. - NOTIMPLEMENTED(); - return false; + if (!compositing_iosurface_.get() || + !compositing_iosurface_->HasIOSurface()) + return false; + + if (!output->initialize(size.width(), size.height(), true)) + return false; + + return compositing_iosurface_->CopyTo( + size, output->getTopDevice()->accessBitmap(true).getPixels()); } void RenderWidgetHostViewMac::AsyncCopyFromCompositingSurface( |