blob: 17bc7b2fe42287ee34a70608cad23be4e38d319d [file] [log] [blame]
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +01001// Copyright 2014 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/proxy/compositor_layer_resource.h"
6
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +01007#include "base/logging.h"
8#include "gpu/command_buffer/client/gles2_implementation.h"
9#include "gpu/command_buffer/common/mailbox.h"
10#include "ppapi/proxy/compositor_resource.h"
11#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
12#include "ppapi/thunk/enter.h"
13#include "ppapi/thunk/ppb_graphics_3d_api.h"
14#include "ppapi/thunk/ppb_image_data_api.h"
15
16using gpu::gles2::GLES2Implementation;
17using ppapi::thunk::EnterResourceNoLock;
18using ppapi::thunk::PPB_ImageData_API;
19using ppapi::thunk::PPB_Graphics3D_API;
20
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010021namespace ppapi {
22namespace proxy {
23
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010024namespace {
25
26float clamp(float value) {
27 return std::min(std::max(value, 0.0f), 1.0f);
28}
29
30void OnTextureReleased(
31 const ScopedPPResource& layer,
32 const ScopedPPResource& context,
33 uint32_t texture,
34 const scoped_refptr<TrackedCallback>& release_callback,
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +010035 int32_t result,
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010036 uint32_t sync_point,
37 bool is_lost) {
38 if (!TrackedCallback::IsPending(release_callback))
39 return;
40
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +010041 if (result != PP_OK) {
42 release_callback->Run(result);
43 return;
44 }
45
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010046 do {
47 if (!sync_point)
48 break;
49
50 EnterResourceNoLock<PPB_Graphics3D_API> enter(context.get(), true);
51 if (enter.failed())
52 break;
53
54 PPB_Graphics3D_Shared* graphics =
55 static_cast<PPB_Graphics3D_Shared*>(enter.object());
56
57 GLES2Implementation* gl = graphics->gles2_impl();
58 gl->WaitSyncPointCHROMIUM(sync_point);
59 } while (false);
60
61 release_callback->Run(is_lost ? PP_ERROR_FAILED : PP_OK);
62}
63
64void OnImageReleased(
65 const ScopedPPResource& layer,
66 const ScopedPPResource& image,
67 const scoped_refptr<TrackedCallback>& release_callback,
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +010068 int32_t result,
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010069 uint32_t sync_point,
70 bool is_lost) {
71 if (!TrackedCallback::IsPending(release_callback))
72 return;
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +010073 release_callback->Run(result);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010074}
75
76} // namespace
77
78CompositorLayerResource::CompositorLayerResource(
79 Connection connection,
80 PP_Instance instance,
81 const CompositorResource* compositor)
82 : PluginResource(connection, instance),
83 compositor_(compositor),
84 source_size_(PP_MakeFloatSize(0.0f, 0.0f)) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010085}
86
87CompositorLayerResource::~CompositorLayerResource() {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010088 DCHECK(!compositor_);
89 DCHECK(release_callback_.is_null());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010090}
91
92thunk::PPB_CompositorLayer_API*
93CompositorLayerResource::AsPPB_CompositorLayer_API() {
94 return this;
95}
96
97int32_t CompositorLayerResource::SetColor(float red,
98 float green,
99 float blue,
100 float alpha,
101 const PP_Size* size) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100102 if (!compositor_)
103 return PP_ERROR_BADRESOURCE;
104
105 if (compositor_->IsInProgress())
106 return PP_ERROR_INPROGRESS;
107
108 if (!SetType(TYPE_COLOR))
109 return PP_ERROR_BADARGUMENT;
110 DCHECK(data_.color);
111
112 if (!size)
113 return PP_ERROR_BADARGUMENT;
114
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100115 data_.color->red = clamp(red);
116 data_.color->green = clamp(green);
117 data_.color->blue = clamp(blue);
118 data_.color->alpha = clamp(alpha);
119 data_.common.size = *size;
120
121 return PP_OK;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100122}
123
124int32_t CompositorLayerResource::SetTexture(
125 PP_Resource context,
126 uint32_t texture,
127 const PP_Size* size,
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100128 const scoped_refptr<TrackedCallback>& release_callback) {
129 int32_t rv = CheckForSetTextureAndImage(TYPE_TEXTURE, release_callback);
130 if (rv != PP_OK)
131 return rv;
132 DCHECK(data_.texture);
133
134 EnterResourceNoLock<PPB_Graphics3D_API> enter(context, true);
135 if (enter.failed())
136 return PP_ERROR_BADRESOURCE;
137
138 if (!size || size->width <= 0 || size->height <= 0)
139 return PP_ERROR_BADARGUMENT;
140
141 PPB_Graphics3D_Shared* graphics =
142 static_cast<PPB_Graphics3D_Shared*>(enter.object());
143
144 GLES2Implementation* gl = graphics->gles2_impl();
145
146 // Generate a Mailbox for the texture.
147 gl->GenMailboxCHROMIUM(
148 reinterpret_cast<GLbyte*>(data_.texture->mailbox.name));
149 gl->ProduceTextureDirectCHROMIUM(
150 texture, GL_TEXTURE_2D,
151 reinterpret_cast<const GLbyte*>(data_.texture->mailbox.name));
152
153 // Set the source size to (1, 1). It will be used to verify the source_rect
154 // passed to SetSourceRect().
155 source_size_ = PP_MakeFloatSize(1.0f, 1.0f);
156
157 data_.common.size = *size;
158 data_.common.resource_id = compositor_->GenerateResourceId();
159 data_.texture->sync_point = gl->InsertSyncPointCHROMIUM();
160 data_.texture->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f);
161 data_.texture->source_rect.size = source_size_;
162
163 // If the PP_Resource of this layer is released by the plugin, the
164 // release_callback will be aborted immediately, but the texture or image
165 // in this layer may still being used by chromium compositor. So we have to
166 // use ScopedPPResource to keep this resource alive until the texture or image
167 // is released by the chromium compositor.
168 release_callback_ = base::Bind(
169 &OnTextureReleased,
170 ScopedPPResource(pp_resource()), // Keep layer alive.
171 ScopedPPResource(context), // Keep context alive
172 texture,
173 release_callback);
174
175 return PP_OK_COMPLETIONPENDING;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100176}
177
178int32_t CompositorLayerResource::SetImage(
179 PP_Resource image_data,
180 const PP_Size* size,
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100181 const scoped_refptr<TrackedCallback>& release_callback) {
182 int32_t rv = CheckForSetTextureAndImage(TYPE_IMAGE, release_callback);
183 if (rv != PP_OK)
184 return rv;
185 DCHECK(data_.image);
186
187 EnterResourceNoLock<PPB_ImageData_API> enter(image_data, true);
188 if (enter.failed())
189 return PP_ERROR_BADRESOURCE;
190
191 PP_ImageDataDesc desc;
192 if (!enter.object()->Describe(&desc))
193 return PP_ERROR_BADARGUMENT;
194
195 // TODO(penghuang): Support image which width * 4 != stride.
196 if (desc.size.width * 4 != desc.stride)
197 return PP_ERROR_BADARGUMENT;
198
199 // TODO(penghuang): Support all formats.
200 if (desc.format != PP_IMAGEDATAFORMAT_RGBA_PREMUL)
201 return PP_ERROR_BADARGUMENT;
202
203 if (!size || size->width <= 0 || size->height <= 0)
204 return PP_ERROR_BADARGUMENT;
205
206 // Set the source size to image's size. It will be used to verify
207 // the source_rect passed to SetSourceRect().
208 source_size_ = PP_MakeFloatSize(desc.size.width, desc.size.height);
209
210 data_.common.size = size ? *size : desc.size;
211 data_.common.resource_id = compositor_->GenerateResourceId();
212 data_.image->resource = enter.resource()->host_resource().host_resource();
213 data_.image->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f);
214 data_.image->source_rect.size = source_size_;
215
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100216 // If the PP_Resource of this layer is released by the plugin, the
217 // release_callback will be aborted immediately, but the texture or image
218 // in this layer may still being used by chromium compositor. So we have to
219 // use ScopedPPResource to keep this resource alive until the texture or image
220 // is released by the chromium compositor.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100221 release_callback_ = base::Bind(
222 &OnImageReleased,
223 ScopedPPResource(pp_resource()), // Keep layer alive.
224 ScopedPPResource(image_data), // Keep image_data alive.
225 release_callback);
226
227 return PP_OK_COMPLETIONPENDING;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100228}
229
230int32_t CompositorLayerResource::SetClipRect(const PP_Rect* rect) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100231 if (!compositor_)
232 return PP_ERROR_BADRESOURCE;
233
234 if (compositor_->IsInProgress())
235 return PP_ERROR_INPROGRESS;
236
237 data_.common.clip_rect = rect ? *rect : PP_MakeRectFromXYWH(0, 0, 0, 0);
238 return PP_OK;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100239}
240
241int32_t CompositorLayerResource::SetTransform(const float matrix[16]) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100242 if (!compositor_)
243 return PP_ERROR_BADRESOURCE;
244
245 if (compositor_->IsInProgress())
246 return PP_ERROR_INPROGRESS;
247
248 std::copy(matrix, matrix + 16, data_.common.transform.matrix);
249 return PP_OK;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100250}
251
252int32_t CompositorLayerResource::SetOpacity(float opacity) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100253 if (!compositor_)
254 return PP_ERROR_BADRESOURCE;
255
256 if (compositor_->IsInProgress())
257 return PP_ERROR_INPROGRESS;
258
259 data_.common.opacity = clamp(opacity);
260 return PP_OK;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100261}
262
263int32_t CompositorLayerResource::SetBlendMode(PP_BlendMode mode) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100264 if (!compositor_)
265 return PP_ERROR_BADRESOURCE;
266
267 if (compositor_->IsInProgress())
268 return PP_ERROR_INPROGRESS;
269
270 switch (mode) {
271 case PP_BLENDMODE_NONE:
272 case PP_BLENDMODE_SRC_OVER:
273 data_.common.blend_mode = mode;
274 return PP_OK;
275 }
276 return PP_ERROR_BADARGUMENT;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100277}
278
279int32_t CompositorLayerResource::SetSourceRect(
280 const PP_FloatRect* rect) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100281 if (!compositor_)
282 return PP_ERROR_BADRESOURCE;
283
284 if (compositor_->IsInProgress())
285 return PP_ERROR_INPROGRESS;
286
287 if (!rect ||
288 rect->point.x < 0.0f ||
289 rect->point.y < 0.0f ||
290 rect->point.x + rect->size.width > source_size_.width ||
291 rect->point.y + rect->size.height > source_size_.height) {
292 return PP_ERROR_BADARGUMENT;
293 }
294
295 if (data_.texture) {
296 data_.texture->source_rect = *rect;
297 return PP_OK;
298 }
299 if (data_.image) {
300 data_.image->source_rect = *rect;
301 return PP_OK;
302 }
303 return PP_ERROR_BADARGUMENT;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100304}
305
306int32_t CompositorLayerResource::SetPremultipliedAlpha(PP_Bool premult) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100307 if (!compositor_)
308 return PP_ERROR_BADRESOURCE;
309
310 if (compositor_->IsInProgress())
311 return PP_ERROR_INPROGRESS;
312
313 if (data_.texture) {
314 data_.texture->premult_alpha = PP_ToBool(premult);
315 return PP_OK;
316 }
317 return PP_ERROR_BADARGUMENT;
318}
319
320bool CompositorLayerResource::SetType(LayerType type) {
321 if (type == TYPE_COLOR) {
322 if (data_.is_null())
323 data_.color.reset(new CompositorLayerData::ColorLayer());
324 return data_.color;
325 }
326
327 if (type == TYPE_TEXTURE) {
328 if (data_.is_null())
329 data_.texture.reset(new CompositorLayerData::TextureLayer());
330 return data_.texture;
331 }
332
333 if (type == TYPE_IMAGE) {
334 if (data_.is_null())
335 data_.image.reset(new CompositorLayerData::ImageLayer());
336 return data_.image;
337 }
338
339 // Should not be reached.
340 DCHECK(false);
341 return false;
342}
343
344int32_t CompositorLayerResource::CheckForSetTextureAndImage(
345 LayerType type,
346 const scoped_refptr<TrackedCallback>& release_callback) {
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100347 if (!compositor_)
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100348 return PP_ERROR_BADRESOURCE;
349
350 if (compositor_->IsInProgress())
351 return PP_ERROR_INPROGRESS;
352
353 if (!SetType(type))
354 return PP_ERROR_BADARGUMENT;
355
356 // The layer's image has been set and it is not committed.
357 if (!release_callback_.is_null())
358 return PP_ERROR_INPROGRESS;
359
360 // Do not allow using a block callback as a release callback.
361 if (release_callback->is_blocking())
362 return PP_ERROR_BADARGUMENT;
363
364 return PP_OK;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100365}
366
367} // namespace proxy
368} // namespace ppapi