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