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