ppb_graphics_3d_shared.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
6
7#include "base/logging.h"
8#include "gpu/command_buffer/client/gles2_cmd_helper.h"
9#include "gpu/command_buffer/client/gles2_implementation.h"
10#include "gpu/command_buffer/client/transfer_buffer.h"
11#include "ppapi/c/pp_errors.h"
12
13namespace ppapi {
14
15PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(PP_Instance instance)
16    : Resource(OBJECT_IS_IMPL, instance) {
17}
18
19PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(const HostResource& host_resource)
20    : Resource(OBJECT_IS_PROXY, host_resource) {
21}
22
23PPB_Graphics3D_Shared::~PPB_Graphics3D_Shared() {
24  // Make sure that GLES2 implementation has already been destroyed.
25  DCHECK(!gles2_helper_.get());
26  DCHECK(!transfer_buffer_.get());
27  DCHECK(!gles2_impl_.get());
28}
29
30thunk::PPB_Graphics3D_API* PPB_Graphics3D_Shared::AsPPB_Graphics3D_API() {
31  return this;
32}
33
34int32_t PPB_Graphics3D_Shared::GetAttribs(int32_t attrib_list[]) {
35  // TODO(alokp): Implement me.
36  return PP_ERROR_FAILED;
37}
38
39int32_t PPB_Graphics3D_Shared::SetAttribs(const int32_t attrib_list[]) {
40  // TODO(alokp): Implement me.
41  return PP_ERROR_FAILED;
42}
43
44int32_t PPB_Graphics3D_Shared::GetError() {
45  // TODO(alokp): Implement me.
46  return PP_ERROR_FAILED;
47}
48
49int32_t PPB_Graphics3D_Shared::ResizeBuffers(int32_t width, int32_t height) {
50  if ((width < 0) || (height < 0))
51    return PP_ERROR_BADARGUMENT;
52
53  ScopedNoLocking already_locked(this);
54  gles2_impl()->ResizeCHROMIUM(width, height, 1.f);
55  // TODO(alokp): Check if resize succeeded and return appropriate error code.
56  return PP_OK;
57}
58
59int32_t PPB_Graphics3D_Shared::SwapBuffers(
60    scoped_refptr<TrackedCallback> callback) {
61  ScopedNoLocking already_locked(this);
62  if (HasPendingSwap()) {
63    Log(PP_LOGLEVEL_ERROR, "PPB_Graphics3D.SwapBuffers: Plugin attempted swap "
64                           "with previous swap still pending.");
65    // Already a pending SwapBuffers that hasn't returned yet.
66    return PP_ERROR_INPROGRESS;
67  }
68
69  swap_callback_ = callback;
70  return DoSwapBuffers();
71}
72
73int32_t PPB_Graphics3D_Shared::GetAttribMaxValue(int32_t attribute,
74                                                 int32_t* value) {
75  // TODO(alokp): Implement me.
76  return PP_ERROR_FAILED;
77}
78
79void* PPB_Graphics3D_Shared::MapTexSubImage2DCHROMIUM(GLenum target,
80                                                      GLint level,
81                                                      GLint xoffset,
82                                                      GLint yoffset,
83                                                      GLsizei width,
84                                                      GLsizei height,
85                                                      GLenum format,
86                                                      GLenum type,
87                                                      GLenum access) {
88  ScopedNoLocking already_locked(this);
89  return gles2_impl_->MapTexSubImage2DCHROMIUM(
90      target, level, xoffset, yoffset, width, height, format, type, access);
91}
92
93void PPB_Graphics3D_Shared::UnmapTexSubImage2DCHROMIUM(const void* mem) {
94  ScopedNoLocking already_locked(this);
95  gles2_impl_->UnmapTexSubImage2DCHROMIUM(mem);
96}
97
98void PPB_Graphics3D_Shared::SwapBuffersACK(int32_t pp_error) {
99  DCHECK(HasPendingSwap());
100  swap_callback_->Run(pp_error);
101}
102
103bool PPB_Graphics3D_Shared::HasPendingSwap() const {
104  return TrackedCallback::IsPending(swap_callback_);
105}
106
107bool PPB_Graphics3D_Shared::CreateGLES2Impl(
108    int32 command_buffer_size,
109    int32 transfer_buffer_size,
110    gpu::gles2::GLES2Implementation* share_gles2) {
111  ScopedNoLocking already_locked(this);
112  gpu::CommandBuffer* command_buffer = GetCommandBuffer();
113  DCHECK(command_buffer);
114
115  // Create the GLES2 helper, which writes the command buffer protocol.
116  gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer));
117  if (!gles2_helper_->Initialize(command_buffer_size))
118    return false;
119
120  // Create a transfer buffer used to copy resources between the renderer
121  // process and the GPU process.
122  const int32 kMinTransferBufferSize = 256 * 1024;
123  const int32 kMaxTransferBufferSize = 16 * 1024 * 1024;
124  transfer_buffer_.reset(new gpu::TransferBuffer(gles2_helper_.get()));
125
126  // Create the object exposing the OpenGL API.
127  gles2_impl_.reset(new gpu::gles2::GLES2Implementation(
128      gles2_helper_.get(),
129      share_gles2 ? share_gles2->share_group() : NULL,
130      transfer_buffer_.get(),
131      false,
132      true,
133      NULL  // Do not use GpuMemoryBuffers.
134      ));
135
136  if (!gles2_impl_->Initialize(
137      transfer_buffer_size,
138      kMinTransferBufferSize,
139      std::max(kMaxTransferBufferSize, transfer_buffer_size))) {
140    return false;
141  }
142
143  gles2_impl_->PushGroupMarkerEXT(0, "PPAPIContext");
144
145  return true;
146}
147
148void PPB_Graphics3D_Shared::DestroyGLES2Impl() {
149  ScopedNoLocking already_locked(this);
150  gles2_impl_.reset();
151  transfer_buffer_.reset();
152  gles2_helper_.reset();
153}
154
155void PPB_Graphics3D_Shared::PushAlreadyLocked() {
156  // Do nothing. This should be overridden in the plugin side.
157}
158
159void PPB_Graphics3D_Shared::PopAlreadyLocked() {
160  // Do nothing. This should be overridden in the plugin side.
161}
162
163}  // namespace ppapi
164
165