Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/gpu/CMakeLists.txt5
-rw-r--r--source/blender/gpu/GPU_draw.h3
-rw-r--r--source/blender/gpu/SConscript3
-rw-r--r--source/blender/gpu/intern/gpu_draw.c120
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h32
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c2
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp27
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.h2
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp12
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp28
-rw-r--r--source/gameengine/Ketsji/BL_Texture.h1
-rw-r--r--source/gameengine/Ketsji/CMakeLists.txt4
12 files changed, 222 insertions, 17 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 59e384cbd4b..d80e756f0b6 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -71,5 +71,10 @@ endif()
add_definitions(-DGLEW_STATIC)
+if(WITH_IMAGE_DDS)
+ add_definitions(-DWITH_DDS)
+endif()
+
+
blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 438cfd6b741..59140b2be80 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -122,6 +122,9 @@ void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h, int m
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);
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index cf1c91f25fe..7ab0c6cce46 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -17,4 +17,7 @@ incs += ' ' + env['BF_OPENGL_INC']
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] )
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 4197e1a3edb..1e261e10ed6 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -427,8 +427,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
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 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
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 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
}
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 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
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 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
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 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
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 */
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 2cb1dfe149a..dcb5cdd7d32 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -50,6 +50,13 @@ struct ImMetaData;
#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 @@ typedef struct ImBuf {
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 @@ typedef struct ImBuf {
#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[];
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 5dff3e1aea0..68a094c26d0 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -162,6 +162,8 @@ void IMB_freeImBuf(ImBuf *ibuf)
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
IMB_metadata_free(ibuf);
+ if (ibuf->dds_data.data != NULL)
+ free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
MEM_freeN(ibuf);
}
}
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index 438988fbe48..82f355e1bb2 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -1016,6 +1016,10 @@ uint DirectDrawSurface::mipmapCount() const
else return 1;
}
+uint DirectDrawSurface::fourCC() const
+{
+ return header.pf.fourcc;
+}
uint DirectDrawSurface::width() const
{
@@ -1131,6 +1135,29 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
}
}
+// It was easier to copy this function from upstream than to resync.
+// This should be removed if a resync ever occurs.
+void* DirectDrawSurface::readData(uint &rsize)
+{
+ uint header_size = 128; // sizeof(DDSHeader);
+ if (header.hasDX10Header())
+ {
+ header_size += 20; // sizeof(DDSHeader10);
+ }
+
+ uint size = stream.size - header_size;
+ rsize = size;
+
+ unsigned char *data = new unsigned char[size];
+
+ stream.seek(header_size);
+ mem_read(stream, data, size);
+
+ // Maybe check if size == rsize? assert() isn't in this scope...
+
+ return data;
+}
+
void DirectDrawSurface::readLinearImage(Image * img)
{
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
index ddae8826620..a851533b1f3 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
@@ -158,6 +158,7 @@ public:
bool hasAlpha() const;
uint mipmapCount() const;
+ uint fourCC() const;
uint width() const;
uint height() const;
uint depth() const;
@@ -171,6 +172,7 @@ public:
void setUserVersion(int version);
void mipmap(Image * img, uint f, uint m);
+ void* readData(uint &size);
// void mipmap(FloatImage * img, uint f, uint m);
void printInfo() const;
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index 071d94c2076..fba326f7865 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -123,6 +123,8 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
ibuf->ftype = DDS;
ibuf->profile = IB_PROFILE_SRGB;
+ ibuf->dds_data.fourcc = dds.fourCC();
+ ibuf->dds_data.nummipmaps = dds.mipmapCount();
if ((flags & IB_test) == 0) {
if (!imb_addrectImBuf(ibuf)) return(ibuf);
@@ -136,10 +138,18 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
cp[0] = pixel.r; /* set R component of col */
cp[1] = pixel.g; /* set G component of col */
cp[2] = pixel.b; /* set B component of col */
- if (bits_per_pixel == 32)
+ if (dds.hasAlpha())
cp[3] = pixel.a; /* set A component of col */
rect[i] = col;
}
+
+ if (ibuf->dds_data.fourcc != FOURCC_DDS)
+ ibuf->dds_data.data = (unsigned char*)dds.readData(ibuf->dds_data.size);
+ else {
+ ibuf->dds_data.data = NULL;
+ ibuf->dds_data.size = 0;
+ }
+
IMB_flipy(ibuf);
}
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp
index 576da0d3f40..19247664dfa 100644
--- a/source/gameengine/Ketsji/BL_Texture.cpp
+++ b/source/gameengine/Ketsji/BL_Texture.cpp
@@ -144,7 +144,15 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap)
mNeedsDeleted = 1;
glGenTextures(1, (GLuint*)&mTexture);
+
+#ifdef WITH_DDS
+ if (ibuf->ftype & DDS)
+ InitGLCompressedTex(ibuf, mipmap);
+ else
+ InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
+#else
InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
+#endif
// track created units
BL_TextureObject obj;
@@ -183,6 +191,26 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
+void BL_Texture::InitGLCompressedTex(ImBuf* ibuf, bool mipmap)
+{
+#ifndef WITH_DDS
+ // Fall back to uncompressed if DDS isn't enabled
+ InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
+ return;
+#else
+ glBindTexture(GL_TEXTURE_2D, mTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+
+ if (GPU_upload_dxt_texture(ibuf) == 0) {
+ InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
+ return;
+ }
+#endif
+}
void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
{
diff --git a/source/gameengine/Ketsji/BL_Texture.h b/source/gameengine/Ketsji/BL_Texture.h
index 2673be2bc42..a6bd354d260 100644
--- a/source/gameengine/Ketsji/BL_Texture.h
+++ b/source/gameengine/Ketsji/BL_Texture.h
@@ -35,6 +35,7 @@ private:
void InitNonPow2Tex(unsigned int *p,int x,int y,bool mipmap );
void InitGLTex(unsigned int *p,int x,int y,bool mipmap );
+ void InitGLCompressedTex(struct ImBuf *p, bool mipmap);
public:
BL_Texture();
~BL_Texture( );
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index c7f54838c10..4b3426e0784 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -221,6 +221,10 @@ set(SRC
add_definitions(-DGLEW_STATIC)
+if(WITH_IMAGE_DDS)
+ add_definitions(-DWITH_DDS)
+endif()
+
if(WITH_SDL)
list(APPEND INC_SYS
${SDL_INCLUDE_DIR}