static VGboolean blend_use_shader(struct shader *shader) { struct vg_context *ctx = shader->context; VGboolean advanced_blending; switch (ctx->state.vg.blend_mode) { case VG_BLEND_DST_OVER: case VG_BLEND_MULTIPLY: case VG_BLEND_SCREEN: case VG_BLEND_DARKEN: case VG_BLEND_LIGHTEN: case VG_BLEND_ADDITIVE: advanced_blending = VG_TRUE; break; case VG_BLEND_SRC_OVER: if (util_format_has_alpha(ctx->draw_buffer->strb->format)) { /* no blending is required if the paints and the image are opaque */ advanced_blending = !paint_is_opaque(ctx->state.vg.fill_paint) || !paint_is_opaque(ctx->state.vg.stroke_paint); if (!advanced_blending && shader->drawing_image) { advanced_blending = util_format_has_alpha(shader->image->sampler_view->format); } break; } /* fall through */ default: advanced_blending = VG_FALSE; break; } return advanced_blending; }
/** * Return the base format just like _mesa_base_fbo_format does. */ static GLenum st_pipe_format_to_base_format(enum pipe_format format) { GLenum base_format; if (util_format_is_depth_or_stencil(format)) { if (util_format_is_depth_and_stencil(format)) { base_format = GL_DEPTH_STENCIL; } else { if (format == PIPE_FORMAT_S8_USCALED) base_format = GL_STENCIL_INDEX; else base_format = GL_DEPTH_COMPONENT; } } else { /* is this enough? */ if (util_format_has_alpha(format)) base_format = GL_RGBA; else base_format = GL_RGB; } return base_format; }
static void renderer_validate_blend(struct renderer *renderer, const struct vg_state *state, enum pipe_format fb_format) { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); blend.rt[0].colormask = PIPE_MASK_RGBA; blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; /* TODO alpha masking happens after blending? */ switch (state->blend_mode) { case VG_BLEND_SRC: blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; break; case VG_BLEND_SRC_OVER: if (!util_format_has_alpha(fb_format)) { blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; blend.rt[0].blend_enable = 1; } break; case VG_BLEND_SRC_IN: blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].blend_enable = 1; break; case VG_BLEND_DST_IN: blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; blend.rt[0].blend_enable = 1; break; case VG_BLEND_DST_OVER: case VG_BLEND_MULTIPLY: case VG_BLEND_SCREEN: case VG_BLEND_DARKEN: case VG_BLEND_LIGHTEN: case VG_BLEND_ADDITIVE: /* need a shader */ break; default: assert(!"not implemented blend mode"); break; } cso_set_blend(renderer->cso, &blend); }
/** * Given a user-specified texture base format, the actual gallium texture * format and the current GL_DEPTH_MODE, return a texture swizzle. * * Consider the case where the user requests a GL_RGB internal texture * format the driver actually uses an RGBA format. The A component should * be ignored and sampling from the texture should always return (r,g,b,1). * But if we rendered to the texture we might have written A values != 1. * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1. * This function computes the texture swizzle needed to get the expected * values. * * In the case of depth textures, the GL_DEPTH_MODE state determines the * texture swizzle. * * This result must be composed with the user-specified swizzle to get * the final swizzle. */ static unsigned compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, enum pipe_format actualFormat) { switch (baseFormat) { case GL_RGBA: return SWIZZLE_XYZW; case GL_RGB: if (util_format_has_alpha(actualFormat)) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_RG: if (util_format_get_nr_components(actualFormat) > 2) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_RED: if (util_format_get_nr_components(actualFormat) > 1) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_ALPHA: if (util_format_get_nr_components(actualFormat) > 1) return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_W); else return SWIZZLE_XYZW; case GL_LUMINANCE: if (util_format_get_nr_components(actualFormat) > 1) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_LUMINANCE_ALPHA: if (util_format_get_nr_components(actualFormat) > 2) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); else return SWIZZLE_XYZW; case GL_INTENSITY: if (util_format_get_nr_components(actualFormat) > 1) return SWIZZLE_XXXX; else return SWIZZLE_XYZW; case GL_STENCIL_INDEX: return SWIZZLE_XYZW; case GL_DEPTH_STENCIL: /* fall-through */ case GL_DEPTH_COMPONENT: /* Now examine the depth mode */ switch (depthMode) { case GL_LUMINANCE: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); case GL_INTENSITY: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); case GL_ALPHA: return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_X); case GL_RED: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE); default: assert(!"Unexpected depthMode"); return SWIZZLE_XYZW; } default: assert(!"Unexpected baseFormat"); return SWIZZLE_XYZW; } }
static boolean st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type tex_type, int level, enum pipe_format pipe_format, struct pipe_resource *tex, boolean mipmap) { struct st_context *st = (struct st_context *) stctxi; struct gl_context *ctx = st->ctx; struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); struct gl_texture_object *texObj; struct gl_texture_image *texImage; struct st_texture_object *stObj; struct st_texture_image *stImage; GLenum internalFormat; GLuint width, height, depth; GLenum target; switch (tex_type) { case ST_TEXTURE_1D: target = GL_TEXTURE_1D; break; case ST_TEXTURE_2D: target = GL_TEXTURE_2D; break; case ST_TEXTURE_3D: target = GL_TEXTURE_3D; break; case ST_TEXTURE_RECT: target = GL_TEXTURE_RECTANGLE_ARB; break; default: return FALSE; } texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); stObj = st_texture_object(texObj); /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); stObj->surface_based = GL_TRUE; } texImage = _mesa_get_tex_image(ctx, texObj, target, level); stImage = st_texture_image(texImage); if (tex) { gl_format texFormat = st_pipe_format_to_mesa_format(pipe_format); if (util_format_has_alpha(tex->format)) internalFormat = GL_RGBA; else internalFormat = GL_RGB; _mesa_init_teximage_fields(ctx, texImage, tex->width0, tex->height0, 1, 0, internalFormat, texFormat); width = tex->width0; height = tex->height0; depth = tex->depth0; /* grow the image size until we hit level = 0 */ while (level > 0) { if (width != 1) width <<= 1; if (height != 1) height <<= 1; if (depth != 1) depth <<= 1; level--; } } else { _mesa_clear_texture_image(ctx, texImage); width = height = depth = 0; } pipe_resource_reference(&stImage->pt, tex); stObj->width0 = width; stObj->height0 = height; stObj->depth0 = depth; stObj->surface_format = pipe_format; _mesa_dirty_texobj(ctx, texObj, GL_TRUE); _mesa_unlock_texture(ctx, texObj); return TRUE; }
/** * Given a user-specified texture base format, the actual gallium texture * format and the current GL_DEPTH_MODE, return a texture swizzle. * * Consider the case where the user requests a GL_RGB internal texture * format the driver actually uses an RGBA format. The A component should * be ignored and sampling from the texture should always return (r,g,b,1). * But if we rendered to the texture we might have written A values != 1. * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1. * This function computes the texture swizzle needed to get the expected * values. * * In the case of depth textures, the GL_DEPTH_MODE state determines the * texture swizzle. * * This result must be composed with the user-specified swizzle to get * the final swizzle. */ static unsigned compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, enum pipe_format actualFormat, unsigned glsl_version) { switch (baseFormat) { case GL_RGBA: return SWIZZLE_XYZW; case GL_RGB: if (util_format_has_alpha(actualFormat)) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_RG: if (util_format_get_nr_components(actualFormat) > 2) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_RED: if (util_format_get_nr_components(actualFormat) > 1) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_ALPHA: if (util_format_get_nr_components(actualFormat) > 1) return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_W); else return SWIZZLE_XYZW; case GL_LUMINANCE: if (util_format_get_nr_components(actualFormat) > 1) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); else return SWIZZLE_XYZW; case GL_LUMINANCE_ALPHA: if (util_format_get_nr_components(actualFormat) > 2) return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); else return SWIZZLE_XYZW; case GL_INTENSITY: if (util_format_get_nr_components(actualFormat) > 1) return SWIZZLE_XXXX; else return SWIZZLE_XYZW; case GL_STENCIL_INDEX: case GL_DEPTH_STENCIL: case GL_DEPTH_COMPONENT: /* Now examine the depth mode */ switch (depthMode) { case GL_LUMINANCE: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); case GL_INTENSITY: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); case GL_ALPHA: /* The texture(sampler*Shadow) functions from GLSL 1.30 ignore * the depth mode and return float, while older shadow* functions * and ARB_fp instructions return vec4 according to the depth mode. * * The problem with the GLSL 1.30 functions is that GL_ALPHA forces * them to return 0, breaking them completely. * * A proper fix would increase code complexity and that's not worth * it for a rarely used feature such as the GL_ALPHA depth mode * in GL3. Therefore, change GL_ALPHA to GL_INTENSITY for all * shaders that use GLSL 1.30 or later. * * BTW, it's required that sampler views are updated when * shaders change (check_sampler_swizzle takes care of that). */ if (glsl_version && glsl_version >= 130) return SWIZZLE_XXXX; else return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_X); case GL_RED: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE); default: assert(!"Unexpected depthMode"); return SWIZZLE_XYZW; } default: assert(!"Unexpected baseFormat"); return SWIZZLE_XYZW; } }
void fd2_emit_state(struct fd_context *ctx, const enum fd_dirty_3d_state dirty) { struct fd2_blend_stateobj *blend = fd2_blend_stateobj(ctx->blend); struct fd2_zsa_stateobj *zsa = fd2_zsa_stateobj(ctx->zsa); struct fd_ringbuffer *ring = ctx->batch->draw; /* NOTE: we probably want to eventually refactor this so each state * object handles emitting it's own state.. although the mapping of * state to registers is not always orthogonal, sometimes a single * register contains bitfields coming from multiple state objects, * so not sure the best way to deal with that yet. */ if (dirty & FD_DIRTY_SAMPLE_MASK) { OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK)); OUT_RING(ring, ctx->sample_mask); } if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_STENCIL_REF)) { struct pipe_stencil_ref *sr = &ctx->stencil_ref; OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL)); OUT_RING(ring, zsa->rb_depthcontrol); OUT_PKT3(ring, CP_SET_CONSTANT, 4); OUT_RING(ring, CP_REG(REG_A2XX_RB_STENCILREFMASK_BF)); OUT_RING(ring, zsa->rb_stencilrefmask_bf | A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[1])); OUT_RING(ring, zsa->rb_stencilrefmask | A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[0])); OUT_RING(ring, zsa->rb_alpha_ref); } if (ctx->rasterizer && dirty & FD_DIRTY_RASTERIZER) { struct fd2_rasterizer_stateobj *rasterizer = fd2_rasterizer_stateobj(ctx->rasterizer); OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL)); OUT_RING(ring, rasterizer->pa_cl_clip_cntl); OUT_RING(ring, rasterizer->pa_su_sc_mode_cntl | A2XX_PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE); OUT_PKT3(ring, CP_SET_CONSTANT, 5); OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_POINT_SIZE)); OUT_RING(ring, rasterizer->pa_su_point_size); OUT_RING(ring, rasterizer->pa_su_point_minmax); OUT_RING(ring, rasterizer->pa_su_line_cntl); OUT_RING(ring, rasterizer->pa_sc_line_stipple); OUT_PKT3(ring, CP_SET_CONSTANT, 6); OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_VTX_CNTL)); OUT_RING(ring, rasterizer->pa_su_vtx_cntl); OUT_RING(ring, fui(1.0)); /* PA_CL_GB_VERT_CLIP_ADJ */ OUT_RING(ring, fui(1.0)); /* PA_CL_GB_VERT_DISC_ADJ */ OUT_RING(ring, fui(1.0)); /* PA_CL_GB_HORZ_CLIP_ADJ */ OUT_RING(ring, fui(1.0)); /* PA_CL_GB_HORZ_DISC_ADJ */ } /* NOTE: scissor enabled bit is part of rasterizer state: */ if (dirty & (FD_DIRTY_SCISSOR | FD_DIRTY_RASTERIZER)) { struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx); OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL)); OUT_RING(ring, xy2d(scissor->minx, /* PA_SC_WINDOW_SCISSOR_TL */ scissor->miny)); OUT_RING(ring, xy2d(scissor->maxx, /* PA_SC_WINDOW_SCISSOR_BR */ scissor->maxy)); ctx->batch->max_scissor.minx = MIN2(ctx->batch->max_scissor.minx, scissor->minx); ctx->batch->max_scissor.miny = MIN2(ctx->batch->max_scissor.miny, scissor->miny); ctx->batch->max_scissor.maxx = MAX2(ctx->batch->max_scissor.maxx, scissor->maxx); ctx->batch->max_scissor.maxy = MAX2(ctx->batch->max_scissor.maxy, scissor->maxy); } if (dirty & FD_DIRTY_VIEWPORT) { OUT_PKT3(ring, CP_SET_CONSTANT, 7); OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE)); OUT_RING(ring, fui(ctx->viewport.scale[0])); /* PA_CL_VPORT_XSCALE */ OUT_RING(ring, fui(ctx->viewport.translate[0])); /* PA_CL_VPORT_XOFFSET */ OUT_RING(ring, fui(ctx->viewport.scale[1])); /* PA_CL_VPORT_YSCALE */ OUT_RING(ring, fui(ctx->viewport.translate[1])); /* PA_CL_VPORT_YOFFSET */ OUT_RING(ring, fui(ctx->viewport.scale[2])); /* PA_CL_VPORT_ZSCALE */ OUT_RING(ring, fui(ctx->viewport.translate[2])); /* PA_CL_VPORT_ZOFFSET */ OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL)); OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT | A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Z_SCALE_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Z_OFFSET_ENA); } if (dirty & (FD_DIRTY_PROG | FD_DIRTY_VTXSTATE | FD_DIRTY_TEXSTATE)) { fd2_program_validate(ctx); fd2_program_emit(ring, &ctx->prog); } if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONST)) { emit_constants(ring, VS_CONST_BASE * 4, &ctx->constbuf[PIPE_SHADER_VERTEX], (dirty & FD_DIRTY_PROG) ? ctx->prog.vp : NULL); emit_constants(ring, PS_CONST_BASE * 4, &ctx->constbuf[PIPE_SHADER_FRAGMENT], (dirty & FD_DIRTY_PROG) ? ctx->prog.fp : NULL); } if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_ZSA)) { OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL)); OUT_RING(ring, blend ? zsa->rb_colorcontrol | blend->rb_colorcontrol : 0); } if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_FRAMEBUFFER)) { enum pipe_format format = pipe_surface_format(ctx->batch->framebuffer.cbufs[0]); bool has_alpha = util_format_has_alpha(format); OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_CONTROL)); OUT_RING(ring, blend ? blend->rb_blendcontrol_alpha | COND(has_alpha, blend->rb_blendcontrol_rgb) | COND(!has_alpha, blend->rb_blendcontrol_no_alpha_rgb) : 0); OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_MASK)); OUT_RING(ring, blend ? blend->rb_colormask : 0xf); } if (dirty & FD_DIRTY_BLEND_COLOR) { OUT_PKT3(ring, CP_SET_CONSTANT, 5); OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_RED)); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[0])); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[1])); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[2])); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[3])); } if (dirty & (FD_DIRTY_TEX | FD_DIRTY_PROG)) emit_textures(ring, ctx); }