Disable mipmapping in texture paint mode, so fast redrawing will now
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Sun, 26 Nov 2006 23:14:52 +0000 (23:14 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Sun, 26 Nov 2006 23:14:52 +0000 (23:14 +0000)
work by default for power-of-two textures.

Improved texture painting across different images a bit.

source/blender/include/BDR_drawmesh.h
source/blender/makesdna/DNA_image_types.h
source/blender/src/drawmesh.c
source/blender/src/drawscene.c
source/blender/src/editface.c
source/blender/src/imagepaint.c
source/blender/src/space.c
source/blender/src/toets.c

index 15e18135c6717bec4fb730e9a3bfb6a76a6fad22..60c87308e201ef5317f4c05708b468671fd5e84f 100644 (file)
@@ -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); 
index ad8b3daf6576afbdcc9ea3735374dcbc22a9fcc8..deabcee590acad5750ce64fb23efef690f6a593c 100644 (file)
@@ -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
 
index d5ac0f779a617385e31bdcccd97e58adb9560790..d275558ec8c6c82ecbeaac13f2420a25583c06e0 100644 (file)
@@ -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) {
index 6d5251494c092ba58125fb9c213635e0dbf51846..e8bdf6b73309264e0d5d8cf79f30abeb5dee6617 100644 (file)
@@ -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();
        
index a92aadc3c63ae23921fc912feee5024829deb37a..0d15318b0944b4ec6359b33195368626887ecf79 100644 (file)
@@ -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) */
index 0cb8c2feb66ff0c3775433b66ccd2aaa4ed4ffb6..21573ba0a118aaa26a99493c13abe5af2cb5319b 100644 (file)
@@ -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 */
index a85979b6fe948896b4370fd9dc449b86ed111d49..9d10fda2bb37717ee73b42236018cdc57374a9b3 100644 (file)
@@ -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);
index b6f0e90ad1af5993c75b33d17bf07f79d73b7479..ba81d049cb515c0a125356b4f9cb664dc6312af5 100644 (file)
@@ -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();
                }