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.
5 #ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
6 #define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
8 #include "base/atomicops.h"
9 #include "base/basictypes.h"
10 #include "base/callback.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "content/common/content_export.h"
13 #include "gpu/command_buffer/client/gles2_interface.h"
14 #include "gpu/command_buffer/common/mailbox_holder.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
36 class GLHelperScaling
;
40 typedef void (gpu::gles2::GLES2Interface::*GenFunc
)(GLsizei n
, GLuint
* ids
);
41 typedef void (gpu::gles2::GLES2Interface::*DeleteFunc
)(GLsizei n
,
43 ScopedGLuint(gpu::gles2::GLES2Interface
* gl
,
45 DeleteFunc delete_func
)
46 : gl_(gl
), id_(0u), delete_func_(delete_func
) {
47 (gl_
->*gen_func
)(1, &id_
);
50 operator GLuint() const { return id_
; }
52 GLuint
id() const { return id_
; }
56 (gl_
->*delete_func_
)(1, &id_
);
61 gpu::gles2::GLES2Interface
* gl_
;
63 DeleteFunc delete_func_
;
65 DISALLOW_COPY_AND_ASSIGN(ScopedGLuint
);
68 class ScopedBuffer
: public ScopedGLuint
{
70 explicit ScopedBuffer(gpu::gles2::GLES2Interface
* gl
)
72 &gpu::gles2::GLES2Interface::GenBuffers
,
73 &gpu::gles2::GLES2Interface::DeleteBuffers
) {}
76 class ScopedFramebuffer
: public ScopedGLuint
{
78 explicit ScopedFramebuffer(gpu::gles2::GLES2Interface
* gl
)
80 &gpu::gles2::GLES2Interface::GenFramebuffers
,
81 &gpu::gles2::GLES2Interface::DeleteFramebuffers
) {}
84 class ScopedTexture
: public ScopedGLuint
{
86 explicit ScopedTexture(gpu::gles2::GLES2Interface
* gl
)
88 &gpu::gles2::GLES2Interface::GenTextures
,
89 &gpu::gles2::GLES2Interface::DeleteTextures
) {}
92 template <GLenum Target
>
95 typedef void (gpu::gles2::GLES2Interface::*BindFunc
)(GLenum target
,
97 ScopedBinder(gpu::gles2::GLES2Interface
* gl
, GLuint id
, BindFunc bind_func
)
98 : gl_(gl
), bind_func_(bind_func
) {
99 (gl_
->*bind_func_
)(Target
, id
);
102 virtual ~ScopedBinder() { (gl_
->*bind_func_
)(Target
, 0); }
105 gpu::gles2::GLES2Interface
* gl_
;
108 DISALLOW_COPY_AND_ASSIGN(ScopedBinder
);
111 template <GLenum Target
>
112 class ScopedBufferBinder
: ScopedBinder
<Target
> {
114 ScopedBufferBinder(gpu::gles2::GLES2Interface
* gl
, GLuint id
)
115 : ScopedBinder
<Target
>(gl
, id
, &gpu::gles2::GLES2Interface::BindBuffer
) {}
118 template <GLenum Target
>
119 class ScopedFramebufferBinder
: ScopedBinder
<Target
> {
121 ScopedFramebufferBinder(gpu::gles2::GLES2Interface
* gl
, GLuint id
)
122 : ScopedBinder
<Target
>(gl
,
124 &gpu::gles2::GLES2Interface::BindFramebuffer
) {}
127 template <GLenum Target
>
128 class ScopedTextureBinder
: ScopedBinder
<Target
> {
130 ScopedTextureBinder(gpu::gles2::GLES2Interface
* gl
, GLuint id
)
131 : ScopedBinder
<Target
>(gl
, id
, &gpu::gles2::GLES2Interface::BindTexture
) {
135 class ReadbackYUVInterface
;
136 class GLHelperReadbackSupport
;
138 // Provides higher level operations on top of the gpu::gles2::GLES2Interface
140 class CONTENT_EXPORT GLHelper
{
142 GLHelper(gpu::gles2::GLES2Interface
* gl
,
143 gpu::ContextSupport
* context_support
);
147 // Bilinear single pass, fastest possible.
148 SCALER_QUALITY_FAST
= 1,
150 // Bilinear upscale + N * 50% bilinear downscales.
151 // This is still fast enough for most purposes and
152 // Image quality is nearly as good as the BEST option.
153 SCALER_QUALITY_GOOD
= 2,
155 // Bicubic upscale + N * 50% bicubic downscales.
156 // Produces very good quality scaled images, but it's
157 // 2-8x slower than the "GOOD" quality, so it's not always
159 SCALER_QUALITY_BEST
= 3,
162 // Copies the block of pixels specified with |src_subrect| from |src_texture|,
163 // scales it to |dst_size|, and writes it into |out|.
164 // |src_size| is the size of |src_texture|. The result is in |out_color_type|
165 // format and is potentially flipped vertically to make it a correct image
166 // representation. |callback| is invoked with the copy result when the copy
167 // operation has completed.
168 // Note that the src_texture will have the min/mag filter set to GL_LINEAR
169 // and wrap_s/t set to CLAMP_TO_EDGE in this call.
170 void CropScaleReadbackAndCleanTexture(
172 const gfx::Size
& src_size
,
173 const gfx::Rect
& src_subrect
,
174 const gfx::Size
& dst_size
,
176 const SkColorType out_color_type
,
177 const base::Callback
<void(bool)>& callback
,
178 GLHelper::ScalerQuality quality
);
180 // Copies the block of pixels specified with |src_subrect| from |src_mailbox|,
181 // scales it to |dst_size|, and writes it into |out|.
182 // |src_size| is the size of |src_mailbox|. The result is in |out_color_type|
183 // format and is potentially flipped vertically to make it a correct image
184 // representation. |callback| is invoked with the copy result when the copy
185 // operation has completed.
186 // Note that the texture bound to src_mailbox will have the min/mag filter set
187 // to GL_LINEAR and wrap_s/t set to CLAMP_TO_EDGE in this call. src_mailbox is
188 // assumed to be GL_TEXTURE_2D.
189 void CropScaleReadbackAndCleanMailbox(
190 const gpu::Mailbox
& src_mailbox
,
192 const gfx::Size
& src_size
,
193 const gfx::Rect
& src_subrect
,
194 const gfx::Size
& dst_size
,
196 const SkColorType out_color_type
,
197 const base::Callback
<void(bool)>& callback
,
198 GLHelper::ScalerQuality quality
);
200 // Copies the texture data out of |texture| into |out|. |size| is the
201 // size of the texture. No post processing is applied to the pixels. The
202 // texture is assumed to have a format of GL_RGBA with a pixel type of
203 // GL_UNSIGNED_BYTE. This is a blocking call that calls glReadPixels on the
204 // current OpenGL context.
205 void ReadbackTextureSync(GLuint texture
,
206 const gfx::Rect
& src_rect
,
210 void ReadbackTextureAsync(GLuint texture
,
211 const gfx::Size
& dst_size
,
213 SkColorType color_type
,
214 const base::Callback
<void(bool)>& callback
);
216 // Creates a copy of the specified texture. |size| is the size of the texture.
217 // Note that the src_texture will have the min/mag filter set to GL_LINEAR
218 // and wrap_s/t set to CLAMP_TO_EDGE in this call.
219 GLuint
CopyTexture(GLuint texture
, const gfx::Size
& size
);
221 // Creates a scaled copy of the specified texture. |src_size| is the size of
222 // the texture and |dst_size| is the size of the resulting copy.
223 // Note that the src_texture will have the min/mag filter set to GL_LINEAR
224 // and wrap_s/t set to CLAMP_TO_EDGE in this call.
225 GLuint
CopyAndScaleTexture(GLuint texture
,
226 const gfx::Size
& src_size
,
227 const gfx::Size
& dst_size
,
228 bool vertically_flip_texture
,
229 ScalerQuality quality
);
231 // Returns the shader compiled from the source.
232 GLuint
CompileShaderFromSource(const GLchar
* source
, GLenum type
);
234 // Copies all pixels from |previous_texture| into |texture| that are
235 // inside the region covered by |old_damage| but not part of |new_damage|.
236 void CopySubBufferDamage(GLenum target
,
238 GLuint previous_texture
,
239 const SkRegion
& new_damage
,
240 const SkRegion
& old_damage
);
242 // Simply creates a texture.
243 GLuint
CreateTexture();
244 // Deletes a texture.
245 void DeleteTexture(GLuint texture_id
);
247 // Insert a sync point into the GL command buffer.
248 uint32
InsertSyncPoint();
249 // Wait for the sync point before executing further GL commands.
250 void WaitSyncPoint(uint32 sync_point
);
252 // Creates a mailbox holder that is attached to the given texture id, with a
253 // sync point to wait on before using the mailbox. Returns a holder with an
254 // empty mailbox on failure.
255 // Note the texture is assumed to be GL_TEXTURE_2D.
256 gpu::MailboxHolder
ProduceMailboxHolderFromTexture(GLuint texture_id
);
258 // Creates a texture and consumes a mailbox into it. Returns 0 on failure.
259 // Note the mailbox is assumed to be GL_TEXTURE_2D.
260 GLuint
ConsumeMailboxToTexture(const gpu::Mailbox
& mailbox
,
263 // Resizes the texture's size to |size|.
264 void ResizeTexture(GLuint texture
, const gfx::Size
& size
);
266 // Copies the framebuffer data given in |rect| to |texture|.
267 void CopyTextureSubImage(GLuint texture
, const gfx::Rect
& rect
);
269 // Copies the all framebuffer data to |texture|. |size| specifies the
270 // size of the framebuffer.
271 void CopyTextureFullImage(GLuint texture
, const gfx::Size
& size
);
273 // Flushes GL commands.
276 // Force commands in the current command buffer to be executed before commands
277 // in other command buffers from the same process (ie channel to the GPU
279 void InsertOrderingBarrier();
281 // A scaler will cache all intermediate textures and programs
282 // needed to scale from a specified size to a destination size.
283 // If the source or destination sizes changes, you must create
285 class CONTENT_EXPORT ScalerInterface
{
288 virtual ~ScalerInterface() {}
290 // Note that the src_texture will have the min/mag filter set to GL_LINEAR
291 // and wrap_s/t set to CLAMP_TO_EDGE in this call.
292 virtual void Scale(GLuint source_texture
, GLuint dest_texture
) = 0;
293 virtual const gfx::Size
& SrcSize() = 0;
294 virtual const gfx::Rect
& SrcSubrect() = 0;
295 virtual const gfx::Size
& DstSize() = 0;
298 // Note that the quality may be adjusted down if texture
299 // allocations fail or hardware doesn't support the requtested
300 // quality. Note that ScalerQuality enum is arranged in
301 // numerical order for simplicity.
302 ScalerInterface
* CreateScaler(ScalerQuality quality
,
303 const gfx::Size
& src_size
,
304 const gfx::Rect
& src_subrect
,
305 const gfx::Size
& dst_size
,
306 bool vertically_flip_texture
,
309 // Create a readback pipeline that will scale a subsection of the source
310 // texture, then convert it to YUV422 planar form and then read back that.
311 // This reduces the amount of memory read from GPU to CPU memory by a factor
312 // 2.6, which can be quite handy since readbacks have very limited speed
313 // on some platforms. All values in |dst_size| must be a multiple of two. If
314 // |use_mrt| is true, the pipeline will try to optimize the YUV conversion
315 // using the multi-render-target extension. |use_mrt| should only be set to
316 // false for testing.
317 ReadbackYUVInterface
* CreateReadbackPipelineYUV(ScalerQuality quality
,
318 const gfx::Size
& src_size
,
319 const gfx::Rect
& src_subrect
,
320 const gfx::Size
& dst_size
,
321 bool flip_vertically
,
324 // Returns the maximum number of draw buffers available,
325 // 0 if GL_EXT_draw_buffers is not available.
326 GLint
MaxDrawBuffers();
328 // Checks whether the readbback is supported for texture with the
329 // matching config. This doesnt check for cross format readbacks.
330 bool IsReadbackConfigSupported(SkColorType texture_format
);
333 class CopyTextureToImpl
;
335 // Creates |copy_texture_to_impl_| if NULL.
336 void InitCopyTextToImpl();
337 // Creates |scaler_impl_| if NULL.
338 void InitScalerImpl();
340 enum ReadbackSwizzle
{
345 gpu::gles2::GLES2Interface
* gl_
;
346 gpu::ContextSupport
* context_support_
;
347 scoped_ptr
<CopyTextureToImpl
> copy_texture_to_impl_
;
348 scoped_ptr
<GLHelperScaling
> scaler_impl_
;
349 scoped_ptr
<GLHelperReadbackSupport
> readback_support_
;
351 DISALLOW_COPY_AND_ASSIGN(GLHelper
);
354 // Similar to a ScalerInterface, a yuv readback pipeline will
355 // cache a scaler and all intermediate textures and frame buffers
356 // needed to scale, crop, letterbox and read back a texture from
357 // the GPU into CPU-accessible RAM. A single readback pipeline
358 // can handle multiple outstanding readbacks at the same time, but
359 // if the source or destination sizes change, you'll need to create
360 // a new readback pipeline.
361 class CONTENT_EXPORT ReadbackYUVInterface
{
363 ReadbackYUVInterface() {}
364 virtual ~ReadbackYUVInterface() {}
366 // Note that |target| must use YV12 format. |paste_location| specifies where
367 // the captured pixels that are read back will be placed in the video frame.
368 // The region defined by the |paste_location| and the |dst_size| specified in
369 // the call to CreateReadbackPipelineYUV() must be fully contained within
370 // |target->visible_rect()|.
371 virtual void ReadbackYUV(const gpu::Mailbox
& mailbox
,
373 const scoped_refptr
<media::VideoFrame
>& target
,
374 const gfx::Point
& paste_location
,
375 const base::Callback
<void(bool)>& callback
) = 0;
376 virtual GLHelper::ScalerInterface
* scaler() = 0;
379 } // namespace content
381 #endif // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_