Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/intern/gpu_draw.c')
-rw-r--r--source/blender/gpu/intern/gpu_draw.c472
1 files changed, 236 insertions, 236 deletions
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index edc2f2171a5..f1c82dc53a7 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -50,6 +50,7 @@
#include "MEM_guardedalloc.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -207,53 +208,232 @@ static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget)
return NULL;
}
-typedef struct VerifyThreadData {
- ImBuf *ibuf;
- float *srgb_frect;
-} VerifyThreadData;
+static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
+{
+ uint bindcode = 0;
+ const bool mipmap = GPU_get_mipmap();
+
+#ifdef WITH_DDS
+ if (ibuf->ftype == IMB_FTYPE_DDS) {
+ /* DDS is loaded directly in compressed form. */
+ GPU_create_gl_tex_compressed(
+ &bindcode, ibuf->rect, ibuf->x, ibuf->y, textarget, mipmap, ima, ibuf);
+ return bindcode;
+ }
+#endif
+
+ /* Regular uncompressed texture. */
+ float *rect_float = ibuf->rect_float;
+ uchar *rect = (uchar *)ibuf->rect;
+ bool compress_as_srgb = false;
+
+ if (rect_float == NULL) {
+ /* Byte image is in original colorspace from the file. If the file is sRGB
+ * scene linear, or non-color data no conversion is needed. Otherwise we
+ * compress as scene linear + sRGB transfer function to avoid precision loss
+ * in common cases.
+ *
+ * We must also convert to premultiplied for correct texture interpolation
+ * and consistency with float images. */
+ if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
+ compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace);
+
+ rect = MEM_mallocN(sizeof(uchar) * 4 * ibuf->x * ibuf->y, __func__);
+ if (rect == NULL) {
+ return bindcode;
+ }
+
+ IMB_colormanagement_imbuf_to_srgb_texture(
+ rect, 0, 0, ibuf->x, ibuf->y, ibuf, compress_as_srgb);
+ }
+ }
+ else if (ibuf->channels != 4) {
+ /* Float image is already in scene linear colorspace or non-color data by
+ * convention, no colorspace conversion needed. But we do require 4 channels
+ * currently. */
+ rect_float = MEM_mallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, __func__);
+ if (rect_float == NULL) {
+ return bindcode;
+ }
-static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect,
- ImBuf *ibuf,
- const int start_line,
- const int height)
+ IMB_buffer_float_from_float(rect_float,
+ ibuf->rect_float,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+
+ /* Create OpenGL texture. */
+ GPU_create_gl_tex(&bindcode,
+ (uint *)rect,
+ rect_float,
+ ibuf->x,
+ ibuf->y,
+ textarget,
+ mipmap,
+ compress_as_srgb,
+ ima);
+
+ /* Free buffers if needed. */
+ if (rect && rect != (uchar *)ibuf->rect) {
+ MEM_freeN(rect);
+ }
+ if (rect_float && rect_float != ibuf->rect_float) {
+ MEM_freeN(rect_float);
+ }
+
+ return bindcode;
+}
+
+static void gpu_texture_update_scaled(
+ uchar *rect, float *rect_float, int full_w, int full_h, int x, int y, int w, int h)
{
- size_t offset = ibuf->channels * start_line * ibuf->x;
- float *current_srgb_frect = srgb_frect + offset;
- float *current_rect_float = ibuf->rect_float + offset;
- IMB_buffer_float_from_float(current_srgb_frect,
- current_rect_float,
- ibuf->channels,
- IB_PROFILE_SRGB,
- IB_PROFILE_LINEAR_RGB,
- true,
- ibuf->x,
- height,
- ibuf->x,
- ibuf->x);
- IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height);
+ /* Partial update with scaling. */
+ int limit_w = smaller_power_of_2_limit(full_w);
+ int limit_h = smaller_power_of_2_limit(full_h);
+ float xratio = limit_w / (float)full_w;
+ float yratio = limit_h / (float)full_h;
+
+ /* Find sub coordinates in scaled image. Take ceiling because we will be
+ * losing 1 pixel due to rounding errors in x,y. */
+ int sub_x = x * xratio;
+ int sub_y = y * yratio;
+ int sub_w = (int)ceil(xratio * w);
+ int sub_h = (int)ceil(yratio * h);
+
+ /* ...but take back if we are over the limit! */
+ if (sub_w + sub_x > limit_w) {
+ sub_w--;
+ }
+ if (sub_h + sub_y > limit_h) {
+ sub_h--;
+ }
+
+ /* Scale pixels. */
+ ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h);
+ IMB_scaleImBuf(ibuf, sub_w, sub_h);
+
+ if (ibuf->rect_float) {
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_FLOAT, ibuf->rect_float);
+ }
+ else {
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ }
+
+ IMB_freeImBuf(ibuf);
}
-static void verify_thread_do(void *data_v, int start_scanline, int num_scanlines)
+static void gpu_texture_update_unscaled(
+ uchar *rect, float *rect_float, int x, int y, int w, int h, GLint tex_stride, GLint tex_offset)
{
- VerifyThreadData *data = (VerifyThreadData *)data_v;
- gpu_verify_high_bit_srgb_buffer_slice(
- data->srgb_frect, data->ibuf, start_scanline, num_scanlines);
+ /* Partial update without scaling. Stride and offset are used to copy only a
+ * subset of a possible larger buffer than what we are updating. */
+ GLint row_length;
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, tex_stride);
+
+ if (rect_float == NULL) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect + tex_offset);
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, rect_float + tex_offset);
+ }
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
}
-static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect, ImBuf *ibuf)
+static void gpu_texture_update_from_ibuf(ImBuf *ibuf, int x, int y, int w, int h)
{
- if (ibuf->y < 64) {
- gpu_verify_high_bit_srgb_buffer_slice(srgb_frect, ibuf, 0, ibuf->y);
+ /* Partial update of texture for texture painting. This is often much
+ * quicker than fully updating the texture for high resolution images.
+ * Assumes the OpenGL texture is bound to 0. */
+ const bool scaled = is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y);
+
+ if (scaled) {
+ /* Extra padding to account for bleed from neighboring pixels. */
+ const int padding = 4;
+ const int xmax = min_ii(x + w + padding, ibuf->x);
+ const int ymax = min_ii(y + h + padding, ibuf->y);
+ x = max_ii(x - padding, 0);
+ y = max_ii(y - padding, 0);
+ w = xmax - x;
+ h = ymax - y;
+ }
+
+ /* Get texture data pointers. */
+ float *rect_float = ibuf->rect_float;
+ uchar *rect = (uchar *)ibuf->rect;
+ GLint tex_stride = ibuf->x;
+ GLint tex_offset = ibuf->channels * (y * ibuf->x + x);
+
+ if (rect_float == NULL) {
+ /* Byte pixels. */
+ if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
+ const bool compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(
+ ibuf->rect_colorspace);
+
+ rect = MEM_mallocN(sizeof(uchar) * 4 * w * h, __func__);
+ if (rect == NULL) {
+ return;
+ }
+
+ tex_stride = w;
+ tex_offset = 0;
+
+ /* Convert to scene linear with sRGB compression, and premultiplied for
+ * correct texture interpolation. */
+ IMB_colormanagement_imbuf_to_srgb_texture(rect, x, y, w, h, ibuf, compress_as_srgb);
+ }
+ }
+ else if (ibuf->channels != 4 || scaled) {
+ /* Float pixels. */
+ rect_float = MEM_mallocN(sizeof(float) * 4 * x * y, __func__);
+ if (rect_float == NULL) {
+ return;
+ }
+
+ tex_stride = w;
+ tex_offset = 0;
+
+ size_t ibuf_offset = (y * ibuf->x + x) * ibuf->channels;
+ IMB_buffer_float_from_float(rect_float,
+ ibuf->rect_float + ibuf_offset,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ w,
+ h,
+ x,
+ ibuf->x);
+ }
+
+ if (scaled) {
+ /* Slower update where we first have to scale the input pixels. */
+ gpu_texture_update_scaled(rect, rect_float, ibuf->x, ibuf->y, x, y, w, h);
}
else {
- VerifyThreadData data;
- data.ibuf = ibuf;
- data.srgb_frect = srgb_frect;
- IMB_processor_apply_threaded_scanlines(ibuf->y, verify_thread_do, &data);
+ /* Fast update at same resolution. */
+ gpu_texture_update_unscaled(rect, rect_float, x, y, w, h, tex_stride, tex_offset);
+ }
+
+ /* Free buffers if needed. */
+ if (rect && rect != (uchar *)ibuf->rect) {
+ MEM_freeN(rect);
+ }
+ if (rect_float && rect_float != ibuf->rect_float) {
+ MEM_freeN(rect_float);
}
}
-GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data)
+GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget)
{
if (ima == NULL) {
return NULL;
@@ -286,62 +466,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
return *tex;
}
- /* flag to determine whether deep format is used */
- bool use_high_bit_depth = false, do_color_management = false;
-
- if (ibuf->rect_float) {
- use_high_bit_depth = true;
-
- /* TODO unneeded when float images are correctly treated as linear always */
- if (!is_data) {
- do_color_management = true;
- }
- }
-
- const int rectw = ibuf->x;
- const int recth = ibuf->y;
- uint *rect = ibuf->rect;
- float *frect = NULL;
- float *srgb_frect = NULL;
-
- 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");
- gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf);
- }
- else {
- frect = ibuf->rect_float;
- }
- }
-
- const bool mipmap = GPU_get_mipmap();
-
-#ifdef WITH_DDS
- if (ibuf->ftype == IMB_FTYPE_DDS) {
- GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf);
- }
- else
-#endif
- {
- GPU_create_gl_tex(
- &bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima);
- }
-
- /* mark as non-color data texture */
- if (bindcode) {
- if (is_data) {
- ima->gpuflag |= IMA_GPU_IS_DATA;
- }
- else {
- ima->gpuflag &= ~IMA_GPU_IS_DATA;
- }
- }
-
- /* clean up */
- if (srgb_frect) {
- MEM_freeN(srgb_frect);
- }
+ bindcode = gpu_texture_create_from_ibuf(ima, ibuf, textarget);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -349,15 +474,14 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
return *tex;
}
-static void **gpu_gen_cube_map(
- uint *rect, float *frect, int rectw, int recth, bool use_high_bit_depth)
+static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth)
{
- size_t block_size = use_high_bit_depth ? sizeof(float[4]) : sizeof(uchar[4]);
+ size_t block_size = frect ? sizeof(float[4]) : sizeof(uchar[4]);
void **sides = NULL;
int h = recth / 2;
int w = rectw / 3;
- if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) {
+ if (w != h) {
return sides;
}
@@ -376,7 +500,7 @@ static void **gpu_gen_cube_map(
* | NegZ | PosZ | PosY |
* |______|______|______|
*/
- if (use_high_bit_depth) {
+ if (frect) {
float(*frectb)[4] = (float(*)[4])frect;
float(**fsides)[4] = (float(**)[4])sides;
@@ -430,7 +554,7 @@ void GPU_create_gl_tex(uint *bind,
int recth,
int textarget,
bool mipmap,
- bool use_high_bit_depth,
+ bool use_srgb,
Image *ima)
{
ImBuf *ibuf = NULL;
@@ -441,7 +565,7 @@ void GPU_create_gl_tex(uint *bind,
rectw = smaller_power_of_2_limit(rectw);
recth = smaller_power_of_2_limit(recth);
- if (use_high_bit_depth) {
+ if (frect) {
ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
IMB_scaleImBuf(ibuf, rectw, recth);
@@ -459,12 +583,15 @@ void GPU_create_gl_tex(uint *bind,
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
+ GLenum internal_format = (frect) ? GL_RGBA16F : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
+
if (textarget == GL_TEXTURE_2D) {
- if (use_high_bit_depth) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ if (frect) {
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
}
else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
@@ -484,15 +611,14 @@ void GPU_create_gl_tex(uint *bind,
int w = rectw / 3, h = recth / 2;
if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) {
- void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth, use_high_bit_depth);
- GLenum informat = use_high_bit_depth ? GL_RGBA16F : GL_RGBA8;
- GLenum type = use_high_bit_depth ? GL_FLOAT : GL_UNSIGNED_BYTE;
+ void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth);
+ GLenum type = frect ? GL_FLOAT : GL_UNSIGNED_BYTE;
if (cube_map) {
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
0,
- informat,
+ internal_format,
w,
h,
0,
@@ -617,14 +743,14 @@ void GPU_create_gl_tex_compressed(
#ifndef WITH_DDS
(void)ibuf;
/* Fall back to uncompressed if DDS isn't enabled */
- GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima);
+ GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, true, ima);
#else
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf) == 0) {
glDeleteTextures(1, (GLuint *)bind);
- GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima);
+ GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, true, ima);
}
glBindTexture(textarget, 0);
@@ -680,146 +806,20 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
}
}
-/* check if image has been downscaled and do scaled partial update */
-static bool gpu_check_scaled_image(
- ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
-{
- if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) {
- int x_limit = smaller_power_of_2_limit(ibuf->x);
- int y_limit = smaller_power_of_2_limit(ibuf->y);
-
- float xratio = x_limit / (float)ibuf->x;
- float yratio = y_limit / (float)ibuf->y;
-
- /* find new width, height and x,y gpu texture coordinates */
-
- /* take ceiling because we will be losing 1 pixel due to rounding errors in x,y... */
- int rectw = (int)ceil(xratio * w);
- int recth = (int)ceil(yratio * h);
-
- x *= xratio;
- y *= yratio;
-
- /* ...but take back if we are over the limit! */
- if (rectw + x > x_limit) {
- rectw--;
- }
- if (recth + y > y_limit) {
- recth--;
- }
-
- GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
-
- /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */
- if (frect) {
- ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h);
- IMB_scaleImBuf(ibuf_scale, rectw, recth);
-
- glTexSubImage2D(
- GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_FLOAT, ibuf_scale->rect_float);
-
- IMB_freeImBuf(ibuf_scale);
- }
- /* byte images are not continuous in memory so do manual interpolation */
- else {
- uchar *scalerect = MEM_mallocN(rectw * recth * sizeof(*scalerect) * 4, "scalerect");
- uint *p = (uint *)scalerect;
- int i, j;
- float inv_xratio = 1.0f / xratio;
- float inv_yratio = 1.0f / yratio;
- for (i = 0; i < rectw; i++) {
- float u = (x + i) * inv_xratio;
- for (j = 0; j < recth; j++) {
- float v = (y + j) * inv_yratio;
- bilinear_interpolation_color_wrap(ibuf, (uchar *)(p + i + j * (rectw)), NULL, u, v);
- }
- }
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, scalerect);
-
- MEM_freeN(scalerect);
- }
-
- if (GPU_get_mipmap()) {
- glGenerateMipmap(GL_TEXTURE_2D);
- }
- else {
- ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
- }
-
- GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
-
- return true;
- }
-
- return false;
-}
-
void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
{
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) {
- /* these cases require full reload still */
+ /* Full reload of texture. */
GPU_free_image(ima);
}
else {
- /* for the special case, we can do a partial update
- * which is much quicker for painting */
- GLint row_length, skip_pixels, skip_rows;
-
- /* if color correction is needed, we must update the part that needs updating. */
- if (ibuf->rect_float) {
- float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
- bool is_data = (ima->gpuflag & IMA_GPU_IS_DATA) != 0;
- IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
-
- if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
- MEM_freeN(buffer);
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer);
-
- MEM_freeN(buffer);
-
- if (GPU_get_mipmap()) {
- glGenerateMipmap(GL_TEXTURE_2D);
- }
- else {
- ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
- }
-
- GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
+ /* Partial update of texture. */
GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
- glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
- glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
- glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
- 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);
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+ gpu_texture_update_from_ibuf(ibuf, x, y, w, h);
- /* see comment above as to why we are using gpu mipmap generation here */
if (GPU_get_mipmap()) {
glGenerateMipmap(GL_TEXTURE_2D);
}
@@ -1242,7 +1242,7 @@ static void gpu_free_image_immediate(Image *ima)
}
}
- ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE | IMA_GPU_IS_DATA);
+ ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE);
}
void GPU_free_image(Image *ima)