[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48425] trunk/blender/source: Finally committing support for compressed textures on the GPU (DDS+DXT).

Daniel Salazar - 3Developer.com zanqdo at gmail.com
Sat Jun 30 22:26:41 CEST 2012


This is awesome, does this help cycles too?

Daniel Salazar
patazstudio.com


On Fri, Jun 29, 2012 at 10:34 PM, Mitchell Stokes <mogurijin at gmail.com>wrote:

> Revision: 48425
>
> http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48425
> Author:   moguri
> Date:     2012-06-30 04:34:34 +0000 (Sat, 30 Jun 2012)
> Log Message:
> -----------
> Finally committing support for compressed textures on the GPU (DDS+DXT).
> This patch started out as a patch by me, then cleaned up by Kupoman during
> his work on Cucumber.
>
> One important thing to keep in mind when using this feature is that you'll
> need to flip your textures vertically (both the GIMP and Photoshop DDS
> tools I've seen have support for this on export). This is a quirk in using
> a texture format originally made for DirectX/DirectDraw, and flipping the
> compressed data is a real headache. Another quick fix for this issue is to
> change the Y value for the Size in the Mapping panel in the Texture
> properties to -1 (default is 1).
>
> Modified Paths:
> --------------
>     trunk/blender/source/blender/gpu/CMakeLists.txt
>     trunk/blender/source/blender/gpu/GPU_draw.h
>     trunk/blender/source/blender/gpu/SConscript
>     trunk/blender/source/blender/gpu/intern/gpu_draw.c
>     trunk/blender/source/blender/imbuf/IMB_imbuf_types.h
>     trunk/blender/source/blender/imbuf/intern/allocimbuf.c
>     trunk/blender/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
>     trunk/blender/source/blender/imbuf/intern/dds/DirectDrawSurface.h
>     trunk/blender/source/blender/imbuf/intern/dds/dds_api.cpp
>     trunk/blender/source/gameengine/Ketsji/BL_Texture.cpp
>     trunk/blender/source/gameengine/Ketsji/BL_Texture.h
>     trunk/blender/source/gameengine/Ketsji/CMakeLists.txt
>
> Modified: trunk/blender/source/blender/gpu/CMakeLists.txt
> ===================================================================
> --- trunk/blender/source/blender/gpu/CMakeLists.txt     2012-06-30
> 04:29:16 UTC (rev 48424)
> +++ trunk/blender/source/blender/gpu/CMakeLists.txt     2012-06-30
> 04:34:34 UTC (rev 48425)
> @@ -71,5 +71,10 @@
>
>  add_definitions(-DGLEW_STATIC)
>
> +if(WITH_IMAGE_DDS)
> +       add_definitions(-DWITH_DDS)
> +endif()
> +
> +
>  blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}")
>
>
> Modified: trunk/blender/source/blender/gpu/GPU_draw.h
> ===================================================================
> --- trunk/blender/source/blender/gpu/GPU_draw.h 2012-06-30 04:29:16 UTC
> (rev 48424)
> +++ trunk/blender/source/blender/gpu/GPU_draw.h 2012-06-30 04:34:34 UTC
> (rev 48425)
> @@ -122,6 +122,9 @@
>  void GPU_update_images_framechange(void);
>  int GPU_update_image_time(struct Image *ima, double time);
>  int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int
> tftile, int compare, int mipmap);
> +void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float
> *frect, int rectw, int recth, int mipmap, int use_hight_bit_depth, struct
> Image *ima);
> +void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix,
> int x, int y, int mipmap, struct Image *ima, struct ImBuf *ibuf);
> +int GPU_upload_dxt_texture(struct ImBuf *ibuf);
>  void GPU_free_image(struct Image *ima);
>  void GPU_free_images(void);
>  void GPU_free_images_anim(void);
>
> Modified: trunk/blender/source/blender/gpu/SConscript
> ===================================================================
> --- trunk/blender/source/blender/gpu/SConscript 2012-06-30 04:29:16 UTC
> (rev 48424)
> +++ trunk/blender/source/blender/gpu/SConscript 2012-06-30 04:34:34 UTC
> (rev 48425)
> @@ -17,4 +17,7 @@
>  if env['WITH_BF_SMOKE']:
>      defs.append('WITH_SMOKE')
>
> +if env['WITH_BF_DDS']:
> +       defs.append('WITH_DDS')
> +
>  env.BlenderLib ( 'bf_gpu', sources, Split(incs), defines = defs,
> libtype=['core','player'], priority=[160,110] )
>
> Modified: trunk/blender/source/blender/gpu/intern/gpu_draw.c
> ===================================================================
> --- trunk/blender/source/blender/gpu/intern/gpu_draw.c  2012-06-30
> 04:29:16 UTC (rev 48424)
> +++ trunk/blender/source/blender/gpu/intern/gpu_draw.c  2012-06-30
> 04:34:34 UTC (rev 48425)
> @@ -427,8 +427,8 @@
>         ImBuf *ibuf = NULL;
>         unsigned int *bind = NULL;
>         int rectw, recth, tpx=0, tpy=0, y;
> -       unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL;
> -       float *ftilerect= NULL, *fscalerect = NULL, *frect = NULL;
> +       unsigned int *tilerect= NULL, *rect= NULL;
> +       float *ftilerect= NULL, *frect = NULL;
>         float *srgb_frect = NULL;
>         short texwindx, texwindy, texwinsx, texwinsy;
>         /* flag to determine whether high resolution format is used */
> @@ -611,7 +611,32 @@
>                         rect= tilerect;
>                 }
>         }
> +#ifdef WITH_DDS
> +       if (ibuf->ftype & DDS)
> +               GPU_create_gl_tex_compressed(bind, rect, rectw, recth,
> mipmap, ima, ibuf);
> +       else
> +#endif
> +               GPU_create_gl_tex(bind, rect, frect, rectw, recth, mipmap,
> use_high_bit_depth, ima);
>
> +       /* clean up */
> +       if (tilerect)
> +               MEM_freeN(tilerect);
> +       if (ftilerect)
> +               MEM_freeN(ftilerect);
> +       if (srgb_frect)
> +               MEM_freeN(srgb_frect);
> +
> +       return *bind;
> +}
> +
> +void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *
> frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima)
> +{
> +       unsigned int *scalerect = NULL;
> +    float *fscalerect = NULL;
> +
> +    int tpx = rectw;
> +    int tpy = recth;
> +
>         /* scale if not a power of two. this is not strictly necessary for
> newer
>          * GPUs (OpenGL version >= 2.0) since they support
> non-power-of-two-textures */
>         if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) {
> @@ -626,9 +651,9 @@
>                 }
>                 else {
>                         scalerect=
> MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
> -                       gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE,
> rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
> +                       gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE,
> pix, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
>
> -                       rect= scalerect;
> +                       pix= scalerect;
>                 }
>         }
>
> @@ -640,7 +665,7 @@
>                 if (use_high_bit_depth)
>                         glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA16,  rectw,
> recth, 0, GL_RGBA, GL_FLOAT, frect);
>                 else
> -                       glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw,
> recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
> +                       glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw,
> recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
>                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
> GL_LINEAR);
>                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
> gpu_get_mipmap_filter(1));
>         }
> @@ -649,14 +674,14 @@
>                         if (use_high_bit_depth)
>                                 glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA16,
>  rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
>                         else
> -                               glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,
>  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
> +                               glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,
>  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
>
>                         glGenerateMipmapEXT(GL_TEXTURE_2D);
>                 } else {
>                         if (use_high_bit_depth)
>                                 gluBuild2DMipmaps(GL_TEXTURE_2D,
> GL_RGBA16, rectw, recth, GL_RGBA, GL_FLOAT, frect);
>                         else
> -                               gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,
> rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
> +                               gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,
> rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, pix);
>                 }
>                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
> gpu_get_mipmap_filter(0));
>                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
> gpu_get_mipmap_filter(1));
> @@ -668,21 +693,84 @@
>                 glTexParameterf(GL_TEXTURE_2D,
> GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
>         /* set to modulate with vertex color */
>         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
> -
> -       /* clean up */
> -       if (tilerect)
> -               MEM_freeN(tilerect);
> -       if (ftilerect)
> -               MEM_freeN(ftilerect);
> +
>         if (scalerect)
>                 MEM_freeN(scalerect);
>         if (fscalerect)
>                 MEM_freeN(fscalerect);
> -       if (srgb_frect)
> -               MEM_freeN(srgb_frect);
> -       return *bind;
>  }
>
> +/**
> + * GPU_upload_dxt_texture() assumes that the texture is already bound and
> ready to go.
> + * This is so the viewport and the BGE can share some code.
> + * Returns 0 if the provided ImBuf doesn't have a supported DXT
> compression format
> + */
> +int GPU_upload_dxt_texture(ImBuf *ibuf)
> +{
> +       GLint format, err;
> +       int blocksize, height, width, i, size, offset = 0;
> +
> +       height = ibuf->x;
> +       width = ibuf->y;
> +
> +       if (ibuf->dds_data.fourcc == FOURCC_DXT1)
> +               format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
> +       else if (ibuf->dds_data.fourcc == FOURCC_DXT3)
> +               format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
> +       else if (ibuf->dds_data.fourcc == FOURCC_DXT5)
> +               format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
> +       else {
> +               printf("Unable to find a suitable DXT compression, falling
> back to uncompressed\n");
> +               return 0;
> +       }
> +
> +       blocksize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
> +       for (i=0; i<ibuf->dds_data.nummipmaps && (width||height); ++i) {
> +               if (width == 0)
> +                       width = 1;
> +               if (height == 0)
> +                       height = 1;
> +
> +               size = ((width+3)/4)*((height+3)/4)*blocksize;
> +
> +               glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width,
> height,
> +                       0, size, ibuf->dds_data.data + offset);
> +
> +               err = glGetError();
> +
> +               if (err != GL_NO_ERROR)
> +                       printf("OpenGL error: %s\nFormat: %x\n",
> gluErrorString(err), format);
> +
> +               offset += size;
> +               width >>= 1;
> +               height >>= 1;
> +       }
> +
> +       return 1;
> +}
> +
> +void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix,
> int x, int y, int mipmap, Image *ima, ImBuf *ibuf)
> +{
> +#ifndef WITH_DDS
> +       // Fall back to uncompressed if DDS isn't enabled
> +       GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima);
> +#else
> +
> +
> +       glGenTextures(1, (GLuint *)bind);
> +       glBindTexture(GL_TEXTURE_2D, *bind);
> +
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
> gpu_get_mipmap_filter(1));
> +
> +       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
> +
> +       if (GPU_upload_dxt_texture(ibuf) == 0) {
> +               glDeleteTextures(1, (GLuint*)bind);
> +               GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima);
> +       }
> +#endif
> +}
>  static void gpu_verify_repeat(Image *ima)
>  {
>         /* set either clamp or repeat in X/Y */
>
> Modified: trunk/blender/source/blender/imbuf/IMB_imbuf_types.h
> ===================================================================
> --- trunk/blender/source/blender/imbuf/IMB_imbuf_types.h        2012-06-30
> 04:29:16 UTC (rev 48424)
> +++ trunk/blender/source/blender/imbuf/IMB_imbuf_types.h        2012-06-30
> 04:34:34 UTC (rev 48425)
> @@ -50,6 +50,13 @@
>  #define IB_MIPMAP_LEVELS       20
>  #define IB_FILENAME_SIZE       1024
>
> +typedef struct DDSData {
> +       unsigned int fourcc; /* DDS fourcc info */
> +       unsigned int nummipmaps; /* The number of mipmaps in the dds file
> */
> +       unsigned char *data; /* The compressed image data */
> +       unsigned int size; /* The size of the compressed data */
> +} DDSData;
> +
>  /**
>   * \ingroup imbuf
>   * This is the abstraction of an image.  ImBuf is the basic type used for
> all
> @@ -119,6 +126,9 @@
>         unsigned char *encodedbuffer;     /* Compressed image only used
> with png currently */
>         unsigned int   encodedsize;       /* Size of data written to
> encodedbuffer */
>         unsigned int   encodedbuffersize; /* Size of encodedbuffer */
> +
> +       /* information for compressed textures */
> +       struct DDSData dds_data;
>  } ImBuf;
>
>  /* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */
> @@ -215,6 +225,28 @@
>  #define IB_PROFILE_SRGB                        2
>  #define IB_PROFILE_CUSTOM              3
>
> +/* dds */
> +#ifdef WITH_DDS
> +#ifndef MAKEFOURCC
> +#define MAKEFOURCC(ch0, ch1, ch2, ch3)\
> +       ((unsigned long)(unsigned char)(ch0) | \
> +       ((unsigned long)(unsigned char)(ch1) << 8) | \
> +       ((unsigned long)(unsigned char)(ch2) << 16) | \
> +       ((unsigned long)(unsigned char)(ch3) << 24))
> +#endif //MAKEFOURCC
> +
> +/*
> + * FOURCC codes for DX compressed-texture pixel formats
> + */
> +
> +#define FOURCC_DDS   (MAKEFOURCC('D','D','S',' '))
> +#define FOURCC_DXT1  (MAKEFOURCC('D','X','T','1'))
> +#define FOURCC_DXT2  (MAKEFOURCC('D','X','T','2'))
> +#define FOURCC_DXT3  (MAKEFOURCC('D','X','T','3'))
> +#define FOURCC_DXT4  (MAKEFOURCC('D','X','T','4'))
> +#define FOURCC_DXT5  (MAKEFOURCC('D','X','T','5'))
> +
> +#endif // DDS
>  extern const char *imb_ext_image[];
>  extern const char *imb_ext_image_qt[];
>  extern const char *imb_ext_movie[];
>
> Modified: trunk/blender/source/blender/imbuf/intern/allocimbuf.c
> ===================================================================
> --- trunk/blender/source/blender/imbuf/intern/allocimbuf.c      2012-06-30
> 04:29:16 UTC (rev 48424)
> +++ trunk/blender/source/blender/imbuf/intern/allocimbuf.c      2012-06-30
> 04:34:34 UTC (rev 48425)
> @@ -162,6 +162,8 @@
>
> @@ Diff output truncated at 10240 characters. @@
> _______________________________________________
> Bf-blender-cvs mailing list
> Bf-blender-cvs at blender.org
> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
>


More information about the Bf-committers mailing list