Home | History | Annotate | Download | only in surface
      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 UI_SURFACE_ACCELERATED_SURFACE_TRANSFORMER_WIN_H_
      6 #define UI_SURFACE_ACCELERATED_SURFACE_TRANSFORMER_WIN_H_
      7 
      8 #include <d3d9.h>
      9 
     10 #include "base/gtest_prod_util.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/single_thread_task_runner.h"
     13 #include "base/synchronization/lock.h"
     14 #include "base/synchronization/waitable_event.h"
     15 #include "base/win/scoped_comptr.h"
     16 #include "ui/gfx/native_widget_types.h"
     17 #include "ui/gfx/size.h"
     18 #include "ui/surface/surface_export.h"
     19 
     20 namespace gfx {
     21 class Size;
     22 class Rect;
     23 }  // namespace gfx
     24 
     25 // Provides useful image filtering operations that are implemented
     26 // efficiently on DirectX9-class hardware using fragment programs.
     27 class SURFACE_EXPORT AcceleratedSurfaceTransformer {
     28  public:
     29   // Constructs an uninitialized surface transformer. Call Init() before
     30   // using the resulting object.
     31   AcceleratedSurfaceTransformer();
     32 
     33   // Init() initializes the transformer to operate on a device. This must be
     34   // called before any other method of this class, and it must be called
     35   // again after ReleaseAll() or DetachAll() before the class is used.
     36   //
     37   // Returns true if successful.
     38   bool Init(IDirect3DDevice9* device);
     39 
     40   // ReleaseAll() releases all direct3d resource references.
     41   void ReleaseAll();
     42 
     43   // DetachAll() leaks all direct3d resource references. This exists in order to
     44   // work around particular driver bugs, and should only be called at shutdown.
     45   // TODO(ncarter): Update the leak expectations before checkin.
     46   void DetachAll();
     47 
     48   // Draw a textured quad to a surface, flipping orientation in the y direction.
     49   bool CopyInverted(
     50       IDirect3DTexture9* src_texture,
     51       IDirect3DSurface9* dst_surface,
     52       const gfx::Size& dst_size);
     53 
     54   // Draw a textured quad to a surface.
     55   bool Copy(
     56       IDirect3DTexture9* src_texture,
     57       IDirect3DSurface9* dst_surface,
     58       const gfx::Size& dst_size);
     59 
     60   // Get an intermediate buffer of a particular |size|, that can be used as the
     61   // output of one transformation and the to another. The returned surface
     62   // belongs to an internal cache, and is invalidated by a subsequent call to
     63   // this method.
     64   bool GetIntermediateTexture(
     65       const gfx::Size& size,
     66       IDirect3DTexture9** texture,
     67       IDirect3DSurface9** texture_level_zero);
     68 
     69   // Resize a surface using repeated bilinear interpolation.
     70   bool ResizeBilinear(
     71     IDirect3DSurface9* src_surface,
     72     const gfx::Rect& src_subrect,
     73     IDirect3DSurface9* dst_surface,
     74     const gfx::Rect& dst_subrect);
     75 
     76   // Color format conversion from RGB to planar YV12 (also known as YUV420).
     77   //
     78   // YV12 is effectively a twelve bit per pixel format consisting of a full-
     79   // size y (luminance) plane and half-width, half-height u and v (blue and
     80   // red chrominance) planes. This method will allocate three lockable surfaces,
     81   // one for each plane, and return them via the arguments |dst_y|, |dst_u|,
     82   // and |dst_v|. These surface will be created with an ARGB D3DFORMAT, but
     83   // should be interpreted as the appropriate single-byte format when locking.
     84   //
     85   // The dimensions of the outputs (when interpreted as single-component data)
     86   // are as follows:
     87   //   |dst_y| : width and height exactly |dst_size|
     88   //   |dst_u| : width and height are each half of |dst_size|, rounded up.
     89   //   |dst_v| : width and height are each half of |dst_size|, rounded up.
     90   //
     91   // If |src_texture|'s dimensions do not match |dst_size|, the source will be
     92   // bilinearly interpolated during conversion.
     93   //
     94   // Returns true if successful. Caller must be certain to release the surfaces
     95   // even if this function returns false. The returned surfaces belong to an
     96   // internal cache, and are invalidated by a subsequent call to this method.
     97   bool TransformRGBToYV12(
     98       IDirect3DTexture9* src_texture,
     99       const gfx::Size& dst_size,
    100       IDirect3DSurface9** dst_y,
    101       IDirect3DSurface9** dst_u,
    102       IDirect3DSurface9** dst_v);
    103 
    104   // Synchronously copy from a D3D surface into a caller-allocated buffer. This
    105   // will dispatch to one of a couple techniques, depending on which is
    106   // determined to be the faster method for the current device.
    107   bool ReadFast(IDirect3DSurface9* gpu_surface,
    108                 uint8* dst,
    109                 int dst_bytes_per_row,
    110                 int dst_num_rows,
    111                 int dst_stride);
    112 
    113   // Do a read using a particular technique. Which of these is faster depends on
    114   // the hardware. Intended for testing; production code ought to call
    115   // ReadFast().
    116   bool ReadByLockAndCopy(IDirect3DSurface9* gpu_surface,
    117                          uint8* dst,
    118                          int dst_bytes_per_row,
    119                          int dst_num_rows,
    120                          int dst_stride);
    121   bool ReadByGetRenderTargetData(IDirect3DSurface9* gpu_surface,
    122                                  uint8* dst,
    123                                  int dst_bytes_per_row,
    124                                  int dst_num_rows,
    125                                  int dst_stride);
    126 
    127  private:
    128   friend class AcceleratedSurfaceTransformerTest;
    129   FRIEND_TEST_ALL_PREFIXES(AcceleratedSurfaceTransformerTest, Init);
    130 
    131   enum ShaderCombo {
    132     ONE_TEXTURE,
    133     RGB_TO_YV12_FAST__PASS_1_OF_2,
    134     RGB_TO_YV12_FAST__PASS_2_OF_2,
    135     RGB_TO_YV12_SLOW__PASS_1_OF_3,
    136     RGB_TO_YV12_SLOW__PASS_2_OF_3,
    137     RGB_TO_YV12_SLOW__PASS_3_OF_3,
    138     NUM_SHADERS
    139   };
    140 
    141   // Efficient RGB->YV12 in two passes, but requires a device capable of writing
    142   // multiple render targets at the same time.
    143   //
    144   // Returns true if successful.
    145   bool TransformRGBToYV12_MRT(
    146       IDirect3DTexture9* src_surface,
    147       const gfx::Size& dst_size,
    148       const gfx::Size& packed_y_size,
    149       const gfx::Size& packed_uv_size,
    150       IDirect3DSurface9* dst_y,
    151       IDirect3DSurface9* dst_u,
    152       IDirect3DSurface9* dst_v);
    153 
    154   // Slower, less efficient RGB->YV12; does not require the device to have
    155   // multiple render target capability. Runs at about half speed of the fast
    156   // path.
    157   //
    158   // Returns true if successful.
    159   bool TransformRGBToYV12_WithoutMRT(
    160       IDirect3DTexture9* src_surface,
    161       const gfx::Size& dst_size,
    162       const gfx::Size& packed_y_size,
    163       const gfx::Size& packed_uv_size,
    164       IDirect3DSurface9* dst_y,
    165       IDirect3DSurface9* dst_u,
    166       IDirect3DSurface9* dst_v);
    167 
    168   // Helper to allocate appropriately size YUV buffers, accounting for various
    169   // roundings. The sizes of the buffers (in terms of ARGB pixels) are returned
    170   // as |packed_y_size| and |packed_uv_size|.
    171   //
    172   // Returns true if successful. Caller must be certain to release the surfaces
    173   // even if this function returns false. The returned belong to an internal
    174   // cache.
    175   bool AllocYUVBuffers(
    176       const gfx::Size& dst_size,
    177       gfx::Size* packed_y_size,
    178       gfx::Size* packed_uv_size,
    179       IDirect3DSurface9** dst_y,
    180       IDirect3DSurface9** dst_u,
    181       IDirect3DSurface9** dst_v);
    182 
    183   bool CopyWithTextureScale(
    184       IDirect3DTexture9* src_texture,
    185       IDirect3DSurface9* dst_surface,
    186       const gfx::Size& dst_size,
    187       float texture_scale_x,
    188       float texture_scale_y);
    189 
    190   // Set the active vertex and pixel shader combination.
    191   //
    192   // Returns true if successful.
    193   bool SetShaderCombo(ShaderCombo combo);
    194 
    195   // Compiles a vertex and pixel shader combination, if not already compiled.
    196   //
    197   // Returns true if successful.
    198   bool CompileShaderCombo(ShaderCombo shader_combo_name);
    199 
    200   bool DoInit(IDirect3DDevice9* device);
    201 
    202   void DrawScreenAlignedQuad(const gfx::Size& dst_size);
    203 
    204   bool device_supports_multiple_render_targets() const {
    205     return device_supports_multiple_render_targets_;
    206   }
    207 
    208   IDirect3DDevice9* device();
    209 
    210   base::win::ScopedComPtr<IDirect3DDevice9> device_;
    211   base::win::ScopedComPtr<IDirect3DVertexShader9> vertex_shaders_[NUM_SHADERS];
    212   base::win::ScopedComPtr<IDirect3DPixelShader9> pixel_shaders_[NUM_SHADERS];
    213 
    214   // Temporary and scratch surfaces; cached to avoid frequent reallocation.
    215   base::win::ScopedComPtr<IDirect3DTexture9> user_scratch_texture_;
    216   base::win::ScopedComPtr<IDirect3DTexture9> uv_scratch_texture_;
    217   base::win::ScopedComPtr<IDirect3DSurface9> y_scratch_surface_;
    218   base::win::ScopedComPtr<IDirect3DSurface9> u_scratch_surface_;
    219   base::win::ScopedComPtr<IDirect3DSurface9> v_scratch_surface_;
    220   base::win::ScopedComPtr<IDirect3DSurface9> scaler_scratch_surfaces_[2];
    221 
    222   bool device_supports_multiple_render_targets_;
    223   const BYTE* vertex_shader_sources_[NUM_SHADERS];
    224   const BYTE* pixel_shader_sources_[NUM_SHADERS];
    225   DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceTransformer);
    226 };
    227 
    228 #endif  // UI_SURFACE_ACCELERATED_SURFACE_TRANSFORMER_WIN_H_
    229