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
This commit is contained in:
Dalai Felinto
2017-04-04 20:33:23 +02:00
parent bbfa1a8639
commit cbd78c8126
7 changed files with 270 additions and 78 deletions

View File

@@ -74,7 +74,7 @@ void GPU_disable_program_point_size(void);
* GPU_object_material_bind returns 0 if drawing should be skipped * GPU_object_material_bind returns 0 if drawing should be skipped
* - after drawing, the material must be disabled again */ * - 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 Scene *scene, struct SceneLayer *sl,
struct Object *ob, bool glsl, bool *do_alpha_after); struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void); 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); int GPU_select_to_index(unsigned int col);
void GPU_select_to_index_array(unsigned int *col, const unsigned int size); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -42,6 +42,7 @@
#include "DNA_gpu_types.h" #include "DNA_gpu_types.h"
#include "GPU_compositing.h" #include "GPU_compositing.h"
#include "GPU_draw.h"
#include "GPU_extensions.h" #include "GPU_extensions.h"
#include "GPU_framebuffer.h" #include "GPU_framebuffer.h"
#include "GPU_glew.h" #include "GPU_glew.h"
@@ -196,6 +197,8 @@ struct GPUFX {
Batch *quad_batch; Batch *quad_batch;
Batch *point_batch; Batch *point_batch;
struct GPUStateValues attribs;
}; };
#if 0 #if 0
@@ -642,7 +645,7 @@ bool GPU_fx_compositor_initialize_passes(
if (scissor_rect) { if (scissor_rect) {
int w_sc = BLI_rcti_size_x(scissor_rect) + 1; int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
int h_sc = BLI_rcti_size_y(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); glEnable(GL_SCISSOR_TEST);
glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin, glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
w_sc, h_sc); 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); GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0);
/* full screen quad where we will always write to depth buffer */ /* 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); glDepthFunc(GL_ALWAYS);
/* disable scissor from sculpt if any */ /* disable scissor from sculpt if any */
glDisable(GL_SCISSOR_TEST); 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); 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->color_buffer);
GPU_framebuffer_texture_detach(fx->depth_buffer); GPU_framebuffer_texture_detach(fx->depth_buffer);
if (fx->restore_stencil) if (fx->restore_stencil) {
glPopAttrib(); gpuRestoreState(&fx->attribs);
}
src = fx->color_buffer; src = fx->color_buffer;
target = fx->color_buffer_sec; target = fx->color_buffer_sec;

View File

@@ -120,10 +120,10 @@ void GPU_render_text(
Image *ima = (Image *)mtexpoly->tpage; Image *ima = (Image *)mtexpoly->tpage;
const size_t textlen_st = textlen; const size_t textlen_st = textlen;
float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
/* multiline */ /* multiline */
float line_start = 0.0f, line_height; float line_start = 0.0f, line_height;
if (v4) if (v4)
line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]); line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
else else
@@ -131,7 +131,7 @@ void GPU_render_text(
line_height *= 1.2f; /* could be an option? */ line_height *= 1.2f; /* could be an option? */
/* end multiline */ /* end multiline */
/* color has been set */ /* color has been set */
if (mtexpoly->mode & TF_OBCOL) if (mtexpoly->mode & TF_OBCOL)
col = NULL; col = NULL;
@@ -139,22 +139,22 @@ void GPU_render_text(
glColor3f(1.0f, 1.0f, 1.0f); glColor3f(1.0f, 1.0f, 1.0f);
gpuPushMatrix(); gpuPushMatrix();
/* get the tab width */ /* get the tab width */
ImBuf *first_ibuf = BKE_image_get_first_ibuf(ima); ImBuf *first_ibuf = BKE_image_get_first_ibuf(ima);
matrixGlyph(first_ibuf, ' ', &centerx, &centery, matrixGlyph(first_ibuf, ' ', &centerx, &centery,
&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 */ float advance_tab = advance * 4; /* tab width could also be an option */
for (size_t index = 0; index < textlen_st; ) { for (size_t index = 0; index < textlen_st; ) {
unsigned int character; unsigned int character;
float uv[4][2]; float uv[4][2];
/* lets calculate offset stuff */ /* lets calculate offset stuff */
character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index); character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index);
if (character == '\n') { if (character == '\n') {
gpuTranslate2f(line_start, -line_height); gpuTranslate2f(line_start, -line_height);
line_start = 0.0f; line_start = 0.0f;
@@ -164,17 +164,17 @@ void GPU_render_text(
gpuTranslate2f(advance_tab, 0.0f); gpuTranslate2f(advance_tab, 0.0f);
line_start -= advance_tab; /* so we can go back to the start of the line */ line_start -= advance_tab; /* so we can go back to the start of the line */
continue; continue;
} }
else if (character > USHRT_MAX) { else if (character > USHRT_MAX) {
/* not much we can do here bmfonts take ushort */ /* not much we can do here bmfonts take ushort */
character = '?'; character = '?';
} }
/* space starts at offset 1 */ /* space starts at offset 1 */
/* character = character - ' ' + 1; */ /* character = character - ' ' + 1; */
matrixGlyph(first_ibuf, character, & centerx, &centery, matrixGlyph(first_ibuf, character, & centerx, &centery,
&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][0] = (uv_quad[0][0] - centerx) * sizex + transx;
uv[0][1] = (uv_quad[0][1] - centery) * sizey + transy; 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[1][1] = (uv_quad[1][1] - centery) * sizey + transy;
uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx; uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx;
uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy; uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy;
glBegin(GL_POLYGON); glBegin(GL_POLYGON);
if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[0]); if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[0]);
else glTexCoord2fv(uv[0]); else glTexCoord2fv(uv[0]);
if (col) gpu_mcol(col[0]); if (col) gpu_mcol(col[0]);
glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[1]); if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[1]);
else glTexCoord2fv(uv[1]); else glTexCoord2fv(uv[1]);
if (col) gpu_mcol(col[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) ? int size = (textarget == GL_TEXTURE_2D) ?
GPU_max_texture_size() : GPU_max_cube_map_size(); GPU_max_texture_size() : GPU_max_cube_map_size();
int reslimit = (U.glreslimit != 0) ? int reslimit = (U.glreslimit != 0) ?
min_ii(U.glreslimit, size) : size; min_ii(U.glreslimit, size) : size;
return (w > reslimit || h > reslimit); return (w > reslimit || h > reslimit);
} }
@@ -414,7 +414,7 @@ void GPU_clear_tpage(bool force)
{ {
if (GTS.lasttface == NULL && !force) if (GTS.lasttface == NULL && !force)
return; return;
GTS.lasttface = NULL; GTS.lasttface = NULL;
GTS.curtile = 0; GTS.curtile = 0;
GTS.curima = NULL; GTS.curima = NULL;
@@ -427,7 +427,7 @@ void GPU_clear_tpage(bool force)
GTS.curtileXRep = 0; GTS.curtileXRep = 0;
GTS.curtileYRep = 0; GTS.curtileYRep = 0;
GTS.alphablend = -1; GTS.alphablend = -1;
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S); 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 */ /* 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); 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... /* if U.glalphaclip == 1.0, some cards go bonkers...
* turn off alpha test in this case */ * turn off alpha test in this case */
@@ -647,29 +647,29 @@ int GPU_verify_image(
GPU_free_image(ima); GPU_free_image(ima);
ima->tpageflag &= ~IMA_TPAGE_REFRESH; ima->tpageflag &= ~IMA_TPAGE_REFRESH;
} }
if (GTS.tilemode) { if (GTS.tilemode) {
/* tiled mode */ /* tiled mode */
if (ima->repbind == NULL) gpu_make_repbind(ima); if (ima->repbind == NULL) gpu_make_repbind(ima);
if (GTS.tile >= ima->totbind) GTS.tile = 0; if (GTS.tile >= ima->totbind) GTS.tile = 0;
/* this happens when you change repeat buttons */ /* this happens when you change repeat buttons */
if (ima->repbind && textarget == GL_TEXTURE_2D) bind = &ima->repbind[GTS.tile]; if (ima->repbind && textarget == GL_TEXTURE_2D) bind = &ima->repbind[GTS.tile];
else bind = gpu_get_image_bindcode(ima, textarget); else bind = gpu_get_image_bindcode(ima, textarget);
if (*bind == 0) { if (*bind == 0) {
short texwindx = ibuf->x / ima->xrep; short texwindx = ibuf->x / ima->xrep;
short texwindy = ibuf->y / ima->yrep; short texwindy = ibuf->y / ima->yrep;
if (GTS.tile >= ima->xrep * ima->yrep) if (GTS.tile >= ima->xrep * ima->yrep)
GTS.tile = ima->xrep * ima->yrep - 1; GTS.tile = ima->xrep * ima->yrep - 1;
short texwinsy = GTS.tile / ima->xrep; short texwinsy = GTS.tile / ima->xrep;
short texwinsx = GTS.tile - texwinsy * ima->xrep; short texwinsx = GTS.tile - texwinsy * ima->xrep;
texwinsx *= texwindx; texwinsx *= texwindx;
texwinsy *= texwindy; texwinsy *= texwindy;
tpx = texwindx; tpx = texwindx;
tpy = texwindy; tpy = texwindy;
@@ -743,7 +743,7 @@ int GPU_verify_image(
memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow)); memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow));
} }
rect = tilerect; rect = tilerect;
} }
} }
@@ -754,13 +754,13 @@ int GPU_verify_image(
else else
#endif #endif
GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima);
/* mark as non-color data texture */ /* mark as non-color data texture */
if (*bind) { if (*bind) {
if (is_data) if (is_data)
ima->tpageflag |= IMA_GLBIND_IS_DATA; ima->tpageflag |= IMA_GLBIND_IS_DATA;
else else
ima->tpageflag &= ~IMA_GLBIND_IS_DATA; ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
} }
/* clean up */ /* clean up */
@@ -946,7 +946,7 @@ void GPU_create_gl_tex(
if (mip_cube_map) { if (mip_cube_map) {
for (int j = 0; j < 6; j++) { for (int j = 0; j < 6; j++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, 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); 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; size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize;
glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height, glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height,
0, size, ibuf->dds_data.data + offset); 0, size, ibuf->dds_data.data + offset);
offset += size; offset += size;
width >>= 1; width >>= 1;
@@ -1101,7 +1101,7 @@ int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
} }
else { else {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
GTS.curtile = 0; GTS.curtile = 0;
GTS.curima = NULL; GTS.curima = NULL;
GTS.curtilemode = 0; GTS.curtilemode = 0;
@@ -1110,9 +1110,9 @@ int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
return 0; return 0;
} }
gpu_verify_repeat(ima); gpu_verify_repeat(ima);
/* Did this get lost in the image recode? */ /* Did this get lost in the image recode? */
/* BKE_image_tag_time(ima);*/ /* 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"); float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0; bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data); 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)) { if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
MEM_freeN(buffer); MEM_freeN(buffer);
BKE_image_release_ibuf(ima, ibuf, NULL); 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); glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, 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_ROW_LENGTH, row_length);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
@@ -1330,9 +1330,9 @@ void GPU_update_images_framechange(void)
if (ima->tpageflag & IMA_TWINANIM) { if (ima->tpageflag & IMA_TWINANIM) {
if (ima->twend >= ima->xrep * ima->yrep) if (ima->twend >= ima->xrep * ima->yrep)
ima->twend = ima->xrep * ima->yrep - 1; ima->twend = ima->xrep * ima->yrep - 1;
/* check: is bindcode not in the array? free. (to do) */ /* check: is bindcode not in the array? free. (to do) */
ima->lastframe++; ima->lastframe++;
if (ima->lastframe > ima->twend) if (ima->lastframe > ima->twend)
ima->lastframe = ima->twsta; ima->lastframe = ima->twsta;
@@ -1355,9 +1355,9 @@ int GPU_update_image_time(Image *ima, double time)
if (ima->tpageflag & IMA_TWINANIM) { if (ima->tpageflag & IMA_TWINANIM) {
if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1; 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) */ /* check: is the bindcode not in the array? Then free. (still to do) */
float diff = (float)((float)time - ima->lastupdate); float diff = (float)((float)time - ima->lastupdate);
inc = (int)(diff * (float)ima->animspeed); inc = (int)(diff * (float)ima->animspeed);
@@ -1506,7 +1506,7 @@ void GPU_free_image(Image *ima)
/* free repeated image binding */ /* free repeated image binding */
if (ima->repbind) { if (ima->repbind) {
glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
MEM_freeN(ima->repbind); MEM_freeN(ima->repbind);
ima->repbind = NULL; ima->repbind = NULL;
} }
@@ -1579,7 +1579,7 @@ typedef struct GPUMaterialFixed {
float spec[3]; float spec[3];
int hard; int hard;
float alpha; float alpha;
} GPUMaterialFixed; } GPUMaterialFixed;
static struct GPUMaterialState { static struct GPUMaterialState {
GPUMaterialFixed (*matbuf); GPUMaterialFixed (*matbuf);
@@ -1635,12 +1635,12 @@ static void gpu_material_to_fixed(
copy_v3_v3(smat->spec, &bmat->specr); copy_v3_v3(smat->spec, &bmat->specr);
smat->alpha = 1.0f; smat->alpha = 1.0f;
smat->hard = CLAMPIS(bmat->har, 0, 128); smat->hard = CLAMPIS(bmat->har, 0, 128);
if (dimdown) { if (dimdown) {
mul_v3_fl(smat->diff, 0.8f); mul_v3_fl(smat->diff, 0.8f);
mul_v3_fl(smat->spec, 0.5f); mul_v3_fl(smat->spec, 0.5f);
} }
if (gamma) { if (gamma) {
linearrgb_to_srgb_v3_v3(smat->diff, smat->diff); linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
linearrgb_to_srgb_v3_v3(smat->spec, smat->spec); 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) if (bmat->shade_flag & MA_OBCOLOR)
mul_v3_v3(smat->diff, ob->col); mul_v3_v3(smat->diff, ob->col);
mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec); mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec);
smat->hard = CLAMPIS(bmat->har, 1, 128); smat->hard = CLAMPIS(bmat->har, 1, 128);
smat->alpha = 1.0f; smat->alpha = 1.0f;
@@ -1769,7 +1769,7 @@ void GPU_begin_object_materials(
GMS.is_alpha_pass = (v3d->transp != false); GMS.is_alpha_pass = (v3d->transp != false);
if (GMS.use_alpha_pass) if (GMS.use_alpha_pass)
*do_alpha_after = false; *do_alpha_after = false;
if (GMS.totmat > FIXEDMAT) { if (GMS.totmat > FIXEDMAT) {
GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf"); GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf");
GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * 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! */ /* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
GMS.alphablend[0] = GPU_BLEND_SOLID; GMS.alphablend[0] = GPU_BLEND_SOLID;
} }
else { else {
/* no materials assigned? */ /* no materials assigned? */
if (ob->totcol == 0) { if (ob->totcol == 0) {
gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true); 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; GMS.alphablend[0] = GPU_BLEND_SOLID;
} }
/* setup materials */ /* setup materials */
for (a = 1; a <= ob->totcol; a++) { for (a = 1; a <= ob->totcol; a++) {
/* find a suitable material */ /* find a suitable material */
@@ -2021,7 +2021,7 @@ void GPU_set_material_alpha_blend(int alphablend)
{ {
if (GMS.lastalphablend == alphablend) if (GMS.lastalphablend == alphablend)
return; return;
gpu_set_alpha_blend(alphablend); gpu_set_alpha_blend(alphablend);
GMS.lastalphablend = 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].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[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[0].spec[3] = 1.0;
U.light[1].flag = 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].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].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[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[1].spec[3] = 1.0;
U.light[2].flag = 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].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; 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 */ /* disable all lights */
for (int count = 0; count < 8; count++) for (int count = 0; count < 8; count++)
GPU_basic_shader_light_set(count, NULL); GPU_basic_shader_light_set(count, NULL);
/* view direction for specular is not computed correct by default in /* view direction for specular is not computed correct by default in
* opengl, so we set the settings ourselfs */ * opengl, so we set the settings ourselfs */
GPU_basic_shader_light_set_viewer(!ortho); 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; continue;
Lamp *la = base->object->data; Lamp *la = base->object->data;
/* setup lamp transform */ /* setup lamp transform */
gpuPushMatrix(); gpuPushMatrix();
gpuLoadMatrix3D(viewmat); gpuLoadMatrix3D(viewmat);
/* setup light */ /* setup light */
GPULightData light = {0}; 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.constant_attenuation = 1.0f;
light.linear_attenuation = la->att1 / la->dist; light.linear_attenuation = la->att1 / la->dist;
light.quadratic_attenuation = la->att2 / (la->dist * la->dist); light.quadratic_attenuation = la->att2 / (la->dist * la->dist);
if (la->type == LA_SPOT) { if (la->type == LA_SPOT) {
light.type = GPU_LIGHT_SPOT; light.type = GPU_LIGHT_SPOT;
negate_v3_v3(light.direction, base->object->obmat[2]); 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 else
light.type = GPU_LIGHT_POINT; light.type = GPU_LIGHT_POINT;
} }
GPU_basic_shader_light_set(count, &light); GPU_basic_shader_light_set(count, &light);
gpuPopMatrix(); gpuPopMatrix();
count++; count++;
if (count == 8) if (count == 8)
break; 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) \ #define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \
for (i = size; i--; col++) { \ for (i = size; i--; col++) { \
if ((c = *col)) { \ if ((c = *col)) { \
*col = INDEX_FROM_BUF_BITS(c); \ *col = INDEX_FROM_BUF_BITS(c); \
} \ } \
} ((void)0) } ((void)0)
if (size > 0) { if (size > 0) {
unsigned int i, c; 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 #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);
}
}
/** \} */ /** \} */

View File

@@ -33,6 +33,7 @@
#include "BKE_global.h" #include "BKE_global.h"
#include "GPU_batch.h" #include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_framebuffer.h" #include "GPU_framebuffer.h"
#include "GPU_matrix.h" #include "GPU_matrix.h"
#include "GPU_shader.h" #include "GPU_shader.h"
@@ -50,6 +51,7 @@ struct GPUFrameBuffer {
GLuint object; GLuint object;
GPUTexture *colortex[GPU_FB_MAX_SLOTS]; GPUTexture *colortex[GPU_FB_MAX_SLOTS];
GPUTexture *depthtex; GPUTexture *depthtex;
struct GPUStateValues attribs;
}; };
static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) 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 */ /* push attributes */
glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT); gpuSaveState(&fb->attribs, GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */ /* bind framebuffer */
@@ -241,7 +243,7 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
} }
/* push attributes */ /* push attributes */
glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT); gpuSaveState(&fb->attribs, GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */ /* 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 */ /* restore attributes */
glPopAttrib(); gpuRestoreState(&fb->attribs);
} }
void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot) void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)

View File

@@ -31,6 +31,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <float.h> #include <float.h>
#include "GPU_immediate.h"
#include "GPU_draw.h"
#include "GPU_select.h" #include "GPU_select.h"
#include "GPU_extensions.h" #include "GPU_extensions.h"
#include "GPU_glew.h" #include "GPU_glew.h"
@@ -291,6 +293,8 @@ typedef struct GPUPickState {
unsigned int *rect_id; unsigned int *rect_id;
} nearest; } nearest;
}; };
struct GPUStateValues attribs;
} GPUPickState; } GPUPickState;
@@ -316,8 +320,8 @@ void gpu_select_pick_begin(
/* Restrict OpenGL operations for when we don't have cache */ /* Restrict OpenGL operations for when we don't have cache */
if (ps->is_cached == false) { 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 */ /* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 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); gpu_select_pick_load_id(ps->gl.prev_id);
} }
glPopAttrib(); gpuRestoreState(&ps->attribs);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
} }

View File

@@ -32,6 +32,8 @@
#include <stdlib.h> #include <stdlib.h>
#include "GPU_immediate.h"
#include "GPU_draw.h"
#include "GPU_select.h" #include "GPU_select.h"
#include "GPU_extensions.h" #include "GPU_extensions.h"
#include "GPU_glew.h" #include "GPU_glew.h"
@@ -67,6 +69,8 @@ typedef struct GPUQueryState {
char mode; char mode;
unsigned int index; unsigned int index;
int oldhits; int oldhits;
/* OpenGL attrib bits */
struct GPUStateValues attribs;
} GPUQueryState; } GPUQueryState;
static GPUQueryState g_query_state = {0}; 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"); 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); 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 */ /* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 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); glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries);
MEM_freeN(g_query_state.queries); MEM_freeN(g_query_state.queries);
MEM_freeN(g_query_state.id); MEM_freeN(g_query_state.id);
glPopAttrib(); gpuRestoreState(&g_query_state.attribs);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
return hits; return hits;

View File

@@ -285,7 +285,7 @@ void GPU_viewport_unbind(GPUViewport *viewport)
DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl; DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl;
if (dfbl->default_fb) { if (dfbl->default_fb) {
GPU_framebuffer_texture_unbind(NULL, NULL); GPU_framebuffer_texture_unbind(dfbl->default_fb, NULL);
GPU_framebuffer_restore(); GPU_framebuffer_restore();
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);