Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1137)

Side by Side Diff: ppapi/proxy/compositor_resource.cc

Issue 298023004: [PPAPI] Compositor API implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@compositor_api_def_new
Patch Set: Fix review issues Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/compositor_resource.h" 5 #include "ppapi/proxy/compositor_resource.h"
6 6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "gpu/command_buffer/client/gles2_implementation.h"
11 #include "gpu/command_buffer/common/mailbox.h"
12 #include "ppapi/proxy/compositor_layer_resource.h"
13 #include "ppapi/proxy/ppapi_messages.h"
14 #include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
15 #include "ppapi/shared_impl/var.h"
16 #include "ppapi/thunk/enter.h"
17 #include "ppapi/thunk/ppb_graphics_3d_api.h"
18 #include "ppapi/thunk/ppb_image_data_api.h"
19
20 using ppapi::thunk::EnterResourceNoLock;
21 using ppapi::thunk::PPB_Graphics3D_API;
22
7 namespace ppapi { 23 namespace ppapi {
8 namespace proxy { 24 namespace proxy {
9 25
26 namespace {
27
28 class Scoped2DTextureBinder {
29 public:
30 Scoped2DTextureBinder(gpu::gles2::GLES2Implementation* gl, uint32_t id)
31 : gl_(gl), old_id_(-1) {
32 gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, &old_id_);
33 gl_->BindTexture(GL_TEXTURE_2D, id);
34 }
35
36 ~Scoped2DTextureBinder() {
37 gl_->BindTexture(GL_TEXTURE_2D, old_id_);
38 }
39
40 private:
41 gpu::gles2::GLES2Implementation* gl_;
42 int32_t old_id_;
43 };
44
45 } // namespace
46
47 CompositorResource::LayerImpl::LayerImpl(CompositorResource* compositor)
48 : compositor_(compositor),
49 source_size_(PP_MakeFloatSize(0.0f, 0.0f)) {
50 }
51
52 CompositorResource::LayerImpl::~LayerImpl() {}
53
54 int32_t CompositorResource::LayerImpl::SetColor(
55 uint8_t red,
56 uint8_t green,
57 uint8_t blue,
58 uint8_t alpha,
59 const struct PP_Size* size) {
60 if (compositor_->IsInProgress())
61 return PP_ERROR_INPROGRESS;
62
63 if (!SetType(CompositorLayerData::TYPE_COLOR))
64 return PP_ERROR_BADARGUMENT;
65
66 if (!size)
67 return PP_ERROR_BADARGUMENT;
68
69 data_.color.red = red;
70 data_.color.green = green;
71 data_.color.blue = blue;
72 data_.color.alpha = alpha;
73 data_.size = *size;
74
75 return PP_OK;
76 }
77
78 int32_t CompositorResource::LayerImpl::SetTexture(
79 PP_Resource context,
80 uint32_t texture,
81 const struct PP_Size* size,
82 const scoped_refptr<ppapi::TrackedCallback>& release_callback) {
83 if (compositor_->IsInProgress())
84 return PP_ERROR_INPROGRESS;
85
86 if (!SetType(CompositorLayerData::TYPE_TEXTURE))
87 return PP_ERROR_BADARGUMENT;
88
89 // The layer's texture has been set and it is not committed.
90 if (!release_callback_.is_null())
91 return PP_ERROR_INPROGRESS;
92
93 EnterResourceNoLock<PPB_Graphics3D_API> enter(context, true);
94 if (enter.failed())
95 return PP_ERROR_BADARGUMENT;
96
97 if (!size || size->width <= 0 || size->height <= 0)
98 return PP_ERROR_BADARGUMENT;
99
100 // Do not allow using a block callback as a release callback.
101 if (release_callback->is_blocking())
102 return PP_ERROR_BADARGUMENT;
103
104 PPB_Graphics3D_Shared* graphics =
105 static_cast<PPB_Graphics3D_Shared*>(enter.object());
106
107 gpu::gles2::GLES2Implementation* gl = graphics->gles2_impl();
108 Scoped2DTextureBinder scoped_2d_texture_binder(gl, texture);
109
110 // Generate a Mailbox for the texture.
111 gl->GenMailboxCHROMIUM(data_.texture.mailbox);
112 gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, data_.texture.mailbox);
113
114 // Set the source size to (1, 1). It will be used to verify the source_rect
115 // passed to SetSourceRect().
116 source_size_ = PP_MakeFloatSize(1.0f, 1.0f);
117
118 data_.texture.id = compositor_->GenerateResourceId();
119 data_.texture.sync_point = gl->InsertSyncPointCHROMIUM();
120 data_.size = *size;
121 data_.texture.source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f);
122 data_.texture.source_rect.size = source_size_;
123
124 release_callback_ = base::Bind(
125 &CompositorResource::LayerImpl::OnTextureReleased,
126 AsWeakPtr(),
127 ScopedPPResource(context), // Keep context alive
128 texture,
129 release_callback);
130
131 return PP_OK_COMPLETIONPENDING;
132 }
133
134 int32_t CompositorResource::LayerImpl::SetImage(
135 PP_Resource image_data,
136 const struct PP_Size* size,
137 const scoped_refptr<ppapi::TrackedCallback>& release_callback) {
138 if (compositor_->IsInProgress())
139 return PP_ERROR_INPROGRESS;
140
141 if (!SetType(CompositorLayerData::TYPE_IMAGE))
142 return PP_ERROR_BADARGUMENT;
143
144 EnterResourceNoLock<thunk::PPB_ImageData_API> enter(image_data, true);
145 if (enter.failed())
146 return PP_ERROR_BADARGUMENT;
147
148 // The layer's image has been set and it is not committed.
149 if (!release_callback_.is_null())
150 return PP_ERROR_INPROGRESS;
151
152 PP_ImageDataDesc desc;
153 if (!enter.object()->Describe(&desc))
154 return PP_ERROR_BADARGUMENT;
155
156 // TODO(penghuang): Support image which width * 4 != stride.
157 if (desc.size.width * 4 != desc.stride)
158 return PP_ERROR_BADARGUMENT;
159
160 // TODO(penghuang): Support all formats.
161 if (desc.format != PP_IMAGEDATAFORMAT_RGBA_PREMUL)
162 return PP_ERROR_BADARGUMENT;
163
164 if (!size || size->width <= 0 || size->height <= 0)
165 return PP_ERROR_BADARGUMENT;
166
167 // Do not allow using a block callback as a release callback.
168 if (release_callback->is_blocking())
169 return PP_ERROR_BADARGUMENT;
170
171 // Set the source size to image's size. It will be used to verify
172 // the source_rect passed to SetSourceRect().
173 source_size_ = PP_MakeFloatSize(desc.size.width, desc.size.height);
174
175 data_.size = size ? *size : desc.size;
176 data_.image.id = compositor_->GenerateResourceId();
177 data_.image.instance = enter.resource()->host_resource().instance();
178 data_.image.host_resource = enter.resource()->host_resource().host_resource();
179 data_.image.source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f);
180 data_.image.source_rect.size = source_size_;
181
182 release_callback_ = base::Bind(
183 &CompositorResource::LayerImpl::OnImageReleased,
184 AsWeakPtr(),
185 ScopedPPResource(image_data), // Keep image_data alive.
186 release_callback);
187
188 return PP_OK_COMPLETIONPENDING;
189 }
190
191 int32_t CompositorResource::LayerImpl::SetClipRect(const struct PP_Rect* rect) {
192 if (compositor_->IsInProgress())
193 return PP_ERROR_INPROGRESS;
194
195 data_.clip_rect = rect ? *rect : PP_MakeRectFromXYWH(0, 0, 0, 0);
196 return PP_OK;
197 }
198
199 int32_t CompositorResource::LayerImpl::SetTransform(const float matrix[16]) {
200 if (compositor_->IsInProgress())
201 return PP_ERROR_INPROGRESS;
202
203 std::copy(matrix, matrix + 16, data_.transform);
204 return PP_OK;
205 }
206
207 int32_t CompositorResource::LayerImpl::SetOpacity(uint8_t opacity) {
208 if (compositor_->IsInProgress())
209 return PP_ERROR_INPROGRESS;
210
211 data_.opacity = opacity;
212 return PP_OK;
213 }
214
215 int32_t CompositorResource::LayerImpl::SetBlendMode(PP_BlendMode mode) {
216 if (compositor_->IsInProgress())
217 return PP_ERROR_INPROGRESS;
218
219 switch (mode) {
220 case PP_BLENDMODE_NONE:
221 case PP_BLENDMODE_SRC_OVER:
222 data_.blend_mode = mode;
223 return PP_OK;
224 default:
225 break;
raymes 2014/06/03 00:43:22 nit: get rid of the default: case altogether (and
Peng 2014/06/03 18:32:24 I tried without default:. The compiler will give a
raymes 2014/06/04 01:11:38 This is because it is missing PP_BLENDMODE_LAST. I
Peng 2014/06/05 00:50:38 Done.
226 }
227 return PP_ERROR_BADARGUMENT;
228 }
229
230 int32_t CompositorResource::LayerImpl::SetSourceRect(
231 const struct PP_FloatRect* rect) {
232 if (compositor_->IsInProgress())
233 return PP_ERROR_INPROGRESS;
234
235 if (!rect ||
236 rect->point.x < 0.0f ||
237 rect->point.y < 0.0f ||
238 rect->point.x + rect->size.width > source_size_.width ||
239 rect->point.y + rect->size.height > source_size_.height)
240 return PP_ERROR_BADARGUMENT;
241
242 switch (data_.type) {
243 case CompositorLayerData::TYPE_TEXTURE:
244 data_.texture.source_rect = *rect;
245 return PP_OK;
246 case CompositorLayerData::TYPE_IMAGE:
247 data_.image.source_rect = *rect;
248 return PP_OK;
249 default:
250 break;
251 }
252 return PP_ERROR_BADARGUMENT;
253 }
254
255 int32_t CompositorResource::LayerImpl::SetPremultipliedAlpha(PP_Bool premult) {
256 if (compositor_->IsInProgress())
257 return PP_ERROR_INPROGRESS;
258
259 if (data_.type != CompositorLayerData::TYPE_TEXTURE)
260 return PP_ERROR_BADARGUMENT;
261
262 data_.texture.premult_alpha = PP_FromBool(premult);
263 return PP_OK;
264 }
265
266 bool CompositorResource::LayerImpl::SetType(CompositorLayerData::Type type) {
267 DCHECK(type == CompositorLayerData::TYPE_COLOR ||
268 type == CompositorLayerData::TYPE_TEXTURE ||
269 type == CompositorLayerData::TYPE_IMAGE);
270 if (type != data_.type) {
271 if (data_.type != CompositorLayerData::TYPE_UNKNOWN)
272 return false;
273 data_.type = type;
274 }
275 return true;
276 }
277
278 void CompositorResource::LayerImpl::OnTextureReleased(
279 const ScopedPPResource& context,
280 uint32_t texture,
281 const scoped_refptr<TrackedCallback>& release_callback,
282 uint32_t sync_point,
283 bool is_lost) {
284 do {
285 if (!sync_point)
286 break;
287
288 EnterResourceNoLock<PPB_Graphics3D_API> enter(context.get(), true);
289 if (enter.failed())
290 break;
291
292 PPB_Graphics3D_Shared* graphics =
293 static_cast<PPB_Graphics3D_Shared*>(enter.object());
294
295 gpu::gles2::GLES2Implementation* gl = graphics->gles2_impl();
296 gl->WaitSyncPointCHROMIUM(sync_point);
297 } while (false);
298
299 release_callback->Run(PP_OK);
300 }
301
302 void CompositorResource::LayerImpl::OnImageReleased(
303 const ScopedPPResource& image,
304 const scoped_refptr<TrackedCallback>& release_callback,
305 uint32_t sync_point,
306 bool is_lost) {
307 release_callback->Run(PP_OK);
308 }
309
10 CompositorResource::CompositorResource(Connection connection, 310 CompositorResource::CompositorResource(Connection connection,
11 PP_Instance instance) 311 PP_Instance instance)
12 : PluginResource(connection, instance) { 312 : PluginResource(connection, instance),
313 layer_reset_(true),
314 last_resource_id_(0) {
315 SendCreate(RENDERER, PpapiHostMsg_Compositor_Create());
13 } 316 }
14 317
15 CompositorResource::~CompositorResource() { 318 CompositorResource::~CompositorResource() {
16 } 319 }
17 320
18 thunk::PPB_Compositor_API* CompositorResource::AsPPB_Compositor_API() { 321 thunk::PPB_Compositor_API* CompositorResource::AsPPB_Compositor_API() {
19 return this; 322 return this;
20 } 323 }
21 324
325 void CompositorResource::OnReplyReceived(
326 const ResourceMessageReplyParams& params,
327 const IPC::Message& msg) {
328 PPAPI_BEGIN_MESSAGE_MAP(CompositorResource, msg)
329 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
330 PpapiPluginMsg_Compositor_ReleaseResource,
331 OnPluginMsgReleaseResource)
332 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
333 PluginResource::OnReplyReceived(params, msg))
334 PPAPI_END_MESSAGE_MAP()
335 }
336
22 PP_Resource CompositorResource::AddLayer() { 337 PP_Resource CompositorResource::AddLayer() {
23 return 0; 338 LayerImpl* layer = new LayerImpl(this);
339 layers_.push_back(layer);
340 CompositorLayerResource *resource = new CompositorLayerResource(
341 connection(), pp_instance(), layer->AsWeakPtr());
342 return resource->GetReference();
24 } 343 }
25 344
26 int32_t CompositorResource::CommitLayers( 345 int32_t CompositorResource::CommitLayers(
27 const scoped_refptr<ppapi::TrackedCallback>& callback) { 346 const scoped_refptr<ppapi::TrackedCallback>& callback) {
28 return PP_ERROR_NOTSUPPORTED; 347 if (IsInProgress())
348 return PP_ERROR_INPROGRESS;
349
350 std::vector<CompositorLayerData> layers;
351 layers.reserve(layers_.size());
352
353 for (ScopedVector<LayerImpl>::const_iterator it = layers_.begin();
354 it != layers_.end(); ++it) {
355 switch ((*it)->data().type) {
356 case CompositorLayerData::TYPE_UNKNOWN:
357 return PP_ERROR_FAILED;
358 case CompositorLayerData::TYPE_COLOR:
359 case CompositorLayerData::TYPE_TEXTURE:
360 case CompositorLayerData::TYPE_IMAGE:
361 layers.push_back((*it)->data());
362 continue;
363 default:
364 NOTREACHED();
365 }
366 }
367
368 commit_callback_ = callback;
369 Call<PpapiPluginMsg_Compositor_CommitLayersReply>(
370 RENDERER,
371 PpapiHostMsg_Compositor_CommitLayers(layers, layer_reset_),
372 base::Bind(&CompositorResource::OnPluginMsgCommitLayersReply,
373 base::Unretained(this)),
374 callback);
375
376 return PP_OK_COMPLETIONPENDING;
29 } 377 }
30 378
31 int32_t CompositorResource::ResetLayers() { 379 int32_t CompositorResource::ResetLayers() {
32 return PP_ERROR_NOTSUPPORTED; 380 if (IsInProgress())
381 return PP_ERROR_INPROGRESS;
382
383 // Call release_callback for every layer.
384 for (ScopedVector<LayerImpl>::iterator it = layers_.begin();
385 it != layers_.end(); ++it) {
386 ReleaseCallback release_callback = (*it)->release_callback();
387 if (!release_callback.is_null())
388 release_callback.Run(0, false);
389 }
390
391 layers_.clear();
392 layer_reset_ = true;
393 return PP_OK;
394 }
395
396 void CompositorResource::OnPluginMsgCommitLayersReply(
397 const ResourceMessageReplyParams& params) {
398 if (!TrackedCallback::IsPending(commit_callback_))
399 return;
400
401 // On success, we put layers' release_callbacks into a map,
402 // otherwise we will do nothing. So plugin may change layers and
403 // call CommitLayers() again.
404 if (params.result() == PP_OK) {
405 layer_reset_ = false;
406 for (ScopedVector<LayerImpl>::iterator it = layers_.begin();
407 it != layers_.end(); ++it) {
408 switch ((*it)->data().type) {
409 case CompositorLayerData::TYPE_TEXTURE: {
410 ReleaseCallback release_callback = (*it)->release_callback();
411 (*it)->ResetReleaseCallback();
412 if (!release_callback.is_null()) {
413 release_callback_map_.insert(ReleaseCallbackMap::value_type(
414 (*it)->data().texture.id, release_callback));
415 }
416 break;
417 }
418 case CompositorLayerData::TYPE_IMAGE: {
419 ReleaseCallback release_callback = (*it)->release_callback();
420 (*it)->ResetReleaseCallback();
421 if (!release_callback.is_null()) {
422 release_callback_map_.insert(ReleaseCallbackMap::value_type(
423 (*it)->data().image.id, release_callback));
424 }
425 break;
426 }
427 default:
428 break;
429 }
430 }
431 }
432
433 scoped_refptr<TrackedCallback> callback;
434 callback.swap(commit_callback_);
435 callback->Run(params.result());
436 }
437
438 void CompositorResource::OnPluginMsgReleaseResource(
439 const ResourceMessageReplyParams& params,
440 int32_t id,
441 uint32_t sync_point,
442 bool is_lost) {
443 ReleaseCallbackMap::iterator it = release_callback_map_.find(id);
444 DCHECK(it != release_callback_map_.end()) <<
445 "Can not found release_callback_ by id(" << id << ")!";
446 it->second.Run(sync_point, is_lost);
447 release_callback_map_.erase(it);
33 } 448 }
34 449
35 } // namespace proxy 450 } // namespace proxy
36 } // namespace ppapi 451 } // namespace ppapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698