Changeset View
Standalone View
source/blender/draw/intern/draw_manager.c
| Show First 20 Lines • Show All 2,009 Lines • ▼ Show 20 Lines | |||||
| #ifdef DEBUG | #ifdef DEBUG | ||||
| /* Avoid accidental reuse. */ | /* Avoid accidental reuse. */ | ||||
| drw_state_ensure_not_reused(&DST); | drw_state_ensure_not_reused(&DST); | ||||
| #endif | #endif | ||||
| } | } | ||||
| static struct DRWSelectBuffer { | static struct DRWSelectBuffer { | ||||
| struct GPUFrameBuffer *framebuffer; | struct GPUFrameBuffer *framebuffer_depth_only; | ||||
| struct GPUFrameBuffer *framebuffer_select_id; | |||||
| struct GPUTexture *texture_depth; | struct GPUTexture *texture_depth; | ||||
| struct GPUTexture *texture_u32; | |||||
| } g_select_buffer = {NULL}; | } g_select_buffer = {NULL}; | ||||
| static void draw_select_framebuffer_setup(const rcti *rect) | static void draw_select_framebuffer_depth_only_setup(const rcti *rect) | ||||
| { | { | ||||
| if (g_select_buffer.framebuffer == NULL) { | float size[2]; | ||||
| g_select_buffer.framebuffer = GPU_framebuffer_create(); | size[0] = BLI_rcti_size_x(rect); | ||||
| size[1] = BLI_rcti_size_y(rect); | |||||
| if (g_select_buffer.framebuffer_depth_only == NULL) { | |||||
| g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create(); | |||||
| g_select_buffer.framebuffer_select_id = GPU_framebuffer_create(); | |||||
| } | } | ||||
| /* If size mismatch recreate the texture. */ | |||||
| if ((g_select_buffer.texture_depth != NULL) && | if ((g_select_buffer.texture_depth != NULL) && | ||||
| ((GPU_texture_width(g_select_buffer.texture_depth) != BLI_rcti_size_x(rect)) || | ((GPU_texture_width(g_select_buffer.texture_depth) != size[0]) || | ||||
| (GPU_texture_height(g_select_buffer.texture_depth) != BLI_rcti_size_y(rect)))) | (GPU_texture_height(g_select_buffer.texture_depth) != size[1]))) | ||||
| { | { | ||||
| GPU_texture_free(g_select_buffer.texture_depth); | GPU_texture_free(g_select_buffer.texture_depth); | ||||
| g_select_buffer.texture_depth = NULL; | g_select_buffer.texture_depth = NULL; | ||||
| } | } | ||||
| if (g_select_buffer.texture_depth == NULL) { | if (g_select_buffer.texture_depth == NULL) { | ||||
| g_select_buffer.texture_depth = GPU_texture_create_2D( | g_select_buffer.texture_depth = GPU_texture_create_2D( | ||||
| BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GPU_DEPTH_COMPONENT24, NULL, NULL); | size[0], size[1], GPU_DEPTH_COMPONENT24, NULL, NULL); | ||||
| GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0); | GPU_framebuffer_texture_attach( | ||||
| g_select_buffer.framebuffer_depth_only, | |||||
| g_select_buffer.texture_depth, 0, 0); | |||||
fclem: What's the point in this function?
If you want to resize a texture just discard and recreate… | |||||
Done Inline ActionsEven considering the possibility of changing the rendering API, I recognize that I know well the other APIs to make the decision to create this function (I'll remove). However, this change was not due to the peformance of the OpenGL functions, but rather to the complexity of the code, since two framebuffers share the same texture. So if the pointer of a texture is invalidated, it has to be attached in both framebuffers, forcing thus the creation of both even if the second does not need to be used. This creates a bit of duplicate code and confuses a bit. But it really is not an essential change. mano-wii: Even considering the possibility of changing the rendering API, I recognize that I know well… | |||||
| if (!GPU_framebuffer_check_valid(g_select_buffer.framebuffer, NULL)) { | GPU_framebuffer_texture_attach( | ||||
| printf("Error invalid selection framebuffer\n"); | g_select_buffer.framebuffer_select_id, | ||||
| g_select_buffer.texture_depth, 0, 0); | |||||
| GPU_framebuffer_check_valid( | |||||
| g_select_buffer.framebuffer_depth_only, __func__); | |||||
| GPU_framebuffer_check_valid( | |||||
| g_select_buffer.framebuffer_select_id, __func__); | |||||
| } | } | ||||
| } | } | ||||
| static void draw_select_framebuffer_select_id_setup(const rcti *rect) | |||||
| { | |||||
| float size[2]; | |||||
| size[0] = BLI_rcti_size_x(rect); | |||||
| size[1] = BLI_rcti_size_y(rect); | |||||
| draw_select_framebuffer_depth_only_setup(rect); | |||||
| if ((g_select_buffer.texture_u32 != NULL) && | |||||
| ((GPU_texture_width(g_select_buffer.texture_u32) != size[0]) || | |||||
| (GPU_texture_height(g_select_buffer.texture_u32) != size[1]))) | |||||
| { | |||||
| GPU_texture_free(g_select_buffer.texture_u32); | |||||
| g_select_buffer.texture_u32 = NULL; | |||||
| } | |||||
| if (g_select_buffer.texture_u32 == NULL) { | |||||
| g_select_buffer.texture_u32 = GPU_texture_create_2D( | |||||
| size[0], size[1], GPU_R32UI, NULL, NULL); | |||||
| GPU_framebuffer_texture_attach( | |||||
| g_select_buffer.framebuffer_select_id, | |||||
| g_select_buffer.texture_u32, 0, 0); | |||||
| GPU_framebuffer_check_valid( | |||||
| g_select_buffer.framebuffer_select_id, __func__); | |||||
| } | |||||
| } | } | ||||
| /* Must run after all instance datas have been added. */ | /* Must run after all instance datas have been added. */ | ||||
| void DRW_render_instance_buffer_finish(void) | void DRW_render_instance_buffer_finish(void) | ||||
| { | { | ||||
| BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!"); | BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!"); | ||||
| DST.buffer_finish_called = true; | DST.buffer_finish_called = true; | ||||
| DRW_instance_buffer_finish(DST.idatalist); | DRW_instance_buffer_finish(DST.idatalist); | ||||
| ▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | #endif | ||||
| } | } | ||||
| drw_engines_cache_finish(); | drw_engines_cache_finish(); | ||||
| DRW_render_instance_buffer_finish(); | DRW_render_instance_buffer_finish(); | ||||
| } | } | ||||
| /* Setup framebuffer */ | /* Setup framebuffer */ | ||||
| draw_select_framebuffer_setup(rect); | draw_select_framebuffer_depth_only_setup(rect); | ||||
| GPU_framebuffer_bind(g_select_buffer.framebuffer); | GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only); | ||||
| GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f); | GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f); | ||||
| /* Start Drawing */ | /* Start Drawing */ | ||||
| DRW_state_reset(); | DRW_state_reset(); | ||||
| DRW_draw_callbacks_pre_scene(); | DRW_draw_callbacks_pre_scene(); | ||||
| DRW_hair_update(); | DRW_hair_update(); | ||||
| DRW_state_lock( | DRW_state_lock( | ||||
| ▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | void DRW_draw_depth_loop( | ||||
| /* Reset before using it. */ | /* Reset before using it. */ | ||||
| drw_state_prepare_clean_for_draw(&DST); | drw_state_prepare_clean_for_draw(&DST); | ||||
| struct GPUViewport *viewport = GPU_viewport_create(); | struct GPUViewport *viewport = GPU_viewport_create(); | ||||
| GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy}); | GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy}); | ||||
| /* Setup framebuffer */ | /* Setup framebuffer */ | ||||
| draw_select_framebuffer_setup(&ar->winrct); | draw_select_framebuffer_depth_only_setup(&ar->winrct); | ||||
| GPU_framebuffer_bind(g_select_buffer.framebuffer); | GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only); | ||||
| GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f); | GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f); | ||||
| DST.viewport = viewport; | DST.viewport = viewport; | ||||
| DST.options.is_depth = true; | DST.options.is_depth = true; | ||||
| /* Get list of enabled engines */ | /* Get list of enabled engines */ | ||||
| { | { | ||||
| drw_engines_enable_basic(); | drw_engines_enable_basic(); | ||||
| if (DRW_state_draw_support()) { | if (DRW_state_draw_support()) { | ||||
| ▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | #endif | ||||
| glDepthFunc(GL_ALWAYS); | glDepthFunc(GL_ALWAYS); | ||||
| draw_depth_texture_to_screen(g_select_buffer.texture_depth); | draw_depth_texture_to_screen(g_select_buffer.texture_depth); | ||||
| glDepthFunc(GL_LEQUAL); | glDepthFunc(GL_LEQUAL); | ||||
| GPU_matrix_pop(); | GPU_matrix_pop(); | ||||
| GPU_matrix_pop_projection(); | GPU_matrix_pop_projection(); | ||||
| } | } | ||||
| /* Set an opengl context to be used with shaders that draw on U32 colors. */ | |||||
| void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear) | |||||
| { | |||||
| RegionView3D *rv3d = ar->regiondata; | |||||
| DRW_opengl_context_enable(); | |||||
| /* Setup framebuffer */ | |||||
| draw_select_framebuffer_select_id_setup(&ar->winrct); | |||||
| GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); | |||||
| /* dithering and AA break color coding, so disable */ | |||||
| glDisable(GL_DITHER); | |||||
| GPU_depth_test(true); | |||||
| if (clear) { | |||||
| GPU_framebuffer_clear_color_depth( | |||||
| g_select_buffer.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); | |||||
| } | |||||
| if (rv3d->rflag & RV3D_CLIPPING) { | |||||
| ED_view3d_clipping_set(rv3d); | |||||
| } | |||||
| } | |||||
| /* Ends the context for selection and restoring the previous one. */ | |||||
| void DRW_framebuffer_select_id_release(ARegion *ar) | |||||
| { | |||||
| RegionView3D *rv3d = ar->regiondata; | |||||
| if (rv3d->rflag & RV3D_CLIPPING) { | |||||
| ED_view3d_clipping_disable(); | |||||
| } | |||||
| GPU_framebuffer_restore(); | |||||
| GPU_depth_test(false); | |||||
| glEnable(GL_DITHER); | |||||
| DRW_opengl_context_disable(); | |||||
| } | |||||
| /* Read a block of pixels from the select frame buffer. */ | |||||
| void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf) | |||||
| { | |||||
| DRW_opengl_context_enable(); | |||||
| GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); | |||||
| glReadBuffer(GL_COLOR_ATTACHMENT0); | |||||
| glReadPixels(rect->xmin, rect->ymin, | |||||
| BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), | |||||
| GL_RED_INTEGER, GL_UNSIGNED_INT, r_buf); | |||||
| GPU_framebuffer_restore(); | |||||
| DRW_opengl_context_disable(); | |||||
| } | |||||
Done Inline ActionsThis is a state change that is done on the main context, not the DRW context. Just remove the line. Any use of glReadPixels should bind the corect buffer to glReadBuffer beforehand. fclem: This is a state change that is done on the main context, not the DRW context. Just remove the… | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Draw Manager State (DRW_state) | /** \name Draw Manager State (DRW_state) | ||||
| * \{ */ | * \{ */ | ||||
| void DRW_state_dfdy_factors_get(float dfdyfac[2]) | void DRW_state_dfdy_factors_get(float dfdyfac[2]) | ||||
| ▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | if (DST.gl_context == NULL) { | ||||
| /* Nothing has been setup. Nothing to clear. | /* Nothing has been setup. Nothing to clear. | ||||
| * Otherwise, DRW_opengl_context_enable can | * Otherwise, DRW_opengl_context_enable can | ||||
| * create a context in background mode. (see T62355) */ | * create a context in background mode. (see T62355) */ | ||||
| return; | return; | ||||
| } | } | ||||
| DRW_opengl_context_enable(); | DRW_opengl_context_enable(); | ||||
| DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_u32); | |||||
| DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth); | DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth); | ||||
| GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer); | GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_select_id); | ||||
| GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only); | |||||
| DRW_hair_free(); | DRW_hair_free(); | ||||
| DRW_shape_cache_free(); | DRW_shape_cache_free(); | ||||
| DRW_stats_free(); | DRW_stats_free(); | ||||
| DRW_globals_free(); | DRW_globals_free(); | ||||
| DrawEngineType *next; | DrawEngineType *next; | ||||
| for (DrawEngineType *type = DRW_engines.first; type; type = next) { | for (DrawEngineType *type = DRW_engines.first; type; type = next) { | ||||
| ▲ Show 20 Lines • Show All 156 Lines • Show Last 20 Lines | |||||
What's the point in this function?
If you want to resize a texture just discard and recreate it. Adding new functions to the GPU API for something used only in one place (and that can be done without it) for no real performance gain is not really a good idea. If you doubt about the speed at which the driver allocates textures, resizing the viewport discard all GPU textures from all the TextureLists and it's still very fluid.
Making the GPU API more complex means that we will have more work to do when porting to vulkan/other API.
Also just as a note, I would prefer GPU_texture_new_size() to be named GPU_texture_size_set().