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_BROWSER_COMPOSITOR_GL_HELPER_H_ |
| 6 #define CONTENT_BROWSER_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 "content/common/content_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 content { |
| 32 |
| 33 class GLHelperScaling; |
| 34 |
| 35 class 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 CONTENT_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 CONTENT_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 CONTENT_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 content |
| 381 |
| 382 #endif // CONTENT_BROWSER_COMPOSITOR_GL_HELPER_H_ |
OLD | NEW |