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:
Diffstat (limited to 'source/blender/gpu/intern/gpu_draw.c')
-rw-r--r--source/blender/gpu/intern/gpu_draw.c210
1 files changed, 122 insertions, 88 deletions
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index f4810c540c3..33402426b62 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -52,6 +52,9 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "BLI_threads.h"
+#include "BLI_blenlib.h"
+
#include "BKE_bmfont.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -62,9 +65,6 @@
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
-#include "BLI_threads.h"
-#include "BLI_blenlib.h"
-
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
@@ -92,7 +92,7 @@ void GPU_render_text(MTFace *tface, int mode,
float *v1, float *v2, float *v3, float *v4, int glattrib)
{
if ((mode & GEMAT_TEXT) && (textlen>0) && tface->tpage) {
- Image* ima = (Image*)tface->tpage;
+ Image* ima = (Image *)tface->tpage;
int index, character;
float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
float advance_tab;
@@ -101,9 +101,9 @@ void GPU_render_text(MTFace *tface, int mode,
float line_start= 0.0f, line_height;
if (v4)
- line_height= MAX4(v1[1], v2[1], v3[1], v4[2]) - MIN4(v1[1], v2[1], v3[1], v4[2]);
+ line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
else
- line_height= MAX3(v1[1], v2[1], v3[1]) - MIN3(v1[1], v2[1], v3[1]);
+ line_height = max_fff(v1[1], v2[1], v3[1]) - min_fff(v1[1], v2[1], v3[1]);
line_height *= 1.2f; /* could be an option? */
/* end multiline */
@@ -189,30 +189,21 @@ void GPU_render_text(MTFace *tface, int mode,
/* Checking powers of two for images since opengl 1.x requires it */
-static int is_pow2_limit(int num)
+static bool is_power_of_2_resolution(int w, int h)
{
- /* take texture clamping into account */
-
- /* XXX: texturepaint not global! */
-#if 0
- if (G.f & G_TEXTUREPAINT)
- return 1;*/
-#endif
+ return is_power_of_2_i(w) && is_power_of_2_i(h);
+}
- if (U.glreslimit != 0 && num > U.glreslimit)
- return 0;
+static bool is_over_resolution_limit(int w, int h)
+{
+ if (U.glreslimit != 0)
+ return (w > U.glreslimit || h > U.glreslimit);
- return is_power_of_2_i(num);
+ return false;
}
-static int smaller_pow2_limit(int num)
+static int smaller_power_of_2_limit(int num)
{
- /* XXX: texturepaint not global! */
-#if 0
- if (G.f & G_TEXTUREPAINT)
- return 1;*/
-#endif
-
/* take texture clamping into account */
if (U.glreslimit != 0 && num > U.glreslimit)
return U.glreslimit;
@@ -252,6 +243,25 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap)
}
}
+static void gpu_generate_mipmap(GLenum target)
+{
+ int is_ati = GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY);
+ int target_enabled = 0;
+
+ /* work around bug in ATI driver, need to have GL_TEXTURE_2D enabled
+ * http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation */
+ if (is_ati) {
+ target_enabled = glIsEnabled(target);
+ if (!target_enabled)
+ glEnable(target);
+ }
+
+ glGenerateMipmapEXT(target);
+
+ if (is_ati && !target_enabled)
+ glDisable(target);
+}
+
void GPU_set_mipmap(int mipmap)
{
if (GTS.domipmap != (mipmap != 0)) {
@@ -376,7 +386,12 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
}
else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* for OpenGL render we use the alpha channel, this makes alpha blend correct */
+ if (GLEW_VERSION_1_4)
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ else
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* if U.glalphaclip == 1.0, some cards go bonkers...
* turn off alpha test in this case */
@@ -424,7 +439,7 @@ static void gpu_verify_reflection(Image *ima)
}
}
-int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap, int is_data)
+int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap, bool is_data)
{
ImBuf *ibuf = NULL;
unsigned int *bind = NULL;
@@ -537,8 +552,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
if (do_color_management) {
srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
- ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0,
+ ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
/* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
frect= srgb_frect + texwinsy*ibuf->x + texwinsx;
@@ -562,8 +578,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
if (do_color_management) {
frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
- ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0,
+ ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
/* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
}
@@ -643,7 +660,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
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)
+/* Image *ima can be NULL */
+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;
@@ -654,9 +672,10 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int
/* 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
* Then don't bother scaling for hardware that supports NPOT textures! */
- if (!GPU_non_power_of_two_support() && (!is_pow2_limit(rectw) || !is_pow2_limit(recth))) {
- rectw= smaller_pow2_limit(rectw);
- recth= smaller_pow2_limit(recth);
+ if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) ||
+ is_over_resolution_limit(rectw, recth)) {
+ rectw= smaller_power_of_2_limit(rectw);
+ recth= smaller_power_of_2_limit(recth);
if (use_high_bit_depth) {
fscalerect= MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
@@ -691,7 +710,7 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
- glGenerateMipmapEXT(GL_TEXTURE_2D);
+ gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
if (use_high_bit_depth)
@@ -702,7 +721,8 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int
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));
- ima->tpageflag |= IMA_MIPMAP_COMPLETE;
+ if (ima)
+ ima->tpageflag |= IMA_MIPMAP_COMPLETE;
}
if (GLEW_EXT_texture_filter_anisotropic)
@@ -744,16 +764,19 @@ int GPU_upload_dxt_texture(ImBuf *ibuf)
return FALSE;
}
- if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) {
+ if (!is_power_of_2_resolution(width, height)) {
printf("Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
return FALSE;
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ 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));
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ if (GLEW_EXT_texture_filter_anisotropic)
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
+
blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
for (i=0; i<ibuf->dds_data.nummipmaps && (width||height); ++i) {
if (width == 0)
@@ -791,7 +814,7 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x,
glBindTexture(GL_TEXTURE_2D, *bind);
if (GPU_upload_dxt_texture(ibuf) == 0) {
- glDeleteTextures(1, (GLuint*)bind);
+ glDeleteTextures(1, (GLuint *)bind);
GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima);
}
#endif
@@ -904,8 +927,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf ||
- (!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) ||
- (w == 0) || (h == 0))
+ (w == 0) || (h == 0))
{
/* these cases require full reload still */
GPU_free_image(ima);
@@ -934,7 +956,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
/* we have already accounted for the case where GTS.gpu_mipmap is false
* so we will be using GPU mipmap generation here */
if (GPU_get_mipmap()) {
- glGenerateMipmapEXT(GL_TEXTURE_2D);
+ gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -959,7 +981,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
/* see comment above as to why we are using gpu mipmap generation here */
if (GPU_get_mipmap()) {
- glGenerateMipmapEXT(GL_TEXTURE_2D);
+ gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1242,7 +1264,7 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat,
static Material *gpu_active_node_material(Material *ma)
{
if (ma && ma->use_nodes && ma->nodetree) {
- bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
+ bNode *node = nodeGetActiveID(ma->nodetree, ID_MA);
if (node)
return (Material *)node->id;
@@ -1253,16 +1275,15 @@ static Material *gpu_active_node_material(Material *ma)
return ma;
}
-void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_after)
+void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, bool glsl, bool *do_alpha_after)
{
Material *ma;
GPUMaterial *gpumat;
GPUBlendMode alphablend;
int a;
-
int gamma = BKE_scene_check_color_management_enabled(scene);
-
int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
+ int use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP); /* assumes v3d->defmaterial->preview is set */
/* initialize state */
memset(&GMS, 0, sizeof(GMS));
@@ -1274,7 +1295,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.gob = ob;
GMS.gscene = scene;
- GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */
+ GMS.totmat= use_matcap? 1 : ob->totcol+1; /* materials start from 1, default material is 0 */
GMS.glay= (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */
GMS.gviewmat= rv3d->viewmat;
GMS.gviewinv= rv3d->viewinv;
@@ -1287,7 +1308,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.use_alpha_pass = (do_alpha_after != NULL);
GMS.is_alpha_pass = (v3d->transp != FALSE);
if (GMS.use_alpha_pass)
- *do_alpha_after = FALSE;
+ *do_alpha_after = false;
if (GMS.totmat > FIXEDMAT) {
GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf");
@@ -1300,59 +1321,72 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.alphablend= GMS.alphablend_fixed;
}
- /* no materials assigned? */
- if (ob->totcol==0) {
- gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes);
-
+ /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */
+ if (use_matcap) {
+ GMS.gmatbuf[0] = v3d->defmaterial;
+ GPU_material_matcap(scene, v3d->defmaterial);
+
/* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
-
- if (glsl) {
- GMS.gmatbuf[0]= &defmaterial;
- GPU_material_from_blender(GMS.gscene, &defmaterial);
- }
-
+
GMS.alphablend[0]= GPU_BLEND_SOLID;
}
+ else {
- /* setup materials */
- for (a=1; a<=ob->totcol; a++) {
- /* find a suitable material */
- ma= give_current_material(ob, a);
- if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma);
- if (ma==NULL) ma= &defmaterial;
-
- /* create glsl material if requested */
- gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
-
- if (gpumat) {
- /* do glsl only if creating it succeed, else fallback */
- GMS.gmatbuf[a]= ma;
- alphablend = GPU_material_alpha_blend(gpumat, ob->col);
- }
- else {
- /* fixed function opengl materials */
- gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes);
+ /* no materials assigned? */
+ if (ob->totcol==0) {
+ gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes);
- if (GMS.use_alpha_pass) {
- GMS.matbuf[a].diff[3]= ma->alpha;
- alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
+ /* do material 1 too, for displists! */
+ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
+
+ if (glsl) {
+ GMS.gmatbuf[0]= &defmaterial;
+ GPU_material_from_blender(GMS.gscene, &defmaterial);
+ }
+
+ GMS.alphablend[0]= GPU_BLEND_SOLID;
+ }
+
+ /* setup materials */
+ for (a=1; a<=ob->totcol; a++) {
+ /* find a suitable material */
+ ma= give_current_material(ob, a);
+ if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma);
+ if (ma==NULL) ma= &defmaterial;
+
+ /* create glsl material if requested */
+ gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
+
+ if (gpumat) {
+ /* do glsl only if creating it succeed, else fallback */
+ GMS.gmatbuf[a]= ma;
+ alphablend = GPU_material_alpha_blend(gpumat, ob->col);
}
else {
- GMS.matbuf[a].diff[3]= 1.0f;
- alphablend = GPU_BLEND_SOLID;
+ /* fixed function opengl materials */
+ gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes);
+
+ if (GMS.use_alpha_pass) {
+ GMS.matbuf[a].diff[3]= ma->alpha;
+ alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
+ }
+ else {
+ GMS.matbuf[a].diff[3]= 1.0f;
+ alphablend = GPU_BLEND_SOLID;
+ }
}
- }
- /* setting 'do_alpha_after = TRUE' indicates this object needs to be
- * drawn in a second alpha pass for improved blending */
- if (do_alpha_after && !GMS.is_alpha_pass)
- if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
- *do_alpha_after = TRUE;
+ /* setting 'do_alpha_after = TRUE' indicates this object needs to be
+ * drawn in a second alpha pass for improved blending */
+ if (do_alpha_after && !GMS.is_alpha_pass)
+ if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
+ *do_alpha_after = true;
- GMS.alphablend[a]= alphablend;
+ GMS.alphablend[a]= alphablend;
+ }
}
-
+
/* let's start with a clean state */
GPU_disable_material();
}