New feature:

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.
This commit is contained in:
Ton Roosendaal 2013-03-17 14:38:58 +00:00
parent 50c28740d4
commit 0a4b030145
9 changed files with 89 additions and 62 deletions

View 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

View 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);

View 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 */

View 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)

View 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)

View 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);

View 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;

View 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.
*/

View 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",