Changeset View
Changeset View
Standalone View
Standalone View
source/blender/windowmanager/intern/wm_stereo.c
| Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_report.h" | #include "BKE_report.h" | ||||
| #include "GHOST_C-api.h" | #include "GHOST_C-api.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "GPU_immediate.h" | #include "GPU_immediate.h" | ||||
| #include "GPU_framebuffer.h" | |||||
| #include "GPU_texture.h" | |||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "wm.h" | #include "wm.h" | ||||
| #include "wm_draw.h" /* wmDrawTriple */ | #include "wm_draw.h" | ||||
| #include "wm_window.h" | #include "wm_window.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| static void wm_method_draw_stereo3d_pageflip(wmWindow *win) | |||||
| { | |||||
| wmDrawData *drawdata; | |||||
| int view; | |||||
| for (view = 0; view < 2; view ++) { | |||||
| drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); | |||||
| if (view == STEREO_LEFT_ID) | |||||
| glDrawBuffer(GL_BACK_LEFT); | |||||
| else //STEREO_RIGHT_ID | |||||
| glDrawBuffer(GL_BACK_RIGHT); | |||||
| wm_triple_draw_textures(win, drawdata->triple, 1.0f); | |||||
| } | |||||
| glDrawBuffer(GL_BACK); | |||||
| } | |||||
| static GPUInterlaceShader interlace_gpu_id_from_type(eStereo3dInterlaceType interlace_type) | static GPUInterlaceShader interlace_gpu_id_from_type(eStereo3dInterlaceType interlace_type) | ||||
| { | { | ||||
| switch (interlace_type) { | switch (interlace_type) { | ||||
| case S3D_INTERLACE_ROW: | case S3D_INTERLACE_ROW: | ||||
| return GPU_SHADER_INTERLACE_ROW; | return GPU_SHADER_INTERLACE_ROW; | ||||
| case S3D_INTERLACE_COLUMN: | case S3D_INTERLACE_COLUMN: | ||||
| return GPU_SHADER_INTERLACE_COLUMN; | return GPU_SHADER_INTERLACE_COLUMN; | ||||
| case S3D_INTERLACE_CHECKERBOARD: | case S3D_INTERLACE_CHECKERBOARD: | ||||
| default: | default: | ||||
| return GPU_SHADER_INTERLACE_CHECKER; | return GPU_SHADER_INTERLACE_CHECKER; | ||||
| } | } | ||||
| } | } | ||||
| static void wm_method_draw_stereo3d_interlace(wmWindow *win) | void wm_stereo3d_draw_interlace(wmWindow *win, ARegion *ar) | ||||
| { | { | ||||
| bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0; | bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0; | ||||
| enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type; | enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type; | ||||
| wmDrawData *drawdata[2]; | |||||
| for (int eye = 0; eye < 2; eye++) { | |||||
| int view = swap ? !eye : eye; | |||||
| drawdata[eye] = BLI_findlink(&win->drawdata, (view * 2) + 1); | |||||
| } | |||||
| const int sizex = WM_window_pixels_x(win); | |||||
| const int sizey = WM_window_pixels_y(win); | |||||
| /* wmOrtho for the screen has this same offset */ | /* wmOrtho for the screen has this same offset */ | ||||
| float ratiox = 1.0f; | float halfx = GLA_PIXEL_OFS / ar->winx; | ||||
| float ratioy = 1.0f; | float halfy = GLA_PIXEL_OFS / ar->winy; | ||||
| float halfx = GLA_PIXEL_OFS / sizex; | |||||
| float halfy = GLA_PIXEL_OFS / sizex; | |||||
| Gwn_VertFormat *format = immVertexFormat(); | Gwn_VertFormat *format = immVertexFormat(); | ||||
| unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | ||||
| unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | ||||
| immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE); | /* leave GL_TEXTURE0 as the latest active texture */ | ||||
| for (int view = 1; view >= 0; view--) { | |||||
| /* leave GL_TEXTURE0 as the latest bind texture */ | GPUTexture *texture = wm_draw_region_texture(ar, view); | ||||
| for (int eye = 1; eye >= 0; eye--) { | glActiveTexture(GL_TEXTURE0 + view); | ||||
| glActiveTexture(GL_TEXTURE0 + eye); | glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); | ||||
| glBindTexture(GL_TEXTURE_2D, drawdata[eye]->triple->bind); | |||||
| } | } | ||||
| immUniform1i("image_a", 0); | immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE); | ||||
| immUniform1i("image_b", 1); | immUniform1i("image_a", (swap)? 1: 0); | ||||
| immUniform1i("image_b", (swap)? 0: 1); | |||||
| immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type)); | immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type)); | ||||
| immBegin(GWN_PRIM_TRI_FAN, 4); | immBegin(GWN_PRIM_TRI_FAN, 4); | ||||
| immAttrib2f(texcoord, halfx, halfy); | immAttrib2f(texcoord, halfx, halfy); | ||||
| immVertex2f(pos, 0.0f, 0.0f); | immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymin); | ||||
| immAttrib2f(texcoord, ratiox + halfx, halfy); | immAttrib2f(texcoord, 1.0f + halfx, halfy); | ||||
| immVertex2f(pos, sizex, 0.0f); | immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymin); | ||||
| immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy); | immAttrib2f(texcoord, 1.0f + halfx, 1.0f + halfy); | ||||
| immVertex2f(pos, sizex, sizey); | immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymax + 1); | ||||
| immAttrib2f(texcoord, halfx, ratioy + halfy); | immAttrib2f(texcoord, halfx, 1.0f + halfy); | ||||
| immVertex2f(pos, 0.0f, sizey); | immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymax + 1); | ||||
| immEnd(); | immEnd(); | ||||
| immUnbindProgram(); | immUnbindProgram(); | ||||
| for (int eye = 1; eye >= 0; eye--) { | for (int view = 1; view >= 0; view--) { | ||||
| glActiveTexture(GL_TEXTURE0 + eye); | glActiveTexture(GL_TEXTURE0 + view); | ||||
| glBindTexture(GL_TEXTURE_2D, 0); | glBindTexture(GL_TEXTURE_2D, 0); | ||||
| } | } | ||||
| } | } | ||||
| static void wm_method_draw_stereo3d_anaglyph(wmWindow *win) | void wm_stereo3d_draw_anaglyph(wmWindow *win, ARegion *ar) | ||||
| { | { | ||||
| wmDrawData *drawdata; | for (int view = 0; view < 2; view ++) { | ||||
| int view, bit; | int bit = view + 1; | ||||
| for (view = 0; view < 2; view ++) { | |||||
| drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); | |||||
| bit = view + 1; | |||||
| switch (win->stereo3d_format->anaglyph_type) { | switch (win->stereo3d_format->anaglyph_type) { | ||||
| case S3D_ANAGLYPH_REDCYAN: | case S3D_ANAGLYPH_REDCYAN: | ||||
| glColorMask((1&bit) ? GL_TRUE : GL_FALSE, | glColorMask((1&bit) ? GL_TRUE : GL_FALSE, | ||||
| (2&bit) ? GL_TRUE : GL_FALSE, | (2&bit) ? GL_TRUE : GL_FALSE, | ||||
| (2&bit) ? GL_TRUE : GL_FALSE, | (2&bit) ? GL_TRUE : GL_FALSE, | ||||
| GL_FALSE); | GL_FALSE); | ||||
| break; | break; | ||||
| case S3D_ANAGLYPH_GREENMAGENTA: | case S3D_ANAGLYPH_GREENMAGENTA: | ||||
| glColorMask((2&bit) ? GL_TRUE : GL_FALSE, | glColorMask((2&bit) ? GL_TRUE : GL_FALSE, | ||||
| (1&bit) ? GL_TRUE : GL_FALSE, | (1&bit) ? GL_TRUE : GL_FALSE, | ||||
| (2&bit) ? GL_TRUE : GL_FALSE, | (2&bit) ? GL_TRUE : GL_FALSE, | ||||
| GL_FALSE); | GL_FALSE); | ||||
| break; | break; | ||||
| case S3D_ANAGLYPH_YELLOWBLUE: | case S3D_ANAGLYPH_YELLOWBLUE: | ||||
| glColorMask((1&bit) ? GL_TRUE : GL_FALSE, | glColorMask((1&bit) ? GL_TRUE : GL_FALSE, | ||||
| (1&bit) ? GL_TRUE : GL_FALSE, | (1&bit) ? GL_TRUE : GL_FALSE, | ||||
| (2&bit) ? GL_TRUE : GL_FALSE, | (2&bit) ? GL_TRUE : GL_FALSE, | ||||
| GL_FALSE); | GL_FALSE); | ||||
| break; | break; | ||||
| } | } | ||||
| wm_triple_draw_textures(win, drawdata->triple, 1.0f); | wm_draw_region_blend(ar, view, false); | ||||
| } | |||||
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||||
| } | } | ||||
| } | |||||
| static void wm_method_draw_stereo3d_sidebyside(wmWindow *win) | void wm_stereo3d_draw_sidebyside(wmWindow *win, int view) | ||||
| { | { | ||||
| wmDrawData *drawdata; | |||||
| wmDrawTriple *triple; | |||||
| int view; | |||||
| int soffx; | |||||
| bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0; | bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0; | ||||
| Gwn_VertFormat *format = immVertexFormat(); | Gwn_VertFormat *format = immVertexFormat(); | ||||
| unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | ||||
| unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | ||||
| immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA); | immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); | ||||
| glActiveTexture(GL_TEXTURE0); | |||||
| for (view = 0; view < 2; view ++) { | |||||
| drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); | |||||
| triple = drawdata->triple; | |||||
| soffx = WM_window_pixels_x(win) * 0.5f; | int soffx = WM_window_pixels_x(win) * 0.5f; | ||||
| if (view == STEREO_LEFT_ID) { | if (view == STEREO_LEFT_ID) { | ||||
| if (!cross_eyed) | if (!cross_eyed) | ||||
| soffx = 0; | soffx = 0; | ||||
| } | } | ||||
| else { //RIGHT_LEFT_ID | else { //RIGHT_LEFT_ID | ||||
| if (cross_eyed) | if (cross_eyed) | ||||
| soffx = 0; | soffx = 0; | ||||
| } | } | ||||
| const int sizex = WM_window_pixels_x(win); | const int sizex = WM_window_pixels_x(win); | ||||
| const int sizey = WM_window_pixels_y(win); | const int sizey = WM_window_pixels_y(win); | ||||
| /* wmOrtho for the screen has this same offset */ | /* wmOrtho for the screen has this same offset */ | ||||
| const float ratiox = 1.0f; | |||||
| const float ratioy = 1.0f; | |||||
| const float halfx = GLA_PIXEL_OFS / sizex; | const float halfx = GLA_PIXEL_OFS / sizex; | ||||
| const float halfy = GLA_PIXEL_OFS / sizey; | const float halfy = GLA_PIXEL_OFS / sizex; | ||||
| glBindTexture(GL_TEXTURE_2D, triple->bind); | |||||
| immUniform1f("alpha", 1.0f); | immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ | ||||
| immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ | |||||
| immBegin(GWN_PRIM_TRI_FAN, 4); | immBegin(GWN_PRIM_TRI_FAN, 4); | ||||
| immAttrib2f(texcoord, halfx, halfy); | immAttrib2f(texcoord, halfx, halfy); | ||||
| immVertex2f(pos, soffx, 0.0f); | immVertex2f(pos, soffx, 0.0f); | ||||
| immAttrib2f(texcoord, ratiox + halfx, halfy); | immAttrib2f(texcoord, 1.0f + halfx, halfy); | ||||
| immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f); | immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f); | ||||
| immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy); | immAttrib2f(texcoord, 1.0f + halfx, 1.0f + halfy); | ||||
| immVertex2f(pos, soffx + (sizex * 0.5f), sizey); | immVertex2f(pos, soffx + (sizex * 0.5f), sizey); | ||||
| immAttrib2f(texcoord, halfx, ratioy + halfy); | immAttrib2f(texcoord, halfx, 1.0f + halfy); | ||||
| immVertex2f(pos, soffx, sizey); | immVertex2f(pos, soffx, sizey); | ||||
| immEnd(); | immEnd(); | ||||
| } | |||||
| glBindTexture(GL_TEXTURE_2D, 0); | |||||
| immUnbindProgram(); | immUnbindProgram(); | ||||
| } | } | ||||
| static void wm_method_draw_stereo3d_topbottom(wmWindow *win) | void wm_stereo3d_draw_topbottom(wmWindow *win, int view) | ||||
| { | { | ||||
| wmDrawData *drawdata; | |||||
| wmDrawTriple *triple; | |||||
| int view; | |||||
| int soffy; | |||||
| Gwn_VertFormat *format = immVertexFormat(); | Gwn_VertFormat *format = immVertexFormat(); | ||||
| unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | ||||
| unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); | ||||
| immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA); | immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); | ||||
| glActiveTexture(GL_TEXTURE0); | |||||
| for (view = 0; view < 2; view ++) { | |||||
| drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); | |||||
| triple = drawdata->triple; | |||||
| int soffy; | |||||
| if (view == STEREO_LEFT_ID) { | if (view == STEREO_LEFT_ID) { | ||||
| soffy = WM_window_pixels_y(win) * 0.5f; | soffy = WM_window_pixels_y(win) * 0.5f; | ||||
| } | } | ||||
| else { /* STEREO_RIGHT_ID */ | else { /* STEREO_RIGHT_ID */ | ||||
| soffy = 0; | soffy = 0; | ||||
| } | } | ||||
| const int sizex = WM_window_pixels_x(win); | const int sizex = WM_window_pixels_x(win); | ||||
| const int sizey = WM_window_pixels_y(win); | const int sizey = WM_window_pixels_y(win); | ||||
| /* wmOrtho for the screen has this same offset */ | /* wmOrtho for the screen has this same offset */ | ||||
| const float ratiox = 1.0f; | |||||
| const float ratioy = 1.0f; | |||||
| const float halfx = GLA_PIXEL_OFS / sizex; | const float halfx = GLA_PIXEL_OFS / sizex; | ||||
| const float halfy = GLA_PIXEL_OFS / sizey; | const float halfy = GLA_PIXEL_OFS / sizex; | ||||
| glBindTexture(GL_TEXTURE_2D, triple->bind); | |||||
| immUniform1f("alpha", 1.0f); | immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ | ||||
| immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ | |||||
| immBegin(GWN_PRIM_TRI_FAN, 4); | immBegin(GWN_PRIM_TRI_FAN, 4); | ||||
| immAttrib2f(texcoord, halfx, halfy); | immAttrib2f(texcoord, halfx, halfy); | ||||
| immVertex2f(pos, 0.0f, soffy); | immVertex2f(pos, 0.0f, soffy); | ||||
| immAttrib2f(texcoord, ratiox + halfx, halfy); | immAttrib2f(texcoord, 1.0f + halfx, halfy); | ||||
| immVertex2f(pos, sizex, soffy); | immVertex2f(pos, sizex, soffy); | ||||
| immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy); | immAttrib2f(texcoord, 1.0f + halfx, 1.0f + halfy); | ||||
| immVertex2f(pos, sizex, soffy + (sizey * 0.5f)); | immVertex2f(pos, sizex, soffy + (sizey * 0.5f)); | ||||
| immAttrib2f(texcoord, halfx, ratioy + halfy); | immAttrib2f(texcoord, halfx, 1.0f + halfy); | ||||
| immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f)); | immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f)); | ||||
| immEnd(); | immEnd(); | ||||
| } | |||||
| immUnbindProgram(); | immUnbindProgram(); | ||||
| glBindTexture(GL_TEXTURE_2D, 0); | |||||
| } | } | ||||
| void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win) | |||||
| { | |||||
| switch (win->stereo3d_format->display_mode) { | |||||
| case S3D_DISPLAY_ANAGLYPH: | |||||
| wm_method_draw_stereo3d_anaglyph(win); | |||||
| break; | |||||
| case S3D_DISPLAY_INTERLACE: | |||||
| wm_method_draw_stereo3d_interlace(win); | |||||
| break; | |||||
| case S3D_DISPLAY_PAGEFLIP: | |||||
| wm_method_draw_stereo3d_pageflip(win); | |||||
| break; | |||||
| case S3D_DISPLAY_SIDEBYSIDE: | |||||
| wm_method_draw_stereo3d_sidebyside(win); | |||||
| break; | |||||
| case S3D_DISPLAY_TOPBOTTOM: | |||||
| wm_method_draw_stereo3d_topbottom(win); | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| static bool wm_stereo3d_quadbuffer_supported(void) | static bool wm_stereo3d_quadbuffer_supported(void) | ||||
| { | { | ||||
| GLboolean stereo = GL_FALSE; | GLboolean stereo = GL_FALSE; | ||||
| glGetBooleanv(GL_STEREO, &stereo); | glGetBooleanv(GL_STEREO, &stereo); | ||||
| return stereo == GL_TRUE; | return stereo == GL_TRUE; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 267 Lines • Show Last 20 Lines | |||||