OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_ | |
6 #define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_ | |
7 | |
8 #include "base/atomicops.h" | |
9 #include "base/callback.h" | |
10 #include "base/macros.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" | |
16 | |
17 namespace gfx { | |
18 class Point; | |
19 class Rect; | |
20 class Size; | |
21 } | |
22 | |
23 namespace gpu { | |
24 class ContextSupport; | |
25 struct Mailbox; | |
26 } | |
27 | |
28 namespace media { | |
29 class VideoFrame; | |
30 }; | |
31 | |
32 class SkRegion; | |
33 | |
34 namespace content { | |
35 | |
36 class GLHelperScaling; | |
37 | |
38 class ScopedGLuint { | |
39 public: | |
40 typedef void (gpu::gles2::GLES2Interface::*GenFunc)(GLsizei n, GLuint* ids); | |
41 typedef void (gpu::gles2::GLES2Interface::*DeleteFunc)(GLsizei n, | |
42 const GLuint* ids); | |
43 ScopedGLuint(gpu::gles2::GLES2Interface* gl, | |
44 GenFunc gen_func, | |
45 DeleteFunc delete_func) | |
46 : gl_(gl), id_(0u), delete_func_(delete_func) { | |
47 (gl_->*gen_func)(1, &id_); | |
48 } | |
49 | |
50 operator GLuint() const { return id_; } | |
51 | |
52 GLuint id() const { return id_; } | |
53 | |
54 ~ScopedGLuint() { | |
55 if (id_ != 0) { | |
56 (gl_->*delete_func_)(1, &id_); | |
57 } | |
58 } | |
59 | |
60 private: | |
61 gpu::gles2::GLES2Interface* gl_; | |
62 GLuint id_; | |
63 DeleteFunc delete_func_; | |
64 | |
65 DISALLOW_COPY_AND_ASSIGN(ScopedGLuint); | |
66 }; | |
67 | |
68 class ScopedBuffer : public ScopedGLuint { | |
69 public: | |
70 explicit ScopedBuffer(gpu::gles2::GLES2Interface* gl) | |
71 : ScopedGLuint(gl, | |
72 &gpu::gles2::GLES2Interface::GenBuffers, | |
73 &gpu::gles2::GLES2Interface::DeleteBuffers) {} | |
74 }; | |
75 | |
76 class ScopedFramebuffer : public ScopedGLuint { | |
77 public: | |
78 explicit ScopedFramebuffer(gpu::gles2::GLES2Interface* gl) | |
79 : ScopedGLuint(gl, | |
80 &gpu::gles2::GLES2Interface::GenFramebuffers, | |
81 &gpu::gles2::GLES2Interface::DeleteFramebuffers) {} | |
82 }; | |
83 | |
84 class ScopedTexture : public ScopedGLuint { | |
85 public: | |
86 explicit ScopedTexture(gpu::gles2::GLES2Interface* gl) | |
87 : ScopedGLuint(gl, | |
88 &gpu::gles2::GLES2Interface::GenTextures, | |
89 &gpu::gles2::GLES2Interface::DeleteTextures) {} | |
90 }; | |
91 | |
92 template <GLenum Target> | |
93 class ScopedBinder { | |
94 public: | |
95 typedef void (gpu::gles2::GLES2Interface::*BindFunc)(GLenum target, | |
96 GLuint id); | |
97 ScopedBinder(gpu::gles2::GLES2Interface* gl, GLuint id, BindFunc bind_func) | |
98 : gl_(gl), bind_func_(bind_func) { | |
99 (gl_->*bind_func_)(Target, id); | |
100 } | |
101 | |
102 virtual ~ScopedBinder() { (gl_->*bind_func_)(Target, 0); } | |
103 | |
104 private: | |
105 gpu::gles2::GLES2Interface* gl_; | |
106 BindFunc bind_func_; | |
107 | |
108 DISALLOW_COPY_AND_ASSIGN(ScopedBinder); | |
109 }; | |
110 | |
111 template <GLenum Target> | |
112 class ScopedBufferBinder : ScopedBinder<Target> { | |
113 public: | |
114 ScopedBufferBinder(gpu::gles2::GLES2Interface* gl, GLuint id) | |
115 : ScopedBinder<Target>(gl, id, &gpu::gles2::GLES2Interface::BindBuffer) {} | |
116 }; | |
117 | |
118 template <GLenum Target> | |
119 class ScopedFramebufferBinder : ScopedBinder<Target> { | |
120 public: | |
121 ScopedFramebufferBinder(gpu::gles2::GLES2Interface* gl, GLuint id) | |
122 : ScopedBinder<Target>(gl, | |
123 id, | |
124 &gpu::gles2::GLES2Interface::BindFramebuffer) {} | |
125 }; | |
126 | |
127 template <GLenum Target> | |
128 class ScopedTextureBinder : ScopedBinder<Target> { | |
129 public: | |
130 ScopedTextureBinder(gpu::gles2::GLES2Interface* gl, GLuint id) | |
131 : ScopedBinder<Target>(gl, id, &gpu::gles2::GLES2Interface::BindTexture) { | |
132 } | |
133 }; | |
134 | |
135 class ReadbackYUVInterface; | |
136 class GLHelperReadbackSupport; | |
137 | |
138 // Provides higher level operations on top of the gpu::gles2::GLES2Interface | |
139 // interfaces. | |
140 class CONTENT_EXPORT GLHelper { | |
141 public: | |
142 GLHelper(gpu::gles2::GLES2Interface* gl, | |
143 gpu::ContextSupport* context_support); | |
144 ~GLHelper(); | |
145 | |
146 enum ScalerQuality { | |
147 // Bilinear single pass, fastest possible. | |
148 SCALER_QUALITY_FAST = 1, | |
149 | |
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, | |
154 | |
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 | |
158 // worth it. | |
159 SCALER_QUALITY_BEST = 3, | |
160 }; | |
161 | |
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( | |
171 GLuint src_texture, | |
172 const gfx::Size& src_size, | |
173 const gfx::Rect& src_subrect, | |
174 const gfx::Size& dst_size, | |
175 unsigned char* out, | |
176 const SkColorType out_color_type, | |
177 const base::Callback<void(bool)>& callback, | |
178 GLHelper::ScalerQuality quality); | |
179 | |
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, | |
191 const gpu::SyncToken& sync_token, | |
192 const gfx::Size& src_size, | |
193 const gfx::Rect& src_subrect, | |
194 const gfx::Size& dst_size, | |
195 unsigned char* out, | |
196 const SkColorType out_color_type, | |
197 const base::Callback<void(bool)>& callback, | |
198 GLHelper::ScalerQuality quality); | |
199 | |
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, | |
207 unsigned char* out, | |
208 SkColorType format); | |
209 | |
210 void ReadbackTextureAsync(GLuint texture, | |
211 const gfx::Size& dst_size, | |
212 unsigned char* out, | |
213 SkColorType color_type, | |
214 const base::Callback<void(bool)>& callback); | |
215 | |
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); | |
220 | |
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); | |
230 | |
231 // Returns the shader compiled from the source. | |
232 GLuint CompileShaderFromSource(const GLchar* source, GLenum type); | |
233 | |
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, | |
237 GLuint texture, | |
238 GLuint previous_texture, | |
239 const SkRegion& new_damage, | |
240 const SkRegion& old_damage); | |
241 | |
242 // Simply creates a texture. | |
243 GLuint CreateTexture(); | |
244 // Deletes a texture. | |
245 void DeleteTexture(GLuint texture_id); | |
246 | |
247 // Inserts a fence sync, flushes, and generates a sync token. | |
248 void GenerateSyncToken(gpu::SyncToken* sync_token); | |
249 | |
250 // Wait for the sync token before executing further GL commands. | |
251 void WaitSyncToken(const gpu::SyncToken& sync_token); | |
252 | |
253 // Creates a mailbox holder that is attached to the given texture id, with a | |
254 // sync point to wait on before using the mailbox. Returns a holder with an | |
255 // empty mailbox on failure. | |
256 // Note the texture is assumed to be GL_TEXTURE_2D. | |
257 gpu::MailboxHolder ProduceMailboxHolderFromTexture(GLuint texture_id); | |
258 | |
259 // Creates a texture and consumes a mailbox into it. Returns 0 on failure. | |
260 // Note the mailbox is assumed to be GL_TEXTURE_2D. | |
261 GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, | |
262 const gpu::SyncToken& sync_token); | |
263 | |
264 // Resizes the texture's size to |size|. | |
265 void ResizeTexture(GLuint texture, const gfx::Size& size); | |
266 | |
267 // Copies the framebuffer data given in |rect| to |texture|. | |
268 void CopyTextureSubImage(GLuint texture, const gfx::Rect& rect); | |
269 | |
270 // Copies the all framebuffer data to |texture|. |size| specifies the | |
271 // size of the framebuffer. | |
272 void CopyTextureFullImage(GLuint texture, const gfx::Size& size); | |
273 | |
274 // Flushes GL commands. | |
275 void Flush(); | |
276 | |
277 // Force commands in the current command buffer to be executed before commands | |
278 // in other command buffers from the same process (ie channel to the GPU | |
279 // process). | |
280 void InsertOrderingBarrier(); | |
281 | |
282 // A scaler will cache all intermediate textures and programs | |
283 // needed to scale from a specified size to a destination size. | |
284 // If the source or destination sizes changes, you must create | |
285 // a new scaler. | |
286 class CONTENT_EXPORT ScalerInterface { | |
287 public: | |
288 ScalerInterface() {} | |
289 virtual ~ScalerInterface() {} | |
290 | |
291 // Note that the src_texture will have the min/mag filter set to GL_LINEAR | |
292 // and wrap_s/t set to CLAMP_TO_EDGE in this call. | |
293 virtual void Scale(GLuint source_texture, GLuint dest_texture) = 0; | |
294 virtual const gfx::Size& SrcSize() = 0; | |
295 virtual const gfx::Rect& SrcSubrect() = 0; | |
296 virtual const gfx::Size& DstSize() = 0; | |
297 }; | |
298 | |
299 // Note that the quality may be adjusted down if texture | |
300 // allocations fail or hardware doesn't support the requtested | |
301 // quality. Note that ScalerQuality enum is arranged in | |
302 // numerical order for simplicity. | |
303 ScalerInterface* CreateScaler(ScalerQuality quality, | |
304 const gfx::Size& src_size, | |
305 const gfx::Rect& src_subrect, | |
306 const gfx::Size& dst_size, | |
307 bool vertically_flip_texture, | |
308 bool swizzle); | |
309 | |
310 // Create a readback pipeline that will scale a subsection of the source | |
311 // texture, then convert it to YUV422 planar form and then read back that. | |
312 // This reduces the amount of memory read from GPU to CPU memory by a factor | |
313 // 2.6, which can be quite handy since readbacks have very limited speed | |
314 // on some platforms. All values in |dst_size| must be a multiple of two. If | |
315 // |use_mrt| is true, the pipeline will try to optimize the YUV conversion | |
316 // using the multi-render-target extension. |use_mrt| should only be set to | |
317 // false for testing. | |
318 ReadbackYUVInterface* CreateReadbackPipelineYUV(ScalerQuality quality, | |
319 const gfx::Size& src_size, | |
320 const gfx::Rect& src_subrect, | |
321 const gfx::Size& dst_size, | |
322 bool flip_vertically, | |
323 bool use_mrt); | |
324 | |
325 // Returns the maximum number of draw buffers available, | |
326 // 0 if GL_EXT_draw_buffers is not available. | |
327 GLint MaxDrawBuffers(); | |
328 | |
329 // Checks whether the readbback is supported for texture with the | |
330 // matching config. This doesnt check for cross format readbacks. | |
331 bool IsReadbackConfigSupported(SkColorType texture_format); | |
332 | |
333 protected: | |
334 class CopyTextureToImpl; | |
335 | |
336 // Creates |copy_texture_to_impl_| if NULL. | |
337 void InitCopyTextToImpl(); | |
338 // Creates |scaler_impl_| if NULL. | |
339 void InitScalerImpl(); | |
340 | |
341 enum ReadbackSwizzle { | |
342 kSwizzleNone = 0, | |
343 kSwizzleBGRA | |
344 }; | |
345 | |
346 gpu::gles2::GLES2Interface* gl_; | |
347 gpu::ContextSupport* context_support_; | |
348 scoped_ptr<CopyTextureToImpl> copy_texture_to_impl_; | |
349 scoped_ptr<GLHelperScaling> scaler_impl_; | |
350 scoped_ptr<GLHelperReadbackSupport> readback_support_; | |
351 | |
352 DISALLOW_COPY_AND_ASSIGN(GLHelper); | |
353 }; | |
354 | |
355 // Similar to a ScalerInterface, a yuv readback pipeline will | |
356 // cache a scaler and all intermediate textures and frame buffers | |
357 // needed to scale, crop, letterbox and read back a texture from | |
358 // the GPU into CPU-accessible RAM. A single readback pipeline | |
359 // can handle multiple outstanding readbacks at the same time, but | |
360 // if the source or destination sizes change, you'll need to create | |
361 // a new readback pipeline. | |
362 class CONTENT_EXPORT ReadbackYUVInterface { | |
363 public: | |
364 ReadbackYUVInterface() {} | |
365 virtual ~ReadbackYUVInterface() {} | |
366 | |
367 // Note that |target| must use YV12 format. |paste_location| specifies where | |
368 // the captured pixels that are read back will be placed in the video frame. | |
369 // The region defined by the |paste_location| and the |dst_size| specified in | |
370 // the call to CreateReadbackPipelineYUV() must be fully contained within | |
371 // |target->visible_rect()|. | |
372 virtual void ReadbackYUV(const gpu::Mailbox& mailbox, | |
373 const gpu::SyncToken& sync_token, | |
374 const scoped_refptr<media::VideoFrame>& target, | |
375 const gfx::Point& paste_location, | |
376 const base::Callback<void(bool)>& callback) = 0; | |
377 virtual GLHelper::ScalerInterface* scaler() = 0; | |
378 }; | |
379 | |
380 } // namespace content | |
381 | |
382 #endif // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_ | |
OLD | NEW |