Changeset View
Changeset View
Standalone View
Standalone View
source/blender/windowmanager/intern/wm_draw.c
| Show First 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | static void wm_region_test_render_do_draw(const Scene *scene, | ||||
| struct Depsgraph *depsgraph, | struct Depsgraph *depsgraph, | ||||
| ScrArea *sa, | ScrArea *sa, | ||||
| ARegion *region) | ARegion *region) | ||||
| { | { | ||||
| /* tag region for redraw from render engine preview running inside of it */ | /* tag region for redraw from render engine preview running inside of it */ | ||||
| if (sa->spacetype == SPACE_VIEW3D && region->regiontype == RGN_TYPE_WINDOW) { | if (sa->spacetype == SPACE_VIEW3D && region->regiontype == RGN_TYPE_WINDOW) { | ||||
| RegionView3D *rv3d = region->regiondata; | RegionView3D *rv3d = region->regiondata; | ||||
| RenderEngine *engine = rv3d->render_engine; | RenderEngine *engine = rv3d->render_engine; | ||||
| GPUViewport *viewport = WM_draw_region_get_viewport(region, 0); | GPUViewport *viewport = WM_draw_region_get_viewport(region); | ||||
| if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) { | if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) { | ||||
| View3D *v3d = sa->spacedata.first; | View3D *v3d = sa->spacedata.first; | ||||
| rcti border_rect; | rcti border_rect; | ||||
| /* do partial redraw when possible */ | /* do partial redraw when possible */ | ||||
| if (ED_view3d_calc_render_border(scene, depsgraph, v3d, region, &border_rect)) { | if (ED_view3d_calc_render_border(scene, depsgraph, v3d, region, &border_rect)) { | ||||
| ED_region_tag_redraw_partial(region, &border_rect, false); | ED_region_tag_redraw_partial(region, &border_rect, false); | ||||
| ▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
| static void wm_draw_region_buffer_free(ARegion *region) | static void wm_draw_region_buffer_free(ARegion *region) | ||||
| { | { | ||||
| if (region->draw_buffer) { | if (region->draw_buffer) { | ||||
| for (int view = 0; view < 2; view++) { | for (int view = 0; view < 2; view++) { | ||||
| if (region->draw_buffer->offscreen[view]) { | if (region->draw_buffer->offscreen[view]) { | ||||
| GPU_offscreen_free(region->draw_buffer->offscreen[view]); | GPU_offscreen_free(region->draw_buffer->offscreen[view]); | ||||
| } | } | ||||
| if (region->draw_buffer->viewport[view]) { | |||||
| GPU_viewport_free(region->draw_buffer->viewport[view]); | |||||
| } | } | ||||
| if (region->draw_buffer->viewport) { | |||||
| GPU_viewport_free(region->draw_buffer->viewport); | |||||
| } | } | ||||
| MEM_freeN(region->draw_buffer); | MEM_freeN(region->draw_buffer); | ||||
| region->draw_buffer = NULL; | region->draw_buffer = NULL; | ||||
| } | } | ||||
| } | } | ||||
| static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) | static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) | ||||
| { | { | ||||
| /* Setup offscreen color texture for drawing. */ | /* Setup offscreen color texture for drawing. */ | ||||
| GPUTexture *texture = GPU_offscreen_color_texture(offscreen); | GPUTexture *texture = GPU_offscreen_color_texture(offscreen); | ||||
| /* We don't support multisample textures here. */ | /* We don't support multisample textures here. */ | ||||
| BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D); | BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D); | ||||
| glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); | glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); | ||||
| /* No mipmaps or filtering. */ | /* No mipmaps or filtering. */ | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); | ||||
| /* GL_TEXTURE_BASE_LEVEL = 0 by default */ | /* GL_TEXTURE_BASE_LEVEL = 0 by default */ | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
| glBindTexture(GL_TEXTURE_2D, 0); | glBindTexture(GL_TEXTURE_2D, 0); | ||||
| } | } | ||||
| static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_viewport) | static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_viewport) | ||||
| { | { | ||||
| if (region->draw_buffer) { | if (region->draw_buffer) { | ||||
| if (region->draw_buffer->stereo != stereo) { | if (region->draw_buffer->stereo != stereo) { | ||||
| /* Free draw buffer on stereo changes. */ | /* Free draw buffer on stereo changes. */ | ||||
| Show All 9 Lines | if (region->draw_buffer) { | ||||
| } | } | ||||
| } | } | ||||
| if (!region->draw_buffer) { | if (!region->draw_buffer) { | ||||
| if (use_viewport) { | if (use_viewport) { | ||||
| /* Allocate viewport which includes an offscreen buffer with depth | /* Allocate viewport which includes an offscreen buffer with depth | ||||
| * multisample, etc. */ | * multisample, etc. */ | ||||
| region->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); | region->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); | ||||
| region->draw_buffer->viewport[0] = GPU_viewport_create(); | region->draw_buffer->viewport = GPU_viewport_create(stereo); | ||||
| region->draw_buffer->viewport[1] = (stereo) ? GPU_viewport_create() : NULL; | |||||
| } | } | ||||
| else { | else { | ||||
| /* Allocate offscreen buffer if it does not exist. This one has no | /* Allocate offscreen buffer if it does not exist. This one has no | ||||
| * depth or multisample buffers. 3D view creates own buffers with | * depth or multisample buffers. 3D view creates own buffers with | ||||
| * the data it needs. */ | * the data it needs. */ | ||||
| GPUOffScreen *offscreen = GPU_offscreen_create( | GPUOffScreen *offscreen = GPU_offscreen_create( | ||||
| region->winx, region->winy, 0, false, false, NULL); | region->winx, region->winy, 0, false, false, NULL); | ||||
| if (!offscreen) { | if (!offscreen) { | ||||
| Show All 25 Lines | |||||
| } | } | ||||
| static void wm_draw_region_bind(ARegion *region, int view) | static void wm_draw_region_bind(ARegion *region, int view) | ||||
| { | { | ||||
| if (!region->draw_buffer) { | if (!region->draw_buffer) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (region->draw_buffer->viewport[view]) { | if (region->draw_buffer->viewport) { | ||||
| GPU_viewport_bind(region->draw_buffer->viewport[view], ®ion->winrct); | GPU_viewport_bind(region->draw_buffer->viewport, view, ®ion->winrct); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_offscreen_bind(region->draw_buffer->offscreen[view], false); | GPU_offscreen_bind(region->draw_buffer->offscreen[view], false); | ||||
| /* For now scissor is expected by region drawing, we could disable it | /* For now scissor is expected by region drawing, we could disable it | ||||
| * and do the enable/disable in the specific cases that setup scissor. */ | * and do the enable/disable in the specific cases that setup scissor. */ | ||||
| glEnable(GL_SCISSOR_TEST); | glEnable(GL_SCISSOR_TEST); | ||||
| glScissor(0, 0, region->winx, region->winy); | glScissor(0, 0, region->winx, region->winy); | ||||
| } | } | ||||
| region->draw_buffer->bound_view = view; | region->draw_buffer->bound_view = view; | ||||
| } | } | ||||
| static void wm_draw_region_unbind(ARegion *region, int view) | static void wm_draw_region_unbind(ARegion *region, int view) | ||||
| { | { | ||||
| if (!region->draw_buffer) { | if (!region->draw_buffer) { | ||||
| return; | return; | ||||
| } | } | ||||
| region->draw_buffer->bound_view = -1; | region->draw_buffer->bound_view = -1; | ||||
| if (region->draw_buffer->viewport[view]) { | if (region->draw_buffer->viewport) { | ||||
| GPU_viewport_unbind(region->draw_buffer->viewport[view]); | GPU_viewport_unbind(region->draw_buffer->viewport); | ||||
| } | } | ||||
| else { | else { | ||||
| glDisable(GL_SCISSOR_TEST); | glDisable(GL_SCISSOR_TEST); | ||||
| GPU_offscreen_unbind(region->draw_buffer->offscreen[view], false); | GPU_offscreen_unbind(region->draw_buffer->offscreen[view], false); | ||||
| } | } | ||||
| } | } | ||||
| static void wm_draw_region_blit(ARegion *region, int view) | static void wm_draw_region_blit(ARegion *region, int view) | ||||
| { | { | ||||
| if (!region->draw_buffer) { | if (!region->draw_buffer) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (view == -1) { | if (view == -1) { | ||||
| /* Non-stereo drawing. */ | /* Non-stereo drawing. */ | ||||
| view = 0; | view = 0; | ||||
| } | } | ||||
| else if (view > 0) { | else if (view > 0) { | ||||
| if (region->draw_buffer->viewport[view] == NULL && | if (region->draw_buffer->viewport == NULL && region->draw_buffer->offscreen[view] == NULL) { | ||||
| region->draw_buffer->offscreen[view] == NULL) { | |||||
| /* Region does not need stereo or failed to allocate stereo buffers. */ | /* Region does not need stereo or failed to allocate stereo buffers. */ | ||||
| view = 0; | view = 0; | ||||
| } | } | ||||
| } | } | ||||
| if (region->draw_buffer->viewport[view]) { | if (region->draw_buffer->viewport) { | ||||
| GPU_viewport_draw_to_screen(region->draw_buffer->viewport[view], ®ion->winrct); | GPU_viewport_draw_to_screen(region->draw_buffer->viewport, view, ®ion->winrct); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_offscreen_draw_to_screen( | GPU_offscreen_draw_to_screen( | ||||
| region->draw_buffer->offscreen[view], region->winrct.xmin, region->winrct.ymin); | region->draw_buffer->offscreen[view], region->winrct.xmin, region->winrct.ymin); | ||||
| } | } | ||||
| } | } | ||||
| GPUTexture *wm_draw_region_texture(ARegion *region, int view) | GPUTexture *wm_draw_region_texture(ARegion *region, int view) | ||||
| { | { | ||||
| if (!region->draw_buffer) { | if (!region->draw_buffer) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (region->draw_buffer->viewport[view]) { | GPUViewport *viewport = region->draw_buffer->viewport; | ||||
| return GPU_viewport_color_texture(region->draw_buffer->viewport[view]); | if (viewport) { | ||||
| return GPU_viewport_color_texture(viewport, view); | |||||
| } | } | ||||
| else { | else { | ||||
| return GPU_offscreen_color_texture(region->draw_buffer->offscreen[view]); | return GPU_offscreen_color_texture(region->draw_buffer->offscreen[view]); | ||||
| } | } | ||||
| } | } | ||||
| void wm_draw_region_blend(ARegion *region, int view, bool blend) | void wm_draw_region_blend(ARegion *region, int view, bool blend) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | void wm_draw_region_blend(ARegion *region, int view, bool blend) | ||||
| glBindTexture(GL_TEXTURE_2D, 0); | glBindTexture(GL_TEXTURE_2D, 0); | ||||
| if (blend) { | if (blend) { | ||||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
| GPU_blend(false); | GPU_blend(false); | ||||
| } | } | ||||
| } | } | ||||
| GPUViewport *WM_draw_region_get_viewport(ARegion *region, int view) | GPUViewport *WM_draw_region_get_viewport(ARegion *region) | ||||
fclem: The only part where the view is really required is `DRW_notify_view_update`.
This is the only… | |||||
| { | { | ||||
| if (!region->draw_buffer) { | if (!region->draw_buffer) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| return region->draw_buffer->viewport[view]; | GPUViewport *viewport = region->draw_buffer->viewport; | ||||
| return viewport; | |||||
| } | } | ||||
| GPUViewport *WM_draw_region_get_bound_viewport(ARegion *region) | GPUViewport *WM_draw_region_get_bound_viewport(ARegion *region) | ||||
Done Inline ActionsThis can be removed and replaced by wm_region_use_viewport. fclem: This can be removed and replaced by wm_region_use_viewport. | |||||
Done Inline ActionsNot sure, wouldn't that fail in DRW_draw_render_loop_ex? if (WM_draw_region_get_bound_viewport(region)) {
/* Don't unbind the framebuffer yet in this case and let
* GPU_viewport_unbind do it, so that we can still do further
* drawing of action zones on top. */
}jbakker: Not sure, wouldn't that fail in DRW_draw_render_loop_ex?
```
if… | |||||
Done Inline ActionsIn this instance it only checks if we are rendering of this areas or for offscreen or for window display. Anyways that's a bit of a bad level call even. We should take this decision from a DRW state not from the area state. Leave it as is for now. fclem: In this instance it only checks if we are rendering of this areas or for offscreen or for… | |||||
| { | { | ||||
| if (!region->draw_buffer || region->draw_buffer->bound_view == -1) { | if (!region->draw_buffer || region->draw_buffer->bound_view == -1) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| int view = region->draw_buffer->bound_view; | GPUViewport *viewport = region->draw_buffer->viewport; | ||||
| return region->draw_buffer->viewport[view]; | return viewport; | ||||
| } | } | ||||
| static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) | static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| bScreen *screen = WM_window_get_active_screen(win); | bScreen *screen = WM_window_get_active_screen(win); | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | for (ARegion *region = sa->regionbase.first; region; region = region->next) { | ||||
| sview = STEREO_RIGHT_ID; | sview = STEREO_RIGHT_ID; | ||||
| wm_draw_region_stereo_set(bmain, sa, region, sview); | wm_draw_region_stereo_set(bmain, sa, region, sview); | ||||
| } | } | ||||
| wm_draw_region_bind(region, view); | wm_draw_region_bind(region, view); | ||||
| ED_region_do_draw(C, region); | ED_region_do_draw(C, region); | ||||
| wm_draw_region_unbind(region, view); | wm_draw_region_unbind(region, view); | ||||
| } | } | ||||
| if (use_viewport) { | |||||
| GPUViewport *viewport = region->draw_buffer->viewport; | |||||
| GPU_viewport_stereo_composite(viewport, win->stereo3d_format); | |||||
| } | |||||
Done Inline ActionsSo if I understand correctly, you are mixing the stereo views here and saving the result in the first view. fclem: So if I understand correctly, you are mixing the stereo views here and saving the result in the… | |||||
Done Inline ActionsYes as pixels do not move we don't need additional textures for the merging. The color management process is then also straight forward. I will add a Comment to the GPU_viewport_stereo_composite function. jbakker: Yes as pixels do not move we don't need additional textures for the merging. The color… | |||||
| } | } | ||||
| else { | else { | ||||
| wm_draw_region_buffer_create(region, false, use_viewport); | wm_draw_region_buffer_create(region, false, use_viewport); | ||||
| wm_draw_region_bind(region, 0); | wm_draw_region_bind(region, 0); | ||||
| ED_region_do_draw(C, region); | ED_region_do_draw(C, region); | ||||
| wm_draw_region_unbind(region, 0); | wm_draw_region_unbind(region, 0); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | #if 0 | ||||
| glClearColor(0, 0, 0, 0); | glClearColor(0, 0, 0, 0); | ||||
| glClear(GL_COLOR_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT); | ||||
| #endif | #endif | ||||
| /* Blit non-overlapping area regions. */ | /* Blit non-overlapping area regions. */ | ||||
| ED_screen_areas_iter(win, screen, sa) | ED_screen_areas_iter(win, screen, sa) | ||||
| { | { | ||||
| for (ARegion *region = sa->regionbase.first; region; region = region->next) { | for (ARegion *region = sa->regionbase.first; region; region = region->next) { | ||||
| if (region->visible && region->overlap == false) { | if (region->visible && region->overlap == false) { | ||||
| if (view == -1 && region->draw_buffer && region->draw_buffer->stereo) { | |||||
| /* Stereo drawing from textures. */ | |||||
| if (win->stereo3d_format->display_mode == S3D_DISPLAY_ANAGLYPH) { | |||||
| wm_stereo3d_draw_anaglyph(win, region); | |||||
| } | |||||
| else { | |||||
| wm_stereo3d_draw_interlace(win, region); | |||||
| } | |||||
| } | |||||
| else { | |||||
| /* Blit from offscreen buffer. */ | /* Blit from offscreen buffer. */ | ||||
Done Inline Actionsremove branch if there is nothing different in both branches fclem: remove branch if there is nothing different in both branches | |||||
| wm_draw_region_blit(region, view); | wm_draw_region_blit(region, view); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| /* Draw paint cursors. */ | /* Draw paint cursors. */ | ||||
| if (wm->paintcursors.first) { | if (wm->paintcursors.first) { | ||||
| ED_screen_areas_iter(win, screen, sa) | ED_screen_areas_iter(win, screen, sa) | ||||
| { | { | ||||
| for (ARegion *region = sa->regionbase.first; region; region = region->next) { | for (ARegion *region = sa->regionbase.first; region; region = region->next) { | ||||
| if (region->visible && region == screen->active_region) { | if (region->visible && region == screen->active_region) { | ||||
| CTX_wm_area_set(C, sa); | CTX_wm_area_set(C, sa); | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | if (wm->drags.first) { | ||||
| wm_drags_draw(C, win, NULL); | wm_drags_draw(C, win, NULL); | ||||
| } | } | ||||
| } | } | ||||
| static void wm_draw_window(bContext *C, wmWindow *win) | static void wm_draw_window(bContext *C, wmWindow *win) | ||||
| { | { | ||||
| bScreen *screen = WM_window_get_active_screen(win); | bScreen *screen = WM_window_get_active_screen(win); | ||||
| bool stereo = WM_stereo3d_enabled(win, false); | bool stereo = WM_stereo3d_enabled(win, false); | ||||
| /* Draw area regions into their own framebuffer. This way we can redraw | /* Draw area regions into their own framebuffer. This way we can redraw | ||||
| * the areas that need it, and blit the rest from existing framebuffers. */ | * the areas that need it, and blit the rest from existing framebuffers. */ | ||||
| wm_draw_window_offscreen(C, win, stereo); | wm_draw_window_offscreen(C, win, stereo); | ||||
| /* Now we draw into the window framebuffer, in full window coordinates. */ | /* Now we draw into the window framebuffer, in full window coordinates. */ | ||||
| if (!stereo) { | if (!stereo) { | ||||
| /* Regular mono drawing. */ | /* Regular mono drawing. */ | ||||
| wm_draw_window_onscreen(C, win, -1); | wm_draw_window_onscreen(C, win, -1); | ||||
| ▲ Show 20 Lines • Show All 249 Lines • Show Last 20 Lines | |||||
The only part where the view is really required is DRW_notify_view_update.
This is the only time I found GPU_viewport_framebuffer_view_set is required. Can we workaround this by having a function call for this only in DRW_notify_view_update?