OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "webkit/plugins/ppapi/ppb_surface_3d_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/message_loop.h" | |
9 #include "gpu/command_buffer/client/gles2_implementation.h" | |
10 #include "gpu/command_buffer/common/command_buffer.h" | |
11 #include "ppapi/c/ppb_graphics_3d.h" | |
12 #include "ppapi/c/ppp_graphics_3d.h" | |
13 #include "webkit/plugins/ppapi/common.h" | |
14 #include "webkit/plugins/ppapi/plugin_module.h" | |
15 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | |
16 #include "webkit/plugins/ppapi/ppb_context_3d_impl.h" | |
17 #include "webkit/plugins/ppapi/resource_helper.h" | |
18 | |
19 using ppapi::thunk::PPB_Surface3D_API; | |
20 | |
21 namespace webkit { | |
22 namespace ppapi { | |
23 | |
24 PPB_Surface3D_Impl::PPB_Surface3D_Impl(PP_Instance instance) | |
25 : Resource(instance), | |
26 bound_to_instance_(false), | |
27 swap_initiated_(false), | |
28 context_(NULL), | |
29 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
30 } | |
31 | |
32 PPB_Surface3D_Impl::~PPB_Surface3D_Impl() { | |
33 if (context_) | |
34 context_->BindSurfacesImpl(NULL, NULL); | |
35 } | |
36 | |
37 // static | |
38 PP_Resource PPB_Surface3D_Impl::Create(PP_Instance instance, | |
39 PP_Config3D_Dev config, | |
40 const int32_t* attrib_list) { | |
41 scoped_refptr<PPB_Surface3D_Impl> surface( | |
42 new PPB_Surface3D_Impl(instance)); | |
43 if (!surface->Init(config, attrib_list)) | |
44 return 0; | |
45 return surface->GetReference(); | |
46 } | |
47 | |
48 PPB_Surface3D_API* PPB_Surface3D_Impl::AsPPB_Surface3D_API() { | |
49 return this; | |
50 } | |
51 | |
52 int32_t PPB_Surface3D_Impl::SetAttrib(int32_t attribute, int32_t value) { | |
53 // TODO(alokp): Implement me. | |
54 return 0; | |
55 } | |
56 | |
57 int32_t PPB_Surface3D_Impl::GetAttrib(int32_t attribute, int32_t* value) { | |
58 // TODO(alokp): Implement me. | |
59 return 0; | |
60 } | |
61 | |
62 int32_t PPB_Surface3D_Impl::SwapBuffers(PP_CompletionCallback callback) { | |
63 if (!callback.func) { | |
64 // Blocking SwapBuffers isn't supported (since we have to be on the main | |
65 // thread). | |
66 return PP_ERROR_BLOCKS_MAIN_THREAD; | |
67 } | |
68 | |
69 if (swap_callback_.get() && !swap_callback_->completed()) { | |
70 // Already a pending SwapBuffers that hasn't returned yet. | |
71 return PP_ERROR_INPROGRESS; | |
72 } | |
73 | |
74 if (!context_) | |
75 return PP_ERROR_FAILED; | |
76 | |
77 PluginModule* plugin_module = ResourceHelper::GetPluginModule(this); | |
78 if (!plugin_module) | |
79 return PP_ERROR_FAILED; | |
80 | |
81 swap_callback_ = new TrackedCompletionCallback( | |
82 plugin_module->GetCallbackTracker(), pp_resource(), callback); | |
83 gpu::gles2::GLES2Implementation* impl = context_->gles2_impl(); | |
84 if (impl) | |
85 context_->gles2_impl()->SwapBuffers(); | |
86 context_->platform_context()->Echo( | |
87 base::Bind(&PPB_Surface3D_Impl::OnSwapBuffers, | |
88 weak_ptr_factory_.GetWeakPtr())); | |
89 // |SwapBuffers()| should not call us back synchronously, but double-check. | |
90 DCHECK(!swap_callback_->completed()); | |
91 return PP_OK_COMPLETIONPENDING; | |
92 } | |
93 | |
94 bool PPB_Surface3D_Impl::Init(PP_Config3D_Dev config, | |
95 const int32_t* attrib_list) { | |
96 return true; | |
97 } | |
98 | |
99 bool PPB_Surface3D_Impl::BindToInstance(bool bind) { | |
100 bound_to_instance_ = bind; | |
101 return true; | |
102 } | |
103 | |
104 bool PPB_Surface3D_Impl::BindToContext(PPB_Context3D_Impl* context) { | |
105 if (context == context_) | |
106 return true; | |
107 | |
108 PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(this); | |
109 if (!plugin_instance) | |
110 return false; | |
111 | |
112 if (!context && bound_to_instance_) | |
113 plugin_instance->BindGraphics(pp_instance(), 0); | |
114 | |
115 // Unbind from the current context. | |
116 if (context && context->platform_context()) { | |
117 // Resize the backing texture to the size of the instance when it is bound. | |
118 // TODO(alokp): This should be the responsibility of plugins. | |
119 gpu::gles2::GLES2Implementation* impl = context->gles2_impl(); | |
120 if (impl) { | |
121 const gfx::Size& size = plugin_instance->position().size(); | |
122 impl->ResizeCHROMIUM(size.width(), size.height()); | |
123 } | |
124 } | |
125 context_ = context; | |
126 return true; | |
127 } | |
128 | |
129 void PPB_Surface3D_Impl::ViewInitiatedPaint() { | |
130 } | |
131 | |
132 void PPB_Surface3D_Impl::ViewFlushedPaint() { | |
133 if (swap_initiated_ && swap_callback_.get() && !swap_callback_->completed()) { | |
134 // We must clear swap_callback_ before issuing the callback. It will be | |
135 // common for the plugin to issue another SwapBuffers in response to the | |
136 // callback, and we don't want to think that a callback is already pending. | |
137 swap_initiated_ = false; | |
138 scoped_refptr<TrackedCompletionCallback> callback; | |
139 callback.swap(swap_callback_); | |
140 callback->Run(PP_OK); // Will complete abortively if necessary. | |
141 } | |
142 } | |
143 | |
144 unsigned int PPB_Surface3D_Impl::GetBackingTextureId() { | |
145 return context_ ? context_->platform_context()->GetBackingTextureId() : 0; | |
146 } | |
147 | |
148 void PPB_Surface3D_Impl::OnSwapBuffers() { | |
149 PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(this); | |
150 if (!plugin_instance) | |
151 return; | |
152 | |
153 if (bound_to_instance_ && plugin_instance) { | |
154 plugin_instance->CommitBackingTexture(); | |
155 swap_initiated_ = true; | |
156 } else if (swap_callback_.get() && !swap_callback_->completed()) { | |
157 // If we're off-screen, no need to trigger compositing so run the callback | |
158 // immediately. | |
159 swap_initiated_ = false; | |
160 scoped_refptr<TrackedCompletionCallback> callback; | |
161 callback.swap(swap_callback_); | |
162 callback->Run(PP_OK); // Will complete abortively if necessary. | |
163 } | |
164 } | |
165 | |
166 void PPB_Surface3D_Impl::OnContextLost() { | |
167 PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(this); | |
168 if (bound_to_instance_ && plugin_instance) | |
169 plugin_instance->BindGraphics(pp_instance(), 0); | |
170 | |
171 // Send context lost to plugin. This may have been caused by a PPAPI call, so | |
172 // avoid re-entering. | |
173 MessageLoop::current()->PostTask( | |
174 FROM_HERE, base::Bind(&PPB_Surface3D_Impl::SendContextLost, this)); | |
175 } | |
176 | |
177 void PPB_Surface3D_Impl::SendContextLost() { | |
178 PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(this); | |
179 | |
180 // By the time we run this, the instance may have been deleted, or in the | |
181 // process of being deleted. Even in the latter case, we don't want to send a | |
182 // callback after DidDestroy. | |
183 if (!plugin_instance || !plugin_instance->container()) | |
184 return; | |
185 const PPP_Graphics3D* ppp_graphics_3d = | |
186 static_cast<const PPP_Graphics3D*>( | |
187 plugin_instance->module()->GetPluginInterface( | |
188 PPP_GRAPHICS_3D_INTERFACE)); | |
189 if (ppp_graphics_3d) | |
190 ppp_graphics_3d->Graphics3DContextLost(pp_instance()); | |
191 } | |
192 | |
193 } // namespace ppapi | |
194 } // namespace webkit | |
OLD | NEW |