Flag and adapter class for software compositing.
I'm adding a new CCRendererSkia class to CC, providing support for compositing a website to a software bitmap. However, the rest of the software compositing pipeline (delegating shared-memory resources and quadlists to the root compositor) is not yet done, so there's no way to get this bitmap onto the screen. As a stopgap, add an adapter class that uploads to a viewport-sized GL texture every frame, and a flag --force-software-compositing to activate it. BUG=124671 Review URL: https://chromiumcodereview.appspot.com/10873099 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@158388 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
content
@ -816,6 +816,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
|
||||
switches::kEnableSandboxLogging,
|
||||
#endif
|
||||
switches::kEnableSeccompSandbox,
|
||||
switches::kEnableSoftwareCompositingGLAdapter,
|
||||
switches::kEnableStatsTable,
|
||||
switches::kEnableThreadedCompositing,
|
||||
switches::kDisableThreadedCompositing,
|
||||
|
@ -85,6 +85,8 @@
|
||||
'renderer/geolocation_dispatcher.h',
|
||||
'renderer/gpu/compositor_output_surface.cc',
|
||||
'renderer/gpu/compositor_output_surface.h',
|
||||
'renderer/gpu/compositor_software_output_device_gl_adapter.cc',
|
||||
'renderer/gpu/compositor_software_output_device_gl_adapter.h',
|
||||
'renderer/gpu/compositor_thread.cc',
|
||||
'renderer/gpu/compositor_thread.h',
|
||||
'renderer/gpu/input_event_filter.cc',
|
||||
|
@ -401,6 +401,10 @@ const char kForceFieldTrials[] = "force-fieldtrials";
|
||||
// overrides this if present.
|
||||
const char kForceRendererAccessibility[] = "force-renderer-accessibility";
|
||||
|
||||
// Force the compositor to use its software implementation instead of GL.
|
||||
const char kEnableSoftwareCompositingGLAdapter[] =
|
||||
"enable-software-compositing-gl-adapter";
|
||||
|
||||
// Passes gpu device_id from browser process to GPU process.
|
||||
const char kGpuDeviceID[] = "gpu-device-id";
|
||||
|
||||
|
@ -115,6 +115,7 @@ extern const char kEnableRendererSideMixing[];
|
||||
extern const char kEnableSSLCachedInfo[];
|
||||
extern const char kEnableSandboxLogging[];
|
||||
extern const char kEnableSeccompSandbox[];
|
||||
CONTENT_EXPORT extern const char kEnableSoftwareCompositingGLAdapter[];
|
||||
CONTENT_EXPORT extern const char kEnableSmoothScrolling[];
|
||||
CONTENT_EXPORT extern const char kEnableStatsTable[];
|
||||
extern const char kEnableStrictSiteIsolation[];
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
|
||||
|
||||
using WebKit::WebGraphicsContext3D;
|
||||
using WebKit::WebCompositorSoftwareOutputDevice;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -28,12 +29,14 @@ IPC::ForwardingMessageFilter* CompositorOutputSurface::CreateFilter(
|
||||
|
||||
CompositorOutputSurface::CompositorOutputSurface(
|
||||
int32 routing_id,
|
||||
WebGraphicsContext3D* context3D)
|
||||
WebGraphicsContext3D* context3D,
|
||||
WebCompositorSoftwareOutputDevice* software_device)
|
||||
: output_surface_filter_(
|
||||
RenderThreadImpl::current()->compositor_output_surface_filter())
|
||||
, client_(NULL)
|
||||
, routing_id_(routing_id)
|
||||
, context3D_(context3D) {
|
||||
RenderThreadImpl::current()->compositor_output_surface_filter()),
|
||||
client_(NULL),
|
||||
routing_id_(routing_id),
|
||||
context3D_(context3D),
|
||||
software_device_(software_device) {
|
||||
DCHECK(output_surface_filter_);
|
||||
capabilities_.hasParentCompositor = false;
|
||||
DetachFromThread();
|
||||
@ -56,8 +59,10 @@ bool CompositorOutputSurface::bindToClient(
|
||||
WebKit::WebCompositorOutputSurfaceClient* client) {
|
||||
DCHECK(CalledOnValidThread());
|
||||
DCHECK(!client_);
|
||||
if (!context3D_->makeContextCurrent())
|
||||
return false;
|
||||
if (context3D_.get()) {
|
||||
if (!context3D_->makeContextCurrent())
|
||||
return false;
|
||||
}
|
||||
|
||||
client_ = client;
|
||||
|
||||
@ -74,6 +79,11 @@ WebGraphicsContext3D* CompositorOutputSurface::context3D() const {
|
||||
return context3D_.get();
|
||||
}
|
||||
|
||||
WebCompositorSoftwareOutputDevice* CompositorOutputSurface::softwareDevice()
|
||||
const {
|
||||
return software_device_.get();
|
||||
}
|
||||
|
||||
void CompositorOutputSurface::sendFrameToParentCompositor(
|
||||
const WebKit::WebCompositorFrame&) {
|
||||
DCHECK(CalledOnValidThread());
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "base/threading/non_thread_safe.h"
|
||||
#include "base/time.h"
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebCompositorOutputSurface.h"
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebCompositorSoftwareOutputDevice.h"
|
||||
|
||||
namespace base {
|
||||
class TaskRunner;
|
||||
@ -33,7 +34,8 @@ class CompositorOutputSurface
|
||||
base::TaskRunner* target_task_runner);
|
||||
|
||||
CompositorOutputSurface(int32 routing_id,
|
||||
WebKit::WebGraphicsContext3D* context3d);
|
||||
WebKit::WebGraphicsContext3D* context3d,
|
||||
WebKit::WebCompositorSoftwareOutputDevice* software);
|
||||
virtual ~CompositorOutputSurface();
|
||||
|
||||
// WebCompositorOutputSurface implementation.
|
||||
@ -41,6 +43,7 @@ class CompositorOutputSurface
|
||||
WebKit::WebCompositorOutputSurfaceClient* client) OVERRIDE;
|
||||
virtual const Capabilities& capabilities() const OVERRIDE;
|
||||
virtual WebKit::WebGraphicsContext3D* context3D() const OVERRIDE;
|
||||
virtual WebKit::WebCompositorSoftwareOutputDevice* softwareDevice() const;
|
||||
virtual void sendFrameToParentCompositor(
|
||||
const WebKit::WebCompositorFrame&) OVERRIDE;
|
||||
|
||||
@ -54,7 +57,7 @@ class CompositorOutputSurface
|
||||
int routing_id_;
|
||||
Capabilities capabilities_;
|
||||
scoped_ptr<WebKit::WebGraphicsContext3D> context3D_;
|
||||
scoped_ptr<WebKit::WebCompositorSoftwareOutputDevice> software_device_;
|
||||
};
|
||||
|
||||
#endif // CONTENT_RENDERER_GPU_COMPOSITOR_OUTPUT_SURFACE_H_
|
||||
|
||||
|
@ -0,0 +1,178 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "content/renderer/gpu/compositor_software_output_device_gl_adapter.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkPixelRef.h"
|
||||
#include "third_party/skia/include/core/SkDevice.h"
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
using WebKit::WebImage;
|
||||
using WebKit::WebGraphicsContext3D;
|
||||
using WebKit::WebSize;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CompositorSoftwareOutputDeviceGLAdapter::
|
||||
CompositorSoftwareOutputDeviceGLAdapter(WebGraphicsContext3D* context3D)
|
||||
: initialized_(false),
|
||||
program_(0),
|
||||
vertex_shader_(0),
|
||||
fragment_shader_(0),
|
||||
vertex_buffer_(0),
|
||||
framebuffer_texture_id_(0),
|
||||
context3d_(context3D),
|
||||
locked_for_write_(false) {
|
||||
}
|
||||
|
||||
CompositorSoftwareOutputDeviceGLAdapter::
|
||||
~CompositorSoftwareOutputDeviceGLAdapter() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
WebImage* CompositorSoftwareOutputDeviceGLAdapter::lock(bool forWrite) {
|
||||
locked_for_write_ = forWrite;
|
||||
image_ = device_->accessBitmap(forWrite);
|
||||
return &image_;
|
||||
}
|
||||
|
||||
void CompositorSoftwareOutputDeviceGLAdapter::unlock() {
|
||||
if (locked_for_write_)
|
||||
Draw(device_->accessBitmap(false).pixelRef()->pixels());
|
||||
image_.reset();
|
||||
}
|
||||
|
||||
void CompositorSoftwareOutputDeviceGLAdapter::didChangeViewportSize(
|
||||
WebSize size) {
|
||||
if (!initialized_)
|
||||
Initialize();
|
||||
|
||||
if (framebuffer_texture_size_ != gfx::Size(size))
|
||||
Resize(size);
|
||||
}
|
||||
|
||||
void CompositorSoftwareOutputDeviceGLAdapter::Initialize() {
|
||||
// Vertex shader that flips the y axis.
|
||||
static const char g_vertex_shader[] =
|
||||
"attribute vec4 a_Position;"
|
||||
"attribute vec2 a_texCoord;"
|
||||
"varying vec2 v_texCoord;"
|
||||
"void main() {"
|
||||
" gl_Position = a_Position;"
|
||||
" gl_Position.y = -gl_Position.y;"
|
||||
" v_texCoord = a_texCoord;"
|
||||
"}";
|
||||
|
||||
// Pixel shader that swizzles RGBA -> BGRA.
|
||||
static const char g_fragment_shader[] =
|
||||
"precision mediump float;"
|
||||
"varying vec2 v_texCoord;"
|
||||
"uniform sampler2D s_texture;"
|
||||
"void main() {"
|
||||
" gl_FragColor = texture2D(s_texture, v_texCoord).bgra;"
|
||||
"}";
|
||||
|
||||
const GLfloat attribs[] = {
|
||||
-1.0f, -1.0f,
|
||||
1.0f, -1.0f,
|
||||
-1.0f, 1.0f,
|
||||
1.0f, 1.0f,
|
||||
0.0f, 0.0f,
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
1.0f, 1.0f
|
||||
};
|
||||
|
||||
context3d_->makeContextCurrent();
|
||||
|
||||
vertex_shader_ = context3d_->createShader(GL_VERTEX_SHADER);
|
||||
context3d_->shaderSource(vertex_shader_, g_vertex_shader);
|
||||
context3d_->compileShader(vertex_shader_);
|
||||
|
||||
fragment_shader_ = context3d_->createShader(GL_FRAGMENT_SHADER);
|
||||
context3d_->shaderSource(fragment_shader_, g_fragment_shader);
|
||||
context3d_->compileShader(fragment_shader_);
|
||||
|
||||
program_ = context3d_->createProgram();
|
||||
context3d_->attachShader(program_, vertex_shader_);
|
||||
context3d_->attachShader(program_, fragment_shader_);
|
||||
|
||||
vertex_buffer_ = context3d_->createBuffer();
|
||||
context3d_->bindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
|
||||
context3d_->bufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), attribs,
|
||||
GL_STATIC_DRAW);
|
||||
context3d_->enableVertexAttribArray(0);
|
||||
context3d_->vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
context3d_->bindAttribLocation(program_, 0, "a_Position");
|
||||
context3d_->enableVertexAttribArray(1);
|
||||
context3d_->vertexAttribPointer(
|
||||
1, 2, GL_FLOAT, GL_FALSE, 0, 8 * sizeof(GLfloat));
|
||||
context3d_->bindAttribLocation(program_, 1, "a_texCoord");
|
||||
|
||||
context3d_->linkProgram(program_);
|
||||
context3d_->useProgram(program_);
|
||||
|
||||
int texture_uniform = context3d_->getUniformLocation(program_, "s_texture");
|
||||
context3d_->uniform1i(texture_uniform, 0);
|
||||
context3d_->disable(GL_SCISSOR_TEST);
|
||||
context3d_->clearColor(0, 0, 1, 1);
|
||||
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
void CompositorSoftwareOutputDeviceGLAdapter::Destroy() {
|
||||
if (!initialized_)
|
||||
return;
|
||||
|
||||
context3d_->makeContextCurrent();
|
||||
context3d_->deleteShader(vertex_shader_);
|
||||
context3d_->deleteShader(fragment_shader_);
|
||||
context3d_->deleteProgram(program_);
|
||||
context3d_->deleteBuffer(vertex_buffer_);
|
||||
if (framebuffer_texture_id_)
|
||||
context3d_->deleteTexture(framebuffer_texture_id_);
|
||||
}
|
||||
|
||||
void CompositorSoftwareOutputDeviceGLAdapter::Resize(
|
||||
const gfx::Size& viewport_size) {
|
||||
framebuffer_texture_size_ = viewport_size;
|
||||
device_.reset(new SkDevice(SkBitmap::kARGB_8888_Config,
|
||||
viewport_size.width(), viewport_size.height(), true));
|
||||
|
||||
context3d_->makeContextCurrent();
|
||||
context3d_->ensureFramebufferCHROMIUM();
|
||||
framebuffer_texture_id_ = context3d_->createTexture();
|
||||
context3d_->bindTexture(GL_TEXTURE_2D, framebuffer_texture_id_);
|
||||
context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
context3d_->viewport(0, 0, viewport_size.width(), viewport_size.height());
|
||||
context3d_->reshape(viewport_size.width(), viewport_size.height());
|
||||
}
|
||||
|
||||
void CompositorSoftwareOutputDeviceGLAdapter::Draw(void* pixels) {
|
||||
if (!initialized_)
|
||||
NOTREACHED();
|
||||
if (!framebuffer_texture_id_)
|
||||
NOTREACHED();
|
||||
|
||||
context3d_->makeContextCurrent();
|
||||
context3d_->ensureFramebufferCHROMIUM();
|
||||
context3d_->clear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
context3d_->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
framebuffer_texture_size_.width(), framebuffer_texture_size_.height(),
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
context3d_->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
context3d_->prepareTexture();
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_GL_ADAPTER_H_
|
||||
#define CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_GL_ADAPTER_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/threading/non_thread_safe.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebImage.h"
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebCompositorSoftwareOutputDevice.h"
|
||||
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
|
||||
#include "ui/gfx/size.h"
|
||||
|
||||
// This class can be created only on the main thread, but then becomes pinned
|
||||
// to a fixed thread when bindToClient is called.
|
||||
class CompositorSoftwareOutputDeviceGLAdapter
|
||||
: NON_EXPORTED_BASE(public WebKit::WebCompositorSoftwareOutputDevice),
|
||||
NON_EXPORTED_BASE(public base::NonThreadSafe) {
|
||||
public:
|
||||
CompositorSoftwareOutputDeviceGLAdapter(
|
||||
WebKit::WebGraphicsContext3D* context3d);
|
||||
virtual ~CompositorSoftwareOutputDeviceGLAdapter();
|
||||
|
||||
virtual WebKit::WebImage* lock(bool forWrite) OVERRIDE;
|
||||
virtual void unlock() OVERRIDE;
|
||||
|
||||
virtual void didChangeViewportSize(WebKit::WebSize size) OVERRIDE;
|
||||
|
||||
private:
|
||||
void Initialize();
|
||||
void Destroy();
|
||||
void Resize(const gfx::Size& viewportSize);
|
||||
void Draw(void* pixels);
|
||||
|
||||
bool initialized_;
|
||||
int program_;
|
||||
int vertex_shader_;
|
||||
int fragment_shader_;
|
||||
unsigned int vertex_buffer_;
|
||||
unsigned framebuffer_texture_id_;
|
||||
gfx::Size framebuffer_texture_size_;
|
||||
|
||||
scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
|
||||
scoped_ptr<SkDevice> device_;
|
||||
WebKit::WebImage image_;
|
||||
bool locked_for_write_;
|
||||
};
|
||||
|
||||
#endif // CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_GL_ADAPTER_H_
|
@ -74,6 +74,7 @@
|
||||
#include "content/renderer/geolocation_dispatcher.h"
|
||||
#include "content/renderer/gpu/compositor_thread.h"
|
||||
#include "content/renderer/gpu/compositor_output_surface.h"
|
||||
#include "content/renderer/gpu/compositor_software_output_device_gl_adapter.h"
|
||||
#include "content/renderer/idle_user_detector.h"
|
||||
#include "content/renderer/input_tag_speech_dispatcher.h"
|
||||
#include "content/renderer/java/java_bridge_dispatcher.h"
|
||||
@ -1888,9 +1889,6 @@ WebStorageNamespace* RenderViewImpl::createSessionStorageNamespace(
|
||||
}
|
||||
|
||||
WebKit::WebCompositorOutputSurface* RenderViewImpl::createOutputSurface() {
|
||||
// TODO(aelias): if force-software-mode is on, create an output surface
|
||||
// without a 3D context.
|
||||
|
||||
// Explicitly disable antialiasing for the compositor. As of the time of
|
||||
// this writing, the only platform that supported antialiasing for the
|
||||
// compositor was Mac OS X, because the on-screen OpenGL context creation
|
||||
@ -1908,7 +1906,15 @@ WebKit::WebCompositorOutputSurface* RenderViewImpl::createOutputSurface() {
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
return new CompositorOutputSurface(routing_id(), context);
|
||||
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
|
||||
if (command_line.HasSwitch(switches::kEnableSoftwareCompositingGLAdapter)) {
|
||||
// In the absence of a software-based delegating renderer, use this
|
||||
// stopgap adapter class to present the software renderer output using a
|
||||
// 3d context.
|
||||
return new CompositorOutputSurface(routing_id(), NULL,
|
||||
new CompositorSoftwareOutputDeviceGLAdapter(context));
|
||||
} else
|
||||
return new CompositorOutputSurface(routing_id(), context, NULL);
|
||||
}
|
||||
|
||||
void RenderViewImpl::didAddMessageToConsole(
|
||||
|
Reference in New Issue
Block a user