Index: content/browser/compositor/gl_helper.h |
diff --git a/content/browser/compositor/gl_helper.h b/content/browser/compositor/gl_helper.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8ebba5f04e2174d13dce2ab1a464d699d0d84806 |
--- /dev/null |
+++ b/content/browser/compositor/gl_helper.h |
@@ -0,0 +1,382 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef CONTENT_BROWSER_COMPOSITOR_GL_HELPER_H_ |
+#define CONTENT_BROWSER_COMPOSITOR_GL_HELPER_H_ |
+ |
+#include <memory> |
+ |
+#include "base/atomicops.h" |
+#include "base/callback.h" |
+#include "base/macros.h" |
+#include "content/common/content_export.h" |
+#include "gpu/command_buffer/client/gles2_interface.h" |
+#include "gpu/command_buffer/common/mailbox_holder.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
+ |
+namespace gfx { |
+class Point; |
+class Rect; |
+class Size; |
+} |
+ |
+namespace gpu { |
+class ContextSupport; |
+struct Mailbox; |
+} |
+ |
+class SkRegion; |
+ |
+namespace content { |
+ |
+class GLHelperScaling; |
+ |
+class ScopedGLuint { |
+ public: |
+ typedef void (gpu::gles2::GLES2Interface::*GenFunc)(GLsizei n, GLuint* ids); |
+ typedef void (gpu::gles2::GLES2Interface::*DeleteFunc)(GLsizei n, |
+ const GLuint* ids); |
+ ScopedGLuint(gpu::gles2::GLES2Interface* gl, |
+ GenFunc gen_func, |
+ DeleteFunc delete_func) |
+ : gl_(gl), id_(0u), delete_func_(delete_func) { |
+ (gl_->*gen_func)(1, &id_); |
+ } |
+ |
+ operator GLuint() const { return id_; } |
+ |
+ GLuint id() const { return id_; } |
+ |
+ ~ScopedGLuint() { |
+ if (id_ != 0) { |
+ (gl_->*delete_func_)(1, &id_); |
+ } |
+ } |
+ |
+ private: |
+ gpu::gles2::GLES2Interface* gl_; |
+ GLuint id_; |
+ DeleteFunc delete_func_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedGLuint); |
+}; |
+ |
+class ScopedBuffer : public ScopedGLuint { |
+ public: |
+ explicit ScopedBuffer(gpu::gles2::GLES2Interface* gl) |
+ : ScopedGLuint(gl, |
+ &gpu::gles2::GLES2Interface::GenBuffers, |
+ &gpu::gles2::GLES2Interface::DeleteBuffers) {} |
+}; |
+ |
+class ScopedFramebuffer : public ScopedGLuint { |
+ public: |
+ explicit ScopedFramebuffer(gpu::gles2::GLES2Interface* gl) |
+ : ScopedGLuint(gl, |
+ &gpu::gles2::GLES2Interface::GenFramebuffers, |
+ &gpu::gles2::GLES2Interface::DeleteFramebuffers) {} |
+}; |
+ |
+class ScopedTexture : public ScopedGLuint { |
+ public: |
+ explicit ScopedTexture(gpu::gles2::GLES2Interface* gl) |
+ : ScopedGLuint(gl, |
+ &gpu::gles2::GLES2Interface::GenTextures, |
+ &gpu::gles2::GLES2Interface::DeleteTextures) {} |
+}; |
+ |
+template <GLenum Target> |
+class ScopedBinder { |
+ public: |
+ typedef void (gpu::gles2::GLES2Interface::*BindFunc)(GLenum target, |
+ GLuint id); |
+ ScopedBinder(gpu::gles2::GLES2Interface* gl, GLuint id, BindFunc bind_func) |
+ : gl_(gl), bind_func_(bind_func) { |
+ (gl_->*bind_func_)(Target, id); |
+ } |
+ |
+ virtual ~ScopedBinder() { (gl_->*bind_func_)(Target, 0); } |
+ |
+ private: |
+ gpu::gles2::GLES2Interface* gl_; |
+ BindFunc bind_func_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedBinder); |
+}; |
+ |
+template <GLenum Target> |
+class ScopedBufferBinder : ScopedBinder<Target> { |
+ public: |
+ ScopedBufferBinder(gpu::gles2::GLES2Interface* gl, GLuint id) |
+ : ScopedBinder<Target>(gl, id, &gpu::gles2::GLES2Interface::BindBuffer) {} |
+}; |
+ |
+template <GLenum Target> |
+class ScopedFramebufferBinder : ScopedBinder<Target> { |
+ public: |
+ ScopedFramebufferBinder(gpu::gles2::GLES2Interface* gl, GLuint id) |
+ : ScopedBinder<Target>(gl, |
+ id, |
+ &gpu::gles2::GLES2Interface::BindFramebuffer) {} |
+}; |
+ |
+template <GLenum Target> |
+class ScopedTextureBinder : ScopedBinder<Target> { |
+ public: |
+ ScopedTextureBinder(gpu::gles2::GLES2Interface* gl, GLuint id) |
+ : ScopedBinder<Target>(gl, id, &gpu::gles2::GLES2Interface::BindTexture) { |
+ } |
+}; |
+ |
+class ReadbackYUVInterface; |
+class GLHelperReadbackSupport; |
+ |
+// Provides higher level operations on top of the gpu::gles2::GLES2Interface |
+// interfaces. |
+class CONTENT_EXPORT GLHelper { |
+ public: |
+ GLHelper(gpu::gles2::GLES2Interface* gl, |
+ gpu::ContextSupport* context_support); |
+ ~GLHelper(); |
+ |
+ enum ScalerQuality { |
+ // Bilinear single pass, fastest possible. |
+ SCALER_QUALITY_FAST = 1, |
+ |
+ // Bilinear upscale + N * 50% bilinear downscales. |
+ // This is still fast enough for most purposes and |
+ // Image quality is nearly as good as the BEST option. |
+ SCALER_QUALITY_GOOD = 2, |
+ |
+ // Bicubic upscale + N * 50% bicubic downscales. |
+ // Produces very good quality scaled images, but it's |
+ // 2-8x slower than the "GOOD" quality, so it's not always |
+ // worth it. |
+ SCALER_QUALITY_BEST = 3, |
+ }; |
+ |
+ // Copies the block of pixels specified with |src_subrect| from |src_texture|, |
+ // scales it to |dst_size|, and writes it into |out|. |
+ // |src_size| is the size of |src_texture|. The result is in |out_color_type| |
+ // format and is potentially flipped vertically to make it a correct image |
+ // representation. |callback| is invoked with the copy result when the copy |
+ // operation has completed. |
+ // Note that the src_texture will have the min/mag filter set to GL_LINEAR |
+ // and wrap_s/t set to CLAMP_TO_EDGE in this call. |
+ void CropScaleReadbackAndCleanTexture( |
+ GLuint src_texture, |
+ const gfx::Size& src_size, |
+ const gfx::Rect& src_subrect, |
+ const gfx::Size& dst_size, |
+ unsigned char* out, |
+ const SkColorType out_color_type, |
+ const base::Callback<void(bool)>& callback, |
+ GLHelper::ScalerQuality quality); |
+ |
+ // Copies the block of pixels specified with |src_subrect| from |src_mailbox|, |
+ // scales it to |dst_size|, and writes it into |out|. |
+ // |src_size| is the size of |src_mailbox|. The result is in |out_color_type| |
+ // format and is potentially flipped vertically to make it a correct image |
+ // representation. |callback| is invoked with the copy result when the copy |
+ // operation has completed. |
+ // Note that the texture bound to src_mailbox will have the min/mag filter set |
+ // to GL_LINEAR and wrap_s/t set to CLAMP_TO_EDGE in this call. src_mailbox is |
+ // assumed to be GL_TEXTURE_2D. |
+ void CropScaleReadbackAndCleanMailbox( |
+ const gpu::Mailbox& src_mailbox, |
+ const gpu::SyncToken& sync_token, |
+ const gfx::Size& src_size, |
+ const gfx::Rect& src_subrect, |
+ const gfx::Size& dst_size, |
+ unsigned char* out, |
+ const SkColorType out_color_type, |
+ const base::Callback<void(bool)>& callback, |
+ GLHelper::ScalerQuality quality); |
+ |
+ // Copies the texture data out of |texture| into |out|. |size| is the |
+ // size of the texture. No post processing is applied to the pixels. The |
+ // texture is assumed to have a format of GL_RGBA with a pixel type of |
+ // GL_UNSIGNED_BYTE. This is a blocking call that calls glReadPixels on the |
+ // current OpenGL context. |
+ void ReadbackTextureSync(GLuint texture, |
+ const gfx::Rect& src_rect, |
+ unsigned char* out, |
+ SkColorType format); |
+ |
+ void ReadbackTextureAsync(GLuint texture, |
+ const gfx::Size& dst_size, |
+ unsigned char* out, |
+ SkColorType color_type, |
+ const base::Callback<void(bool)>& callback); |
+ |
+ // Creates a copy of the specified texture. |size| is the size of the texture. |
+ // Note that the src_texture will have the min/mag filter set to GL_LINEAR |
+ // and wrap_s/t set to CLAMP_TO_EDGE in this call. |
+ GLuint CopyTexture(GLuint texture, const gfx::Size& size); |
+ |
+ // Creates a scaled copy of the specified texture. |src_size| is the size of |
+ // the texture and |dst_size| is the size of the resulting copy. |
+ // Note that the src_texture will have the min/mag filter set to GL_LINEAR |
+ // and wrap_s/t set to CLAMP_TO_EDGE in this call. |
+ GLuint CopyAndScaleTexture(GLuint texture, |
+ const gfx::Size& src_size, |
+ const gfx::Size& dst_size, |
+ bool vertically_flip_texture, |
+ ScalerQuality quality); |
+ |
+ // Returns the shader compiled from the source. |
+ GLuint CompileShaderFromSource(const GLchar* source, GLenum type); |
+ |
+ // Copies all pixels from |previous_texture| into |texture| that are |
+ // inside the region covered by |old_damage| but not part of |new_damage|. |
+ void CopySubBufferDamage(GLenum target, |
+ GLuint texture, |
+ GLuint previous_texture, |
+ const SkRegion& new_damage, |
+ const SkRegion& old_damage); |
+ |
+ // Simply creates a texture. |
+ GLuint CreateTexture(); |
+ // Deletes a texture. |
+ void DeleteTexture(GLuint texture_id); |
+ |
+ // Inserts a fence sync, flushes, and generates a sync token. |
+ void GenerateSyncToken(gpu::SyncToken* sync_token); |
+ |
+ // Wait for the sync token before executing further GL commands. |
+ void WaitSyncToken(const gpu::SyncToken& sync_token); |
+ |
+ // Creates a mailbox holder that is attached to the given texture id, with a |
+ // sync point to wait on before using the mailbox. Returns a holder with an |
+ // empty mailbox on failure. |
+ // Note the texture is assumed to be GL_TEXTURE_2D. |
+ gpu::MailboxHolder ProduceMailboxHolderFromTexture(GLuint texture_id); |
+ |
+ // Creates a texture and consumes a mailbox into it. Returns 0 on failure. |
+ // Note the mailbox is assumed to be GL_TEXTURE_2D. |
+ GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, |
+ const gpu::SyncToken& sync_token); |
+ |
+ // Resizes the texture's size to |size|. |
+ void ResizeTexture(GLuint texture, const gfx::Size& size); |
+ |
+ // Copies the framebuffer data given in |rect| to |texture|. |
+ void CopyTextureSubImage(GLuint texture, const gfx::Rect& rect); |
+ |
+ // Copies the all framebuffer data to |texture|. |size| specifies the |
+ // size of the framebuffer. |
+ void CopyTextureFullImage(GLuint texture, const gfx::Size& size); |
+ |
+ // Flushes GL commands. |
+ void Flush(); |
+ |
+ // Force commands in the current command buffer to be executed before commands |
+ // in other command buffers from the same process (ie channel to the GPU |
+ // process). |
+ void InsertOrderingBarrier(); |
+ |
+ // A scaler will cache all intermediate textures and programs |
+ // needed to scale from a specified size to a destination size. |
+ // If the source or destination sizes changes, you must create |
+ // a new scaler. |
+ class CONTENT_EXPORT ScalerInterface { |
+ public: |
+ ScalerInterface() {} |
+ virtual ~ScalerInterface() {} |
+ |
+ // Note that the src_texture will have the min/mag filter set to GL_LINEAR |
+ // and wrap_s/t set to CLAMP_TO_EDGE in this call. |
+ virtual void Scale(GLuint source_texture, GLuint dest_texture) = 0; |
+ virtual const gfx::Size& SrcSize() = 0; |
+ virtual const gfx::Rect& SrcSubrect() = 0; |
+ virtual const gfx::Size& DstSize() = 0; |
+ }; |
+ |
+ // Note that the quality may be adjusted down if texture |
+ // allocations fail or hardware doesn't support the requtested |
+ // quality. Note that ScalerQuality enum is arranged in |
+ // numerical order for simplicity. |
+ ScalerInterface* CreateScaler(ScalerQuality quality, |
+ const gfx::Size& src_size, |
+ const gfx::Rect& src_subrect, |
+ const gfx::Size& dst_size, |
+ bool vertically_flip_texture, |
+ bool swizzle); |
+ |
+ // Create a readback pipeline that will scale a subsection of the source |
+ // texture, then convert it to YUV422 planar form and then read back that. |
+ // This reduces the amount of memory read from GPU to CPU memory by a factor |
+ // 2.6, which can be quite handy since readbacks have very limited speed |
+ // on some platforms. All values in |dst_size| must be a multiple of two. If |
+ // |use_mrt| is true, the pipeline will try to optimize the YUV conversion |
+ // using the multi-render-target extension. |use_mrt| should only be set to |
+ // false for testing. |
+ ReadbackYUVInterface* CreateReadbackPipelineYUV(ScalerQuality quality, |
+ const gfx::Size& src_size, |
+ const gfx::Rect& src_subrect, |
+ const gfx::Size& dst_size, |
+ bool flip_vertically, |
+ bool use_mrt); |
+ |
+ // Returns the maximum number of draw buffers available, |
+ // 0 if GL_EXT_draw_buffers is not available. |
+ GLint MaxDrawBuffers(); |
+ |
+ // Checks whether the readbback is supported for texture with the |
+ // matching config. This doesnt check for cross format readbacks. |
+ bool IsReadbackConfigSupported(SkColorType texture_format); |
+ |
+ protected: |
+ class CopyTextureToImpl; |
+ |
+ // Creates |copy_texture_to_impl_| if NULL. |
+ void InitCopyTextToImpl(); |
+ // Creates |scaler_impl_| if NULL. |
+ void InitScalerImpl(); |
+ |
+ enum ReadbackSwizzle { kSwizzleNone = 0, kSwizzleBGRA }; |
+ |
+ gpu::gles2::GLES2Interface* gl_; |
+ gpu::ContextSupport* context_support_; |
+ std::unique_ptr<CopyTextureToImpl> copy_texture_to_impl_; |
+ std::unique_ptr<GLHelperScaling> scaler_impl_; |
+ std::unique_ptr<GLHelperReadbackSupport> readback_support_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GLHelper); |
+}; |
+ |
+// Similar to a ScalerInterface, a yuv readback pipeline will |
+// cache a scaler and all intermediate textures and frame buffers |
+// needed to scale, crop, letterbox and read back a texture from |
+// the GPU into CPU-accessible RAM. A single readback pipeline |
+// can handle multiple outstanding readbacks at the same time, but |
+// if the source or destination sizes change, you'll need to create |
+// a new readback pipeline. |
+class CONTENT_EXPORT ReadbackYUVInterface { |
+ public: |
+ ReadbackYUVInterface() {} |
+ virtual ~ReadbackYUVInterface() {} |
+ |
+ // Note that |target| must use YV12 format. |paste_location| specifies where |
+ // the captured pixels that are read back will be placed in the video frame. |
+ // The region defined by the |paste_location| and the |dst_size| specified in |
+ // the call to CreateReadbackPipelineYUV() must be fully contained within |
+ // |target->visible_rect()|. |
+ virtual void ReadbackYUV(const gpu::Mailbox& mailbox, |
+ const gpu::SyncToken& sync_token, |
+ const gfx::Rect& target_visible_rect, |
+ int y_plane_row_stride_bytes, |
+ unsigned char* y_plane_data, |
+ int u_plane_row_stride_bytes, |
+ unsigned char* u_plane_data, |
+ int v_plane_row_stride_bytes, |
+ unsigned char* v_plane_data, |
+ const gfx::Point& paste_location, |
+ const base::Callback<void(bool)>& callback) = 0; |
+ virtual GLHelper::ScalerInterface* scaler() = 0; |
+}; |
+ |
+} // namespace content |
+ |
+#endif // CONTENT_BROWSER_COMPOSITOR_GL_HELPER_H_ |