[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