| 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 |