New feature:
authorTon Roosendaal <ton@blender.org>
Sun, 17 Mar 2013 14:38:58 +0000 (14:38 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 17 Mar 2013 14:38:58 +0000 (14:38 +0000)
Automatic switching for drawing pixel buffers via glDrawPixels or using GPU textures

It works with a User Preference limit, in megapixels, to define whether to use
GPU or direct pixel drawing. Default is now initialized to 10 MP (4k buffers).

Especially for zooming out (draw smaller) texture drawing is much smaller. Also
Nvidia cards typically draw much faster with textures in general.

Added to node backdrop first now, the other editors follow in a next commit.

For coders: added new DNA function to initialize new struct variables, so you
don't have to sub-version files anymore.

   DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname")

"filesdna" is the sdna description of the current file being versioned.

source/blender/blenkernel/BKE_main.h
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/BIF_glutil.h
source/blender/editors/screen/glutil.c
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_genfile.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/intern/dna_genfile.c
source/blender/makesrna/intern/rna_userdef.c

index 8e4d370e8a041c5f14d72ea3b9e546a586d62f21..2dc0a36adb6f072c5147fb81f4ccb4273977bfd6 100644 (file)
@@ -95,6 +95,10 @@ typedef struct Main {
 #define MAIN_VERSION_ATLEAST(main, ver, subver) \
        ((main)->versionfile > (ver) || (main->versionfile == (ver) && (main)->subversionfile >= (subver)))
 
+#define MAIN_VERSION_OLDER(main, ver, subver) \
+       ((main)->versionfile < (ver) || (main->versionfile == (ver) && (main)->subversionfile < (subver)))
+
+       
 #ifdef __cplusplus
 }
 #endif
index 928ec17999e665e2e8095fe67d8d099cc5d75b31..5fe7d692b8f0216c284c6de900c598fe636b5bf2 100644 (file)
@@ -7436,6 +7436,21 @@ static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
        }
 }
 
+/* initialize userdef with non-UI dependency stuff */
+/* other initializers (such as theme color defaults) go to resources.c */
+static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
+{
+       Main *bmain = bfd->main;
+       UserDef *user = bfd->user;
+       
+       if (user == NULL) return;
+       
+       if (bmain->versionfile < 267) {
+       
+               if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
+                       user->image_gpubuffer_limit = 10;
+       }
+}
 
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
@@ -8772,14 +8787,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       if (!MAIN_VERSION_ATLEAST(main, 265, 8)) {
+       if (MAIN_VERSION_OLDER(main, 265, 9)) {
                Mesh *me;
                for (me = main->mesh.first; me; me = me->id.next) {
                        BKE_mesh_do_versions_cd_flag_init(me);
                }
        }
 
-       if (!MAIN_VERSION_ATLEAST(main, 265, 9)) {
+       if (MAIN_VERSION_OLDER(main, 265, 10)) {
                Brush *br;
                for (br = main->brush.first; br; br = br->id.next) {
                        if (br->ob_mode & OB_MODE_TEXTURE_PAINT) {
@@ -8789,7 +8804,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
 
        // add storage for compositor translate nodes when not existing
-       if (!MAIN_VERSION_ATLEAST(main, 265, 10)) {
+       if (MAIN_VERSION_OLDER(main, 265, 11)) {
                bNodeTreeType *ntreetype;
                bNodeTree *ntree;
 
@@ -8801,10 +8816,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        do_version_node_fix_translate_wrapping(NULL, NULL, ntree);
        }
 
-       // if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
-
+       if (main->versionfile < 267) {
+               
+               /* TIP: to initialize new variables added, use the new function
+                  DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname")
+                  example: 
+                               if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
+                                       user->image_gpubuffer_limit = 10;
+                */
+               
+       }
+       
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
-       /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
+       /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
 
        /* don't forget to set version number in blender.c! */
 }
@@ -9001,9 +9025,11 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
        }
        
        /* do before read_libraries, but skip undo case */
-//     if (fd->memfile==NULL) (the mesh shuffle hacks don't work yet? ton)
+       if (fd->memfile==NULL)
                do_versions(fd, NULL, bfd->main);
        
+       do_versions_userdef(fd, bfd);
+       
        read_libraries(fd, &mainlist);
        
        blo_join_main(&mainlist);
index 31f89063f058224bdb78e710db18ddb8558a5cdd..40d73c39b8c08833ce00947861582677346a63b2 100644 (file)
@@ -129,7 +129,7 @@ void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y
 void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect);
 
 /**
- * Functions like a limited glDrawPixels, but actually draws the
+ * glaDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the
  * image using textures, which can be tremendously faster on low-end
  * cards, and also avoids problems with the raster position being
  * clipped when offscreen. The routine respects the glPixelZoom values,
@@ -143,6 +143,14 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
 
 void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect);
 
+/**
+ * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef.
+ * only RGBA
+ * needs glaDefine2DArea to be set.
+ */
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, void *rect);
+
+
 void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY);
 
 /* 2D Drawing Assistance */
index f6e9b5e4f8abb8bc4aa24160ea045fa06064003c..6e7972200c773c9e61eb4bf97a5258ab90136cba 100644 (file)
@@ -669,6 +669,22 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
        }
 }
 
+/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, void *rect)
+{
+       if (U.image_gpubuffer_limit) {
+               /* Megapixels, use float math to prevent overflow */
+               float img_size = ((float)img_w * (float)img_h) / (1024.0f * 1024.0f);
+               
+               if (U.image_gpubuffer_limit > (int)img_size) {
+                       glColor4f(1.0, 1.0, 1.0, 1.0);
+                       glaDrawPixelsTex(x, y, img_w, img_h, format, rect);
+                       return;
+               }
+       }
+       glaDrawPixelsSafe(x, y, img_w, img_h, img_w, GL_RGBA, format, rect);
+}
+
 /* 2D Drawing Assistance */
 
 void glaDefine2DArea(rcti *screen_rect)
index 0b067e8cee2a9924a7ffc80f771a402214de508c..3b4d1f1ae2609c4dafc265f891f908a117f30266 100644 (file)
@@ -3301,7 +3301,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
                                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                                        glPixelZoom(snode->zoom, snode->zoom);
                                        
-                                       glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
+                                       glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, display_buffer);
                                        
                                        glPixelZoom(1.0f, 1.0f);
                                        glDisable(GL_BLEND);
@@ -3309,7 +3309,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
                                else {
                                        glPixelZoom(snode->zoom, snode->zoom);
 
-                                       glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
+                                       glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, display_buffer);
                                        
                                        glPixelZoom(1.0f, 1.0f);
                                }
@@ -3358,57 +3358,6 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
        }
 }
 
-#if 0
-/* note: needs to be userpref or opengl profile option */
-static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
-{
-
-       draw_nodespace_grid(snode);
-       
-       if (snode->flag & SNODE_BACKDRAW) {
-               Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
-               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-               if (ibuf) {
-                       int x, y;
-                       float zoom = 1.0;
-
-                       glMatrixMode(GL_PROJECTION);
-                       glPushMatrix();
-                       glMatrixMode(GL_MODELVIEW);
-                       glPushMatrix();
-                       
-                       glaDefine2DArea(&sa->winrct);
-
-                       if (ibuf->x > sa->winx || ibuf->y > sa->winy) {
-                               float zoomx, zoomy;
-                               zoomx = (float)sa->winx / ibuf->x;
-                               zoomy = (float)sa->winy / ibuf->y;
-                               zoom = min_ff(zoomx, zoomy);
-                       }
-                       
-                       x = (sa->winx - zoom * ibuf->x) / 2 + snode->xof;
-                       y = (sa->winy - zoom * ibuf->y) / 2 + snode->yof;
-
-                       glPixelZoom(zoom, zoom);
-
-                       glColor4f(1.0, 1.0, 1.0, 1.0);
-                       if (ibuf->rect)
-                               glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
-                       else if (ibuf->channels == 4)
-                               glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float);
-
-                       glPixelZoom(1.0, 1.0);
-
-                       glMatrixMode(GL_PROJECTION);
-                       glPopMatrix();
-                       glMatrixMode(GL_MODELVIEW);
-                       glPopMatrix();
-
-                       BKE_image_release_ibuf(ima, ibuf, NULL);
-               }
-       }
-}
-#endif
 
 /* if v2d not NULL, it clips and returns 0 if not visible */
 int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
index ac75b03c7425b7cdce4fc973d5a715cee71b8b99..96d71288c62aeb196141dc931a4a0ff6aa6a3c3f 100644 (file)
@@ -71,6 +71,8 @@ void *DNA_struct_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *c
 int DNA_elem_array_size(const char *astr, int len);
 int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name);
 
+bool DNA_struct_elem_find(struct SDNA *sdna, const char *stype, const char *vartype, const char *name);
+
 
 int DNA_elem_type_size(const eSDNA_Type elem_nr);
 
index 10e85437e5f6ef81eefd329725fbd1e1d206c8f3..5a16ff39e68f49dd3417d8e5198ff444d48086df 100644 (file)
@@ -451,7 +451,7 @@ typedef struct UserDef {
 
        short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */
 
-       short pad4;
+       short image_gpubuffer_limit; /* If set, amount of mega-pixels to use for texture drawing of images */
        
        float glalphaclip;
        
index 86014c4e80e651e12cbd01666a333b59929c2f8f..1225821102abd03cec908a105366fe0e59731634 100644 (file)
@@ -1314,6 +1314,22 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch
        return (int)((intptr_t)cp);
 }
 
+bool DNA_struct_elem_find(SDNA *sdna, const char *stype, const char *vartype, const char *name)
+{
+       
+       const int SDNAnr = DNA_struct_find_nr(sdna, stype);
+       
+       if (SDNAnr >= 0) {
+               const short * const spo = sdna->structs[SDNAnr];
+               char * const cp = find_elem(sdna, vartype, name, spo, NULL, NULL);
+               
+               if (cp) return true;
+               return (int)((intptr_t)cp);
+       }
+       return false;
+}
+
+
 /**
  * Returns the size in bytes of a primitive type.
  */
index f113d1a2b619d02a836ffa3a5e7b0cc515ccacca..3824ee289569b7a2c0061e776654f0838d62ad39 100644 (file)
@@ -3456,6 +3456,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "GPU Mipmap Generation", "Generate Image Mipmaps on the GPU");
        RNA_def_property_update(prop, 0, "rna_userdef_gl_gpu_mipmaps");
 
+       prop = RNA_def_property(srna, "image_gpubuffer_limit", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "image_gpubuffer_limit");
+       RNA_def_property_range(prop, 0, 128);
+       RNA_def_property_ui_text(prop, "Image GPU draw limit", "If set, amount of Mega Pixels to use for drawing Images as GPU textures");
+       
+       
        prop = RNA_def_property(srna, "use_vertex_buffer_objects", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_VBO);
        RNA_def_property_ui_text(prop, "VBOs",