summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc3
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.cc165
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.h133
-rw-r--r--gpu/command_buffer/service/gpu_scheduler_linux.cc61
-rw-r--r--gpu/command_buffer/service/gpu_scheduler_mac.cc147
-rw-r--r--gpu/command_buffer/service/gpu_scheduler_unittest.cc27
-rw-r--r--gpu/command_buffer/service/gpu_scheduler_win.cc60
7 files changed, 554 insertions, 42 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 530342b..eef54c3 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2362,8 +2362,9 @@ void GLES2DecoderImpl::Destroy() {
if (context_.get()) {
context_->ReleaseCurrent(NULL);
- context_ = NULL;
+ context_->Destroy();
}
+ context_ = NULL;
offscreen_target_frame_buffer_.reset();
offscreen_target_color_texture_.reset();
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index a6442e9..70f84a4 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -19,33 +19,120 @@ using ::base::SharedMemory;
namespace gpu {
-GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
- gles2::GLES2Decoder* decoder,
- CommandParser* parser)
- : command_buffer_(command_buffer),
- decoder_(decoder),
- parser_(parser),
- unscheduled_count_(0) {
- // Map the ring buffer and create the parser.
- if (!parser) {
- Buffer ring_buffer = command_buffer_->GetRingBuffer();
- if (ring_buffer.ptr) {
- parser_.reset(new CommandParser(ring_buffer.ptr,
- ring_buffer.size,
- 0,
- ring_buffer.size,
- 0,
- decoder_));
- } else {
- parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
- decoder_));
- }
+GpuScheduler* GpuScheduler::Create(CommandBuffer* command_buffer,
+ gles2::ContextGroup* group) {
+ DCHECK(command_buffer);
+
+ gles2::GLES2Decoder* decoder = gles2::GLES2Decoder::Create(group);
+
+ GpuScheduler* scheduler = new GpuScheduler(command_buffer,
+ decoder,
+ NULL);
+
+ decoder->set_engine(scheduler);
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableGPUServiceLogging)) {
+ decoder->set_debug(true);
}
+
+ return scheduler;
+}
+
+GpuScheduler* GpuScheduler::CreateForTests(CommandBuffer* command_buffer,
+ gles2::GLES2Decoder* decoder,
+ CommandParser* parser) {
+ DCHECK(command_buffer);
+ GpuScheduler* scheduler = new GpuScheduler(command_buffer,
+ decoder,
+ parser);
+
+ return scheduler;
}
GpuScheduler::~GpuScheduler() {
+ Destroy();
+}
+
+bool GpuScheduler::InitializeCommon(
+ const scoped_refptr<gfx::GLSurface>& surface,
+ const scoped_refptr<gfx::GLContext>& context,
+ const gfx::Size& size,
+ const gles2::DisallowedExtensions& disallowed_extensions,
+ const char* allowed_extensions,
+ const std::vector<int32>& attribs) {
+ DCHECK(context);
+
+ if (!context->MakeCurrent(surface))
+ return false;
+
+#if !defined(OS_MACOSX) && !defined(TOUCH_UI)
+ // Set up swap interval for onscreen contexts.
+ if (!surface->IsOffscreen()) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
+ context->SetSwapInterval(0);
+ else
+ context->SetSwapInterval(1);
+ }
+#endif
+
+ // Map the ring buffer and create the parser.
+ Buffer ring_buffer = command_buffer_->GetRingBuffer();
+ if (ring_buffer.ptr) {
+ parser_.reset(new CommandParser(ring_buffer.ptr,
+ ring_buffer.size,
+ 0,
+ ring_buffer.size,
+ 0,
+ decoder_.get()));
+ } else {
+ parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
+ decoder_.get()));
+ }
+
+ // Initialize the decoder with either the view or pbuffer GLContext.
+ // TODO(apatrick): The GpuScheduler should know nothing about the surface the
+ // decoder is rendering to. Get rid of the surface parameter.
+ if (!decoder_->Initialize(surface,
+ context,
+ size,
+ disallowed_extensions,
+ allowed_extensions,
+ attribs)) {
+ LOG(ERROR) << "GpuScheduler::InitializeCommon failed because decoder "
+ << "failed to initialize.";
+ Destroy();
+ return false;
+ }
+
+ return true;
}
+void GpuScheduler::DestroyCommon() {
+ if (decoder_.get()) {
+ decoder_->MakeCurrent();
+ decoder_->Destroy();
+ decoder_.reset();
+ }
+
+ parser_.reset();
+}
+
+bool GpuScheduler::SetParent(GpuScheduler* parent_scheduler,
+ uint32 parent_texture_id) {
+ if (parent_scheduler)
+ return decoder_->SetParent(parent_scheduler->decoder_.get(),
+ parent_texture_id);
+ else
+ return decoder_->SetParent(NULL, 0);
+}
+
+#if defined(OS_MACOSX)
+namespace {
+const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1;
+}
+#endif
+
void GpuScheduler::PutChanged() {
TRACE_EVENT1("gpu", "GpuScheduler:PutChanged", "this", this);
@@ -56,6 +143,23 @@ void GpuScheduler::PutChanged() {
if (state.error != error::kNoError)
return;
+ if (decoder_.get()) {
+ if (!decoder_->MakeCurrent()) {
+ LOG(ERROR) << "Context lost because MakeCurrent failed.";
+ command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
+ command_buffer_->SetParseError(error::kLostContext);
+ return;
+ }
+ }
+
+#if defined(OS_MACOSX)
+ bool do_rate_limiting = surface_.get() != NULL;
+
+ // Don't swamp the browser process with SwapBuffers calls it can't handle.
+ DCHECK(!do_rate_limiting ||
+ swap_buffers_count_ - acknowledged_swap_buffers_count_ == 0);
+#endif
+
error::Error error = error::kNoError;
while (!parser_->IsEmpty()) {
error = parser_->ProcessCommand();
@@ -122,9 +226,28 @@ int32 GpuScheduler::GetGetOffset() {
return parser_->get();
}
+void GpuScheduler::SetResizeCallback(
+ Callback1<gfx::Size>::Type* callback) {
+ decoder_->SetResizeCallback(callback);
+}
+
void GpuScheduler::SetCommandProcessedCallback(
Callback0::Type* callback) {
command_processed_callback_.reset(callback);
}
+GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
+ gles2::GLES2Decoder* decoder,
+ CommandParser* parser)
+ : command_buffer_(command_buffer),
+ decoder_(decoder),
+ parser_(parser),
+ unscheduled_count_(0),
+#if defined(OS_MACOSX)
+ swap_buffers_count_(0),
+ acknowledged_swap_buffers_count_(0),
+#endif
+ method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index 32b072c..72ffe26 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -5,29 +5,77 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_
#define GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_
+#include <map>
+#include <queue>
+#include <vector>
+
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/shared_memory.h"
+#include "base/task.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "gpu/command_buffer/service/cmd_parser.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+#include "ui/gfx/surface/transport_dib.h"
+
+#if defined(OS_MACOSX)
+#include "ui/gfx/surface/accelerated_surface_mac.h"
+#endif
+
+namespace gfx {
+class GLContext;
+class GLShareGroup;
+class GLSurface;
+}
namespace gpu {
+namespace gles2 {
+class ContextGroup;
+}
-// This class schedules commands that have been flushed. They are received via
-// a command buffer and forwarded to a command parser. TODO(apatrick): This
-// class should not know about the decoder. Do not add additional dependencies
-// on it.
+// This class processes commands in a command buffer. It is event driven and
+// posts tasks to the current message loop to do additional work.
class GpuScheduler : public CommandBufferEngine {
public:
- GpuScheduler(CommandBuffer* command_buffer,
- gles2::GLES2Decoder* decoder,
- CommandParser* parser);
+ // If a group is not passed in one will be created.
+ static GpuScheduler* Create(CommandBuffer* command_buffer,
+ gles2::ContextGroup* group);
+
+ // This constructor is for unit tests.
+ static GpuScheduler* CreateForTests(CommandBuffer* command_buffer,
+ gles2::GLES2Decoder* decoder,
+ CommandParser* parser);
virtual ~GpuScheduler();
+ // Platform specific code to create GLContexts and GLSurfaces that are
+ // handed off to the next function.
+ bool Initialize(gfx::PluginWindowHandle hwnd,
+ const gfx::Size& size,
+ bool software,
+ const gles2::DisallowedExtensions& disallowed_extensions,
+ const char* allowed_extensions,
+ const std::vector<int32>& attribs,
+ gfx::GLShareGroup* share_group);
+
+ // Takes ownership of GLSurface and GLContext.
+ bool InitializeCommon(
+ const scoped_refptr<gfx::GLSurface>& surface,
+ const scoped_refptr<gfx::GLContext>& context,
+ const gfx::Size& size,
+ const gles2::DisallowedExtensions& disallowed_extensions,
+ const char* allowed_extensions,
+ const std::vector<int32>& attribs);
+
+ void Destroy();
+ void DestroyCommon();
+
+ bool SetParent(GpuScheduler* parent_scheduler, uint32 parent_texture_id);
+
void PutChanged();
// Sets whether commands should be processed by this scheduler. Setting to
@@ -49,29 +97,84 @@ class GpuScheduler : public CommandBufferEngine {
virtual bool SetGetOffset(int32 offset);
virtual int32 GetGetOffset();
+#if defined(OS_MACOSX)
+ // To prevent the GPU process from overloading the browser process,
+ // we need to track the number of swap buffers calls issued and
+ // acknowledged per on-screen context, and keep the GPU from getting
+ // too far ahead of the browser. Note that this
+ // is also predicated on a flow control mechanism between the
+ // renderer and GPU processes.
+ uint64 swap_buffers_count() const;
+ uint64 acknowledged_swap_buffers_count() const;
+ void set_acknowledged_swap_buffers_count(
+ uint64 acknowledged_swap_buffers_count);
+
+ // Needed only on Mac OS X, which does not render into an on-screen
+ // window and therefore requires the backing store to be resized
+ // manually. Returns an opaque identifier for the new backing store.
+ // There are two versions of this method: one for use with the IOSurface
+ // available in Mac OS X 10.6; and, one for use with the
+ // TransportDIB-based version used on Mac OS X 10.5.
+ virtual uint64 SetWindowSizeForIOSurface(const gfx::Size& size);
+ virtual TransportDIB::Handle SetWindowSizeForTransportDIB(
+ const gfx::Size& size);
+ virtual void SetTransportDIBAllocAndFree(
+ Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
+ Callback1<TransportDIB::Id>::Type* deallocator);
+ // Returns the id of the current surface that is being rendered to
+ // (or 0 if no such surface has been created).
+ virtual uint64 GetSurfaceId();
+
+ void DidDestroySurface();
+
+ // Sets a callback which is called when a SwapBuffers command is processed.
+ // Must be called after Initialize().
+ // It is not defined on which thread this callback is called.
+ void SetSwapBuffersCallback(Callback0::Type* callback);
+#endif
+
+ // Sets a callback that is called when a glResizeCHROMIUM command
+ // is processed.
+ void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
+
void SetCommandProcessedCallback(Callback0::Type* callback);
+ // Get the GLES2Decoder associated with this scheduler.
+ gles2::GLES2Decoder* decoder() const { return decoder_.get(); }
+
private:
+ // If a group is not passed in one will be created.
+ GpuScheduler(CommandBuffer* command_buffer,
+ gles2::GLES2Decoder* decoder,
+ CommandParser* parser);
+
+#if defined(OS_MACOSX)
+ // Called via a callback just before we are supposed to call the
+ // user's swap buffers callback.
+ void WillSwapBuffers();
+#endif
// The GpuScheduler holds a weak reference to the CommandBuffer. The
// CommandBuffer owns the GpuScheduler and holds a strong reference to it
// through the ProcessCommands callback.
CommandBuffer* command_buffer_;
- // Does not own decoder. TODO(apatrick): The GpuScheduler shouldn't need a
- // pointer to the decoder, it is only used to initialize the CommandParser,
- // which could be an argument to the constructor, and to determine the
- // reason for context lost.
- gles2::GLES2Decoder* decoder_;
-
- // TODO(apatrick): The GpuScheduler currently creates and owns the parser.
- // This should be an argument to the constructor.
+ scoped_ptr<gles2::GLES2Decoder> decoder_;
scoped_ptr<CommandParser> parser_;
// Greater than zero if this is waiting to be rescheduled before continuing.
int unscheduled_count_;
scoped_ptr<Callback0::Type> scheduled_callback_;
+
+#if defined(OS_MACOSX)
+ uint64 swap_buffers_count_;
+ uint64 acknowledged_swap_buffers_count_;
+ scoped_ptr<AcceleratedSurface> surface_;
+ scoped_ptr<Callback0::Type> wrapped_swap_buffers_callback_;
+#endif
+
+ ScopedRunnableMethodFactory<GpuScheduler> method_factory_;
scoped_ptr<Callback0::Type> command_processed_callback_;
};
diff --git a/gpu/command_buffer/service/gpu_scheduler_linux.cc b/gpu/command_buffer/service/gpu_scheduler_linux.cc
new file mode 100644
index 0000000..7cb7689
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_scheduler_linux.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 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 "gpu/command_buffer/service/gpu_scheduler.h"
+#include "ui/gfx/gl/gl_context.h"
+#include "ui/gfx/gl/gl_share_group.h"
+#include "ui/gfx/gl/gl_surface.h"
+
+using ::base::SharedMemory;
+
+namespace gpu {
+
+bool GpuScheduler::Initialize(
+ gfx::PluginWindowHandle window,
+ const gfx::Size& size,
+ bool software,
+ const gles2::DisallowedExtensions& disallowed_extensions,
+ const char* allowed_extensions,
+ const std::vector<int32>& attribs,
+ gfx::GLShareGroup* share_group) {
+#if defined(TOUCH_UI)
+ NOTIMPLEMENTED();
+ return false;
+#endif
+
+ // Create either a view or pbuffer based GLSurface.
+ scoped_refptr<gfx::GLSurface> surface;
+ if (window)
+ surface = gfx::GLSurface::CreateViewGLSurface(software, window);
+ else
+ surface = gfx::GLSurface::CreateOffscreenGLSurface(software,
+ gfx::Size(1, 1));
+ if (!surface.get()) {
+ LOG(ERROR) << "GpuScheduler::Initialize failed.\n";
+ Destroy();
+ return false;
+ }
+
+ // Create a GLContext and attach the surface.
+ scoped_refptr<gfx::GLContext> context(
+ gfx::GLContext::CreateGLContext(share_group, surface.get()));
+ if (!context.get()) {
+ LOG(ERROR) << "CreateGLContext failed.\n";
+ Destroy();
+ return false;
+ }
+
+ return InitializeCommon(surface,
+ context,
+ size,
+ disallowed_extensions,
+ allowed_extensions,
+ attribs);
+}
+
+void GpuScheduler::Destroy() {
+ DestroyCommon();
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_scheduler_mac.cc b/gpu/command_buffer/service/gpu_scheduler_mac.cc
new file mode 100644
index 0000000..b172db7
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_scheduler_mac.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2011 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 "gpu/command_buffer/service/gpu_scheduler.h"
+#include "ui/gfx/gl/gl_context.h"
+#include "ui/gfx/gl/gl_share_group.h"
+#include "ui/gfx/gl/gl_surface.h"
+
+using ::base::SharedMemory;
+
+namespace gpu {
+
+bool GpuScheduler::Initialize(
+ gfx::PluginWindowHandle window,
+ const gfx::Size& size,
+ bool software,
+ const gles2::DisallowedExtensions& disallowed_extensions,
+ const char* allowed_extensions,
+ const std::vector<int32>& attribs,
+ gfx::GLShareGroup* share_group) {
+ scoped_refptr<gfx::GLSurface> surface(
+ gfx::GLSurface::CreateOffscreenGLSurface(software, gfx::Size(1, 1)));
+ if (!surface.get()) {
+ LOG(ERROR) << "CreateOffscreenGLSurface failed.\n";
+ Destroy();
+ return false;
+ }
+
+ // Create a GLContext and attach the surface.
+ scoped_refptr<gfx::GLContext> context(
+ gfx::GLContext::CreateGLContext(share_group, surface.get()));
+ if (!context.get()) {
+ LOG(ERROR) << "CreateGLContext failed.\n";
+ Destroy();
+ return false;
+ }
+
+ // On Mac OS X since we can not render on-screen we don't even
+ // attempt to create a view based GLContext. The only difference
+ // between "on-screen" and "off-screen" rendering on this platform
+ // is whether we allocate an AcceleratedSurface, which transmits the
+ // rendering results back to the browser.
+ if (window) {
+ surface_.reset(new AcceleratedSurface());
+
+ // Note that although the GLContext is passed to Initialize and the
+ // GLContext will later be owned by the decoder, AcceleratedSurface does
+ // not hold on to the reference. It simply extracts the underlying GL
+ // context in order to share the namespace with another context.
+ if (!surface_->Initialize(context.get(), false)) {
+ LOG(ERROR) << "GpuScheduler::Initialize failed to "
+ << "initialize AcceleratedSurface.";
+ Destroy();
+ return false;
+ }
+ }
+
+ return InitializeCommon(surface,
+ context,
+ size,
+ disallowed_extensions,
+ allowed_extensions,
+ attribs);
+}
+
+void GpuScheduler::Destroy() {
+ if (surface_.get()) {
+ surface_->Destroy();
+ surface_.reset();
+ }
+
+ DestroyCommon();
+}
+
+uint64 GpuScheduler::SetWindowSizeForIOSurface(const gfx::Size& size) {
+ // Note: The following line changes the current context again.
+ return surface_->SetSurfaceSize(size);
+}
+
+TransportDIB::Handle GpuScheduler::SetWindowSizeForTransportDIB(
+ const gfx::Size& size) {
+ return surface_->SetTransportDIBSize(size);
+}
+
+void GpuScheduler::SetTransportDIBAllocAndFree(
+ Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
+ Callback1<TransportDIB::Id>::Type* deallocator) {
+ surface_->SetTransportDIBAllocAndFree(allocator, deallocator);
+}
+
+uint64 GpuScheduler::GetSurfaceId() {
+ if (!surface_.get())
+ return 0;
+ return surface_->GetSurfaceId();
+}
+
+uint64 GpuScheduler::swap_buffers_count() const {
+ return swap_buffers_count_;
+}
+
+uint64 GpuScheduler::acknowledged_swap_buffers_count() const {
+ return acknowledged_swap_buffers_count_;
+}
+
+void GpuScheduler::set_acknowledged_swap_buffers_count(
+ uint64 acknowledged_swap_buffers_count) {
+ acknowledged_swap_buffers_count_ = acknowledged_swap_buffers_count;
+}
+
+void GpuScheduler::DidDestroySurface() {
+ // When a browser window with a GpuScheduler is closed, the render process
+ // will attempt to finish all GL commands, it will busy-wait on the GPU
+ // process until the command queue is empty. If a paint is pending, the GPU
+ // process won't process any GL commands until the browser sends a paint ack,
+ // but since the browser window is already closed, it will never arrive.
+ // To break this infinite loop, the browser tells the GPU process that the
+ // surface became invalid, which causes the GPU process to not wait for paint
+ // acks.
+ surface_.reset();
+}
+
+void GpuScheduler::SetSwapBuffersCallback(
+ Callback0::Type* callback) {
+ wrapped_swap_buffers_callback_.reset(callback);
+ decoder_->SetSwapBuffersCallback(
+ NewCallback(this,
+ &GpuScheduler::WillSwapBuffers));
+}
+
+void GpuScheduler::WillSwapBuffers() {
+ DCHECK(decoder_.get());
+ DCHECK(decoder_->GetGLContext());
+ DCHECK(decoder_->GetGLContext()->IsCurrent(decoder_->GetGLSurface()));
+
+ ++swap_buffers_count_;
+
+ if (surface_.get()) {
+ surface_->SwapBuffers();
+ }
+
+ if (wrapped_swap_buffers_callback_.get()) {
+ wrapped_swap_buffers_callback_->Run();
+ }
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_scheduler_unittest.cc b/gpu/command_buffer/service/gpu_scheduler_unittest.cc
index ce4fa11..4fb54b4 100644
--- a/gpu/command_buffer/service/gpu_scheduler_unittest.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_unittest.cc
@@ -46,7 +46,7 @@ class GpuSchedulerTest : public testing::Test {
async_api_.reset(new StrictMock<AsyncAPIMock>);
- decoder_.reset(new gles2::MockGLES2Decoder());
+ decoder_ = new gles2::MockGLES2Decoder();
parser_ = new CommandParser(buffer_,
kRingBufferEntries,
@@ -55,9 +55,13 @@ class GpuSchedulerTest : public testing::Test {
0,
async_api_.get());
- scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(),
- decoder_.get(),
- parser_));
+ scheduler_.reset(gpu::GpuScheduler::CreateForTests(command_buffer_.get(),
+ decoder_,
+ parser_));
+
+ EXPECT_CALL(*decoder_, Destroy())
+ .Times(1)
+ .RetiresOnSaturation();
}
virtual void TearDown() {
@@ -76,7 +80,7 @@ class GpuSchedulerTest : public testing::Test {
scoped_ptr<base::SharedMemory> shared_memory_;
Buffer shared_memory_buffer_;
int32* buffer_;
- scoped_ptr<gles2::MockGLES2Decoder> decoder_;
+ gles2::MockGLES2Decoder* decoder_;
CommandParser* parser_;
scoped_ptr<AsyncAPIMock> async_api_;
scoped_ptr<GpuScheduler> scheduler_;
@@ -142,6 +146,19 @@ TEST_F(GpuSchedulerTest, ProcessesTwoCommands) {
scheduler_->PutChanged();
}
+TEST_F(GpuSchedulerTest, SchedulerSetsTheGLContext) {
+ EXPECT_CALL(*decoder_, MakeCurrent())
+ .WillOnce(Return(true))
+ .WillOnce(Return(true));
+
+ CommandBuffer::State state;
+ state.put_offset = 0;
+ EXPECT_CALL(*command_buffer_, GetState())
+ .WillRepeatedly(Return(state));
+
+ scheduler_->PutChanged();
+}
+
TEST_F(GpuSchedulerTest, SetsErrorCodeOnCommandBuffer) {
CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
header[0].command = 7;
diff --git a/gpu/command_buffer/service/gpu_scheduler_win.cc b/gpu/command_buffer/service/gpu_scheduler_win.cc
new file mode 100644
index 0000000..72a463b
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_scheduler_win.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2011 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 <windows.h>
+
+#include "gpu/command_buffer/service/gpu_scheduler.h"
+#include "ui/gfx/gl/gl_context.h"
+#include "ui/gfx/gl/gl_share_group.h"
+#include "ui/gfx/gl/gl_surface.h"
+
+using ::base::SharedMemory;
+
+namespace gpu {
+
+bool GpuScheduler::Initialize(
+ gfx::PluginWindowHandle window,
+ const gfx::Size& size,
+ bool software,
+ const gles2::DisallowedExtensions& disallowed_extensions,
+ const char* allowed_extensions,
+ const std::vector<int32>& attribs,
+ gfx::GLShareGroup* share_group) {
+ // Create either a view or pbuffer based GLSurface.
+ scoped_refptr<gfx::GLSurface> surface;
+ if (window) {
+ surface = gfx::GLSurface::CreateViewGLSurface(software, window);
+ } else {
+ surface = gfx::GLSurface::CreateOffscreenGLSurface(software,
+ gfx::Size(1, 1));
+ }
+
+ if (!surface.get()) {
+ LOG(ERROR) << "GpuScheduler::Initialize failed.\n";
+ Destroy();
+ return false;
+ }
+
+ // Create a GLContext and attach the surface.
+ scoped_refptr<gfx::GLContext> context(
+ gfx::GLContext::CreateGLContext(share_group, surface.get()));
+ if (!context.get()) {
+ LOG(ERROR) << "CreateGLContext failed.\n";
+ Destroy();
+ return false;
+ }
+
+ return InitializeCommon(surface,
+ context,
+ size,
+ disallowed_extensions,
+ allowed_extensions,
+ attribs);
+}
+
+void GpuScheduler::Destroy() {
+ DestroyCommon();
+}
+
+} // namespace gpu