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