From 9afa4619eddd61e2b125cf10bb13f567702f9d9e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 26 Nov 2006 23:14:52 +0000 Subject: [PATCH] Disable mipmapping in texture paint mode, so fast redrawing will now work by default for power-of-two textures. Improved texture painting across different images a bit. --- source/blender/include/BDR_drawmesh.h | 9 ++-- source/blender/makesdna/DNA_image_types.h | 7 +-- source/blender/src/drawmesh.c | 64 +++++++++++++++++++---- source/blender/src/drawscene.c | 2 +- source/blender/src/editface.c | 6 ++- source/blender/src/imagepaint.c | 29 +++++----- source/blender/src/space.c | 6 +++ source/blender/src/toets.c | 7 +-- 8 files changed, 94 insertions(+), 36 deletions(-) diff --git a/source/blender/include/BDR_drawmesh.h b/source/blender/include/BDR_drawmesh.h index 15e18135c67..60c87308e20 100644 --- a/source/blender/include/BDR_drawmesh.h +++ b/source/blender/include/BDR_drawmesh.h @@ -47,11 +47,6 @@ struct EdgeHash; */ void set_mipmap(int mipmap); -/** - * Returns the current setting for mipmapping. - */ -int get_mipmap(void); - /** * Enables or disable linear mipmap setting for realtime images (textures). * Note that this will will destroy all texture bindings in OpenGL. @@ -76,6 +71,10 @@ void free_realtime_image(struct Image *ima); void free_all_realtime_images(void); void make_repbind(struct Image *ima); int set_tpage(struct MTFace *tface); + +void texpaint_enable_mipmap(void); +void texpaint_disable_mipmap(void); + void draw_tface_mesh(struct Object *ob, struct Mesh *me, int dt); struct EdgeHash *get_tface_mesh_marked_edge_info(struct Mesh *me); void init_realtime_GL(void); diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index ad8b3daf657..deabcee590a 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -92,9 +92,10 @@ typedef struct Image { #define IMA_NOCOLLECT 32 /* tpageflag */ -#define IMA_TILES 1 -#define IMA_TWINANIM 2 -#define IMA_COLCYCLE 4 /* Depreciated */ +#define IMA_TILES 1 +#define IMA_TWINANIM 2 +#define IMA_COLCYCLE 4 /* Depreciated */ +#define IMA_MIPMAP_COMPLETE 8 /* all mipmap levels in OpenGL texture set? */ #endif diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index d5ac0f779a6..d275558ec8c 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -134,13 +134,12 @@ void set_mipmap(int mipmap) } } - /** * Returns the current setting for mipmapping. */ -int get_mipmap(void) +static int get_mipmap(void) { - return fDoMipMap; + return fDoMipMap && (!(G.f & G_TEXTUREPAINT)); } /** @@ -398,7 +397,7 @@ int set_tpage(MTFace *tface) } glBindTexture( GL_TEXTURE_2D, *bind); - if (!fDoMipMap) + if (!get_mipmap()) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -406,10 +405,12 @@ int set_tpage(MTFace *tface) } else { int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; - + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + ima->tpageflag |= IMA_MIPMAP_COMPLETE; } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -435,7 +436,7 @@ int set_tpage(MTFace *tface) void update_realtime_image(Image *ima, int x, int y, int w, int h) { - if (ima->repbind || fDoMipMap || !ima->bindcode || !ima->ibuf || + if (ima->repbind || get_mipmap() || !ima->bindcode || !ima->ibuf || (!is_pow2(ima->ibuf->x) || !is_pow2(ima->ibuf->y)) || (w == 0) || (h == 0)) { /* these special cases require full reload still */ @@ -461,6 +462,9 @@ void update_realtime_image(Image *ima, int x, int y, int w, int h) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); + + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } } @@ -469,12 +473,14 @@ void free_realtime_image(Image *ima) if(ima->bindcode) { glDeleteTextures(1, (GLuint *)&ima->bindcode); ima->bindcode= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } if(ima->repbind) { glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); MEM_freeN(ima->repbind); ima->repbind= NULL; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } } @@ -482,10 +488,49 @@ void free_all_realtime_images(void) { Image* ima; - ima= G.main->image.first; - while(ima) { + for(ima=G.main->image.first; ima; ima=ima->id.next) free_realtime_image(ima); - ima= ima->id.next; +} + +/* these two functions are called on entering and exiting texture paint mode, + temporary disabling/enabling mipmapping on all images for quick texture + updates with glTexSubImage2D. images that didn't change don't have to be + re-uploaded to OpenGL */ +void texpaint_disable_mipmap(void) +{ + Image* ima; + + if(!fDoMipMap) + return; + + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + } +} + +void texpaint_enable_mipmap(void) +{ + Image* ima; + + if(!fDoMipMap) + return; + + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { + int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; + + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + free_realtime_image(ima); + } } } @@ -497,6 +542,7 @@ void make_repbind(Image *ima) glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); MEM_freeN(ima->repbind); ima->repbind= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } ima->totbind= ima->xrep*ima->yrep; if(ima->totbind>1) { diff --git a/source/blender/src/drawscene.c b/source/blender/src/drawscene.c index 6d5251494c0..e8bdf6b7330 100644 --- a/source/blender/src/drawscene.c +++ b/source/blender/src/drawscene.c @@ -78,7 +78,7 @@ void set_scene(Scene *sce) /* also see scene.c: set_scene_bg() */ if(G.f & G_VERTEXPAINT) set_vpaint(); if(G.f & G_TEXTUREPAINT) - G.f &= ~G_TEXTUREPAINT; + set_texturepaint(); if(G.f & G_WEIGHTPAINT) set_wpaint(); diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index a92aadc3c63..0d15318b094 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -1505,14 +1505,18 @@ void set_texturepaint() /* toggle */ if(me) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - if(G.f & G_TEXTUREPAINT) + if(G.f & G_TEXTUREPAINT) { G.f &= ~G_TEXTUREPAINT; + texpaint_enable_mipmap(); + } else if (me) { G.f |= G_TEXTUREPAINT; brush_check_exists(&G.scene->toolsettings->imapaint.brush); + texpaint_disable_mipmap(); } allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); } /* Get the barycentric coordinates of 2d point p in 2d triangle (v1, v2, v3) */ diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 0cb8c2feb66..21573ba0a11 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -544,29 +544,34 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho if (texpaint) { - /* pick face and image */ + /* pick new face and image */ if (facesel_face_pick(s->me, mval, &newfaceindex, 0)) { newimage = (Image*)((s->me->mtface+newfaceindex)->tpage); - texpaint_pick_uv(s->ob, s->me, newfaceindex, mval, newuv); + if(newimage && newimage->ibuf && newimage->ibuf->rect) + texpaint_pick_uv(s->ob, s->me, newfaceindex, mval, newuv); + else + newimage = NULL; } else newuv[0] = newuv[1] = 0.0f; /* see if stroke is broken, and if so finish painting in old position */ if (s->image) { - if (newimage == s->image) { - texpaint_pick_uv(s->ob, s->me, s->faceindex, mval, fwuv); - texpaint_pick_uv(s->ob, s->me, newfaceindex, prevmval, bkuv); + texpaint_pick_uv(s->ob, s->me, s->faceindex, mval, fwuv); + texpaint_pick_uv(s->ob, s->me, newfaceindex, prevmval, bkuv); + + if (newimage == s->image) breakstroke= texpaint_break_stroke(s->uv, fwuv, bkuv, newuv); - } else breakstroke= 1; } + else + fwuv[0]= fwuv[1]= 0.0f; if (breakstroke) { texpaint_pick_uv(s->ob, s->me, s->faceindex, mval, fwuv); - redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, fwuv, - time, 1, pressure); + redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, + fwuv, time, 1, pressure); imapaint_clear_partial_redraw(); brush_painter_break_stroke(painter); } @@ -579,10 +584,10 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho /* paint in new image */ if (newimage) { if (breakstroke) - redraw|= imapaint_paint_sub_stroke(s, painter, newimage, texpaint, - bkuv, time, 0, pressure); - redraw|= imapaint_paint_sub_stroke(s, painter, newimage, texpaint, newuv, - time, 1, pressure); + redraw|= imapaint_paint_sub_stroke(s, painter, newimage, + texpaint, bkuv, time, 0, pressure); + redraw|= imapaint_paint_sub_stroke(s, painter, newimage, texpaint, + newuv, time, 1, pressure); } /* update state */ diff --git a/source/blender/src/space.c b/source/blender/src/space.c index a85979b6fe9..9d10fda2bb3 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -408,6 +408,9 @@ static void SaveState(void) init_realtime_GL(); init_gl_stuff(); + if(G.f & G_TEXTUREPAINT) + texpaint_enable_mipmap(); + if(G.scene->camera==0 || G.scene->camera->type!=OB_CAMERA) error("no (correct) camera"); @@ -416,6 +419,9 @@ static void SaveState(void) static void RestoreState(void) { + if(G.f & G_TEXTUREPAINT) + texpaint_disable_mipmap(); + curarea->win_swap = 0; curarea->head_swap=0; allqueue(REDRAWVIEW3D, 1); diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index b6f0e90ad1a..ba81d049cb5 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -690,11 +690,8 @@ int blenderqread(unsigned short event, short val) set_faceselect(); if(G.f & G_VERTEXPAINT) set_vpaint(); - if(G.f & G_TEXTUREPAINT) { - G.f &= ~G_TEXTUREPAINT; - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWBUTSEDIT, 0); - } + if(G.f & G_TEXTUREPAINT) + set_texturepaint(); if(G.f & G_WEIGHTPAINT) set_wpaint(); }