diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2017-04-04 21:33:23 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2017-04-05 16:02:31 +0300 |
commit | cbd78c81268f06e7b658ae042f3ab6a3816149b0 (patch) | |
tree | d5740e2643a7c42185ae94bc04575223c1af9045 /source/blender/gpu | |
parent | bbfa1a8639114d66ed0c4971a1996e08e520bd06 (diff) |
Immediate Mode: replacing glPushAttrib/glPopAttrib
Reference document: http://docs.gl/gl3/glPushAttrib
This patch only tackles the bits that are set by Blender with the
following exceptions:
1) Deprecated states (e.g., GL_STIPPLE) are not saved/restored
2) The exception being GL_ALPHA_TEST, which will be removed, but it may
affect drawing too much now. To be removed once we no longer set GL_ALPHA_TEST
elsewhere.
3) paint_cursor will be tackled separated, since it was abusing
glPush/PopAttrib in the first place.
4) Despite what the glPushAttrib page above may suggest, GL_DEPTH_WRITEMASK needs glGet, not glIsEnabled
5) BGE is still a problem since it relies on GL_ALL_ATTRIB_BITS which
would lead to a way more complete/lenghty solution. Since the BGE has
other (OpenGL deprecated) problems anyways, it can be handled on its own
time.
Finally, the original design for 2.8 was to implement a proper stack
system. However we need to move to core profile sooner than later. So
this is a pragmatic temporary (that may be permanent) solution.
Reviewers: merwin, campbellbarton
Differential Revision: https://developer.blender.org/D2600
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/GPU_draw.h | 54 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_compositing.c | 14 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 252 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 10 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_select_pick.c | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_select_sample_query.c | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 2 |
7 files changed, 270 insertions, 78 deletions
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 47ddabbed19..3704f909336 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -74,7 +74,7 @@ void GPU_disable_program_point_size(void); * GPU_object_material_bind returns 0 if drawing should be skipped * - after drawing, the material must be disabled again */ -void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d, +void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d, struct Scene *scene, struct SceneLayer *sl, struct Object *ob, bool glsl, bool *do_alpha_after); void GPU_end_object_materials(void); @@ -175,6 +175,58 @@ void GPU_select_index_get(int index, int *r_col); int GPU_select_to_index(unsigned int col); void GPU_select_to_index_array(unsigned int *col, const unsigned int size); +typedef enum eGPUStateMask { + GPU_DEPTH_BUFFER_BIT = (1 << 0), + GPU_ENABLE_BIT = (1 << 1), + GPU_SCISSOR_BIT = (1 << 2), + GPU_VIEWPORT_BIT = (1 << 3), + GPU_BLEND_BIT = (1 << 4), +} eGPUStateMask; + +typedef struct GPUStateValues +{ + eGPUStateMask mask; + + /* GL_ENABLE_BIT */ + unsigned int is_alpha_test : 1; + unsigned int is_blend : 1; + bool is_clip_plane[6]; + unsigned int is_cull_face : 1; + unsigned int is_depth_test : 1; + unsigned int is_dither : 1; + bool is_light[8]; + unsigned int is_lighting : 1; + unsigned int is_line_smooth : 1; + unsigned int is_color_logic_op : 1; + unsigned int is_map1_vertex3 : 1; + unsigned int is_multisample : 1; + unsigned int is_normalize : 1; + unsigned int is_polygon_offset_line : 1; + unsigned int is_polygon_offset_fill : 1; + unsigned int is_polygon_smooth : 1; + unsigned int is_sample_alpha_to_coverage : 1; + unsigned int is_scissor_test : 1; + unsigned int is_stencil_test : 1; + unsigned int is_texture_2d : 1; + + /* GL_DEPTH_BUFFER_BIT */ + /* unsigned int is_depth_test : 1; */ + int depth_func; + double depth_clear_value; + bool depth_write_mask; + + /* GL_SCISSOR_BIT */ + int scissor_box[4]; + /* unsigned int is_scissor_test : 1; */ + + /* GL_VIEWPORT_BIT */ + int viewport[4]; + double near_far[2]; +} GPUStateValues; + +void gpuSaveState(GPUStateValues *attribs, eGPUStateMask mask); +void gpuRestoreState(GPUStateValues *attribs); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 5214b6b1ab7..8ae100a7d95 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -42,6 +42,7 @@ #include "DNA_gpu_types.h" #include "GPU_compositing.h" +#include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_framebuffer.h" #include "GPU_glew.h" @@ -196,6 +197,8 @@ struct GPUFX { Batch *quad_batch; Batch *point_batch; + + struct GPUStateValues attribs; }; #if 0 @@ -642,7 +645,7 @@ bool GPU_fx_compositor_initialize_passes( if (scissor_rect) { int w_sc = BLI_rcti_size_x(scissor_rect) + 1; int h_sc = BLI_rcti_size_y(scissor_rect) + 1; - glPushAttrib(GL_SCISSOR_BIT); + gpuSaveState(&fx->attribs, GPU_SCISSOR_BIT); glEnable(GL_SCISSOR_TEST); glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin, w_sc, h_sc); @@ -718,7 +721,7 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0); /* full screen quad where we will always write to depth buffer */ - glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT); + gpuSaveState(&fx->attribs, GPU_DEPTH_BUFFER_BIT | GPU_SCISSOR_BIT); glDepthFunc(GL_ALWAYS); /* disable scissor from sculpt if any */ glDisable(GL_SCISSOR_TEST); @@ -751,7 +754,7 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glPopAttrib(); + gpuRestoreState(&fx->attribs); } @@ -781,8 +784,9 @@ bool GPU_fx_do_composite_pass( GPU_framebuffer_texture_detach(fx->color_buffer); GPU_framebuffer_texture_detach(fx->depth_buffer); - if (fx->restore_stencil) - glPopAttrib(); + if (fx->restore_stencil) { + gpuRestoreState(&fx->attribs); + } src = fx->color_buffer; target = fx->color_buffer_sec; diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index fb246aa802e..9c8a4254b7d 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -120,10 +120,10 @@ void GPU_render_text( Image *ima = (Image *)mtexpoly->tpage; const size_t textlen_st = textlen; float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - + /* multiline */ float line_start = 0.0f, line_height; - + if (v4) line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]); else @@ -131,7 +131,7 @@ void GPU_render_text( line_height *= 1.2f; /* could be an option? */ /* end multiline */ - + /* color has been set */ if (mtexpoly->mode & TF_OBCOL) col = NULL; @@ -139,22 +139,22 @@ void GPU_render_text( glColor3f(1.0f, 1.0f, 1.0f); gpuPushMatrix(); - + /* get the tab width */ ImBuf *first_ibuf = BKE_image_get_first_ibuf(ima); matrixGlyph(first_ibuf, ' ', ¢erx, ¢ery, - &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - + &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + float advance_tab = advance * 4; /* tab width could also be an option */ - - + + for (size_t index = 0; index < textlen_st; ) { unsigned int character; float uv[4][2]; /* lets calculate offset stuff */ character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index); - + if (character == '\n') { gpuTranslate2f(line_start, -line_height); line_start = 0.0f; @@ -164,17 +164,17 @@ void GPU_render_text( gpuTranslate2f(advance_tab, 0.0f); line_start -= advance_tab; /* so we can go back to the start of the line */ continue; - + } else if (character > USHRT_MAX) { /* not much we can do here bmfonts take ushort */ character = '?'; } - + /* space starts at offset 1 */ /* character = character - ' ' + 1; */ matrixGlyph(first_ibuf, character, & centerx, ¢ery, - &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); uv[0][0] = (uv_quad[0][0] - centerx) * sizex + transx; uv[0][1] = (uv_quad[0][1] - centery) * sizey + transy; @@ -182,13 +182,13 @@ void GPU_render_text( uv[1][1] = (uv_quad[1][1] - centery) * sizey + transy; uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx; uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy; - + glBegin(GL_POLYGON); if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[0]); else glTexCoord2fv(uv[0]); if (col) gpu_mcol(col[0]); glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - + if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[1]); else glTexCoord2fv(uv[1]); if (col) gpu_mcol(col[1]); @@ -232,7 +232,7 @@ static bool is_over_resolution_limit(GLenum textarget, int w, int h) int size = (textarget == GL_TEXTURE_2D) ? GPU_max_texture_size() : GPU_max_cube_map_size(); int reslimit = (U.glreslimit != 0) ? - min_ii(U.glreslimit, size) : size; + min_ii(U.glreslimit, size) : size; return (w > reslimit || h > reslimit); } @@ -414,7 +414,7 @@ void GPU_clear_tpage(bool force) { if (GTS.lasttface == NULL && !force) return; - + GTS.lasttface = NULL; GTS.curtile = 0; GTS.curima = NULL; @@ -427,7 +427,7 @@ void GPU_clear_tpage(bool force) GTS.curtileXRep = 0; GTS.curtileYRep = 0; GTS.alphablend = -1; - + glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_GEN_S); @@ -455,7 +455,7 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend) /* for OpenGL render we use the alpha channel, this makes alpha blend correct */ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - + /* if U.glalphaclip == 1.0, some cards go bonkers... * turn off alpha test in this case */ @@ -647,29 +647,29 @@ int GPU_verify_image( GPU_free_image(ima); ima->tpageflag &= ~IMA_TPAGE_REFRESH; } - + if (GTS.tilemode) { /* tiled mode */ if (ima->repbind == NULL) gpu_make_repbind(ima); if (GTS.tile >= ima->totbind) GTS.tile = 0; - + /* this happens when you change repeat buttons */ if (ima->repbind && textarget == GL_TEXTURE_2D) bind = &ima->repbind[GTS.tile]; else bind = gpu_get_image_bindcode(ima, textarget); - + if (*bind == 0) { short texwindx = ibuf->x / ima->xrep; short texwindy = ibuf->y / ima->yrep; - + if (GTS.tile >= ima->xrep * ima->yrep) GTS.tile = ima->xrep * ima->yrep - 1; - + short texwinsy = GTS.tile / ima->xrep; short texwinsx = GTS.tile - texwinsy * ima->xrep; - + texwinsx *= texwindx; texwinsy *= texwindy; - + tpx = texwindx; tpy = texwindy; @@ -743,7 +743,7 @@ int GPU_verify_image( memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow)); } - + rect = tilerect; } } @@ -754,13 +754,13 @@ int GPU_verify_image( else #endif GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); - + /* mark as non-color data texture */ if (*bind) { if (is_data) - ima->tpageflag |= IMA_GLBIND_IS_DATA; + ima->tpageflag |= IMA_GLBIND_IS_DATA; else - ima->tpageflag &= ~IMA_GLBIND_IS_DATA; + ima->tpageflag &= ~IMA_GLBIND_IS_DATA; } /* clean up */ @@ -946,7 +946,7 @@ void GPU_create_gl_tex( if (mip_cube_map) { for (int j = 0; j < 6; j++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, - informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]); + informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]); } } gpu_del_cube_map(mip_cube_map); @@ -1027,7 +1027,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf) size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize; glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height, - 0, size, ibuf->dds_data.data + offset); + 0, size, ibuf->dds_data.data + offset); offset += size; width >>= 1; @@ -1101,7 +1101,7 @@ int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend) } else { glDisable(GL_TEXTURE_2D); - + GTS.curtile = 0; GTS.curima = NULL; GTS.curtilemode = 0; @@ -1110,9 +1110,9 @@ int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend) return 0; } - + gpu_verify_repeat(ima); - + /* Did this get lost in the image recode? */ /* BKE_image_tag_time(ima);*/ @@ -1265,7 +1265,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf"); bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0; IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data); - + if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) { MEM_freeN(buffer); BKE_image_release_ibuf(ima, ibuf, NULL); @@ -1306,7 +1306,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i glPixelStorei(GL_UNPACK_SKIP_ROWS, y); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ibuf->rect); + GL_UNSIGNED_BYTE, ibuf->rect); glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); @@ -1330,9 +1330,9 @@ void GPU_update_images_framechange(void) if (ima->tpageflag & IMA_TWINANIM) { if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1; - + /* check: is bindcode not in the array? free. (to do) */ - + ima->lastframe++; if (ima->lastframe > ima->twend) ima->lastframe = ima->twsta; @@ -1355,9 +1355,9 @@ int GPU_update_image_time(Image *ima, double time) if (ima->tpageflag & IMA_TWINANIM) { if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1; - + /* check: is the bindcode not in the array? Then free. (still to do) */ - + float diff = (float)((float)time - ima->lastupdate); inc = (int)(diff * (float)ima->animspeed); @@ -1506,7 +1506,7 @@ void GPU_free_image(Image *ima) /* free repeated image binding */ if (ima->repbind) { glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); - + MEM_freeN(ima->repbind); ima->repbind = NULL; } @@ -1579,7 +1579,7 @@ typedef struct GPUMaterialFixed { float spec[3]; int hard; float alpha; -} GPUMaterialFixed; +} GPUMaterialFixed; static struct GPUMaterialState { GPUMaterialFixed (*matbuf); @@ -1635,12 +1635,12 @@ static void gpu_material_to_fixed( copy_v3_v3(smat->spec, &bmat->specr); smat->alpha = 1.0f; smat->hard = CLAMPIS(bmat->har, 0, 128); - + if (dimdown) { mul_v3_fl(smat->diff, 0.8f); mul_v3_fl(smat->spec, 0.5f); } - + if (gamma) { linearrgb_to_srgb_v3_v3(smat->diff, smat->diff); linearrgb_to_srgb_v3_v3(smat->spec, smat->spec); @@ -1651,7 +1651,7 @@ static void gpu_material_to_fixed( if (bmat->shade_flag & MA_OBCOLOR) mul_v3_v3(smat->diff, ob->col); - + mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec); smat->hard = CLAMPIS(bmat->har, 1, 128); smat->alpha = 1.0f; @@ -1769,7 +1769,7 @@ void GPU_begin_object_materials( GMS.is_alpha_pass = (v3d->transp != false); if (GMS.use_alpha_pass) *do_alpha_after = false; - + if (GMS.totmat > FIXEDMAT) { GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf"); GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * GMS.totmat, "GMS.matbuf"); @@ -1788,11 +1788,11 @@ void GPU_begin_object_materials( /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); - + GMS.alphablend[0] = GPU_BLEND_SOLID; } else { - + /* no materials assigned? */ if (ob->totcol == 0) { gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true); @@ -1807,7 +1807,7 @@ void GPU_begin_object_materials( GMS.alphablend[0] = GPU_BLEND_SOLID; } - + /* setup materials */ for (a = 1; a <= ob->totcol; a++) { /* find a suitable material */ @@ -2021,7 +2021,7 @@ void GPU_set_material_alpha_blend(int alphablend) { if (GMS.lastalphablend == alphablend) return; - + gpu_set_alpha_blend(alphablend); GMS.lastalphablend = alphablend; } @@ -2112,13 +2112,13 @@ int GPU_default_lights(void) U.light[0].col[0] = 0.8; U.light[0].col[1] = 0.8; U.light[0].col[2] = 0.8; U.light[0].spec[0] = 0.5; U.light[0].spec[1] = 0.5; U.light[0].spec[2] = 0.5; U.light[0].spec[3] = 1.0; - + U.light[1].flag = 0; U.light[1].vec[0] = 0.5; U.light[1].vec[1] = 0.5; U.light[1].vec[2] = 0.1; U.light[1].col[0] = 0.4; U.light[1].col[1] = 0.4; U.light[1].col[2] = 0.8; U.light[1].spec[0] = 0.3; U.light[1].spec[1] = 0.3; U.light[1].spec[2] = 0.5; U.light[1].spec[3] = 1.0; - + U.light[2].flag = 0; U.light[2].vec[0] = 0.3; U.light[2].vec[1] = -0.3; U.light[2].vec[2] = -0.2; U.light[2].col[0] = 0.8; U.light[2].col[1] = 0.5; U.light[2].col[2] = 0.4; @@ -2156,7 +2156,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ /* disable all lights */ for (int count = 0; count < 8; count++) GPU_basic_shader_light_set(count, NULL); - + /* view direction for specular is not computed correct by default in * opengl, so we set the settings ourselfs */ GPU_basic_shader_light_set_viewer(!ortho); @@ -2171,11 +2171,11 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ continue; Lamp *la = base->object->data; - + /* setup lamp transform */ gpuPushMatrix(); gpuLoadMatrix3D(viewmat); - + /* setup light */ GPULightData light = {0}; @@ -2194,7 +2194,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ light.constant_attenuation = 1.0f; light.linear_attenuation = la->att1 / la->dist; light.quadratic_attenuation = la->att2 / (la->dist * la->dist); - + if (la->type == LA_SPOT) { light.type = GPU_LIGHT_SPOT; negate_v3_v3(light.direction, base->object->obmat[2]); @@ -2205,11 +2205,11 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ else light.type = GPU_LIGHT_POINT; } - + GPU_basic_shader_light_set(count, &light); - + gpuPopMatrix(); - + count++; if (count == 8) break; @@ -2453,10 +2453,10 @@ void GPU_select_to_index_array(unsigned int *col, const unsigned int size) { #define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \ for (i = size; i--; col++) { \ - if ((c = *col)) { \ - *col = INDEX_FROM_BUF_BITS(c); \ - } \ - } ((void)0) + if ((c = *col)) { \ + *col = INDEX_FROM_BUF_BITS(c); \ + } \ + } ((void)0) if (size > 0) { unsigned int i, c; @@ -2484,4 +2484,130 @@ void GPU_select_to_index_array(unsigned int *col, const unsigned int size) #undef INDEX_BUF_ARRAY } +/** + * Replacement for glPush/PopAttributes + * + * We don't need to cover all the options of legacy OpenGL + * but simply the ones used by Blender. + */ +void gpuSaveState(GPUStateValues *values, eGPUStateMask mask) +{ + values->mask = mask; + + if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) { + values->is_depth_test = glIsEnabled(GL_DEPTH_TEST); + glGetIntegerv(GL_DEPTH_FUNC, &values->depth_func); + glGetDoublev(GL_DEPTH_CLEAR_VALUE, &values->depth_clear_value); + glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&values->depth_write_mask); + } + + if ((mask & GPU_ENABLE_BIT) != 0) { + values->is_alpha_test = glIsEnabled(GL_ALPHA_TEST); + values->is_blend = glIsEnabled(GL_BLEND); + + for (int i = 0; i < 6; i++) { + values->is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i); + } + + values->is_cull_face = glIsEnabled(GL_CULL_FACE); + values->is_depth_test = glIsEnabled(GL_DEPTH_TEST); + values->is_dither = glIsEnabled(GL_DITHER); + + for (int i = 0; i < 8; i++) { + values->is_light[i] = glIsEnabled(GL_LIGHT0 + i); + } + + values->is_line_smooth = glIsEnabled(GL_LINE_SMOOTH); + values->is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP); + values->is_map1_vertex3 = glIsEnabled(GL_MAP1_VERTEX_3); + values->is_multisample = glIsEnabled(GL_MULTISAMPLE); + values->is_normalize = glIsEnabled(GL_NORMALIZE); + values->is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE); + values->is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL); + values->is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH); + values->is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE); + values->is_scissor_test = glIsEnabled(GL_SCISSOR_TEST); + values->is_stencil_test = glIsEnabled(GL_STENCIL_TEST); + values->is_texture_2d = glIsEnabled(GL_TEXTURE_2D); + } + + if ((mask & GPU_SCISSOR_BIT) != 0) { + values->is_scissor_test = glIsEnabled(GL_SCISSOR_TEST); + glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&values->scissor_box); + } + + if ((mask & GPU_VIEWPORT_BIT) != 0) { + glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&values->near_far); + glGetIntegerv(GL_VIEWPORT, (GLint *)&values->viewport); + } + + if ((mask & GPU_BLEND_BIT) != 0) { + values->is_blend = glIsEnabled(GL_BLEND); + } +} + +static void restore_mask(GLenum cap, const bool value) { + if (value) { + glEnable(cap); + } + else { + glDisable(cap); + } +} + +void gpuRestoreState(GPUStateValues *values) +{ + GLint mask = values->mask; + + if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) { + restore_mask(GL_DEPTH_TEST, values->is_depth_test); + glDepthFunc(values->depth_func); + glClearDepth(values->depth_clear_value); + glDepthMask(values->depth_write_mask); + } + + if ((mask & GPU_ENABLE_BIT) != 0) { + restore_mask(GL_BLEND, values->is_blend); + + for (int i = 0; i < 6; i++) { + restore_mask(GL_CLIP_PLANE0 + i, values->is_clip_plane[i]); + } + + restore_mask(GL_CULL_FACE, values->is_cull_face); + restore_mask(GL_DEPTH_TEST, values->is_depth_test); + restore_mask(GL_DITHER, values->is_dither); + + for (int i = 0; i < 6; i++) { + restore_mask(GL_LIGHT0 + i, values->is_light[i]); + } + + restore_mask(GL_LINE_SMOOTH, values->is_line_smooth); + restore_mask(GL_COLOR_LOGIC_OP, values->is_color_logic_op); + restore_mask(GL_MAP1_VERTEX_3, values->is_map1_vertex3); + restore_mask(GL_MULTISAMPLE, values->is_multisample); + restore_mask(GL_NORMALIZE, values->is_normalize); + restore_mask(GL_POLYGON_OFFSET_LINE, values->is_polygon_offset_line); + restore_mask(GL_POLYGON_OFFSET_FILL, values->is_polygon_offset_fill); + restore_mask(GL_POLYGON_SMOOTH, values->is_polygon_smooth); + restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, values->is_sample_alpha_to_coverage); + restore_mask(GL_SCISSOR_TEST, values->is_scissor_test); + restore_mask(GL_STENCIL_TEST, values->is_stencil_test); + restore_mask(GL_TEXTURE_2D, values->is_texture_2d); + } + + if ((mask & GPU_VIEWPORT_BIT) != 0) { + glViewport(values->viewport[0], values->viewport[1], values->viewport[2], values->viewport[3]); + glDepthRange(values->near_far[0], values->near_far[1]); + } + + if ((mask & GPU_SCISSOR_BIT) != 0) { + restore_mask(GL_SCISSOR_TEST, values->is_scissor_test); + glScissor(values->scissor_box[0], values->scissor_box[1], values->scissor_box[2], values->scissor_box[3]); + } + + if ((mask & GPU_BLEND_BIT) != 0) { + restore_mask(GL_BLEND, values->is_blend); + } +} + /** \} */ diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index ce35c43bcec..c6a98d01c02 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -33,6 +33,7 @@ #include "BKE_global.h" #include "GPU_batch.h" +#include "GPU_draw.h" #include "GPU_framebuffer.h" #include "GPU_matrix.h" #include "GPU_shader.h" @@ -50,6 +51,7 @@ struct GPUFrameBuffer { GLuint object; GPUTexture *colortex[GPU_FB_MAX_SLOTS]; GPUTexture *depthtex; + struct GPUStateValues attribs; }; static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) @@ -198,7 +200,7 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex) } /* push attributes */ - glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT); + gpuSaveState(&fb->attribs, GPU_ENABLE_BIT | GPU_VIEWPORT_BIT); glDisable(GL_SCISSOR_TEST); /* bind framebuffer */ @@ -241,7 +243,7 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot) } /* push attributes */ - glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT); + gpuSaveState(&fb->attribs, GPU_ENABLE_BIT | GPU_VIEWPORT_BIT); glDisable(GL_SCISSOR_TEST); /* bind framebuffer */ @@ -294,10 +296,10 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) } -void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex)) +void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *UNUSED(tex)) { /* restore attributes */ - glPopAttrib(); + gpuRestoreState(&fb->attribs); } void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot) diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index 780ffd82671..da75925fe66 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -31,6 +31,8 @@ #include <stdlib.h> #include <float.h> +#include "GPU_immediate.h" +#include "GPU_draw.h" #include "GPU_select.h" #include "GPU_extensions.h" #include "GPU_glew.h" @@ -291,6 +293,8 @@ typedef struct GPUPickState { unsigned int *rect_id; } nearest; }; + + struct GPUStateValues attribs; } GPUPickState; @@ -316,8 +320,8 @@ void gpu_select_pick_begin( /* Restrict OpenGL operations for when we don't have cache */ if (ps->is_cached == false) { + gpuSaveState(&ps->attribs, GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT); - glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT); /* disable writing to the framebuffer */ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -536,7 +540,7 @@ unsigned int gpu_select_pick_end(void) gpu_select_pick_load_id(ps->gl.prev_id); } - glPopAttrib(); + gpuRestoreState(&ps->attribs); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c index ba5fefc5227..96fd2595584 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.c +++ b/source/blender/gpu/intern/gpu_select_sample_query.c @@ -32,6 +32,8 @@ #include <stdlib.h> +#include "GPU_immediate.h" +#include "GPU_draw.h" #include "GPU_select.h" #include "GPU_extensions.h" #include "GPU_glew.h" @@ -67,6 +69,8 @@ typedef struct GPUQueryState { char mode; unsigned int index; int oldhits; + /* OpenGL attrib bits */ + struct GPUStateValues attribs; } GPUQueryState; static GPUQueryState g_query_state = {0}; @@ -94,7 +98,7 @@ void gpu_select_query_begin( g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids"); glGenQueries(g_query_state.num_of_queries, g_query_state.queries); - glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT); + gpuSaveState(&g_query_state.attribs, GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT); /* disable writing to the framebuffer */ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -202,7 +206,7 @@ unsigned int gpu_select_query_end(void) glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries); MEM_freeN(g_query_state.queries); MEM_freeN(g_query_state.id); - glPopAttrib(); + gpuRestoreState(&g_query_state.attribs); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); return hits; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 7c2cb8cd4bb..bcfe4f38f3e 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -285,7 +285,7 @@ void GPU_viewport_unbind(GPUViewport *viewport) DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl; if (dfbl->default_fb) { - GPU_framebuffer_texture_unbind(NULL, NULL); + GPU_framebuffer_texture_unbind(dfbl->default_fb, NULL); GPU_framebuffer_restore(); glEnable(GL_SCISSOR_TEST); |