diff options
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 15 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 45 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 6 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 113 |
4 files changed, 139 insertions, 40 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index df8dbb03284..688386810ea 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -791,11 +791,14 @@ void GPU_pbvh_bmesh_buffers_update( tottri = gpu_bmesh_face_visible_count(bm_faces); if (buffers->smooth) { + /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */ + GWN_BATCH_DISCARD_SAFE(buffers->triangles); /* Count visible vertices */ totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts); } - else + else { totvert = tottri * 3; + } if (!tottri) { buffers->tot_tri = 0; @@ -905,13 +908,11 @@ void GPU_pbvh_bmesh_buffers_update( BMFace *f = BLI_gsetIterator_getKey(&gs_iter); if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMLoop *l_iter; - BMLoop *l_first; + BMVert *v[3]; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(l_iter->v)); - } while ((l_iter = l_iter->next) != l_first); + BM_face_as_array_vert_tri(f, v); + GWN_indexbuf_add_tri_verts( + &elb, BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2])); } } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 83fd689e3b7..7383868843d 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -140,7 +140,7 @@ static struct GPUTextureState { /* Mipmap settings */ -void GPU_set_gpu_mipmapping(int gpu_mipmap) +void GPU_set_gpu_mipmapping(Main *bmain, int gpu_mipmap) { int old_value = GTS.gpu_mipmap; @@ -148,14 +148,14 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap) GTS.gpu_mipmap = gpu_mipmap; if (old_value != GTS.gpu_mipmap) { - GPU_free_images(); + GPU_free_images(bmain); } } -void GPU_set_mipmap(bool mipmap) +void GPU_set_mipmap(Main *bmain, bool mipmap) { if (GTS.domipmap != mipmap) { - GPU_free_images(); + GPU_free_images(bmain); GTS.domipmap = mipmap; } } @@ -203,10 +203,10 @@ static GLenum gpu_get_mipmap_filter(bool mag) } /* Anisotropic filtering settings */ -void GPU_set_anisotropic(float value) +void GPU_set_anisotropic(Main *bmain, float value) { if (GTS.anisotropic != value) { - GPU_free_images(); + GPU_free_images(bmain); /* Clamp value to the maximum value the graphics card supports */ const float max = GPU_max_texture_anisotropy(); @@ -682,7 +682,7 @@ void GPU_create_gl_tex_compressed( * temporary disabling/enabling mipmapping on all images for quick texture * updates with glTexSubImage2D. images that didn't change don't have to be * re-uploaded to OpenGL */ -void GPU_paint_set_mipmap(bool mipmap) +void GPU_paint_set_mipmap(Main *bmain, bool mipmap) { if (!GTS.domipmap) return; @@ -690,7 +690,7 @@ void GPU_paint_set_mipmap(bool mipmap) GTS.texpaint = !mipmap; if (mipmap) { - for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { + for (Image *ima = bmain->image.first; ima; ima = ima->id.next) { if (BKE_image_has_opengl_texture(ima)) { if (ima->tpageflag & IMA_MIPMAP_COMPLETE) { if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { @@ -709,7 +709,7 @@ void GPU_paint_set_mipmap(bool mipmap) } else { - for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { + for (Image *ima = bmain->image.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); @@ -980,7 +980,7 @@ static void gpu_queue_image_for_free(Image *ima) BLI_thread_unlock(LOCK_OPENGL); } -void GPU_free_unused_buffers(void) +void GPU_free_unused_buffers(Main *bmain) { if (!BLI_thread_is_main()) return; @@ -992,7 +992,7 @@ void GPU_free_unused_buffers(void) Image *ima = node->link; /* check in case it was freed in the meantime */ - if (G.main && BLI_findindex(&G.main->image, ima) != -1) + if (bmain && BLI_findindex(&bmain->image, ima) != -1) GPU_free_image(ima); } @@ -1020,24 +1020,29 @@ void GPU_free_image(Image *ima) ima->tpageflag &= ~(IMA_MIPMAP_COMPLETE | IMA_GLBIND_IS_DATA); } -void GPU_free_images(void) +void GPU_free_images(Main *bmain) { - if (G.main) - for (Image *ima = G.main->image.first; ima; ima = ima->id.next) + if (bmain) { + for (Image *ima = bmain->image.first; ima; ima = ima->id.next) { GPU_free_image(ima); + } + } } /* same as above but only free animated images */ -void GPU_free_images_anim(void) +void GPU_free_images_anim(Main *bmain) { - if (G.main) - for (Image *ima = G.main->image.first; ima; ima = ima->id.next) - if (BKE_image_is_animated(ima)) + if (bmain) { + for (Image *ima = bmain->image.first; ima; ima = ima->id.next) { + if (BKE_image_is_animated(ima)) { GPU_free_image(ima); + } + } + } } -void GPU_free_images_old(void) +void GPU_free_images_old(Main *bmain) { static int lasttime = 0; int ctime = (int)PIL_check_seconds_timer(); @@ -1055,7 +1060,7 @@ void GPU_free_images_old(void) lasttime = ctime; - Image *ima = G.main->image.first; + Image *ima = bmain->image.first; while (ima) { if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) { /* If it's in GL memory, deallocate and set time tag to current time diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 302ddc62188..9c776e64ba0 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -723,16 +723,16 @@ void GPU_material_compile(GPUMaterial *mat) } } -void GPU_materials_free(void) +void GPU_materials_free(Main *bmain) { Material *ma; World *wo; extern Material defmaterial; - for (ma = G.main->mat.first; ma; ma = ma->id.next) + for (ma = bmain->mat.first; ma; ma = ma->id.next) GPU_material_free(&ma->gpumaterial); - for (wo = G.main->world.first; wo; wo = wo->id.next) + for (wo = bmain->world.first; wo; wo = wo->id.next) GPU_material_free(&wo->gpumaterial); GPU_material_free(&defmaterial.gpumaterial); diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index ee00a1381f4..21a3aee5f57 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -171,6 +171,10 @@ static GLenum gpu_texture_get_format( default: break; } } + else if (ELEM(data_type, GPU_R8)) { + *data_format = GL_UNSIGNED_BYTE; + *format = GL_RED; + } else { *data_format = GL_FLOAT; *format_flag |= GPU_FORMAT_FLOAT; @@ -882,37 +886,58 @@ GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert) return GPU_texture_create_buffer(data_type, vert->vbo_id); } -void GPU_texture_update(GPUTexture *tex, const float *pixels) +void GPU_texture_update_sub( + GPUTexture *tex, const void *pixels, + int offset_x, int offset_y, int offset_z, int width, int height, int depth) { - BLI_assert(tex->format > -1); + BLI_assert((int)tex->format > -1); BLI_assert(tex->components > -1); GLenum format, data_format; + GLint alignment; gpu_texture_get_format(tex->components, tex->format, &format, &data_format, - &tex->format_flag, &tex->bytesize); + &tex->format_flag, &tex->bytesize); - glBindTexture(tex->target, tex->bindcode); + /* The default pack size for textures is 4, which won't work for byte based textures */ + if (tex->bytesize == 1) { + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + } + glBindTexture(tex->target, tex->bindcode); switch (tex->target) { case GL_TEXTURE_2D: case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_1D_ARRAY: - glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pixels); + glTexSubImage2D( + tex->target, 0, offset_x, offset_y, + width, height, format, data_format, pixels); break; case GL_TEXTURE_1D: - glTexSubImage1D(tex->target, 0, 0, tex->w, format, data_format, pixels); + glTexSubImage1D(tex->target, 0, offset_x, width, format, data_format, pixels); break; case GL_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: - glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->d, format, data_format, pixels); + glTexSubImage3D( + tex->target, 0, offset_x, offset_y, offset_z, + width, height, depth, format, data_format, pixels); break; default: BLI_assert(!"tex->target mode not supported"); } + if (tex->bytesize == 1) { + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); + } + glBindTexture(tex->target, 0); } +void GPU_texture_update(GPUTexture *tex, const void *pixels) +{ + GPU_texture_update_sub(tex, pixels, 0, 0, 0, tex->w, tex->h, tex->d); +} + void GPU_invalid_tex_init(void) { memory_usage = 0; @@ -1045,9 +1070,10 @@ void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter) BLI_assert((!use_filter && !use_mipmap) || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST; - GLenum mipmap = (use_filter) - ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR - : (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST; + GLenum mipmap = ( + (use_filter) ? + (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR : + (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST); glActiveTexture(GL_TEXTURE0 + tex->number); glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap); @@ -1068,6 +1094,33 @@ void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat) glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat); } +static GLenum gpu_get_gl_filterfunction(GPUFilterFunction filter) +{ + switch (filter) { + case GPU_NEAREST: + return GL_NEAREST; + case GPU_LINEAR: + return GL_LINEAR; + default: + BLI_assert(!"Unhandled filter mode"); + return GL_NEAREST; + } +} + +void GPU_texture_filters(GPUTexture *tex, GPUFilterFunction min_filter, GPUFilterFunction mag_filter) +{ + WARN_NOT_BOUND(tex); + + /* Stencil and integer format does not support filtering. */ + BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); + BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR); + + glActiveTexture(GL_TEXTURE0 + tex->number); + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter)); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter)); +} + + static void gpu_texture_delete(GPUTexture *tex) { if (tex->bindcode) @@ -1207,3 +1260,43 @@ int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb) BLI_assert(!"Error: Texture: Framebuffer is not attached"); return 0; } + +void GPU_blend(bool enable) +{ + if (enable) { + glEnable(GL_BLEND); + } + else { + glDisable(GL_BLEND); + } +} + +static GLenum gpu_get_gl_blendfunction(GPUBlendFunction blend) +{ + switch (blend) { + case GPU_ONE: + return GL_ONE; + case GPU_SRC_ALPHA: + return GL_SRC_ALPHA; + case GPU_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + default: + BLI_assert(!"Unhandled blend mode"); + return GL_ZERO; + } +} + +void GPU_blend_set_func_separate( + GPUBlendFunction src_rgb, GPUBlendFunction dst_rgb, + GPUBlendFunction src_alpha, GPUBlendFunction dst_alpha) +{ + glBlendFuncSeparate(gpu_get_gl_blendfunction(src_rgb), + gpu_get_gl_blendfunction(dst_rgb), + gpu_get_gl_blendfunction(src_alpha), + gpu_get_gl_blendfunction(dst_alpha)); +} + +void GPU_blend_set_func(GPUBlendFunction sfactor, GPUBlendFunction dfactor) +{ + glBlendFunc(gpu_get_gl_blendfunction(sfactor), gpu_get_gl_blendfunction(dfactor)); +} |