diff options
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 20 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 67 |
3 files changed, 58 insertions, 31 deletions
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 410e23c9576..23ea9a62ef8 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -581,17 +581,19 @@ const char *GPU_builtin_name(eGPUBuiltin builtin) } /* assign only one texid per buffer to avoid sampling the same texture twice */ -static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key) +static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key1, int key2) { - if (BLI_ghash_haskey(bindhash, key)) { + GHashPair pair = {key1, POINTER_FROM_INT(key2)}; + if (BLI_ghash_haskey(bindhash, &pair)) { /* Reuse existing texid */ - input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, key)); + input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, &pair)); } else { /* Allocate new texid */ input->texid = *texid; (*texid)++; input->bindtex = true; + void *key = BLI_ghashutil_pairalloc(key1, POINTER_FROM_INT(key2)); BLI_ghash_insert(bindhash, key, POINTER_FROM_INT(input->texid)); } } @@ -604,7 +606,7 @@ static void codegen_set_unique_ids(ListBase *nodes) GPUOutput *output; int id = 1, texid = 0; - bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh"); + bindhash = BLI_ghash_pair_new("codegen_set_unique_ids1 gh"); for (node = nodes->first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { @@ -616,11 +618,11 @@ static void codegen_set_unique_ids(ListBase *nodes) input->bindtex = false; if (input->ima) { /* input is texture from image */ - codegen_set_texid(bindhash, input, &texid, input->ima); + codegen_set_texid(bindhash, input, &texid, input->ima, input->image_tile); } else if (input->coba) { /* input is color band texture, check coba pointer */ - codegen_set_texid(bindhash, input, &texid, input->coba); + codegen_set_texid(bindhash, input, &texid, input->coba, 0); } else { /* Either input->ima or input->coba should be non-NULL. */ @@ -635,7 +637,7 @@ static void codegen_set_unique_ids(ListBase *nodes) } } - BLI_ghash_free(bindhash, NULL, NULL); + BLI_ghash_free(bindhash, BLI_ghashutil_pairfree, NULL); } /** @@ -1545,6 +1547,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType input->source = GPU_SOURCE_TEX; input->ima = link->ima; input->iuser = link->iuser; + input->image_tile = link->image_tile; break; case GPU_NODE_LINK_ATTR: input->source = GPU_SOURCE_ATTR; @@ -1789,12 +1792,13 @@ GPUNodeLink *GPU_uniform(float *num) return link; } -GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser) +GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int tile) { GPUNodeLink *link = GPU_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_BLENDER; link->ima = ima; link->iuser = iuser; + link->image_tile = tile; return link; } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 4e09f16ebf8..0e6982c603e 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -99,6 +99,7 @@ struct GPUNodeLink { struct { struct Image *ima; struct ImageUser *iuser; + int image_tile; }; }; }; @@ -138,6 +139,7 @@ typedef struct GPUInput { struct ImageUser *iuser; /* image user */ bool bindtex; /* input is responsible for binding the texture? */ int texid; /* number for multitexture, starting from zero */ + int image_tile; /* image tile */ eGPUType textype; /* texture type (2D, 1D Array ...) */ }; /* GPU_SOURCE_ATTR */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7fa2eb6424c..2d70ce009e2 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -195,13 +195,13 @@ float GPU_get_anisotropic(void) /* Set OpenGL state for an MTFace */ -static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget) +static GPUTexture **gpu_get_tile_gputexture(ImageTile *tile, GLenum textarget) { if (textarget == GL_TEXTURE_2D) { - return &ima->gputexture[TEXTARGET_TEXTURE_2D]; + return &tile->gputexture[TEXTARGET_TEXTURE_2D]; } else if (textarget == GL_TEXTURE_CUBE_MAP) { - return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; + return &tile->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; } return NULL; @@ -476,8 +476,19 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget /* Tag as in active use for garbage collector. */ BKE_image_tag_time(ima); + ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser); + + if (tile == NULL) { + /* TODO(lukas): When a tile gets deleted, the materials using the image + * aren't rebuilt and therefore continue to use it. + * This workaround isn't ideal, the result should be a pink color + * (for a missing tile). With the current behaviour, new tiles also won't + * be detected. */ + tile = BKE_image_get_tile(ima, 0); + } + /* Test if we already have a texture. */ - GPUTexture **tex = gpu_get_image_gputexture(ima, textarget); + GPUTexture **tex = gpu_get_tile_gputexture(tile, textarget); if (*tex) { return *tex; } @@ -485,7 +496,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget /* Check if we have a valid image. If not, we return a dummy * texture with zero bindcode so we don't keep trying. */ uint bindcode = 0; - if (ima->ok == 0) { + if (tile->ok == 0) { *tex = GPU_texture_from_bindcode(textarget, bindcode); return *tex; } @@ -861,11 +872,14 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap) for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { if (BKE_image_has_opengl_texture(ima)) { if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) { - if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - 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)); - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { + GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D]; + if (tex != NULL) { + GPU_texture_bind(tex, 0); + 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)); + GPU_texture_unbind(tex); + } } } else { @@ -880,11 +894,14 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap) else { for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { if (BKE_image_has_opengl_texture(ima)) { - if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { + GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D]; + if (tex != NULL) { + GPU_texture_bind(tex, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + GPU_texture_unbind(tex); + } } } else { @@ -897,14 +914,16 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap) 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); + ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser); + GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D]; - if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) { + if ((tex == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) { /* Full reload of texture. */ GPU_free_image(ima); } else { /* Partial update of texture. */ - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); + GPU_texture_bind(tex, 0); gpu_texture_update_from_ibuf(ima, ibuf, x, y, w, h); @@ -915,7 +934,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; } - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + GPU_texture_unbind(tex); } BKE_image_release_ibuf(ima, ibuf, NULL); @@ -1323,11 +1342,13 @@ void GPU_free_unused_buffers(Main *bmain) static void gpu_free_image_immediate(Image *ima) { - for (int i = 0; i < TEXTARGET_COUNT; i++) { - /* free glsl image binding */ - if (ima->gputexture[i]) { - GPU_texture_free(ima->gputexture[i]); - ima->gputexture[i] = NULL; + LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { + for (int i = 0; i < TEXTARGET_COUNT; i++) { + /* free glsl image binding */ + if (tile->gputexture[i] != NULL) { + GPU_texture_free(tile->gputexture[i]); + tile->gputexture[i] = NULL; + } } } |