gl_helper.h revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
153131982d6290e3a865f400174778deaac452ff3Daniel Dunbar// Copyright (c) 2012 The Chromium Authors. All rights reserved.
253131982d6290e3a865f400174778deaac452ff3Daniel Dunbar// Use of this source code is governed by a BSD-style license that can be
353131982d6290e3a865f400174778deaac452ff3Daniel Dunbar// found in the LICENSE file.
453131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
553131982d6290e3a865f400174778deaac452ff3Daniel Dunbar#ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
653131982d6290e3a865f400174778deaac452ff3Daniel Dunbar#define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
753131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
853131982d6290e3a865f400174778deaac452ff3Daniel Dunbar#include "base/atomicops.h"
953131982d6290e3a865f400174778deaac452ff3Daniel Dunbar#include "base/basictypes.h"
10674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#include "base/callback.h"
11674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#include "base/memory/scoped_ptr.h"
1253131982d6290e3a865f400174778deaac452ff3Daniel Dunbar#include "content/common/content_export.h"
131edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
14255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth
1553131982d6290e3a865f400174778deaac452ff3Daniel Dunbarnamespace gfx {
1653131982d6290e3a865f400174778deaac452ff3Daniel Dunbarclass Rect;
1753131982d6290e3a865f400174778deaac452ff3Daniel Dunbarclass Size;
18f21e4e9326aa3ebc78bc2770722fb5150fe7ede9Daniel Dunbar}
1953131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
2053131982d6290e3a865f400174778deaac452ff3Daniel Dunbarclass SkRegion;
2153131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
2253131982d6290e3a865f400174778deaac452ff3Daniel Dunbarnamespace content {
2353131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
241f7210e808373fa92be3a2d4fa653a6f79d5088bCraig Topperclass GLHelperScaling;
251f7210e808373fa92be3a2d4fa653a6f79d5088bCraig Topper
2653131982d6290e3a865f400174778deaac452ff3Daniel Dunbarclass ScopedWebGLId {
2753131982d6290e3a865f400174778deaac452ff3Daniel Dunbar public:
2853131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  typedef void (WebKit::WebGraphicsContext3D::*DeleteFunc)(WebGLId);
2953131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  ScopedWebGLId(WebKit::WebGraphicsContext3D* context,
3053131982d6290e3a865f400174778deaac452ff3Daniel Dunbar                WebGLId id,
3153131982d6290e3a865f400174778deaac452ff3Daniel Dunbar                DeleteFunc delete_func)
321edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar      : context_(context),
331edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar        id_(id),
341edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar        delete_func_(delete_func) {
351edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar  }
361edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar
371edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar  operator WebGLId() const {
381edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar    return id_;
391edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar  }
401edf6ca2cbb4b01db44683d5e9479a240cfcf497Daniel Dunbar
4193c65e6e661eda75711363bdd5ca15909920e1f0Joerg Sonnenberger  WebGLId id() const { return id_; }
4293c65e6e661eda75711363bdd5ca15909920e1f0Joerg Sonnenberger
4353131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  WebGLId Detach() {
4453131982d6290e3a865f400174778deaac452ff3Daniel Dunbar    WebGLId id = id_;
4553131982d6290e3a865f400174778deaac452ff3Daniel Dunbar    id_ = 0;
46c5252da873d547a19069eaf9030fec203f128f66Dmitri Gribenko    return id;
47c5252da873d547a19069eaf9030fec203f128f66Dmitri Gribenko  }
4853131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
4953131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  ~ScopedWebGLId() {
5053131982d6290e3a865f400174778deaac452ff3Daniel Dunbar    if (id_ != 0) {
5153131982d6290e3a865f400174778deaac452ff3Daniel Dunbar      (context_->*delete_func_)(id_);
5253131982d6290e3a865f400174778deaac452ff3Daniel Dunbar    }
5353131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  }
5453131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
5553131982d6290e3a865f400174778deaac452ff3Daniel Dunbar private:
5653131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  WebKit::WebGraphicsContext3D* context_;
574e82bbb745160f19d76b9b5de5b93ebe224e1acfDaniel Dunbar  WebGLId id_;
5853131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  DeleteFunc delete_func_;
59f8cd708f14a7a172d51899b68809510ae0c4c4c8Joerg Sonnenberger
6053131982d6290e3a865f400174778deaac452ff3Daniel Dunbar  DISALLOW_COPY_AND_ASSIGN(ScopedWebGLId);
6153131982d6290e3a865f400174778deaac452ff3Daniel Dunbar};
6253131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
6353131982d6290e3a865f400174778deaac452ff3Daniel Dunbarclass ScopedBuffer : public ScopedWebGLId {
6453131982d6290e3a865f400174778deaac452ff3Daniel Dunbar public:
65f21e4e9326aa3ebc78bc2770722fb5150fe7ede9Daniel Dunbar  ScopedBuffer(WebKit::WebGraphicsContext3D* context,
66f21e4e9326aa3ebc78bc2770722fb5150fe7ede9Daniel Dunbar               WebGLId id)
67f21e4e9326aa3ebc78bc2770722fb5150fe7ede9Daniel Dunbar      : ScopedWebGLId(context,
6853131982d6290e3a865f400174778deaac452ff3Daniel Dunbar                      id,
6953131982d6290e3a865f400174778deaac452ff3Daniel Dunbar                      &WebKit::WebGraphicsContext3D::deleteBuffer) {}
7053131982d6290e3a865f400174778deaac452ff3Daniel Dunbar};
7153131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
7253131982d6290e3a865f400174778deaac452ff3Daniel Dunbarclass ScopedFramebuffer : public ScopedWebGLId {
7393c65e6e661eda75711363bdd5ca15909920e1f0Joerg Sonnenberger public:
7493c65e6e661eda75711363bdd5ca15909920e1f0Joerg Sonnenberger  ScopedFramebuffer(WebKit::WebGraphicsContext3D* context,
7553131982d6290e3a865f400174778deaac452ff3Daniel Dunbar                    WebGLId id)
7653131982d6290e3a865f400174778deaac452ff3Daniel Dunbar      : ScopedWebGLId(context,
7753131982d6290e3a865f400174778deaac452ff3Daniel Dunbar                      id,
7853131982d6290e3a865f400174778deaac452ff3Daniel Dunbar                      &WebKit::WebGraphicsContext3D::deleteFramebuffer) {}
7953131982d6290e3a865f400174778deaac452ff3Daniel Dunbar};
8053131982d6290e3a865f400174778deaac452ff3Daniel Dunbar
81class ScopedProgram : public ScopedWebGLId {
82 public:
83  ScopedProgram(WebKit::WebGraphicsContext3D* context,
84                WebGLId id)
85      : ScopedWebGLId(context,
86                      id,
87                      &WebKit::WebGraphicsContext3D::deleteProgram) {}
88};
89
90class ScopedShader : public ScopedWebGLId {
91 public:
92  ScopedShader(WebKit::WebGraphicsContext3D* context,
93               WebGLId id)
94      : ScopedWebGLId(context,
95                      id,
96                      &WebKit::WebGraphicsContext3D::deleteShader) {}
97};
98
99class ScopedTexture : public ScopedWebGLId {
100 public:
101  ScopedTexture(WebKit::WebGraphicsContext3D* context,
102                WebGLId id)
103      : ScopedWebGLId(context,
104                      id,
105                      &WebKit::WebGraphicsContext3D::deleteTexture) {}
106};
107
108template <WebKit::WGC3Denum target>
109class ScopedBinder {
110 public:
111  typedef void (WebKit::WebGraphicsContext3D::*BindFunc)(WebKit::WGC3Denum,
112                                                         WebGLId);
113  ScopedBinder(WebKit::WebGraphicsContext3D* context,
114               WebGLId id,
115               BindFunc bind_func)
116      : context_(context),
117        bind_func_(bind_func) {
118    (context_->*bind_func_)(target, id);
119  }
120
121  virtual ~ScopedBinder() {
122    (context_->*bind_func_)(target, 0);
123  }
124
125 private:
126  WebKit::WebGraphicsContext3D* context_;
127  BindFunc bind_func_;
128
129  DISALLOW_COPY_AND_ASSIGN(ScopedBinder);
130};
131
132template <WebKit::WGC3Denum target>
133class ScopedBufferBinder : ScopedBinder<target> {
134 public:
135  ScopedBufferBinder(WebKit::WebGraphicsContext3D* context,
136                     WebGLId id)
137      : ScopedBinder<target>(
138          context,
139          id,
140          &WebKit::WebGraphicsContext3D::bindBuffer) {}
141};
142
143template <WebKit::WGC3Denum target>
144class ScopedFramebufferBinder : ScopedBinder<target> {
145 public:
146  ScopedFramebufferBinder(WebKit::WebGraphicsContext3D* context,
147                          WebGLId id)
148      : ScopedBinder<target>(
149          context,
150          id,
151          &WebKit::WebGraphicsContext3D::bindFramebuffer) {}
152};
153
154template <WebKit::WGC3Denum target>
155class ScopedTextureBinder : ScopedBinder<target> {
156 public:
157  ScopedTextureBinder(WebKit::WebGraphicsContext3D* context,
158                      WebGLId id)
159      : ScopedBinder<target>(
160          context,
161          id,
162          &WebKit::WebGraphicsContext3D::bindTexture) {}
163};
164
165class ScopedFlush {
166 public:
167  explicit ScopedFlush(WebKit::WebGraphicsContext3D* context)
168      : context_(context) {
169  }
170
171  ~ScopedFlush() {
172    context_->flush();
173  }
174
175 private:
176  WebKit::WebGraphicsContext3D* context_;
177
178  DISALLOW_COPY_AND_ASSIGN(ScopedFlush);
179};
180
181// Provides higher level operations on top of the WebKit::WebGraphicsContext3D
182// interfaces.
183class CONTENT_EXPORT GLHelper {
184 public:
185  explicit GLHelper(WebKit::WebGraphicsContext3D* context);
186  ~GLHelper();
187
188  enum ScalerQuality {
189    // Bilinear single pass, fastest possible.
190    SCALER_QUALITY_FAST = 1,
191
192    // Bilinear upscale + N * 50% bilinear downscales.
193    // This is still fast enough for most purposes and
194    // Image quality is nearly as good as the BEST option.
195    SCALER_QUALITY_GOOD = 2,
196
197    // Bicubic upscale + N * 50% bicubic downscales.
198    // Produces very good quality scaled images, but it's
199    // 2-8x slower than the "GOOD" quality, so it's not always
200    // worth it.
201    SCALER_QUALITY_BEST = 3,
202  };
203
204
205  // Copies the block of pixels specified with |src_subrect| from |src_texture|,
206  // scales it to |dst_size|, and writes it into |out|.
207  // |src_size| is the size of |src_texture|. The result is of format GL_BGRA
208  // and is potentially flipped vertically to make it a correct image
209  // representation.  |callback| is invoked with the copy result when the copy
210  // operation has completed.
211  // Note that the src_texture will have the min/mag filter set to GL_LINEAR
212  // and wrap_s/t set to CLAMP_TO_EDGE in this call.
213  void CropScaleReadbackAndCleanTexture(
214      WebKit::WebGLId src_texture,
215      const gfx::Size& src_size,
216      const gfx::Rect& src_subrect,
217      const gfx::Size& dst_size,
218      unsigned char* out,
219      const base::Callback<void(bool)>& callback);
220
221  // Copies the texture data out of |texture| into |out|.  |size| is the
222  // size of the texture.  No post processing is applied to the pixels.  The
223  // texture is assumed to have a format of GL_RGBA with a pixel type of
224  // GL_UNSIGNED_BYTE.  This is a blocking call that calls glReadPixels on this
225  // current context.
226  void ReadbackTextureSync(WebKit::WebGLId texture,
227                           const gfx::Rect& src_rect,
228                           unsigned char* out);
229
230  // Creates a copy of the specified texture. |size| is the size of the texture.
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  WebKit::WebGLId CopyTexture(WebKit::WebGLId texture,
234                              const gfx::Size& size);
235
236  // Creates a scaled copy of the specified texture. |src_size| is the size of
237  // the texture and |dst_size| is the size of the resulting copy.
238  // Note that the src_texture will have the min/mag filter set to GL_LINEAR
239  // and wrap_s/t set to CLAMP_TO_EDGE in this call.
240  WebKit::WebGLId CopyAndScaleTexture(
241      WebKit::WebGLId texture,
242      const gfx::Size& src_size,
243      const gfx::Size& dst_size,
244      bool vertically_flip_texture,
245      ScalerQuality quality);
246
247  // Returns the shader compiled from the source.
248  WebKit::WebGLId CompileShaderFromSource(const WebKit::WGC3Dchar* source,
249                                          WebKit::WGC3Denum type);
250
251  // Copies all pixels from |previous_texture| into |texture| that are
252  // inside the region covered by |old_damage| but not part of |new_damage|.
253  void CopySubBufferDamage(WebKit::WebGLId texture,
254                           WebKit::WebGLId previous_texture,
255                           const SkRegion& new_damage,
256                           const SkRegion& old_damage);
257
258  // A scaler will cache all intermediate textures and programs
259  // needed to scale from a specified size to a destination size.
260  // If the source or destination sizes changes, you must create
261  // a new scaler.
262  class CONTENT_EXPORT ScalerInterface {
263   public:
264    ScalerInterface() {}
265    virtual ~ScalerInterface() {}
266
267    // Note that the src_texture will have the min/mag filter set to GL_LINEAR
268    // and wrap_s/t set to CLAMP_TO_EDGE in this call.
269    virtual void Scale(WebKit::WebGLId source_texture,
270                       WebKit::WebGLId dest_texture) = 0;
271    virtual const gfx::Size& SrcSize() = 0;
272    virtual const gfx::Rect& SrcSubrect() = 0;
273    virtual const gfx::Size& DstSize() = 0;
274  };
275
276  // Note that the quality may be adjusted down if texture
277  // allocations fail or hardware doesn't support the requtested
278  // quality. Note that ScalerQuality enum is arranged in
279  // numerical order for simplicity.
280  ScalerInterface* CreateScaler(ScalerQuality quality,
281                                const gfx::Size& src_size,
282                                const gfx::Rect& src_subrect,
283                                const gfx::Size& dst_size,
284                                bool vertically_flip_texture,
285                                bool swizzle);
286
287 protected:
288  class CopyTextureToImpl;
289
290  // Creates |copy_texture_to_impl_| if NULL.
291  void InitCopyTextToImpl();
292  // Creates |scaler_impl_| if NULL.
293  void InitScalerImpl();
294
295  WebKit::WebGraphicsContext3D* context_;
296  scoped_ptr<CopyTextureToImpl> copy_texture_to_impl_;
297  scoped_ptr<GLHelperScaling> scaler_impl_;
298
299  DISALLOW_COPY_AND_ASSIGN(GLHelper);
300};
301
302}  // namespace content
303
304#endif  // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
305