diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_draw.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 156 |
1 files changed, 118 insertions, 38 deletions
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 5d36ba169f3..59802f2cf58 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -410,9 +410,12 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int ImBuf *ibuf = NULL; unsigned int *bind = NULL; int rectw, recth, tpx=0, tpy=0, y; - unsigned int *rectrow, *tilerectrow; unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL; + float *ftilerect= NULL, *fscalerect = NULL, *frect = NULL; + float *srgb_frect = NULL; short texwindx, texwindy, texwinsx, texwinsy; + /* flag to determine whether high resolution format is used */ + int use_high_bit_depth = FALSE, do_color_management = FALSE; /* initialize tile mode and number of repeats */ GTS.ima = ima; @@ -462,9 +465,20 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if(ibuf==NULL) return 0; - /* ensure we have a char buffer and not only float */ - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); + if(ibuf->rect_float) { + if(U.use_16bit_textures) { + /* use high precision textures. This is relatively harmless because OpenGL gives us + a high precision format only if it is available */ + use_high_bit_depth = TRUE; + } + + /* TODO unneeded when float images are correctly treated as linear always */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + do_color_management = TRUE; + + if(ibuf->rect==NULL) + IMB_rect_from_float(ibuf); + } /* currently, tpage refresh is used by ima sequences */ if(ima->tpageflag & IMA_TPAGE_REFRESH) { @@ -498,17 +512,39 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int tpx= texwindx; tpy= texwindy; - rect= ibuf->rect + texwinsy*ibuf->x + texwinsx; + if(use_high_bit_depth) { + 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, ibuf->profile, 0, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + frect= srgb_frect + texwinsy*ibuf->x + texwinsx; + } + else + frect= ibuf->rect_float + texwinsy*ibuf->x + texwinsx; + } + else + rect= ibuf->rect + texwinsy*ibuf->x + texwinsx; } } else { /* regular image mode */ bind= &ima->bindcode; - + if(*bind==0) { tpx= ibuf->x; tpy= ibuf->y; rect= ibuf->rect; + if(use_high_bit_depth) { + 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, ibuf->profile, 0, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + } + else + frect= ibuf->rect_float; + } } } @@ -523,26 +559,57 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int /* for tiles, copy only part of image into buffer */ if (GTS.tilemode) { - tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); + if(use_high_bit_depth) { + float *frectrow, *ftilerectrow; - for (y=0; y<recth; y++) { - rectrow= &rect[y*ibuf->x]; - tilerectrow= &tilerect[y*rectw]; - - memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); + ftilerect= MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect"); + + for (y=0; y<recth; y++) { + frectrow= &frect[y*ibuf->x]; + ftilerectrow= &ftilerect[y*rectw]; + + memcpy(ftilerectrow, frectrow, tpx*sizeof(*frectrow)); + } + + frect= ftilerect; } + else { + unsigned int *rectrow, *tilerectrow; + + tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); + + for (y=0; y<recth; y++) { + rectrow= &rect[y*ibuf->x]; + tilerectrow= &tilerect[y*rectw]; + + memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); + } - rect= tilerect; + rect= tilerect; + } } - /* scale if not a power of two */ + /* 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 */ if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { rectw= smaller_pow2_limit(rectw); recth= smaller_pow2_limit(recth); - scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); - gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); - rect= scalerect; + if(use_high_bit_depth) { + fscalerect= MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect"); + gluScaleImage(GL_RGBA, tpx, tpy, GL_FLOAT, frect, rectw, recth, GL_FLOAT, fscalerect); + /* frect will refer to ibuf->rect_float when not color converting. We don't want to free that */ + if(do_color_management) + MEM_freeN(frect); + + frect = fscalerect; + } + else { + scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); + gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); + + rect= scalerect; + } } /* create image */ @@ -550,12 +617,18 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int glBindTexture( GL_TEXTURE_2D, *bind); if (!(gpu_get_mipmap() && mipmap)) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + if(use_high_bit_depth) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + else + 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); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); } else { - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); + if(use_high_bit_depth) + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA16, rectw, recth, GL_RGBA, GL_FLOAT, frect); + else + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); 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)); @@ -570,9 +643,14 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int /* clean up */ if (tilerect) MEM_freeN(tilerect); + if (ftilerect) + MEM_freeN(ftilerect); if (scalerect) MEM_freeN(scalerect); - + if (fscalerect) + MEM_freeN(fscalerect); + if (srgb_frect) + MEM_freeN(srgb_frect); return *bind; } @@ -692,23 +770,21 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); - if (ibuf->rect_float){ - /*This case needs a whole new buffer*/ - if(ibuf->rect==NULL) { - IMB_rect_from_float(ibuf); - } - else { - /* Do partial drawing. 'buffer' holds only the changed part. Needed for color corrected result */ - float *buffer = (float *)MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf"); - IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h); - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + /* if color correction is needed, we must update the part that needs updating. */ + if(ibuf->rect_float && (!U.use_16bit_textures || (ibuf->profile == IB_PROFILE_LINEAR_RGB))) { + float *buffer = MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf"); + IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h); + + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer); - MEM_freeN(buffer); - if(ima->tpageflag & IMA_MIPMAP_COMPLETE) - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - return; - } + + MEM_freeN(buffer); + + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + + return; } glBindTexture(GL_TEXTURE_2D, ima->bindcode); @@ -717,8 +793,12 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); glPixelStorei(GL_UNPACK_SKIP_ROWS, y); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ibuf->rect); + if(ibuf->rect_float) + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + GL_FLOAT, ibuf->rect_float); + else + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + GL_UNSIGNED_BYTE, ibuf->rect); glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); |