renderer: add support for ARB_viewport_array

macos/master
Dave Airlie 10 years ago
parent 78370e879f
commit 3f4e3e1cad
  1. 2
      src/vrend_decode.c
  2. 169
      src/vrend_renderer.c
  3. 5
      src/vrend_renderer.h
  4. 14
      src/vrend_shader.c

@ -784,7 +784,7 @@ static int vrend_decode_set_scissor_state(struct vrend_decode_ctx *ctx, int leng
ss[s].maxy = (temp >> 16) & 0xffff; ss[s].maxy = (temp >> 16) & 0xffff;
} }
vrend_set_scissor_state(ctx->grctx, &ss[0]); vrend_set_scissor_state(ctx->grctx, start_slot, num_scissor, ss);
return 0; return 0;
} }

@ -93,8 +93,6 @@ struct global_error_state {
}; };
struct global_renderer_state { struct global_renderer_state {
bool viewport_dirty;
bool scissor_dirty;
GLboolean blend_enabled; GLboolean blend_enabled;
GLboolean depth_test_enabled; GLboolean depth_test_enabled;
GLboolean alpha_test_enabled; GLboolean alpha_test_enabled;
@ -249,6 +247,11 @@ struct vrend_shader_view {
uint32_t old_ids[PIPE_MAX_SHADER_SAMPLER_VIEWS]; uint32_t old_ids[PIPE_MAX_SHADER_SAMPLER_VIEWS];
}; };
struct vrend_viewport {
GLint cur_x, cur_y;
GLsizei width, height;
GLclampd near_val, far_val;
};
struct vrend_sub_context { struct vrend_sub_context {
struct list_head head; struct list_head head;
@ -294,21 +297,19 @@ struct vrend_sub_context {
struct vrend_surface *zsurf; struct vrend_surface *zsurf;
struct vrend_surface *surf[8]; struct vrend_surface *surf[8];
GLint view_cur_x, view_cur_y; struct vrend_viewport vps[PIPE_MAX_VIEWPORTS];
GLsizei view_width, view_height;
GLclampd view_near_val, view_far_val;
float depth_transform, depth_scale; float depth_transform, depth_scale;
/* viewport is negative */ /* viewport is negative */
GLboolean viewport_is_negative; GLboolean viewport_is_negative;
/* this is set if the contents of the FBO look upside down when viewed /* this is set if the contents of the FBO look upside down when viewed
with 0,0 as the bottom corner */ with 0,0 as the bottom corner */
GLboolean inverted_fbo_content; GLboolean inverted_fbo_content;
boolean scissor_state_dirty; uint32_t scissor_state_dirty;
boolean viewport_state_dirty; uint32_t viewport_state_dirty;
boolean stencil_state_dirty; boolean stencil_state_dirty;
uint32_t fb_height; uint32_t fb_height;
struct pipe_scissor_state ss; struct pipe_scissor_state ss[PIPE_MAX_VIEWPORTS];
struct pipe_blend_state blend_state; struct pipe_blend_state blend_state;
struct pipe_depth_stencil_alpha_state dsa_state; struct pipe_depth_stencil_alpha_state dsa_state;
@ -1313,8 +1314,8 @@ void vrend_set_framebuffer_state(struct vrend_context *ctx,
if (ctx->sub->fb_height != new_height || ctx->sub->inverted_fbo_content != new_ibf) { if (ctx->sub->fb_height != new_height || ctx->sub->inverted_fbo_content != new_ibf) {
ctx->sub->fb_height = new_height; ctx->sub->fb_height = new_height;
ctx->sub->inverted_fbo_content = new_ibf; ctx->sub->inverted_fbo_content = new_ibf;
ctx->sub->scissor_state_dirty = TRUE; ctx->sub->scissor_state_dirty = (1 << 0);
ctx->sub->viewport_state_dirty = TRUE; ctx->sub->viewport_state_dirty = (1 << 0);
} }
} }
@ -1332,7 +1333,7 @@ void vrend_set_framebuffer_state(struct vrend_context *ctx,
* an FBO already so don't need to invert rendering? * an FBO already so don't need to invert rendering?
*/ */
void vrend_set_viewport_states(struct vrend_context *ctx, void vrend_set_viewport_states(struct vrend_context *ctx,
int start_slots, int start_slot,
int num_viewports, int num_viewports,
const struct pipe_viewport_state *state) const struct pipe_viewport_state *state)
{ {
@ -1340,39 +1341,50 @@ void vrend_set_viewport_states(struct vrend_context *ctx,
GLint x, y; GLint x, y;
GLsizei width, height; GLsizei width, height;
GLclampd near_val, far_val; GLclampd near_val, far_val;
GLboolean viewport_is_negative = (state->scale[1] < 0) ? GL_TRUE : GL_FALSE; GLboolean viewport_is_negative = (state[0].scale[1] < 0) ? GL_TRUE : GL_FALSE;
GLfloat abs_s1 = fabsf(state->scale[1]); GLfloat abs_s1 = fabsf(state->scale[1]);
int i, idx;
for (i = 0; i < num_viewports; i++) {
idx = start_slot + i;
abs_s1 = fabsf(state[i].scale[1]);
width = state[i].scale[0] * 2.0f;
height = abs_s1 * 2.0f;
x = state[i].translate[0] - state[i].scale[0];
y = state[i].translate[1] - state[i].scale[1];
near_val = state[i].translate[2] - state[i].scale[2];
far_val = near_val + (state[i].scale[2] * 2.0);
if (ctx->sub->vps[idx].cur_x != x ||
ctx->sub->vps[idx].cur_y != y ||
ctx->sub->vps[idx].width != width ||
ctx->sub->vps[idx].height != height) {
ctx->sub->viewport_state_dirty |= (1 << idx);
ctx->sub->vps[idx].cur_x = x;
ctx->sub->vps[idx].cur_y = y;
ctx->sub->vps[idx].width = width;
ctx->sub->vps[idx].height = height;
}
width = state->scale[0] * 2.0f; if (idx == 0) {
height = abs_s1 * 2.0f; if (ctx->sub->viewport_is_negative != viewport_is_negative)
x = state->translate[0] - state->scale[0]; ctx->sub->viewport_is_negative = viewport_is_negative;
y = state->translate[1] - state->scale[1];
near_val = state->translate[2] - state->scale[2];
far_val = near_val + (state->scale[2] * 2.0);
if (ctx->sub->view_cur_x != x ||
ctx->sub->view_cur_y != y ||
ctx->sub->view_width != width ||
ctx->sub->view_height != height) {
ctx->sub->viewport_state_dirty = TRUE;
ctx->sub->view_cur_x = x;
ctx->sub->view_cur_y = y;
ctx->sub->view_width = width;
ctx->sub->view_height = height;
}
if (ctx->sub->viewport_is_negative != viewport_is_negative)
ctx->sub->viewport_is_negative = viewport_is_negative;
ctx->sub->depth_scale = fabsf(far_val - near_val); ctx->sub->depth_scale = fabsf(far_val - near_val);
ctx->sub->depth_transform = near_val; ctx->sub->depth_transform = near_val;
}
if (ctx->sub->view_near_val != near_val || if (ctx->sub->vps[idx].near_val != near_val ||
ctx->sub->view_far_val != far_val) { ctx->sub->vps[idx].far_val != far_val) {
ctx->sub->view_near_val = near_val; ctx->sub->vps[idx].near_val = near_val;
ctx->sub->view_far_val = far_val; ctx->sub->vps[idx].far_val = far_val;
glDepthRange(ctx->sub->view_near_val, ctx->sub->view_far_val); if (idx)
glDepthRangeIndexed(idx, ctx->sub->vps[idx].near_val, ctx->sub->vps[idx].far_val);
else
glDepthRange(ctx->sub->vps[idx].near_val, ctx->sub->vps[idx].far_val);
}
} }
} }
@ -1915,9 +1927,9 @@ void vrend_clear(struct vrend_context *ctx,
vrend_update_frontface_state(ctx); vrend_update_frontface_state(ctx);
if (ctx->sub->stencil_state_dirty) if (ctx->sub->stencil_state_dirty)
vrend_update_stencil_state(ctx); vrend_update_stencil_state(ctx);
if (ctx->sub->scissor_state_dirty || vrend_state.scissor_dirty) if (ctx->sub->scissor_state_dirty)
vrend_update_scissor_state(ctx); vrend_update_scissor_state(ctx);
if (ctx->sub->viewport_state_dirty || vrend_state.viewport_dirty) if (ctx->sub->viewport_state_dirty)
vrend_update_viewport_state(ctx); vrend_update_viewport_state(ctx);
vrend_use_program(0); vrend_use_program(0);
@ -1949,35 +1961,52 @@ void vrend_clear(struct vrend_context *ctx,
static void vrend_update_scissor_state(struct vrend_context *ctx) static void vrend_update_scissor_state(struct vrend_context *ctx)
{ {
struct pipe_scissor_state *ss = &ctx->sub->ss; struct pipe_scissor_state *ss;
struct pipe_rasterizer_state *state = &ctx->sub->rs_state; struct pipe_rasterizer_state *state = &ctx->sub->rs_state;
GLint y; GLint y;
GLuint idx;
unsigned mask = ctx->sub->scissor_state_dirty;
if (ctx->sub->viewport_is_negative)
y = ss->miny;
else
y = ss->miny;
if (state->scissor) if (state->scissor)
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
else else
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
glScissor(ss->minx, y, ss->maxx - ss->minx, ss->maxy - ss->miny); while (mask) {
ctx->sub->scissor_state_dirty = FALSE; idx = u_bit_scan(&mask);
vrend_state.scissor_dirty = FALSE; ss = &ctx->sub->ss[idx];
if (ctx->sub->viewport_is_negative)
y = ss->miny;
else
y = ss->miny;
if (idx > 0)
glScissorIndexed(idx, ss->minx, y, ss->maxx - ss->minx, ss->maxy - ss->miny);
else
glScissor(ss->minx, y, ss->maxx - ss->minx, ss->maxy - ss->miny);
}
ctx->sub->scissor_state_dirty = 0;
} }
static void vrend_update_viewport_state(struct vrend_context *ctx) static void vrend_update_viewport_state(struct vrend_context *ctx)
{ {
GLint cy; GLint cy;
if (ctx->sub->viewport_is_negative) unsigned mask = ctx->sub->viewport_state_dirty;
cy = ctx->sub->view_cur_y - ctx->sub->view_height; int idx;
else while (mask) {
cy = ctx->sub->view_cur_y; idx = u_bit_scan(&mask);
glViewport(ctx->sub->view_cur_x, cy, ctx->sub->view_width, ctx->sub->view_height);
ctx->sub->viewport_state_dirty = FALSE; if (ctx->sub->viewport_is_negative)
vrend_state.viewport_dirty = FALSE; cy = ctx->sub->vps[idx].cur_y - ctx->sub->vps[idx].height;
else
cy = ctx->sub->vps[idx].cur_y;
if (idx > 0)
glViewportIndexedf(idx, ctx->sub->vps[idx].cur_x, cy, ctx->sub->vps[idx].width, ctx->sub->vps[idx].height);
else
glViewport(ctx->sub->vps[idx].cur_x, cy, ctx->sub->vps[idx].width, ctx->sub->vps[idx].height);
}
ctx->sub->viewport_state_dirty = 0;
} }
static GLenum get_gs_xfb_mode(GLenum mode) static GLenum get_gs_xfb_mode(GLenum mode)
@ -2037,10 +2066,10 @@ void vrend_draw_vbo(struct vrend_context *ctx,
vrend_update_frontface_state(ctx); vrend_update_frontface_state(ctx);
if (ctx->sub->stencil_state_dirty) if (ctx->sub->stencil_state_dirty)
vrend_update_stencil_state(ctx); vrend_update_stencil_state(ctx);
if (ctx->sub->scissor_state_dirty || vrend_state.scissor_dirty) if (ctx->sub->scissor_state_dirty)
vrend_update_scissor_state(ctx); vrend_update_scissor_state(ctx);
if (ctx->sub->viewport_state_dirty || vrend_state.viewport_dirty) if (ctx->sub->viewport_state_dirty)
vrend_update_viewport_state(ctx); vrend_update_viewport_state(ctx);
vrend_patch_blend_func(ctx); vrend_patch_blend_func(ctx);
@ -2935,7 +2964,7 @@ void vrend_object_bind_rasterizer(struct vrend_context *ctx,
} }
ctx->sub->rs_state = *state; ctx->sub->rs_state = *state;
ctx->sub->scissor_state_dirty = TRUE; ctx->sub->scissor_state_dirty = (1 << 0);
ctx->sub->shader_dirty = TRUE; ctx->sub->shader_dirty = TRUE;
vrend_hw_emit_rs(ctx); vrend_hw_emit_rs(ctx);
} }
@ -3132,7 +3161,6 @@ void vrend_renderer_init(struct vrend_if_cbs *cbs)
vrend_build_format_list(); vrend_build_format_list();
vrend_clicbs->destroy_gl_context(gl_context); vrend_clicbs->destroy_gl_context(gl_context);
vrend_state.viewport_dirty = vrend_state.scissor_dirty = TRUE;
vrend_state.program_id = (GLuint)-1; vrend_state.program_id = (GLuint)-1;
list_inithead(&vrend_state.fence_list); list_inithead(&vrend_state.fence_list);
list_inithead(&vrend_state.waiting_query_list); list_inithead(&vrend_state.waiting_query_list);
@ -4267,10 +4295,16 @@ void vrend_set_blend_color(struct vrend_context *ctx,
} }
void vrend_set_scissor_state(struct vrend_context *ctx, void vrend_set_scissor_state(struct vrend_context *ctx,
int start_slot,
int num_scissor,
struct pipe_scissor_state *ss) struct pipe_scissor_state *ss)
{ {
ctx->sub->ss = *ss; int i, idx;
ctx->sub->scissor_state_dirty = TRUE; for (i = 0; i < num_scissor; i++) {
idx = start_slot + i;
ctx->sub->ss[idx] = ss[i];
ctx->sub->scissor_state_dirty |= (1 << idx);
}
} }
void vrend_set_polygon_stipple(struct vrend_context *ctx, void vrend_set_polygon_stipple(struct vrend_context *ctx,
@ -4667,7 +4701,7 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
if (info->scissor_enable) { if (info->scissor_enable) {
glScissor(info->scissor.minx, info->scissor.miny, info->scissor.maxx - info->scissor.minx, info->scissor.maxy - info->scissor.miny); glScissor(info->scissor.minx, info->scissor.miny, info->scissor.maxx - info->scissor.minx, info->scissor.maxy - info->scissor.miny);
ctx->sub->scissor_state_dirty = TRUE; ctx->sub->scissor_state_dirty = (1 << 0);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
} else } else
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
@ -5210,7 +5244,11 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
} }
/* initial support */ /* initial support */
caps->v1.max_viewports = 1; if (glewIsSupported("GL_ARB_viewport_array")) {
glGetIntegerv(GL_MAX_VIEWPORTS, &max);
caps->v1.max_viewports = max;
} else
caps->v1.max_viewports = 1;
caps->v1.prim_mask = (1 << PIPE_PRIM_POINTS) | (1 << PIPE_PRIM_LINES) | (1 << PIPE_PRIM_LINE_STRIP) | (1 << PIPE_PRIM_LINE_LOOP) | (1 << PIPE_PRIM_TRIANGLES) | (1 << PIPE_PRIM_TRIANGLE_STRIP) | (1 << PIPE_PRIM_TRIANGLE_FAN); caps->v1.prim_mask = (1 << PIPE_PRIM_POINTS) | (1 << PIPE_PRIM_LINES) | (1 << PIPE_PRIM_LINE_STRIP) | (1 << PIPE_PRIM_LINE_LOOP) | (1 << PIPE_PRIM_TRIANGLES) | (1 << PIPE_PRIM_TRIANGLE_STRIP) | (1 << PIPE_PRIM_TRIANGLE_FAN);
if (use_core_profile == 0) { if (use_core_profile == 0) {
@ -5499,7 +5537,6 @@ void vrend_renderer_reset(void)
vrend_object_fini_resource_table(); vrend_object_fini_resource_table();
vrend_decode_reset(true); vrend_decode_reset(true);
vrend_object_init_resource_table(); vrend_object_init_resource_table();
vrend_state.viewport_dirty = vrend_state.scissor_dirty = TRUE;
vrend_state.program_id = (GLuint)-1; vrend_state.program_id = (GLuint)-1;
vrend_renderer_context_create_internal(0, 0, NULL); vrend_renderer_context_create_internal(0, 0, NULL);
} }

@ -259,7 +259,10 @@ void vrend_renderer_blit(struct vrend_context *ctx,
void vrend_set_stencil_ref(struct vrend_context *ctx, struct pipe_stencil_ref *ref); void vrend_set_stencil_ref(struct vrend_context *ctx, struct pipe_stencil_ref *ref);
void vrend_set_blend_color(struct vrend_context *ctx, struct pipe_blend_color *color); void vrend_set_blend_color(struct vrend_context *ctx, struct pipe_blend_color *color);
void vrend_set_scissor_state(struct vrend_context *ctx, struct pipe_scissor_state *ss); void vrend_set_scissor_state(struct vrend_context *ctx,
int start_slot,
int num_scissor,
struct pipe_scissor_state *ss);
void vrend_set_polygon_stipple(struct vrend_context *ctx, struct pipe_poly_stipple *ps); void vrend_set_polygon_stipple(struct vrend_context *ctx, struct pipe_poly_stipple *ps);

@ -129,6 +129,7 @@ struct dump_ctx {
bool front_face_emitted; bool front_face_emitted;
int color_in_mask; int color_in_mask;
bool has_clipvertex; bool has_clipvertex;
bool has_viewport_idx;
}; };
static inline const char *tgsi_proc_to_prefix(int shader_type) static inline const char *tgsi_proc_to_prefix(int shader_type)
@ -468,6 +469,17 @@ iter_declaration(struct tgsi_iterate_context *iter,
name_prefix = "gl_PrimitiveID"; name_prefix = "gl_PrimitiveID";
break; break;
} }
case TGSI_SEMANTIC_VIEWPORT_INDEX:
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
ctx->outputs[i].glsl_predefined_no_emit = TRUE;
ctx->outputs[i].glsl_no_index = TRUE;
ctx->outputs[i].override_no_wm = TRUE;
ctx->outputs[i].is_int = TRUE;
name_prefix = "gl_ViewportIndex";
if (ctx->glsl_ver_required >= 140)
ctx->has_viewport_idx = true;
break;
}
case TGSI_SEMANTIC_GENERIC: case TGSI_SEMANTIC_GENERIC:
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX)
if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC) if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC)
@ -1794,6 +1806,8 @@ static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr)
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_uniform_buffer_object : require\n"); STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_uniform_buffer_object : require\n");
if (ctx->uses_lodq) if (ctx->uses_lodq)
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_query_lod : require\n"); STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_texture_query_lod : require\n");
if (ctx->has_viewport_idx)
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_viewport_array : require\n");
return glsl_hdr; return glsl_hdr;
} }

Loading…
Cancel
Save