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
3 // found in the LICENSE file.
5 #include "ppapi/proxy/compositor_layer_resource.h"
7 #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"
16 using gpu::gles2::GLES2Implementation
;
17 using ppapi::thunk::EnterResourceNoLock
;
18 using ppapi::thunk::PPB_ImageData_API
;
19 using ppapi::thunk::PPB_Graphics3D_API
;
26 float clamp(float value
) {
27 return std::min(std::max(value
, 0.0f
), 1.0f
);
30 void OnTextureReleased(
31 const ScopedPPResource
& layer
,
32 const ScopedPPResource
& context
,
34 const scoped_refptr
<TrackedCallback
>& release_callback
,
38 if (!TrackedCallback::IsPending(release_callback
))
41 if (result
!= PP_OK
) {
42 release_callback
->Run(result
);
50 EnterResourceNoLock
<PPB_Graphics3D_API
> enter(context
.get(), true);
54 PPB_Graphics3D_Shared
* graphics
=
55 static_cast<PPB_Graphics3D_Shared
*>(enter
.object());
57 GLES2Implementation
* gl
= graphics
->gles2_impl();
58 gl
->WaitSyncPointCHROMIUM(sync_point
);
61 release_callback
->Run(is_lost
? PP_ERROR_FAILED
: PP_OK
);
65 const ScopedPPResource
& layer
,
66 const ScopedPPResource
& image
,
67 const scoped_refptr
<TrackedCallback
>& release_callback
,
71 if (!TrackedCallback::IsPending(release_callback
))
73 release_callback
->Run(result
);
78 CompositorLayerResource::CompositorLayerResource(
79 Connection connection
,
81 const CompositorResource
* compositor
)
82 : PluginResource(connection
, instance
),
83 compositor_(compositor
),
84 source_size_(PP_MakeFloatSize(0.0f
, 0.0f
)) {
87 CompositorLayerResource::~CompositorLayerResource() {
89 DCHECK(release_callback_
.is_null());
92 thunk::PPB_CompositorLayer_API
*
93 CompositorLayerResource::AsPPB_CompositorLayer_API() {
97 int32_t CompositorLayerResource::SetColor(float red
,
101 const PP_Size
* size
) {
103 return PP_ERROR_BADRESOURCE
;
105 if (compositor_
->IsInProgress())
106 return PP_ERROR_INPROGRESS
;
108 if (!SetType(TYPE_COLOR
))
109 return PP_ERROR_BADARGUMENT
;
113 return PP_ERROR_BADARGUMENT
;
115 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
;
124 int32_t CompositorLayerResource::SetTexture(
128 const scoped_refptr
<TrackedCallback
>& release_callback
) {
129 int32_t rv
= CheckForSetTextureAndImage(TYPE_TEXTURE
, release_callback
);
132 DCHECK(data_
.texture
);
134 EnterResourceNoLock
<PPB_Graphics3D_API
> enter(context
, true);
136 return PP_ERROR_BADRESOURCE
;
138 if (!size
|| size
->width
<= 0 || size
->height
<= 0)
139 return PP_ERROR_BADARGUMENT
;
141 PPB_Graphics3D_Shared
* graphics
=
142 static_cast<PPB_Graphics3D_Shared
*>(enter
.object());
144 GLES2Implementation
* gl
= graphics
->gles2_impl();
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
));
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
);
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_
;
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(
170 ScopedPPResource(pp_resource()), // Keep layer alive.
171 ScopedPPResource(context
), // Keep context alive
175 return PP_OK_COMPLETIONPENDING
;
178 int32_t CompositorLayerResource::SetImage(
179 PP_Resource image_data
,
181 const scoped_refptr
<TrackedCallback
>& release_callback
) {
182 int32_t rv
= CheckForSetTextureAndImage(TYPE_IMAGE
, release_callback
);
187 EnterResourceNoLock
<PPB_ImageData_API
> enter(image_data
, true);
189 return PP_ERROR_BADRESOURCE
;
191 PP_ImageDataDesc desc
;
192 if (!enter
.object()->Describe(&desc
))
193 return PP_ERROR_BADARGUMENT
;
195 // TODO(penghuang): Support image which width * 4 != stride.
196 if (desc
.size
.width
* 4 != desc
.stride
)
197 return PP_ERROR_BADARGUMENT
;
199 // TODO(penghuang): Support all formats.
200 if (desc
.format
!= PP_IMAGEDATAFORMAT_RGBA_PREMUL
)
201 return PP_ERROR_BADARGUMENT
;
203 if (!size
|| size
->width
<= 0 || size
->height
<= 0)
204 return PP_ERROR_BADARGUMENT
;
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
);
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_
;
216 // 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.
221 release_callback_
= base::Bind(
223 ScopedPPResource(pp_resource()), // Keep layer alive.
224 ScopedPPResource(image_data
), // Keep image_data alive.
227 return PP_OK_COMPLETIONPENDING
;
230 int32_t CompositorLayerResource::SetClipRect(const PP_Rect
* rect
) {
232 return PP_ERROR_BADRESOURCE
;
234 if (compositor_
->IsInProgress())
235 return PP_ERROR_INPROGRESS
;
237 data_
.common
.clip_rect
= rect
? *rect
: PP_MakeRectFromXYWH(0, 0, 0, 0);
241 int32_t CompositorLayerResource::SetTransform(const float matrix
[16]) {
243 return PP_ERROR_BADRESOURCE
;
245 if (compositor_
->IsInProgress())
246 return PP_ERROR_INPROGRESS
;
248 std::copy(matrix
, matrix
+ 16, data_
.common
.transform
.matrix
);
252 int32_t CompositorLayerResource::SetOpacity(float opacity
) {
254 return PP_ERROR_BADRESOURCE
;
256 if (compositor_
->IsInProgress())
257 return PP_ERROR_INPROGRESS
;
259 data_
.common
.opacity
= clamp(opacity
);
263 int32_t CompositorLayerResource::SetBlendMode(PP_BlendMode mode
) {
265 return PP_ERROR_BADRESOURCE
;
267 if (compositor_
->IsInProgress())
268 return PP_ERROR_INPROGRESS
;
271 case PP_BLENDMODE_NONE
:
272 case PP_BLENDMODE_SRC_OVER
:
273 data_
.common
.blend_mode
= mode
;
276 return PP_ERROR_BADARGUMENT
;
279 int32_t CompositorLayerResource::SetSourceRect(
280 const PP_FloatRect
* rect
) {
282 return PP_ERROR_BADRESOURCE
;
284 if (compositor_
->IsInProgress())
285 return PP_ERROR_INPROGRESS
;
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
;
296 data_
.texture
->source_rect
= *rect
;
300 data_
.image
->source_rect
= *rect
;
303 return PP_ERROR_BADARGUMENT
;
306 int32_t CompositorLayerResource::SetPremultipliedAlpha(PP_Bool premult
) {
308 return PP_ERROR_BADRESOURCE
;
310 if (compositor_
->IsInProgress())
311 return PP_ERROR_INPROGRESS
;
314 data_
.texture
->premult_alpha
= PP_ToBool(premult
);
317 return PP_ERROR_BADARGUMENT
;
320 bool CompositorLayerResource::SetType(LayerType type
) {
321 if (type
== TYPE_COLOR
) {
323 data_
.color
.reset(new CompositorLayerData::ColorLayer());
327 if (type
== TYPE_TEXTURE
) {
329 data_
.texture
.reset(new CompositorLayerData::TextureLayer());
330 return data_
.texture
;
333 if (type
== TYPE_IMAGE
) {
335 data_
.image
.reset(new CompositorLayerData::ImageLayer());
339 // Should not be reached.
344 int32_t CompositorLayerResource::CheckForSetTextureAndImage(
346 const scoped_refptr
<TrackedCallback
>& release_callback
) {
348 return PP_ERROR_BADRESOURCE
;
350 if (compositor_
->IsInProgress())
351 return PP_ERROR_INPROGRESS
;
354 return PP_ERROR_BADARGUMENT
;
356 // The layer's image has been set and it is not committed.
357 if (!release_callback_
.is_null())
358 return PP_ERROR_INPROGRESS
;
360 // Do not allow using a block callback as a release callback.
361 if (release_callback
->is_blocking())
362 return PP_ERROR_BADARGUMENT
;