| Index: webkit/plugins/ppapi/ppb_graphics_3d_impl.cc
 | 
| ===================================================================
 | 
| --- webkit/plugins/ppapi/ppb_graphics_3d_impl.cc	(revision 92908)
 | 
| +++ webkit/plugins/ppapi/ppb_graphics_3d_impl.cc	(working copy)
 | 
| @@ -4,22 +4,60 @@
 | 
|  
 | 
|  #include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h"
 | 
|  
 | 
| -#include "base/logging.h"
 | 
| -#include "ppapi/c/pp_completion_callback.h"
 | 
| -#include "ppapi/c/pp_errors.h"
 | 
| +#include "base/message_loop.h"
 | 
| +#include "gpu/command_buffer/client/gles2_implementation.h"
 | 
| +#include "webkit/plugins/ppapi/plugin_module.h"
 | 
|  #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
 | 
| -#include "webkit/plugins/ppapi/resource_tracker.h"
 | 
|  
 | 
|  using ppapi::thunk::PPB_Graphics3D_API;
 | 
|  
 | 
|  namespace webkit {
 | 
|  namespace ppapi {
 | 
|  
 | 
| +namespace {
 | 
| +const int32 kCommandBufferSize = 1024 * 1024;
 | 
| +const int32 kTransferBufferSize = 1024 * 1024;
 | 
| +
 | 
| +PP_Bool ShmToHandle(base::SharedMemory* shm,
 | 
| +                    size_t size,
 | 
| +                    int* shm_handle,
 | 
| +                    uint32_t* shm_size) {
 | 
| +  if (!shm || !shm_handle || !shm_size)
 | 
| +    return PP_FALSE;
 | 
| +#if defined(OS_POSIX)
 | 
| +  *shm_handle = shm->handle().fd;
 | 
| +#elif defined(OS_WIN)
 | 
| +  *shm_handle = reinterpret_cast<int>(shm->handle());
 | 
| +#else
 | 
| +  #error "Platform not supported."
 | 
| +#endif
 | 
| +  *shm_size = size;
 | 
| +  return PP_TRUE;
 | 
| +}
 | 
| +
 | 
| +PP_Graphics3DTrustedState PPStateFromGPUState(
 | 
| +    const gpu::CommandBuffer::State& s) {
 | 
| +  PP_Graphics3DTrustedState state = {
 | 
| +      s.num_entries,
 | 
| +      s.get_offset,
 | 
| +      s.put_offset,
 | 
| +      s.token,
 | 
| +      static_cast<PPB_Graphics3DTrustedError>(s.error),
 | 
| +      s.generation
 | 
| +  };
 | 
| +  return state;
 | 
| +}
 | 
| +}  // namespace.
 | 
| +
 | 
|  PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PluginInstance* instance)
 | 
| -    : Resource(instance) {
 | 
| +    : Resource(instance),
 | 
| +      bound_to_instance_(false),
 | 
| +      commit_pending_(false),
 | 
| +      callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
 | 
|  }
 | 
|  
 | 
|  PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() {
 | 
| +  DestroyGLES2Impl();
 | 
|  }
 | 
|  
 | 
|  // static
 | 
| @@ -27,38 +65,189 @@
 | 
|                                          PP_Config3D_Dev config,
 | 
|                                          PP_Resource share_context,
 | 
|                                          const int32_t* attrib_list) {
 | 
| -  scoped_refptr<PPB_Graphics3D_Impl> t(new PPB_Graphics3D_Impl(instance));
 | 
| -  if (!t->Init(config, share_context, attrib_list))
 | 
| +  scoped_refptr<PPB_Graphics3D_Impl> graphics_3d(
 | 
| +      new PPB_Graphics3D_Impl(instance));
 | 
| +
 | 
| +  if (!graphics_3d->Init(config, share_context, attrib_list))
 | 
|      return 0;
 | 
| -  return t->GetReference();
 | 
| +
 | 
| +  return graphics_3d->GetReference();
 | 
|  }
 | 
|  
 | 
| +PP_Resource PPB_Graphics3D_Impl::CreateRaw(PluginInstance* instance,
 | 
| +                                           PP_Config3D_Dev config,
 | 
| +                                           PP_Resource share_context,
 | 
| +                                           const int32_t* attrib_list) {
 | 
| +  scoped_refptr<PPB_Graphics3D_Impl> graphics_3d(
 | 
| +      new PPB_Graphics3D_Impl(instance));
 | 
| +
 | 
| +  if (!graphics_3d->InitRaw(config, share_context, attrib_list))
 | 
| +    return 0;
 | 
| +
 | 
| +  return graphics_3d->GetReference();
 | 
| +}
 | 
| +
 | 
|  PPB_Graphics3D_API* PPB_Graphics3D_Impl::AsPPB_Graphics3D_API() {
 | 
|    return this;
 | 
|  }
 | 
|  
 | 
| -int32_t PPB_Graphics3D_Impl::GetAttribs(int32_t* attrib_list) {
 | 
| -  // TODO(alokp): Implement me.
 | 
| -  return PP_ERROR_FAILED;
 | 
| +PP_Bool PPB_Graphics3D_Impl::InitCommandBuffer(int32_t size) {
 | 
| +  return PP_FromBool(GetCommandBuffer()->Initialize(size));
 | 
|  }
 | 
|  
 | 
| -int32_t PPB_Graphics3D_Impl::SetAttribs(int32_t* attrib_list) {
 | 
| -  // TODO(alokp): Implement me.
 | 
| -  return PP_ERROR_FAILED;
 | 
| +PP_Bool PPB_Graphics3D_Impl::GetRingBuffer(int* shm_handle,
 | 
| +                                           uint32_t* shm_size) {
 | 
| +  gpu::Buffer buffer = GetCommandBuffer()->GetRingBuffer();
 | 
| +  return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size);
 | 
|  }
 | 
|  
 | 
| -int32_t PPB_Graphics3D_Impl::SwapBuffers(PP_CompletionCallback callback) {
 | 
| -  // TODO(alokp): Implement me.
 | 
| -  return PP_ERROR_FAILED;
 | 
| +PP_Graphics3DTrustedState PPB_Graphics3D_Impl::GetState() {
 | 
| +  return PPStateFromGPUState(GetCommandBuffer()->GetState());
 | 
|  }
 | 
|  
 | 
| +int32_t PPB_Graphics3D_Impl::CreateTransferBuffer(uint32_t size) {
 | 
| +  return GetCommandBuffer()->CreateTransferBuffer(size, -1);
 | 
| +}
 | 
| +
 | 
| +PP_Bool PPB_Graphics3D_Impl::DestroyTransferBuffer(int32_t id) {
 | 
| +  GetCommandBuffer()->DestroyTransferBuffer(id);
 | 
| +  return PP_TRUE;
 | 
| +}
 | 
| +
 | 
| +PP_Bool PPB_Graphics3D_Impl::GetTransferBuffer(int32_t id,
 | 
| +                                               int* shm_handle,
 | 
| +                                               uint32_t* shm_size) {
 | 
| +  gpu::Buffer buffer = GetCommandBuffer()->GetTransferBuffer(id);
 | 
| +  return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size);
 | 
| +}
 | 
| +
 | 
| +PP_Bool PPB_Graphics3D_Impl::Flush(int32_t put_offset) {
 | 
| +  GetCommandBuffer()->Flush(put_offset);
 | 
| +  return PP_TRUE;
 | 
| +}
 | 
| +
 | 
| +PP_Graphics3DTrustedState PPB_Graphics3D_Impl::FlushSync(int32_t put_offset) {
 | 
| +  gpu::CommandBuffer::State state = GetCommandBuffer()->GetState();
 | 
| +  return PPStateFromGPUState(
 | 
| +      GetCommandBuffer()->FlushSync(put_offset, state.get_offset));
 | 
| +}
 | 
| +
 | 
| +PP_Graphics3DTrustedState PPB_Graphics3D_Impl::FlushSyncFast(
 | 
| +    int32_t put_offset,
 | 
| +    int32_t last_known_get) {
 | 
| +  return PPStateFromGPUState(
 | 
| +      GetCommandBuffer()->FlushSync(put_offset, last_known_get));
 | 
| +}
 | 
| +
 | 
| +bool PPB_Graphics3D_Impl::BindToInstance(bool bind) {
 | 
| +  bound_to_instance_ = bind;
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +unsigned int PPB_Graphics3D_Impl::GetBackingTextureId() {
 | 
| +  return platform_context_->GetBackingTextureId();
 | 
| +}
 | 
| +
 | 
| +void PPB_Graphics3D_Impl::ViewInitiatedPaint() {
 | 
| +}
 | 
| +
 | 
| +void PPB_Graphics3D_Impl::ViewFlushedPaint() {
 | 
| +  commit_pending_ = false;
 | 
| +
 | 
| +  if (HasPendingSwap())
 | 
| +    SwapBuffersACK(PP_OK);
 | 
| +}
 | 
| +
 | 
| +gpu::CommandBuffer* PPB_Graphics3D_Impl::GetCommandBuffer() {
 | 
| +  return platform_context_->GetCommandBuffer();
 | 
| +}
 | 
| +
 | 
| +int32 PPB_Graphics3D_Impl::DoSwapBuffers() {
 | 
| +  // We do not have a GLES2 implementation when using an OOP proxy.
 | 
| +  // The plugin-side proxy is responsible for adding the SwapBuffers command
 | 
| +  // to the command buffer in that case.
 | 
| +  if (gles2_impl())
 | 
| +    gles2_impl()->SwapBuffers();
 | 
| +
 | 
| +  return PP_OK_COMPLETIONPENDING;
 | 
| +}
 | 
| +
 | 
|  bool PPB_Graphics3D_Impl::Init(PP_Config3D_Dev config,
 | 
|                                 PP_Resource share_context,
 | 
|                                 const int32_t* attrib_list) {
 | 
| -  // TODO(alokp): Implement me.
 | 
| -  return false;
 | 
| +  if (!InitRaw(config, share_context, attrib_list))
 | 
| +    return false;
 | 
| +
 | 
| +  gpu::CommandBuffer* command_buffer = GetCommandBuffer();
 | 
| +  if (!command_buffer->Initialize(kCommandBufferSize))
 | 
| +    return false;
 | 
| +
 | 
| +  return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize);
 | 
|  }
 | 
|  
 | 
| +bool PPB_Graphics3D_Impl::InitRaw(PP_Config3D_Dev config,
 | 
| +                                  PP_Resource share_context,
 | 
| +                                  const int32_t* attrib_list) {
 | 
| +  // TODO(alokp): Support shared context.
 | 
| +  DCHECK_EQ(0, share_context);
 | 
| +  if (share_context != 0)
 | 
| +    return 0;
 | 
| +
 | 
| +  platform_context_.reset(instance()->CreateContext3D());
 | 
| +  if (!platform_context_.get())
 | 
| +    return false;
 | 
| +
 | 
| +  if (!platform_context_->Init())
 | 
| +    return false;
 | 
| +
 | 
| +  platform_context_->SetContextLostCallback(
 | 
| +      callback_factory_.NewCallback(&PPB_Graphics3D_Impl::OnContextLost));
 | 
| +  platform_context_->SetSwapBuffersCallback(
 | 
| +      callback_factory_.NewCallback(&PPB_Graphics3D_Impl::OnSwapBuffers));
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +void PPB_Graphics3D_Impl::OnSwapBuffers() {
 | 
| +  if (bound_to_instance_) {
 | 
| +    // If we are bound to the instance, we need to ask the compositor
 | 
| +    // to commit our backing texture so that the graphics appears on the page.
 | 
| +    // When the backing texture will be committed we get notified via
 | 
| +    // ViewFlushedPaint().
 | 
| +    instance()->CommitBackingTexture();
 | 
| +    commit_pending_ = true;
 | 
| +  } else if (HasPendingSwap()) {
 | 
| +    // If we're off-screen, no need to trigger and wait for compositing.
 | 
| +    // Just send the swap-buffers ACK to the plugin immediately.
 | 
| +    commit_pending_ = false;
 | 
| +    SwapBuffersACK(PP_OK);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void PPB_Graphics3D_Impl::OnContextLost() {
 | 
| +  if (bound_to_instance_)
 | 
| +    instance()->BindGraphics(instance()->pp_instance(), 0);
 | 
| +
 | 
| +  // Send context lost to plugin. This may have been caused by a PPAPI call, so
 | 
| +  // avoid re-entering.
 | 
| +  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
 | 
| +      this, &PPB_Graphics3D_Impl::SendContextLost));
 | 
| +}
 | 
| +
 | 
| +void PPB_Graphics3D_Impl::SendContextLost() {
 | 
| +  // By the time we run this, the instance may have been deleted, or in the
 | 
| +  // process of being deleted. Even in the latter case, we don't want to send a
 | 
| +  // callback after DidDestroy.
 | 
| +  if (!instance() || !instance()->container())
 | 
| +    return;
 | 
| +
 | 
| +  const PPP_Graphics3D_Dev* ppp_graphics_3d =
 | 
| +      static_cast<const PPP_Graphics3D_Dev*>(
 | 
| +          instance()->module()->GetPluginInterface(
 | 
| +              PPP_GRAPHICS_3D_DEV_INTERFACE));
 | 
| +  if (ppp_graphics_3d)
 | 
| +    ppp_graphics_3d->Graphics3DContextLost(instance()->pp_instance());
 | 
| +}
 | 
| +
 | 
|  }  // namespace ppapi
 | 
|  }  // namespace webkit
 | 
|  
 | 
| 
 |