⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameswf_render_handler_d3d.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// gameswf_render_handler_d3d.cpp  Paul Kelly & Bob Ives, 2006

// This source code has been donated to the Public Domain.  Do
// whatever you want with it.

// A gameswf::render_handler that uses DX8 or DX9.  
// Based on the xbox code by Thatcher Ulrich <http://tulrich.com> 2003


#include <windows.h>
#include <assert.h>
#include "gameswf.h"
#include "gameswf/gameswf_log.h"
#include "gameswf_types.h"
#include "base/image.h"
#include "base/container.h"

//#define _DX8

#if defined (_DX8)
# include <d3d8.h>
#else
# include <d3d9.h>
#endif

#if DIRECT3D_VERSION < 0x0900
# include <d3dx8tex.h>
# include <d3d8types.h>
  typedef IDirect3D8              IDirect3D;
  typedef IDirect3DDevice8        IDirect3DDevice;
  typedef IDirect3DTexture8       IDirect3DTexture;
  typedef IDirect3DBaseTexture8   IDirect3DBaseTexture;
  typedef IDirect3DSurface8       IDirect3DSurface;
  typedef IDirect3DVertexBuffer8  IDirect3DVertexBuffer;
  typedef D3DVIEWPORT8            D3DVIEWPORT;
  typedef BYTE                    tLock;
#else 
# include <d3dx9tex.h>
# include <d3d9types.h>
  typedef IDirect3D9              IDirect3D;
  typedef IDirect3DDevice9        IDirect3DDevice;
  typedef IDirect3DTexture9       IDirect3DTexture;
  typedef IDirect3DBaseTexture9   IDirect3DBaseTexture;
  typedef IDirect3DSurface9       IDirect3DSurface;
  typedef IDirect3DVertexBuffer9  IDirect3DVertexBuffer;
  typedef D3DVIEWPORT9            D3DVIEWPORT;
  typedef void                    tLock;
#endif

#include <string.h>

#define INIT_SIZE_VERTEX_BUFFER  128

#define Z_DEPTH 1.0f


// A structure for our custom vertex type. We added texture coordinates
struct CUSTOMVERTEX
{
  float x,y,z; // transformed position for the vertex
};

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ)

struct CUSTOMVERTEX2
{
  float x,y,z;    // position
  float tu, tv;   // texture coordinates
};

#define D3DFVF_CUSTOMVERTEX2 (D3DFVF_XYZ|D3DFVF_TEX1)


static inline float clamp( float x,float min,float max ) {
  union { float f; int hex; };
  f = x - min;
  hex &= ~hex>>31;
  f += min - max;
  hex &= hex>>31;
  f += max;
  return f;
}


// bitmap_info_d3d declaration
struct bitmap_info_d3d : public gameswf::bitmap_info
{
  bitmap_info_d3d();
  void convert_to_argb(image::rgba* im);
  bitmap_info_d3d(image::rgb* im);
  bitmap_info_d3d(image::rgba* im);
  bitmap_info_d3d(int width, int height, Uint8* data);
};


struct render_handler_d3d : public gameswf::render_handler
{
  // Some renderer state.

  gameswf::matrix m_current_matrix;
  gameswf::cxform m_current_cxform;

  IDirect3DVertexBuffer* m_pVB; // Buffer to hold vertices
  IDirect3DVertexBuffer* m_pVB2; // Buffer to hold vertices
  DWORD m_nMaxVertices;  // Max Vertices held in m_pVB
  D3DVIEWPORT m_origVP;

  static IDirect3DDevice* m_pd3dDevice; // Our rendering device
  static D3DFORMAT m_FormatRGB;
  static D3DFORMAT m_FormatRGBA;
  static D3DFORMAT m_FormatA;
  static D3DXMATRIX m_ModelViewMatrix;
  static D3DXMATRIX m_ProjMatrix;
  static array<IDirect3DBaseTexture*> m_d3d_textures;

  void set_antialiased(bool enable)
  {
    // not supported
  }

  static void make_next_miplevel(int* width, int* height, Uint8* data)
    // Utility.  Mutates *width, *height and *data to create the
    // next mip level.
  {
    assert(width);
    assert(height);
    assert(data);

    int new_w = *width >> 1;
    int new_h = *height >> 1;
    if (new_w < 1) new_w = 1;
    if (new_h < 1) new_h = 1;

    if (new_w * 2 != *width  || new_h * 2 != *height)
    {
      // Image can't be shrunk along (at least) one
      // of its dimensions, so don't bother
      // resampling.  Technically we should, but
      // it's pretty useless at this point.  Just
      // change the image dimensions and leave the
      // existing pixels.
    }
    else
    {
      // Resample.  Simple average 2x2 --> 1, in-place.
      for (int j = 0; j < new_h; j++) {
        Uint8*  out = ((Uint8*) data) + j * new_w;
        Uint8*  in = ((Uint8*) data) + (j << 1) * *width;
        for (int i = 0; i < new_w; i++) {
          int a;
          a = (*(in + 0) + *(in + 1) + *(in + 0 + *width) + *(in + 1 + *width));
          *(out) = (Uint8) (a >> 2);
          out++;
          in += 2;
        }
      }
    }

    // Munge parameters to reflect the shrunken image.
    *width = new_w;
    *height = new_h;
  }

  struct fill_style
  {
    enum mode
    {
      INVALID,
      COLOR,
      BITMAP_WRAP,
      BITMAP_CLAMP,
      LINEAR_GRADIENT,
      RADIAL_GRADIENT,
    };
    mode  m_mode;
    gameswf::rgba m_color;
    const gameswf::bitmap_info* m_bitmap_info;
    gameswf::matrix m_bitmap_matrix;
    gameswf::cxform m_bitmap_color_transform;
    bool  m_has_nonzero_bitmap_additive_color;

    fill_style()
      :
    m_mode(INVALID),
      m_has_nonzero_bitmap_additive_color(false)
    {
    }

    void  apply(const gameswf::matrix& current_matrix) const
      // Push our style into D3D.
    {
      assert(m_mode != INVALID);

      if (m_mode == COLOR)
      {
        apply_color(m_color);
        m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
        m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
      }
      else if (m_mode == BITMAP_WRAP
        || m_mode == BITMAP_CLAMP)
      {
        assert(m_bitmap_info != NULL);

        apply_color(m_color);

        if (m_bitmap_info == NULL)
        {
          assert(0);
          m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
          m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
        }
        else
        {

          // Set up the texture for rendering.

          // Do the modulate part of the color
          // transform in the first pass.  The
          // additive part, if any, needs to
          // happen in a second pass.

          m_pd3dDevice->SetTexture(0, m_d3d_textures[m_bitmap_info->m_texture_id]);
          m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
          m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );

          if (m_mode == BITMAP_CLAMP)
          {
#if DIRECT3D_VERSION >= 0x0900
            m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
            m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
#else
            m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); 
            m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
#endif
          }
          else
          {
            assert(m_mode == BITMAP_WRAP);
#if DIRECT3D_VERSION >= 0x0900
            m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
            m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
#else
            m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); 
            m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
#endif
          }

          // Set up the bitmap matrix for texgen.
          float inv_width = 1.0f / m_bitmap_info->m_original_width;
          float inv_height = 1.0f / m_bitmap_info->m_original_height;

          gameswf::matrix m = m_bitmap_matrix;
          gameswf::matrix m_cm_inv;
          m_cm_inv.set_inverse(current_matrix);
          m.concatenate(m_cm_inv);

          D3DXMATRIXA16 mat;
          D3DXMatrixIdentity(&mat);

          mat._11 = m.m_[0][0] * inv_width;             mat._12 = m.m_[1][0] * inv_height;  mat._13 = 0.00f; mat._14 = 0.00f;
          mat._21 = m.m_[0][1] * inv_width;             mat._22 = m.m_[1][1] * inv_height;  mat._23 = 0.00f; mat._24 = 0.00f;
          mat._31 = 0.00f;                              mat._32 = 0.00f;                    mat._33 = 0.00f; mat._34 = 0.00f;
          mat._41 = m.m_[0][2] * inv_width;             mat._42 = m.m_[1][2] * inv_height;  mat._43 = 0.00f; mat._44 = 1.00f;

          m_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat );
          m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
          m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
        }
      }
    }


    bool  needs_second_pass() const
      // Return true if we need to do a second pass to make
      // a valid color.  This is for cxforms with additive
      // parts.
    {
      if (m_mode == BITMAP_WRAP
        || m_mode == BITMAP_CLAMP)
      {
        return m_has_nonzero_bitmap_additive_color;
      }
      else
      {
        return false;
      }
    }

    void  apply_second_pass() const
      // Set D3D state for a necessary second pass.
    {
      assert(needs_second_pass());

      // Additive color.
      apply_color(gameswf::rgba(
        Uint8(m_bitmap_color_transform.m_[0][1]), 
        Uint8(m_bitmap_color_transform.m_[1][1]), 
        Uint8(m_bitmap_color_transform.m_[2][1]), 
        Uint8(m_bitmap_color_transform.m_[3][1])));

      m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
      m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);

      m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE );
      m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE );
    }

    void  cleanup_second_pass() const
    {
      m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
      m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
    }


    void  disable() { m_mode = INVALID; }
    void  set_color(gameswf::rgba color) 
    { 
      m_mode = COLOR; 
      m_color = color; 
    }
    void  set_bitmap(const gameswf::bitmap_info* bi, const gameswf::matrix& m, bitmap_wrap_mode wm, const gameswf::cxform& color_transform)
    {
      m_mode = (wm == WRAP_REPEAT) ? BITMAP_WRAP : BITMAP_CLAMP;
      m_bitmap_info = bi;
      m_bitmap_matrix = m;

      m_bitmap_color_transform.m_[0][0] = clamp(color_transform.m_[0][0], 0, 1);
      m_bitmap_color_transform.m_[1][0] = clamp(color_transform.m_[1][0], 0, 1);
      m_bitmap_color_transform.m_[2][0] = clamp(color_transform.m_[2][0], 0, 1);
      m_bitmap_color_transform.m_[3][0] = clamp(color_transform.m_[3][0], 0, 1);

      m_bitmap_color_transform.m_[0][1] = clamp(color_transform.m_[0][1], -255.0f, 255.0f);
      m_bitmap_color_transform.m_[1][1] = clamp(color_transform.m_[1][1], -255.0f, 255.0f);
      m_bitmap_color_transform.m_[2][1] = clamp(color_transform.m_[2][1], -255.0f, 255.0f);
      m_bitmap_color_transform.m_[3][1] = clamp(color_transform.m_[3][1], -255.0f, 255.0f);
      
      m_color = gameswf::rgba(
        Uint8(m_bitmap_color_transform.m_[0][0]*255.0f), 
        Uint8(m_bitmap_color_transform.m_[1][0]*255.0f), 
        Uint8(m_bitmap_color_transform.m_[2][0]*255.0f), 
        Uint8(m_bitmap_color_transform.m_[3][0]*255.0f));

      if (m_bitmap_color_transform.m_[0][1] > 1.0f
        || m_bitmap_color_transform.m_[1][1] > 1.0f
        || m_bitmap_color_transform.m_[2][1] > 1.0f
        || m_bitmap_color_transform.m_[3][1] > 1.0f)
      {
        m_has_nonzero_bitmap_additive_color = true;
      }
      else
      {
        m_has_nonzero_bitmap_additive_color = false;
      }
    }
    bool  is_valid() const { return m_mode != INVALID; }
  };

  // Constructor.
  render_handler_d3d(IDirect3DDevice* device)
    : m_pVB(NULL)
    , m_pVB2(NULL)
    , m_nMaxVertices(INIT_SIZE_VERTEX_BUFFER)
  {
    HRESULT hr;

    m_pd3dDevice = device;
    m_pd3dDevice->AddRef();

    hr = m_pd3dDevice->CreateVertexBuffer( m_nMaxVertices*sizeof(CUSTOMVERTEX)
      , D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB
#if DIRECT3D_VERSION >= 0x0900
      , NULL 
#endif
      );
    assert(hr==S_OK);

    hr = m_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX2)
      , D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_CUSTOMVERTEX2, D3DPOOL_DEFAULT, &m_pVB2
#if DIRECT3D_VERSION >= 0x0900
      , NULL 
#endif
      );
    assert(hr==S_OK);

    // Determine texture formats
    IDirect3D* l_pD3D;
    hr = m_pd3dDevice->GetDirect3D( &l_pD3D );
    assert(hr==S_OK);

#if DIRECT3D_VERSION < 0x0900
    D3DCAPS8 l_DeviceCaps;
#else
    D3DCAPS9 l_DeviceCaps;
#endif
    ZeroMemory( &l_DeviceCaps, sizeof(l_DeviceCaps) );  
    hr = m_pd3dDevice->GetDeviceCaps( &l_DeviceCaps );
    assert(hr==S_OK);

    D3DDISPLAYMODE l_DisplayMode;
    hr = m_pd3dDevice->GetDisplayMode( 
#if DIRECT3D_VERSION >= 0x0900
      0, 
#endif
      &l_DisplayMode );

    if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1))) 
      m_FormatRGB = D3DFMT_DXT1;
    else if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_R8G8B8))) 
      m_FormatRGB = D3DFMT_R8G8B8;
    else       
      m_FormatRGB = D3DFMT_A8R8G8B8;

      if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5))) 
        m_FormatRGBA = D3DFMT_DXT5;
      else
        m_FormatRGBA  = D3DFMT_A8R8G8B8;

    if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8))) 
      m_FormatA = D3DFMT_A8;
    else if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8))) 
      m_FormatA = D3DFMT_A8L8;
    else if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8P8))) 
      m_FormatA = D3DFMT_A8P8;
    else 
      m_FormatA = D3DFMT_A8R8G8B8;

  }

  ~render_handler_d3d()
    // Destructor.
  {
    for (int i = 0; i < m_d3d_textures.size(); i++)
    {
      if( m_d3d_textures[i] )
      {
        m_d3d_textures[i]->Release();
        m_d3d_textures[i] = 0;
      }
    }


    if (m_pVB)
    {
      m_pVB->Release();
      m_pVB = 0;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -