/** * Render a polygon silhouette to stencil buffer. */ void renderer_polygon_stencil(struct renderer *renderer, struct pipe_vertex_buffer *vbuf, VGuint mode, VGuint start, VGuint count) { assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); cso_set_vertex_buffers(renderer->cso, 0, 1, vbuf); if (!renderer->u.polygon_stencil.manual_two_sides) { cso_draw_arrays(renderer->cso, mode, start, count); } else { struct pipe_rasterizer_state raster; struct pipe_depth_stencil_alpha_state dsa; raster = renderer->g3d.rasterizer; dsa = renderer->u.polygon_stencil.dsa; /* front */ raster.cull_face = PIPE_FACE_BACK; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; cso_set_rasterizer(renderer->cso, &raster); cso_set_depth_stencil_alpha(renderer->cso, &dsa); cso_draw_arrays(renderer->cso, mode, start, count); /* back */ raster.cull_face = PIPE_FACE_FRONT; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; cso_set_rasterizer(renderer->cso, &raster); cso_set_depth_stencil_alpha(renderer->cso, &dsa); cso_draw_arrays(renderer->cso, mode, start, count); } }
static void util_set_dsa_disable(struct cso_context *cso) { struct pipe_depth_stencil_alpha_state dsa = {{0}}; cso_set_depth_stencil_alpha(cso, &dsa); }
static void draw(struct program *p) { /* set the render target */ cso_set_framebuffer(p->cso, &p->framebuffer); /* clear the render target */ p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0); /* set misc state we care about */ cso_set_blend(p->cso, &p->blend); cso_set_depth_stencil_alpha(p->cso, &p->depthstencil); cso_set_rasterizer(p->cso, &p->rasterizer); cso_set_viewport(p->cso, &p->viewport); /* shaders */ cso_set_fragment_shader_handle(p->cso, p->fs); cso_set_vertex_shader_handle(p->cso, p->vs); /* vertex element data */ cso_set_vertex_elements(p->cso, 2, p->velem); util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, PIPE_PRIM_TRIANGLES, 3, /* verts */ 2); /* attribs/vert */ p->pipe->flush(p->pipe, NULL); debug_dump_surface_bmp(p->pipe, "result.bmp", p->framebuffer.cbufs[0]); }
/** * Prepare the renderer for polygon filling. */ VGboolean renderer_polygon_fill_begin(struct renderer *renderer, VGboolean save_dsa) { struct pipe_depth_stencil_alpha_state dsa; assert(renderer->state == RENDERER_STATE_INIT); if (save_dsa) cso_save_depth_stencil_alpha(renderer->cso); /* setup stencil ops */ memset(&dsa, 0, sizeof(dsa)); dsa.stencil[0].enabled = 1; dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL; dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].valuemask = ~0; dsa.stencil[0].writemask = ~0; dsa.depth = renderer->g3d.dsa.depth; cso_set_depth_stencil_alpha(renderer->cso, &dsa); renderer->state = RENDERER_STATE_POLYGON_FILL; return VG_TRUE; }
/** * Prepare the renderer for scissor update. This will reset the depth buffer * to 1.0f. */ VGboolean renderer_scissor_begin(struct renderer *renderer, VGboolean restore_dsa) { struct pipe_depth_stencil_alpha_state dsa; assert(renderer->state == RENDERER_STATE_INIT); if (restore_dsa) cso_save_depth_stencil_alpha(renderer->cso); cso_save_blend(renderer->cso); cso_save_fragment_shader(renderer->cso); /* enable depth writes */ memset(&dsa, 0, sizeof(dsa)); dsa.depth.enabled = 1; dsa.depth.writemask = 1; dsa.depth.func = PIPE_FUNC_ALWAYS; cso_set_depth_stencil_alpha(renderer->cso, &dsa); /* disable color writes */ renderer_set_blend(renderer, 0); renderer_set_fs(renderer, RENDERER_FS_SCISSOR); renderer_set_mvp(renderer, NULL); renderer->u.scissor.restore_dsa = restore_dsa; renderer->state = RENDERER_STATE_SCISSOR; /* clear the depth buffer to 1.0f */ renderer->pipe->clear(renderer->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0); return VG_TRUE; }
void renderer_init_state(struct xa_context *r) { struct pipe_depth_stencil_alpha_state dsa; struct pipe_rasterizer_state raster; unsigned i; /* set common initial clip state */ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); cso_set_depth_stencil_alpha(r->cso, &dsa); /* XXX: move to renderer_init_state? */ memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); raster.gl_rasterization_rules = 1; raster.depth_clip = 1; cso_set_rasterizer(r->cso, &raster); /* vertex elements state */ memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3); for (i = 0; i < 3; i++) { r->velems[i].src_offset = i * 4 * sizeof(float); r->velems[i].instance_divisor = 0; r->velems[i].vertex_buffer_index = 0; r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } }
static void update_depth_stencil_alpha(struct st_context *st) { struct pipe_depth_stencil_alpha_state *dsa = &st->state.depth_stencil; struct pipe_stencil_ref sr; struct gl_context *ctx = st->ctx; memset(dsa, 0, sizeof(*dsa)); memset(&sr, 0, sizeof(sr)); if (ctx->Depth.Test && ctx->DrawBuffer->Visual.depthBits > 0) { dsa->depth.enabled = 1; dsa->depth.writemask = ctx->Depth.Mask; dsa->depth.func = st_compare_func_to_pipe(ctx->Depth.Func); } if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) { dsa->stencil[0].enabled = 1; dsa->stencil[0].func = st_compare_func_to_pipe(ctx->Stencil.Function[0]); dsa->stencil[0].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[0]); dsa->stencil[0].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[0]); dsa->stencil[0].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[0]); dsa->stencil[0].valuemask = ctx->Stencil.ValueMask[0] & 0xff; dsa->stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; sr.ref_value[0] = ctx->Stencil.Ref[0] & 0xff; if (ctx->Stencil._TestTwoSide) { const GLuint back = ctx->Stencil._BackFace; dsa->stencil[1].enabled = 1; dsa->stencil[1].func = st_compare_func_to_pipe(ctx->Stencil.Function[back]); dsa->stencil[1].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[back]); dsa->stencil[1].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[back]); dsa->stencil[1].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[back]); dsa->stencil[1].valuemask = ctx->Stencil.ValueMask[back] & 0xff; dsa->stencil[1].writemask = ctx->Stencil.WriteMask[back] & 0xff; sr.ref_value[1] = ctx->Stencil.Ref[back] & 0xff; } else { /* This should be unnecessary. Drivers must not expect this to * contain valid data, except the enabled bit */ dsa->stencil[1] = dsa->stencil[0]; dsa->stencil[1].enabled = 0; sr.ref_value[1] = sr.ref_value[0]; } } if (ctx->Color.AlphaEnabled) { dsa->alpha.enabled = 1; dsa->alpha.func = st_compare_func_to_pipe(ctx->Color.AlphaFunc); dsa->alpha.ref_value = ctx->Color.AlphaRef; } cso_set_depth_stencil_alpha(st->cso_context, dsa); cso_set_stencil_ref(st->cso_context, &sr); }
/** Setup misc state for the filter. */ void pp_filter_misc_state(struct program *p) { cso_set_blend(p->cso, &p->blend); cso_set_depth_stencil_alpha(p->cso, &p->depthstencil); cso_set_rasterizer(p->cso, &p->rasterizer); cso_set_viewport(p->cso, &p->viewport); cso_set_vertex_elements(p->cso, 2, p->velem); }
static void renderer_init_state(struct xorg_renderer *r) { struct pipe_depth_stencil_alpha_state dsa; struct pipe_rasterizer_state raster; /* set common initial clip state */ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); cso_set_depth_stencil_alpha(r->cso, &dsa); /* XXX: move to renderer_init_state? */ memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); raster.gl_rasterization_rules = 1; cso_set_rasterizer(r->cso, &raster); }
/** * Propogate OpenVG state changes to the renderer. Only framebuffer, blending * and scissoring states are relevant here. */ void renderer_validate(struct renderer *renderer, VGbitfield dirty, const struct st_framebuffer *stfb, const struct vg_state *state) { assert(renderer->state == RENDERER_STATE_INIT); dirty |= renderer->dirty; renderer->dirty = 0; if (dirty & FRAMEBUFFER_DIRTY) { struct pipe_framebuffer_state *fb = &renderer->g3d.fb; struct matrix *proj = &renderer->projection; memset(fb, 0, sizeof(struct pipe_framebuffer_state)); fb->width = stfb->width; fb->height = stfb->height; fb->nr_cbufs = 1; fb->cbufs[0] = stfb->strb->surface; fb->zsbuf = stfb->dsrb->surface; cso_set_framebuffer(renderer->cso, fb); vg_set_viewport(renderer, VEGA_Y0_BOTTOM); matrix_load_identity(proj); matrix_translate(proj, -1.0f, -1.0f); matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height); /* we also got a new depth buffer */ if (dirty & DEPTH_STENCIL_DIRTY) { renderer->pipe->clear(renderer->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0); } } /* must be last because it renders to the depth buffer*/ if (dirty & DEPTH_STENCIL_DIRTY) { update_clip_state(renderer, state); cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa); } if (dirty & BLEND_DIRTY) renderer_validate_blend(renderer, state, stfb->strb->format); }
void nine_convert_dsa_state(struct cso_context *ctx, const DWORD *rs) { struct pipe_depth_stencil_alpha_state dsa; memset(&dsa, 0, sizeof(dsa)); /* memcmp safety */ if (rs[D3DRS_ZENABLE]) { dsa.depth.enabled = 1; dsa.depth.writemask = !!rs[D3DRS_ZWRITEENABLE]; dsa.depth.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ZFUNC]); } if (rs[D3DRS_STENCILENABLE]) { dsa.stencil[0].enabled = 1; dsa.stencil[0].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_STENCILFUNC]); dsa.stencil[0].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILFAIL]); dsa.stencil[0].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILPASS]); dsa.stencil[0].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILZFAIL]); dsa.stencil[0].valuemask = rs[D3DRS_STENCILMASK]; dsa.stencil[0].writemask = rs[D3DRS_STENCILWRITEMASK]; if (rs[D3DRS_TWOSIDEDSTENCILMODE]) { dsa.stencil[1].enabled = 1; dsa.stencil[1].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_CCW_STENCILFUNC]); dsa.stencil[1].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILFAIL]); dsa.stencil[1].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILPASS]); dsa.stencil[1].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILZFAIL]); dsa.stencil[1].valuemask = dsa.stencil[0].valuemask; dsa.stencil[1].writemask = dsa.stencil[0].writemask; } } if (rs[D3DRS_ALPHATESTENABLE]) { dsa.alpha.enabled = 1; dsa.alpha.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ALPHAFUNC]); dsa.alpha.ref_value = (float)rs[D3DRS_ALPHAREF] / 255.0f; } cso_set_depth_stencil_alpha(ctx, &dsa); }
static void draw(struct program *p) { const struct pipe_sampler_state *samplers[] = {&p->sampler}; /* set the render target */ cso_set_framebuffer(p->cso, &p->framebuffer); /* clear the render target */ p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0); /* set misc state we care about */ cso_set_blend(p->cso, &p->blend); cso_set_depth_stencil_alpha(p->cso, &p->depthstencil); cso_set_rasterizer(p->cso, &p->rasterizer); cso_set_viewport(p->cso, &p->viewport); /* sampler */ cso_set_samplers(p->cso, PIPE_SHADER_FRAGMENT, 1, samplers); /* texture sampler view */ cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->view); /* shaders */ cso_set_fragment_shader_handle(p->cso, p->fs); cso_set_vertex_shader_handle(p->cso, p->vs); /* vertex element data */ cso_set_vertex_elements(p->cso, 2, p->velem); util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, 0, PIPE_PRIM_QUADS, 4, /* verts */ 2); /* attribs/vert */ p->pipe->flush(p->pipe, NULL, 0); debug_dump_surface_bmp(p->pipe, "result.bmp", p->framebuffer.cbufs[0]); }
/** * Do glClear by drawing a quadrilateral. * The vertices of the quad will be computed from the * ctx->DrawBuffer->_X/Ymin/max fields. */ static void clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) { struct st_context *st = st_context(ctx); struct cso_context *cso = st->cso_context; const struct gl_framebuffer *fb = ctx->DrawBuffer; const GLfloat fb_width = (GLfloat) fb->Width; const GLfloat fb_height = (GLfloat) fb->Height; const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f; const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; unsigned num_layers = util_framebuffer_get_num_layers(&st->state.framebuffer); /* printf("%s %s%s%s %f,%f %f,%f\n", __func__, color ? "color, " : "", depth ? "depth, " : "", stencil ? "stencil" : "", x0, y0, x1, y1); */ cso_save_state(cso, (CSO_BIT_BLEND | CSO_BIT_STENCIL_REF | CSO_BIT_DEPTH_STENCIL_ALPHA | CSO_BIT_RASTERIZER | CSO_BIT_SAMPLE_MASK | CSO_BIT_MIN_SAMPLES | CSO_BIT_VIEWPORT | CSO_BIT_STREAM_OUTPUTS | CSO_BIT_VERTEX_ELEMENTS | CSO_BIT_AUX_VERTEX_BUFFER_SLOT | CSO_BIT_PAUSE_QUERIES | CSO_BITS_ALL_SHADERS)); /* blend state: RGBA masking */ { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); if (clear_buffers & PIPE_CLEAR_COLOR) { int num_buffers = ctx->Extensions.EXT_draw_buffers2 ? ctx->DrawBuffer->_NumColorDrawBuffers : 1; int i; blend.independent_blend_enable = num_buffers > 1; for (i = 0; i < num_buffers; i++) { if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i))) continue; if (ctx->Color.ColorMask[i][0]) blend.rt[i].colormask |= PIPE_MASK_R; if (ctx->Color.ColorMask[i][1]) blend.rt[i].colormask |= PIPE_MASK_G; if (ctx->Color.ColorMask[i][2]) blend.rt[i].colormask |= PIPE_MASK_B; if (ctx->Color.ColorMask[i][3]) blend.rt[i].colormask |= PIPE_MASK_A; } if (ctx->Color.DitherFlag) blend.dither = 1; } cso_set_blend(cso, &blend); } /* depth_stencil state: always pass/set to ref value */ { struct pipe_depth_stencil_alpha_state depth_stencil; memset(&depth_stencil, 0, sizeof(depth_stencil)); if (clear_buffers & PIPE_CLEAR_DEPTH) { depth_stencil.depth.enabled = 1; depth_stencil.depth.writemask = 1; depth_stencil.depth.func = PIPE_FUNC_ALWAYS; } if (clear_buffers & PIPE_CLEAR_STENCIL) { struct pipe_stencil_ref stencil_ref; memset(&stencil_ref, 0, sizeof(stencil_ref)); depth_stencil.stencil[0].enabled = 1; depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS; depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].valuemask = 0xff; depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; stencil_ref.ref_value[0] = ctx->Stencil.Clear; cso_set_stencil_ref(cso, &stencil_ref); } cso_set_depth_stencil_alpha(cso, &depth_stencil); } cso_set_vertex_elements(cso, 2, st->util_velems); cso_set_stream_outputs(cso, 0, NULL, NULL); cso_set_sample_mask(cso, ~0); cso_set_min_samples(cso, 1); cso_set_rasterizer(cso, &st->clear.raster); /* viewport state: viewport matching window dims */ cso_set_viewport_dims(st->cso_context, fb_width, fb_height, st_fb_orientation(fb) == Y_0_TOP); set_fragment_shader(st); cso_set_tessctrl_shader_handle(cso, NULL); cso_set_tesseval_shader_handle(cso, NULL); if (num_layers > 1) set_vertex_shader_layered(st); else set_vertex_shader(st); /* draw quad matching scissor rect. * * Note: if we're only clearing depth/stencil we still setup vertices * with color, but they'll be ignored. * * We can't translate the clear color to the colorbuffer format, * because different colorbuffers may have different formats. */ if (!st_draw_quad(st, x0, y0, x1, y1, ctx->Depth.Clear * 2.0f - 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, (const float *) &ctx->Color.ClearColor.f, num_layers)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear"); } /* Restore pipe state */ cso_restore_state(cso); }
void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx) { struct array *polys = polyarray->array; struct pipe_depth_stencil_alpha_state dsa; struct pipe_stencil_ref sr; struct pipe_blend_state blend; VGfloat min_x = polyarray->min_x; VGfloat min_y = polyarray->min_y; VGfloat max_x = polyarray->max_x; VGfloat max_y = polyarray->max_y; VGint i; #if DEBUG_POLYGON debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n", __FUNCTION__, min_x, min_y, max_x, max_y); #endif set_blend_for_fill(&blend); memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); memset(&sr, 0, sizeof(struct pipe_stencil_ref)); /* only need a fixed 0. Rely on default or move it out at least? */ cso_set_stencil_ref(ctx->cso_context, &sr); cso_save_blend(ctx->cso_context); cso_save_depth_stencil_alpha(ctx->cso_context); dsa.stencil[0].enabled = 1; if (ctx->state.vg.fill_rule == VG_EVEN_ODD) { dsa.stencil[0].writemask = 1; dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT; dsa.stencil[0].func = PIPE_FUNC_ALWAYS; dsa.stencil[0].valuemask = ~0; cso_set_blend(ctx->cso_context, &blend); cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); for (i = 0; i < polys->num_elements; ++i) { struct polygon *poly = (((struct polygon**)polys->data)[i]); draw_polygon(ctx, poly); } } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) { struct pipe_screen *screen = ctx->pipe->screen; if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) { /* front */ dsa.stencil[0].writemask = ~0; dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; dsa.stencil[0].func = PIPE_FUNC_ALWAYS; dsa.stencil[0].valuemask = ~0; /* back */ dsa.stencil[1].enabled = 1; dsa.stencil[1].writemask = ~0; dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; dsa.stencil[1].func = PIPE_FUNC_ALWAYS; dsa.stencil[1].valuemask = ~0; cso_set_blend(ctx->cso_context, &blend); cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); for (i = 0; i < polys->num_elements; ++i) { struct polygon *poly = (((struct polygon**)polys->data)[i]); draw_polygon(ctx, poly); } } else { struct pipe_rasterizer_state raster; memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state)); cso_save_rasterizer(ctx->cso_context); dsa.stencil[0].func = PIPE_FUNC_ALWAYS; dsa.stencil[0].valuemask = ~0; raster.cull_face = PIPE_FACE_BACK; dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; cso_set_blend(ctx->cso_context, &blend); cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); cso_set_rasterizer(ctx->cso_context, &raster); for (i = 0; i < polys->num_elements; ++i) { struct polygon *poly = (((struct polygon**)polys->data)[i]); draw_polygon(ctx, poly); } raster.cull_face = PIPE_FACE_FRONT; dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); cso_set_rasterizer(ctx->cso_context, &raster); for (i = 0; i < polys->num_elements; ++i) { struct polygon *poly = (((struct polygon**)polys->data)[i]); draw_polygon(ctx, poly); } cso_restore_rasterizer(ctx->cso_context); } } /* restore color writes */ cso_restore_blend(ctx->cso_context); /* setup stencil ops */ dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL; dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; dsa.stencil[0].valuemask = dsa.stencil[0].writemask; dsa.stencil[1].enabled = 0; memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth, sizeof(struct pipe_depth_state)); cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); /* render the quad to propagate the rendering from stencil */ renderer_draw_quad(ctx->renderer, min_x, min_y, max_x, max_y, 0.0f/*depth should be disabled*/); cso_restore_depth_stencil_alpha(ctx->cso_context); }
void vg_validate_state(struct vg_context *ctx) { vg_manager_validate_framebuffer(ctx); if ((ctx->state.dirty & BLEND_DIRTY)) { struct pipe_blend_state *blend = &ctx->state.g3d.blend; memset(blend, 0, sizeof(struct pipe_blend_state)); blend->rt[0].blend_enable = 1; blend->rt[0].colormask = PIPE_MASK_RGBA; switch (ctx->state.vg.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; blend->rt[0].blend_enable = 0; break; case VG_BLEND_SRC_OVER: 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; break; case VG_BLEND_DST_OVER: blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; break; case VG_BLEND_SRC_IN: blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 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; 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_SRC_ALPHA; blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; break; case VG_BLEND_MULTIPLY: case VG_BLEND_SCREEN: case VG_BLEND_DARKEN: case VG_BLEND_LIGHTEN: 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; blend->rt[0].blend_enable = 0; break; case VG_BLEND_ADDITIVE: 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_ONE; blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; break; default: assert(!"not implemented blend mode"); } cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend); } if ((ctx->state.dirty & RASTERIZER_DIRTY)) { struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer; memset(raster, 0, sizeof(struct pipe_rasterizer_state)); raster->gl_rasterization_rules = 1; cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer); } if ((ctx->state.dirty & VIEWPORT_DIRTY)) { struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; const VGint param_bytes = 8 * sizeof(VGfloat); VGfloat vs_consts[8] = { 2.f/fb->width, 2.f/fb->height, 1, 1, -1, -1, 0, 0 }; struct pipe_resource **cbuf = &ctx->vs_const_buffer; vg_set_viewport(ctx, VEGA_Y0_BOTTOM); pipe_resource_reference(cbuf, NULL); *cbuf = pipe_buffer_create(ctx->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, param_bytes); if (*cbuf) { st_no_flush_pipe_buffer_write(ctx, *cbuf, 0, param_bytes, vs_consts); } ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf); } if ((ctx->state.dirty & VS_DIRTY)) { cso_set_vertex_shader_handle(ctx->cso_context, vg_plain_vs(ctx)); } /* must be last because it renders to the depth buffer*/ if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) { update_clip_state(ctx); cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa); } shader_set_masking(ctx->shader, ctx->state.vg.masking); shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode); ctx->state.dirty = NONE_DIRTY; }
static void update_clip_state(struct vg_context *ctx) { struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa; struct vg_state *state = &ctx->state.vg; memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); if (state->scissoring) { struct pipe_blend_state *blend = &ctx->state.g3d.blend; struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; int i; dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/ dsa->depth.func = PIPE_FUNC_ALWAYS; dsa->depth.enabled = 1; cso_save_blend(ctx->cso_context); cso_save_fragment_shader(ctx->cso_context); /* set a passthrough shader */ if (!ctx->pass_through_depth_fs) ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe, pass_through_depth_asm, 40, PIPE_SHADER_FRAGMENT); cso_set_fragment_shader_handle(ctx->cso_context, ctx->pass_through_depth_fs->driver); cso_set_depth_stencil_alpha(ctx->cso_context, dsa); ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0); /* disable color writes */ blend->rt[0].colormask = 0; /*disable colorwrites*/ cso_set_blend(ctx->cso_context, blend); /* enable scissoring */ for (i = 0; i < state->scissor_rects_num; ++i) { const float x = state->scissor_rects[i * 4 + 0].f; const float y = state->scissor_rects[i * 4 + 1].f; const float width = state->scissor_rects[i * 4 + 2].f; const float height = state->scissor_rects[i * 4 + 3].f; VGfloat minx, miny, maxx, maxy; minx = 0; miny = 0; maxx = fb->width; maxy = fb->height; if (x > minx) minx = x; if (y > miny) miny = y; if (x + width < maxx) maxx = x + width; if (y + height < maxy) maxy = y + height; /* check for null space */ if (minx >= maxx || miny >= maxy) minx = miny = maxx = maxy = 0; /*glClear(GL_DEPTH_BUFFER_BIT);*/ renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f); } cso_restore_blend(ctx->cso_context); cso_restore_fragment_shader(ctx->cso_context); dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */ dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/ dsa->depth.func = PIPE_FUNC_GEQUAL; } }
struct st_context * st_context_create(struct st_device *st_dev) { struct st_context *st_ctx; st_ctx = CALLOC_STRUCT(st_context); if(!st_ctx) return NULL; st_device_reference(&st_ctx->st_dev, st_dev); st_ctx->real_pipe = st_dev->st_ws->context_create(st_dev->real_screen); if(!st_ctx->real_pipe) { st_context_destroy(st_ctx); return NULL; } st_ctx->pipe = trace_context_create(st_dev->screen, st_ctx->real_pipe); if(!st_ctx->pipe) { st_context_destroy(st_ctx); return NULL; } st_ctx->cso = cso_create_context(st_ctx->pipe); if(!st_ctx->cso) { st_context_destroy(st_ctx); return NULL; } /* disabled blending/masking */ { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.colormask = PIPE_MASK_RGBA; cso_set_blend(st_ctx->cso, &blend); } /* no-op depth/stencil/alpha */ { struct pipe_depth_stencil_alpha_state depthstencil; memset(&depthstencil, 0, sizeof(depthstencil)); cso_set_depth_stencil_alpha(st_ctx->cso, &depthstencil); } /* rasterizer */ { struct pipe_rasterizer_state rasterizer; memset(&rasterizer, 0, sizeof(rasterizer)); rasterizer.front_winding = PIPE_WINDING_CW; rasterizer.cull_mode = PIPE_WINDING_NONE; cso_set_rasterizer(st_ctx->cso, &rasterizer); } /* clip */ { struct pipe_clip_state clip; memset(&clip, 0, sizeof(clip)); st_ctx->pipe->set_clip_state(st_ctx->pipe, &clip); } /* identity viewport */ { struct pipe_viewport_state viewport; viewport.scale[0] = 1.0; viewport.scale[1] = 1.0; viewport.scale[2] = 1.0; viewport.scale[3] = 1.0; viewport.translate[0] = 0.0; viewport.translate[1] = 0.0; viewport.translate[2] = 0.0; viewport.translate[3] = 0.0; cso_set_viewport(st_ctx->cso, &viewport); } /* samplers */ { struct pipe_sampler_state sampler; unsigned i; memset(&sampler, 0, sizeof(sampler)); sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; sampler.normalized_coords = 1; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) cso_single_sampler(st_ctx->cso, i, &sampler); cso_single_sampler_done(st_ctx->cso); } /* default textures */ { struct pipe_screen *screen = st_dev->screen; struct pipe_texture templat; struct pipe_transfer *transfer; unsigned i; memset( &templat, 0, sizeof( templat ) ); templat.target = PIPE_TEXTURE_2D; templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; templat.block.size = 4; templat.block.width = 1; templat.block.height = 1; templat.width[0] = 1; templat.height[0] = 1; templat.depth[0] = 1; templat.last_level = 0; st_ctx->default_texture = screen->texture_create( screen, &templat ); if(st_ctx->default_texture) { transfer = screen->get_tex_transfer(screen, st_ctx->default_texture, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, st_ctx->default_texture->width[0], st_ctx->default_texture->height[0]); if (transfer) { uint32_t *map; map = (uint32_t *) screen->transfer_map(screen, transfer); if(map) { *map = 0x00000000; screen->transfer_unmap(screen, transfer); } screen->tex_transfer_destroy(transfer); } } for (i = 0; i < PIPE_MAX_SAMPLERS; i++) pipe_texture_reference(&st_ctx->sampler_textures[i], st_ctx->default_texture); cso_set_sampler_textures(st_ctx->cso, PIPE_MAX_SAMPLERS, st_ctx->sampler_textures); } /* vertex shader */ { const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC }; const uint semantic_indexes[] = { 0, 0 }; st_ctx->vs = util_make_vertex_passthrough_shader(st_ctx->pipe, 2, semantic_names, semantic_indexes); cso_set_vertex_shader_handle(st_ctx->cso, st_ctx->vs); } /* fragment shader */ { st_ctx->fs = util_make_fragment_passthrough_shader(st_ctx->pipe); cso_set_fragment_shader_handle(st_ctx->cso, st_ctx->fs); } return st_ctx; }
/** * Do glClear by drawing a quadrilateral. * The vertices of the quad will be computed from the * ctx->DrawBuffer->_X/Ymin/max fields. */ static void clear_with_quad(struct gl_context *ctx, GLboolean color, GLboolean depth, GLboolean stencil) { struct st_context *st = st_context(ctx); const struct gl_framebuffer *fb = ctx->DrawBuffer; const GLfloat fb_width = (GLfloat) fb->Width; const GLfloat fb_height = (GLfloat) fb->Height; const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f; const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; union pipe_color_union clearColor; /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, color ? "color, " : "", depth ? "depth, " : "", stencil ? "stencil" : "", x0, y0, x1, y1); */ cso_save_blend(st->cso_context); cso_save_stencil_ref(st->cso_context); cso_save_depth_stencil_alpha(st->cso_context); cso_save_rasterizer(st->cso_context); cso_save_viewport(st->cso_context); cso_save_fragment_shader(st->cso_context); cso_save_stream_outputs(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_geometry_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); cso_save_vertex_buffers(st->cso_context); /* blend state: RGBA masking */ { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); 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; if (color) { if (ctx->Color.ColorMask[0][0]) blend.rt[0].colormask |= PIPE_MASK_R; if (ctx->Color.ColorMask[0][1]) blend.rt[0].colormask |= PIPE_MASK_G; if (ctx->Color.ColorMask[0][2]) blend.rt[0].colormask |= PIPE_MASK_B; if (ctx->Color.ColorMask[0][3]) blend.rt[0].colormask |= PIPE_MASK_A; if (st->ctx->Color.DitherFlag) blend.dither = 1; } cso_set_blend(st->cso_context, &blend); } /* depth_stencil state: always pass/set to ref value */ { struct pipe_depth_stencil_alpha_state depth_stencil; memset(&depth_stencil, 0, sizeof(depth_stencil)); if (depth) { depth_stencil.depth.enabled = 1; depth_stencil.depth.writemask = 1; depth_stencil.depth.func = PIPE_FUNC_ALWAYS; } if (stencil) { struct pipe_stencil_ref stencil_ref; memset(&stencil_ref, 0, sizeof(stencil_ref)); depth_stencil.stencil[0].enabled = 1; depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS; depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].valuemask = 0xff; depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; stencil_ref.ref_value[0] = ctx->Stencil.Clear; cso_set_stencil_ref(st->cso_context, &stencil_ref); } cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil); } cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw); cso_set_stream_outputs(st->cso_context, 0, NULL, 0); cso_set_rasterizer(st->cso_context, &st->clear.raster); /* viewport state: viewport matching window dims */ { const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); struct pipe_viewport_state vp; vp.scale[0] = 0.5f * fb_width; vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f); vp.scale[2] = 1.0f; vp.scale[3] = 1.0f; vp.translate[0] = 0.5f * fb_width; vp.translate[1] = 0.5f * fb_height; vp.translate[2] = 0.0f; vp.translate[3] = 0.0f; cso_set_viewport(st->cso_context, &vp); } set_fragment_shader(st); set_vertex_shader(st); cso_set_geometry_shader_handle(st->cso_context, NULL); if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { st_translate_color(ctx->Color.ClearColor.f, ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, clearColor.f); } /* draw quad matching scissor rect */ draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, &clearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); cso_restore_stencil_ref(st->cso_context); cso_restore_depth_stencil_alpha(st->cso_context); cso_restore_rasterizer(st->cso_context); cso_restore_viewport(st->cso_context); cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); cso_restore_geometry_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); cso_restore_vertex_buffers(st->cso_context); cso_restore_stream_outputs(st->cso_context); }
/** * Copy pixel block from src sampler view to dst surface. * * The sampler view's first_level field indicates the source * mipmap level to use. * * The sampler view's first_layer indicate the layer to use, but for * cube maps it must point to the first face. Face is passed in src_face. * * The main advantage over util_blit_pixels is that it allows to specify * swizzles in pipe_sampler_view::swizzle_?. * * But there is no control over blitting Z and/or stencil. */ void util_blit_pixels_tex(struct blit_state *ctx, struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, unsigned src_face, struct pipe_surface *dst, int dstX0, int dstY0, int dstX1, int dstY1, float z, enum pipe_tex_filter filter, boolean src_xrbias) { boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT; struct pipe_framebuffer_state fb; float s0, t0, s1, t1; unsigned offset; struct pipe_resource *tex = src_sampler_view->texture; assert(filter == PIPE_TEX_FILTER_NEAREST || filter == PIPE_TEX_FILTER_LINEAR); assert(tex); assert(tex->width0 != 0); assert(tex->height0 != 0); s0 = (float) srcX0; s1 = (float) srcX1; t0 = (float) srcY0; t1 = (float) srcY1; if (normalized) { /* normalize according to the mipmap level's size */ int level = src_sampler_view->u.tex.first_level; float w = (float) u_minify(tex->width0, level); float h = (float) u_minify(tex->height0, level); s0 /= w; s1 /= w; t0 /= h; t1 /= h; } assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, PIPE_TEXTURE_2D, dst->texture->nr_samples, PIPE_BIND_RENDER_TARGET)); /* save state (restored below) */ cso_save_state(ctx->cso, (CSO_BIT_BLEND | CSO_BIT_DEPTH_STENCIL_ALPHA | CSO_BIT_RASTERIZER | CSO_BIT_SAMPLE_MASK | CSO_BIT_MIN_SAMPLES | CSO_BIT_FRAGMENT_SAMPLERS | CSO_BIT_FRAGMENT_SAMPLER_VIEWS | CSO_BIT_STREAM_OUTPUTS | CSO_BIT_VIEWPORT | CSO_BIT_FRAMEBUFFER | CSO_BIT_PAUSE_QUERIES | CSO_BIT_FRAGMENT_SHADER | CSO_BIT_VERTEX_SHADER | CSO_BIT_TESSCTRL_SHADER | CSO_BIT_TESSEVAL_SHADER | CSO_BIT_GEOMETRY_SHADER | CSO_BIT_VERTEX_ELEMENTS | CSO_BIT_AUX_VERTEX_BUFFER_SLOT)); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend_write_color); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil); cso_set_sample_mask(ctx->cso, ~0); cso_set_min_samples(ctx->cso, 1); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); cso_set_stream_outputs(ctx->cso, 0, NULL, NULL); /* sampler */ ctx->sampler.normalized_coords = normalized; ctx->sampler.min_img_filter = filter; ctx->sampler.mag_img_filter = filter; { const struct pipe_sampler_state *samplers[] = {&ctx->sampler}; cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 1, samplers); } /* viewport */ ctx->viewport.scale[0] = 0.5f * dst->width; ctx->viewport.scale[1] = 0.5f * dst->height; ctx->viewport.scale[2] = 0.5f; ctx->viewport.translate[0] = 0.5f * dst->width; ctx->viewport.translate[1] = 0.5f * dst->height; ctx->viewport.translate[2] = 0.5f; cso_set_viewport(ctx->cso, &ctx->viewport); /* texture */ cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view); /* shaders */ set_fragment_shader(ctx, src_sampler_view->format, src_xrbias, src_sampler_view->texture->target); set_vertex_shader(ctx); cso_set_tessctrl_shader_handle(ctx->cso, NULL); cso_set_tesseval_shader_handle(ctx->cso, NULL); cso_set_geometry_shader_handle(ctx->cso, NULL); /* drawing dest */ memset(&fb, 0, sizeof(fb)); fb.width = dst->width; fb.height = dst->height; fb.nr_cbufs = 1; fb.cbufs[0] = dst; cso_set_framebuffer(ctx->cso, &fb); /* draw quad */ offset = setup_vertex_data_tex(ctx, src_sampler_view->texture->target, src_face, (float) dstX0 / dst->width * 2.0f - 1.0f, (float) dstY0 / dst->height * 2.0f - 1.0f, (float) dstX1 / dst->width * 2.0f - 1.0f, (float) dstY1 / dst->height * 2.0f - 1.0f, s0, t0, s1, t1, z); util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, cso_get_aux_vertex_buffer_slot(ctx->cso), offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ /* restore state we changed */ cso_restore_state(ctx->cso); }
static void draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLsizei width, GLsizei height, GLfloat zoomX, GLfloat zoomY, struct pipe_sampler_view **sv, int num_sampler_view, void *driver_vp, void *driver_fp, const GLfloat *color, GLboolean invertTex, GLboolean write_depth, GLboolean write_stencil) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; GLfloat x0, y0, x1, y1; GLsizei maxSize; boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT; /* limit checks */ /* XXX if DrawPixels image is larger than max texture size, break * it up into chunks. */ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); assert(width <= maxSize); assert(height <= maxSize); cso_save_rasterizer(cso); cso_save_viewport(cso); cso_save_samplers(cso); cso_save_fragment_sampler_views(cso); cso_save_fragment_shader(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); cso_save_vertex_buffers(cso); if (write_stencil) { cso_save_depth_stencil_alpha(cso); cso_save_blend(cso); } /* rasterizer state: just scissor */ { struct pipe_rasterizer_state rasterizer; memset(&rasterizer, 0, sizeof(rasterizer)); rasterizer.clamp_fragment_color = ctx->Color._ClampFragmentColor; rasterizer.gl_rasterization_rules = 1; rasterizer.scissor = ctx->Scissor.Enabled; cso_set_rasterizer(cso, &rasterizer); } if (write_stencil) { /* Stencil writing bypasses the normal fragment pipeline to * disable color writing and set stencil test to always pass. */ struct pipe_depth_stencil_alpha_state dsa; struct pipe_blend_state blend; /* depth/stencil */ memset(&dsa, 0, sizeof(dsa)); dsa.stencil[0].enabled = 1; dsa.stencil[0].func = PIPE_FUNC_ALWAYS; dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; if (write_depth) { /* writing depth+stencil: depth test always passes */ dsa.depth.enabled = 1; dsa.depth.writemask = ctx->Depth.Mask; dsa.depth.func = PIPE_FUNC_ALWAYS; } cso_set_depth_stencil_alpha(cso, &dsa); /* blend (colormask) */ memset(&blend, 0, sizeof(blend)); cso_set_blend(cso, &blend); } /* fragment shader state: TEX lookup program */ cso_set_fragment_shader_handle(cso, driver_fp); /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, driver_vp); /* texture sampling state: */ { struct pipe_sampler_state sampler; memset(&sampler, 0, sizeof(sampler)); sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; sampler.normalized_coords = normalized; cso_single_sampler(cso, 0, &sampler); if (num_sampler_view > 1) { cso_single_sampler(cso, 1, &sampler); } cso_single_sampler_done(cso); } /* viewport state: viewport matching window dims */ { const float w = (float) ctx->DrawBuffer->Width; const float h = (float) ctx->DrawBuffer->Height; struct pipe_viewport_state vp; vp.scale[0] = 0.5f * w; vp.scale[1] = -0.5f * h; vp.scale[2] = 0.5f; vp.scale[3] = 1.0f; vp.translate[0] = 0.5f * w; vp.translate[1] = 0.5f * h; vp.translate[2] = 0.5f; vp.translate[3] = 0.0f; cso_set_viewport(cso, &vp); } cso_set_vertex_elements(cso, 3, st->velems_util_draw); /* texture state: */ cso_set_fragment_sampler_views(cso, num_sampler_view, sv); /* Compute Gallium window coords (y=0=top) with pixel zoom. * Recall that these coords are transformed by the current * vertex shader and viewport transformation. */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY); invertTex = !invertTex; } x0 = (GLfloat) x; x1 = x + width * ctx->Pixel.ZoomX; y0 = (GLfloat) y; y1 = y + height * ctx->Pixel.ZoomY; /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ z = z * 2.0 - 1.0; draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, normalized ? ((GLfloat) width / sv[0]->texture->width0) : (GLfloat)width, normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height); /* restore state */ cso_restore_rasterizer(cso); cso_restore_viewport(cso); cso_restore_samplers(cso); cso_restore_fragment_sampler_views(cso); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); if (write_stencil) { cso_restore_depth_stencil_alpha(cso); cso_restore_blend(cso); } }
/** * Do glClear by drawing a quadrilateral. * The vertices of the quad will be computed from the * ctx->DrawBuffer->_X/Ymin/max fields. */ static void clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) { struct st_context *st = st_context(ctx); const struct gl_framebuffer *fb = ctx->DrawBuffer; const GLfloat fb_width = (GLfloat) fb->Width; const GLfloat fb_height = (GLfloat) fb->Height; const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f; const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; unsigned num_layers = util_framebuffer_get_num_layers(&st->state.framebuffer); /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, color ? "color, " : "", depth ? "depth, " : "", stencil ? "stencil" : "", x0, y0, x1, y1); */ cso_save_blend(st->cso_context); cso_save_stencil_ref(st->cso_context); cso_save_depth_stencil_alpha(st->cso_context); cso_save_rasterizer(st->cso_context); cso_save_sample_mask(st->cso_context); cso_save_viewport(st->cso_context); cso_save_fragment_shader(st->cso_context); cso_save_stream_outputs(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_geometry_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); cso_save_aux_vertex_buffer_slot(st->cso_context); /* blend state: RGBA masking */ { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); if (clear_buffers & PIPE_CLEAR_COLOR) { int num_buffers = ctx->Extensions.EXT_draw_buffers2 ? ctx->DrawBuffer->_NumColorDrawBuffers : 1; int i; blend.independent_blend_enable = num_buffers > 1; for (i = 0; i < num_buffers; i++) { if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i))) continue; if (ctx->Color.ColorMask[i][0]) blend.rt[i].colormask |= PIPE_MASK_R; if (ctx->Color.ColorMask[i][1]) blend.rt[i].colormask |= PIPE_MASK_G; if (ctx->Color.ColorMask[i][2]) blend.rt[i].colormask |= PIPE_MASK_B; if (ctx->Color.ColorMask[i][3]) blend.rt[i].colormask |= PIPE_MASK_A; } if (st->ctx->Color.DitherFlag) blend.dither = 1; } cso_set_blend(st->cso_context, &blend); } /* depth_stencil state: always pass/set to ref value */ { struct pipe_depth_stencil_alpha_state depth_stencil; memset(&depth_stencil, 0, sizeof(depth_stencil)); if (clear_buffers & PIPE_CLEAR_DEPTH) { depth_stencil.depth.enabled = 1; depth_stencil.depth.writemask = 1; depth_stencil.depth.func = PIPE_FUNC_ALWAYS; } if (clear_buffers & PIPE_CLEAR_STENCIL) { struct pipe_stencil_ref stencil_ref; memset(&stencil_ref, 0, sizeof(stencil_ref)); depth_stencil.stencil[0].enabled = 1; depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS; depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].valuemask = 0xff; depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; stencil_ref.ref_value[0] = ctx->Stencil.Clear; cso_set_stencil_ref(st->cso_context, &stencil_ref); } cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil); } cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw); cso_set_stream_outputs(st->cso_context, 0, NULL, NULL); cso_set_sample_mask(st->cso_context, ~0); cso_set_rasterizer(st->cso_context, &st->clear.raster); /* viewport state: viewport matching window dims */ { const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); struct pipe_viewport_state vp; vp.scale[0] = 0.5f * fb_width; vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f); vp.scale[2] = 1.0f; vp.scale[3] = 1.0f; vp.translate[0] = 0.5f * fb_width; vp.translate[1] = 0.5f * fb_height; vp.translate[2] = 0.0f; vp.translate[3] = 0.0f; cso_set_viewport(st->cso_context, &vp); } set_fragment_shader(st); cso_set_geometry_shader_handle(st->cso_context, NULL); if (num_layers > 1) set_vertex_shader_layered(st); else set_vertex_shader(st); /* We can't translate the clear color to the colorbuffer format, * because different colorbuffers may have different formats. */ /* draw quad matching scissor rect */ draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, num_layers, (union pipe_color_union*)&ctx->Color.ClearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); cso_restore_stencil_ref(st->cso_context); cso_restore_depth_stencil_alpha(st->cso_context); cso_restore_rasterizer(st->cso_context); cso_restore_sample_mask(st->cso_context); cso_restore_viewport(st->cso_context); cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); cso_restore_geometry_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); cso_restore_aux_vertex_buffer_slot(st->cso_context); cso_restore_stream_outputs(st->cso_context); }
/** * Prepare the renderer for polygon silhouette rendering. */ VGboolean renderer_polygon_stencil_begin(struct renderer *renderer, struct pipe_vertex_element *velem, VGFillRule rule, VGboolean restore_dsa) { struct pipe_depth_stencil_alpha_state *dsa; VGboolean manual_two_sides; assert(renderer->state == RENDERER_STATE_INIT); cso_save_vertex_elements(renderer->cso); cso_save_blend(renderer->cso); cso_save_depth_stencil_alpha(renderer->cso); cso_set_vertex_elements(renderer->cso, 1, velem); /* disable color writes */ renderer_set_blend(renderer, 0); manual_two_sides = VG_FALSE; dsa = &renderer->u.polygon_stencil.dsa; memset(dsa, 0, sizeof(*dsa)); if (rule == VG_EVEN_ODD) { dsa->stencil[0].enabled = 1; dsa->stencil[0].writemask = 1; dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT; dsa->stencil[0].func = PIPE_FUNC_ALWAYS; dsa->stencil[0].valuemask = ~0; } else { assert(rule == VG_NON_ZERO); /* front face */ dsa->stencil[0].enabled = 1; dsa->stencil[0].writemask = ~0; dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; dsa->stencil[0].func = PIPE_FUNC_ALWAYS; dsa->stencil[0].valuemask = ~0; if (renderer->pipe->screen->get_param(renderer->pipe->screen, PIPE_CAP_TWO_SIDED_STENCIL)) { /* back face */ dsa->stencil[1] = dsa->stencil[0]; dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; } else { manual_two_sides = VG_TRUE; } } cso_set_depth_stencil_alpha(renderer->cso, dsa); if (manual_two_sides) cso_save_rasterizer(renderer->cso); renderer->u.polygon_stencil.manual_two_sides = manual_two_sides; renderer->u.polygon_stencil.restore_dsa = restore_dsa; renderer->state = RENDERER_STATE_POLYGON_STENCIL; return VG_TRUE; }
/** * Copy pixel block from src surface to dst surface. * Overlapping regions are acceptable. * Flipping and stretching are supported. * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR * \param writemask controls which channels in the dest surface are sourced * from the src surface. Disabled channels are sourced * from (0,0,0,1). */ void util_blit_pixels(struct blit_state *ctx, struct pipe_resource *src_tex, unsigned src_level, int srcX0, int srcY0, int srcX1, int srcY1, int srcZ0, struct pipe_surface *dst, int dstX0, int dstY0, int dstX1, int dstY1, float z, uint filter, uint writemask, uint zs_writemask) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; enum pipe_format src_format, dst_format; struct pipe_sampler_view *sampler_view = NULL; struct pipe_sampler_view sv_templ; struct pipe_surface *dst_surface; struct pipe_framebuffer_state fb; const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); unsigned offset; boolean overlap; float s0, t0, s1, t1; boolean normalized; boolean is_stencil, is_depth, blit_depth, blit_stencil; const struct util_format_description *src_desc = util_format_description(src_tex->format); assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); assert(src_level <= src_tex->last_level); /* do the regions overlap? */ overlap = src_tex == dst->texture && dst->u.tex.level == src_level && dst->u.tex.first_layer == srcZ0 && regions_overlap(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1); src_format = util_format_linear(src_tex->format); dst_format = util_format_linear(dst->texture->format); /* See whether we will blit depth or stencil. */ is_depth = util_format_has_depth(src_desc); is_stencil = util_format_has_stencil(src_desc); blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z); blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL); assert((writemask && !zs_writemask && !is_depth && !is_stencil) || (!writemask && (blit_depth || blit_stencil))); /* * Check for simple case: no format conversion, no flipping, no stretching, * no overlapping, same number of samples. * Filter mode should not matter since there's no stretching. */ if (formats_compatible(src_format, dst_format) && src_tex->nr_samples == dst->texture->nr_samples && is_stencil == blit_stencil && is_depth == blit_depth && srcX0 < srcX1 && dstX0 < dstX1 && srcY0 < srcY1 && dstY0 < dstY1 && (dstX1 - dstX0) == (srcX1 - srcX0) && (dstY1 - dstY0) == (srcY1 - srcY0) && !overlap) { struct pipe_box src_box; src_box.x = srcX0; src_box.y = srcY0; src_box.z = srcZ0; src_box.width = srcW; src_box.height = srcH; src_box.depth = 1; pipe->resource_copy_region(pipe, dst->texture, dst->u.tex.level, dstX0, dstY0, dst->u.tex.first_layer,/* dest */ src_tex, src_level, &src_box); return; } /* XXX Reading multisample textures is unimplemented. */ assert(src_tex->nr_samples <= 1); if (src_tex->nr_samples > 1) { return; } /* It's a mistake to call this function with a stencil format and * without shader stencil export. We don't do software fallbacks here. * Ignore stencil and only copy depth. */ if (blit_stencil && !ctx->has_stencil_export) { blit_stencil = FALSE; if (!blit_depth) return; } if (dst_format == dst->format) { dst_surface = dst; } else { struct pipe_surface templ = *dst; templ.format = dst_format; dst_surface = pipe->create_surface(pipe, dst->texture, &templ); } /* Create a temporary texture when src and dest alias. */ if (src_tex == dst_surface->texture && dst_surface->u.tex.level == src_level && dst_surface->u.tex.first_layer == srcZ0) { /* Make a temporary texture which contains a copy of the source pixels. * Then we'll sample from the temporary texture. */ struct pipe_resource texTemp; struct pipe_resource *tex; struct pipe_sampler_view sv_templ; struct pipe_box src_box; const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); if (srcLeft != srcX0) { /* left-right flip */ int tmp = dstX0; dstX0 = dstX1; dstX1 = tmp; } if (srcTop != srcY0) { /* up-down flip */ int tmp = dstY0; dstY0 = dstY1; dstY1 = tmp; } /* create temp texture */ memset(&texTemp, 0, sizeof(texTemp)); texTemp.target = ctx->internal_target; texTemp.format = src_format; texTemp.last_level = 0; texTemp.width0 = srcW; texTemp.height0 = srcH; texTemp.depth0 = 1; texTemp.array_size = 1; texTemp.bind = PIPE_BIND_SAMPLER_VIEW; tex = screen->resource_create(screen, &texTemp); if (!tex) return; src_box.x = srcLeft; src_box.y = srcTop; src_box.z = srcZ0; src_box.width = srcW; src_box.height = srcH; src_box.depth = 1; /* load temp texture */ pipe->resource_copy_region(pipe, tex, 0, 0, 0, 0, /* dest */ src_tex, src_level, &src_box); normalized = tex->target != PIPE_TEXTURE_RECT; if(normalized) { s0 = 0.0f; s1 = 1.0f; t0 = 0.0f; t1 = 1.0f; } else { s0 = 0; s1 = srcW; t0 = 0; t1 = srcH; } u_sampler_view_default_template(&sv_templ, tex, tex->format); if (!blit_depth && blit_stencil) { /* set a stencil-only format, e.g. Z24S8 --> X24S8 */ sv_templ.format = util_format_stencil_only(tex->format); assert(sv_templ.format != PIPE_FORMAT_NONE); } sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ); if (!sampler_view) { pipe_resource_reference(&tex, NULL); return; } pipe_resource_reference(&tex, NULL); } else { /* Directly sample from the source resource/texture */ u_sampler_view_default_template(&sv_templ, src_tex, src_format); if (!blit_depth && blit_stencil) { /* set a stencil-only format, e.g. Z24S8 --> X24S8 */ sv_templ.format = util_format_stencil_only(src_format); assert(sv_templ.format != PIPE_FORMAT_NONE); } sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ); if (!sampler_view) { return; } s0 = srcX0; s1 = srcX1; t0 = srcY0; t1 = srcY1; normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT; if(normalized) { s0 /= (float)(u_minify(sampler_view->texture->width0, src_level)); s1 /= (float)(u_minify(sampler_view->texture->width0, src_level)); t0 /= (float)(u_minify(sampler_view->texture->height0, src_level)); t1 /= (float)(u_minify(sampler_view->texture->height0, src_level)); } } assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target, sampler_view->texture->nr_samples, PIPE_BIND_SAMPLER_VIEW)); assert(screen->is_format_supported(screen, dst_format, ctx->internal_target, dst_surface->texture->nr_samples, is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET)); /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_sample_mask(ctx->cso); cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_stream_outputs(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_geometry_shader(ctx->cso); cso_save_vertex_elements(ctx->cso); cso_save_aux_vertex_buffer_slot(ctx->cso); cso_save_render_condition(ctx->cso); /* set misc state we care about */ if (writemask) cso_set_blend(ctx->cso, &ctx->blend_write_color); else cso_set_blend(ctx->cso, &ctx->blend_keep_color); cso_set_sample_mask(ctx->cso, ~0); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); cso_set_stream_outputs(ctx->cso, 0, NULL, 0); cso_set_render_condition(ctx->cso, NULL, 0); /* default sampler state */ ctx->sampler.normalized_coords = normalized; ctx->sampler.min_img_filter = filter; ctx->sampler.mag_img_filter = filter; ctx->sampler.min_lod = src_level; ctx->sampler.max_lod = src_level; /* Depth stencil state, fragment shader and sampler setup depending on what * we blit. */ if (blit_depth && blit_stencil) { cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); /* don't filter stencil */ ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil); set_depthstencil_fragment_shader(ctx, sampler_view->texture->target); } else if (blit_depth) { cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth); set_depth_fragment_shader(ctx, sampler_view->texture->target); } else if (blit_stencil) { /* don't filter stencil */ ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil); set_stencil_fragment_shader(ctx, sampler_view->texture->target); } else { /* color */ cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil); set_fragment_shader(ctx, writemask, sampler_view->texture->target); } cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT); /* textures */ if (blit_depth && blit_stencil) { /* Setup two samplers, one for depth and the other one for stencil. */ struct pipe_sampler_view templ; struct pipe_sampler_view *views[2]; templ = *sampler_view; templ.format = util_format_stencil_only(templ.format); assert(templ.format != PIPE_FORMAT_NONE); views[0] = sampler_view; views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ); cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views); pipe_sampler_view_reference(&views[1], NULL); } else { cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view); } /* viewport */ ctx->viewport.scale[0] = 0.5f * dst_surface->width; ctx->viewport.scale[1] = 0.5f * dst_surface->height; ctx->viewport.scale[2] = 0.5f; ctx->viewport.scale[3] = 1.0f; ctx->viewport.translate[0] = 0.5f * dst_surface->width; ctx->viewport.translate[1] = 0.5f * dst_surface->height; ctx->viewport.translate[2] = 0.5f; ctx->viewport.translate[3] = 0.0f; cso_set_viewport(ctx->cso, &ctx->viewport); set_vertex_shader(ctx); cso_set_geometry_shader_handle(ctx->cso, NULL); /* drawing dest */ memset(&fb, 0, sizeof(fb)); fb.width = dst_surface->width; fb.height = dst_surface->height; if (blit_depth || blit_stencil) { fb.zsbuf = dst_surface; } else { fb.nr_cbufs = 1; fb.cbufs[0] = dst_surface; } cso_set_framebuffer(ctx->cso, &fb); /* draw quad */ offset = setup_vertex_data_tex(ctx, (float) dstX0 / dst_surface->width * 2.0f - 1.0f, (float) dstY0 / dst_surface->height * 2.0f - 1.0f, (float) dstX1 / dst_surface->width * 2.0f - 1.0f, (float) dstY1 / dst_surface->height * 2.0f - 1.0f, s0, t0, s1, t1, z); if (ctx->vbuf) { util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, cso_get_aux_vertex_buffer_slot(ctx->cso), offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ } /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_sample_mask(ctx->cso); cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_viewport(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_geometry_shader(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_aux_vertex_buffer_slot(ctx->cso); cso_restore_stream_outputs(ctx->cso); cso_restore_render_condition(ctx->cso); pipe_sampler_view_reference(&sampler_view, NULL); if (dst_surface != dst) pipe_surface_reference(&dst_surface, NULL); }
/** * Copy pixel block from src sampler view to dst surface. * * The sampler view's first_level field indicates the source * mipmap level to use. * * The sampler view's first_layer indicate the layer to use, but for * cube maps it must point to the first face. Face is passed in src_face. * * The main advantage over util_blit_pixels is that it allows to specify swizzles in * pipe_sampler_view::swizzle_?. * * But there is no control over blitting Z and/or stencil. */ void util_blit_pixels_tex(struct blit_state *ctx, struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, unsigned src_face, struct pipe_surface *dst, int dstX0, int dstY0, int dstX1, int dstY1, float z, uint filter) { boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT; struct pipe_framebuffer_state fb; float s0, t0, s1, t1; unsigned offset; struct pipe_resource *tex = src_sampler_view->texture; assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); assert(tex); assert(tex->width0 != 0); assert(tex->height0 != 0); s0 = (float) srcX0; s1 = (float) srcX1; t0 = (float) srcY0; t1 = (float) srcY1; if(normalized) { /* normalize according to the mipmap level's size */ int level = src_sampler_view->u.tex.first_level; float w = (float) u_minify(tex->width0, level); float h = (float) u_minify(tex->height0, level); s0 /= w; s1 /= w; t0 /= h; t1 /= h; } assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, PIPE_TEXTURE_2D, dst->texture->nr_samples, PIPE_BIND_RENDER_TARGET)); /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_sample_mask(ctx->cso); cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_stream_outputs(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_geometry_shader(ctx->cso); cso_save_vertex_elements(ctx->cso); cso_save_aux_vertex_buffer_slot(ctx->cso); /* set misc state we care about */ cso_set_blend(ctx->cso, &ctx->blend_write_color); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil); cso_set_sample_mask(ctx->cso, ~0); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); cso_set_stream_outputs(ctx->cso, 0, NULL, 0); /* sampler */ ctx->sampler.normalized_coords = normalized; ctx->sampler.min_img_filter = filter; ctx->sampler.mag_img_filter = filter; cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT); /* viewport */ ctx->viewport.scale[0] = 0.5f * dst->width; ctx->viewport.scale[1] = 0.5f * dst->height; ctx->viewport.scale[2] = 0.5f; ctx->viewport.scale[3] = 1.0f; ctx->viewport.translate[0] = 0.5f * dst->width; ctx->viewport.translate[1] = 0.5f * dst->height; ctx->viewport.translate[2] = 0.5f; ctx->viewport.translate[3] = 0.0f; cso_set_viewport(ctx->cso, &ctx->viewport); /* texture */ cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view); /* shaders */ set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW, src_sampler_view->texture->target); set_vertex_shader(ctx); cso_set_geometry_shader_handle(ctx->cso, NULL); /* drawing dest */ memset(&fb, 0, sizeof(fb)); fb.width = dst->width; fb.height = dst->height; fb.nr_cbufs = 1; fb.cbufs[0] = dst; cso_set_framebuffer(ctx->cso, &fb); /* draw quad */ offset = setup_vertex_data_tex(ctx, src_sampler_view->texture->target, src_face, (float) dstX0 / dst->width * 2.0f - 1.0f, (float) dstY0 / dst->height * 2.0f - 1.0f, (float) dstX1 / dst->width * 2.0f - 1.0f, (float) dstY1 / dst->height * 2.0f - 1.0f, s0, t0, s1, t1, z); util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, cso_get_aux_vertex_buffer_slot(ctx->cso), offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_sample_mask(ctx->cso); cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_viewport(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_geometry_shader(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_aux_vertex_buffer_slot(ctx->cso); cso_restore_stream_outputs(ctx->cso); }
/** * Do glClear by drawing a quadrilateral. * The vertices of the quad will be computed from the * ctx->DrawBuffer->_X/Ymin/max fields. */ static void clear_with_quad(GLcontext *ctx, GLboolean color, GLboolean depth, GLboolean stencil) { struct st_context *st = ctx->st; const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin; const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax; GLfloat y0, y1; if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { y0 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax); y1 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin); } else { y0 = (GLfloat) ctx->DrawBuffer->_Ymin; y1 = (GLfloat) ctx->DrawBuffer->_Ymax; } /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, color ? "color, " : "", depth ? "depth, " : "", stencil ? "stencil" : "", x0, y0, x1, y1); */ cso_save_blend(st->cso_context); cso_save_depth_stencil_alpha(st->cso_context); cso_save_rasterizer(st->cso_context); cso_save_fragment_shader(st->cso_context); cso_save_vertex_shader(st->cso_context); /* blend state: RGBA masking */ { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; if (color) { if (ctx->Color.ColorMask[0]) blend.colormask |= PIPE_MASK_R; if (ctx->Color.ColorMask[1]) blend.colormask |= PIPE_MASK_G; if (ctx->Color.ColorMask[2]) blend.colormask |= PIPE_MASK_B; if (ctx->Color.ColorMask[3]) blend.colormask |= PIPE_MASK_A; if (st->ctx->Color.DitherFlag) blend.dither = 1; } cso_set_blend(st->cso_context, &blend); } /* depth_stencil state: always pass/set to ref value */ { struct pipe_depth_stencil_alpha_state depth_stencil; memset(&depth_stencil, 0, sizeof(depth_stencil)); if (depth) { depth_stencil.depth.enabled = 1; depth_stencil.depth.writemask = 1; depth_stencil.depth.func = PIPE_FUNC_ALWAYS; } if (stencil) { depth_stencil.stencil[0].enabled = 1; depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS; depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; depth_stencil.stencil[0].ref_value = ctx->Stencil.Clear; depth_stencil.stencil[0].valuemask = 0xff; depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; } cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil); } cso_set_rasterizer(st->cso_context, &st->clear.raster); cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); cso_set_vertex_shader_handle(st->cso_context, st->clear.vs); /* draw quad matching scissor rect (XXX verify coord round-off) */ draw_quad(ctx, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); cso_restore_depth_stencil_alpha(st->cso_context); cso_restore_rasterizer(st->cso_context); cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); }
/** Run function of the MLAA filter. */ static void pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in, struct pipe_resource *out, unsigned int n, bool iscolor) { struct pp_program *p = ppq->p; struct pipe_depth_stencil_alpha_state mstencil; struct pipe_sampler_view v_tmp, *arr[3]; unsigned int w = 0; unsigned int h = 0; const struct pipe_stencil_ref ref = { {1} }; /* Insufficient initialization checks. */ assert(p); assert(ppq); assert(ppq->constbuf); assert(ppq->areamaptex); assert(ppq->inner_tmp); assert(ppq->shaders[n]); w = p->framebuffer.width; h = p->framebuffer.height; memset(&mstencil, 0, sizeof(mstencil)); cso_set_stencil_ref(p->cso, &ref); /* Init the pixel size constant */ if (dimensions[0] != p->framebuffer.width || dimensions[1] != p->framebuffer.height) { constants[0] = 1.0f / p->framebuffer.width; constants[1] = 1.0f / p->framebuffer.height; up_consts(ppq); dimensions[0] = p->framebuffer.width; dimensions[1] = p->framebuffer.height; } cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_VERTEX, 0, ppq->constbuf); cso_set_constant_buffer_resource(p->cso, PIPE_SHADER_FRAGMENT, 0, ppq->constbuf); mstencil.stencil[0].enabled = 1; mstencil.stencil[0].valuemask = mstencil.stencil[0].writemask = ~0; mstencil.stencil[0].func = PIPE_FUNC_ALWAYS; mstencil.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; mstencil.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; p->framebuffer.zsbuf = ppq->stencils; /* First pass: depth edge detection */ if (iscolor) pp_filter_setup_in(p, in); else pp_filter_setup_in(p, ppq->depth); pp_filter_setup_out(p, ppq->inner_tmp[0]); pp_filter_set_fb(p); pp_filter_misc_state(p); cso_set_depth_stencil_alpha(p->cso, &mstencil); p->pipe->clear(p->pipe, PIPE_CLEAR_STENCIL | PIPE_CLEAR_COLOR0, &p->clear_color, 0, 0); cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 0, &p->sampler_point); cso_single_sampler_done(p->cso, PIPE_SHADER_FRAGMENT); cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->view); cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]); /* offsetvs */ cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][2]); pp_filter_draw(p); pp_filter_end_pass(p); /* Second pass: blend weights */ /* Sampler order: areamap, edgesmap, edgesmapL (reversed, thx compiler) */ mstencil.stencil[0].func = PIPE_FUNC_EQUAL; mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_KEEP; cso_set_depth_stencil_alpha(p->cso, &mstencil); pp_filter_setup_in(p, ppq->areamaptex); pp_filter_setup_out(p, ppq->inner_tmp[1]); u_sampler_view_default_template(&v_tmp, ppq->inner_tmp[0], ppq->inner_tmp[0]->format); arr[1] = arr[2] = p->pipe->create_sampler_view(p->pipe, ppq->inner_tmp[0], &v_tmp); pp_filter_set_clear_fb(p); cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 0, &p->sampler_point); cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->sampler_point); cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 2, &p->sampler); cso_single_sampler_done(p->cso, PIPE_SHADER_FRAGMENT); arr[0] = p->view; cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 3, arr); cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][0]); /* passvs */ cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][3]); pp_filter_draw(p); pp_filter_end_pass(p); pipe_sampler_view_reference(&arr[1], NULL); /* Third pass: smoothed edges */ /* Sampler order: colormap, blendmap (wtf compiler) */ pp_filter_setup_in(p, ppq->inner_tmp[1]); pp_filter_setup_out(p, out); pp_filter_set_fb(p); /* Blit the input to the output */ pp_blit(p->pipe, in, 0, 0, w, h, 0, p->framebuffer.cbufs[0], 0, 0, w, h); u_sampler_view_default_template(&v_tmp, in, in->format); arr[0] = p->pipe->create_sampler_view(p->pipe, in, &v_tmp); cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 0, &p->sampler_point); cso_single_sampler(p->cso, PIPE_SHADER_FRAGMENT, 1, &p->sampler_point); cso_single_sampler_done(p->cso, PIPE_SHADER_FRAGMENT); arr[1] = p->view; cso_set_sampler_views(p->cso, PIPE_SHADER_FRAGMENT, 2, arr); cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]); /* offsetvs */ cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][4]); p->blend.rt[0].blend_enable = 1; cso_set_blend(p->cso, &p->blend); pp_filter_draw(p); pp_filter_end_pass(p); pipe_sampler_view_reference(&arr[0], NULL); p->blend.rt[0].blend_enable = 0; p->framebuffer.zsbuf = NULL; }
/** * Generate mipmap images. It's assumed all needed texture memory is * already allocated. * * \param psv the sampler view to the texture to generate mipmap levels for * \param face which cube face to generate mipmaps for (0 for non-cube maps) * \param baseLevel the first mipmap level to use as a src * \param lastLevel the last mipmap level to generate * \param filter the minification filter used to generate mipmap levels with * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST */ void util_gen_mipmap(struct gen_mipmap_state *ctx, struct pipe_sampler_view *psv, uint face, uint baseLevel, uint lastLevel, uint filter) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_framebuffer_state fb; struct pipe_resource *pt = psv->texture; uint dstLevel; uint offset; uint type; boolean is_depth = util_format_is_depth_or_stencil(psv->format); /* The texture object should have room for the levels which we're * about to generate. */ assert(lastLevel <= pt->last_level); /* If this fails, why are we here? */ assert(lastLevel > baseLevel); assert(filter == PIPE_TEX_FILTER_LINEAR || filter == PIPE_TEX_FILTER_NEAREST); type = util_pipe_tex_to_tgsi_tex(pt->target, 1); /* check if we can render in the texture's format */ if (!screen->is_format_supported(screen, psv->format, pt->target, pt->nr_samples, is_depth ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET)) { /* The caller should check if the format is renderable. */ assert(0); return; } /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_sample_mask(ctx->cso); cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_stream_outputs(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_geometry_shader(ctx->cso); cso_save_viewport(ctx->cso); cso_save_vertex_elements(ctx->cso); cso_save_aux_vertex_buffer_slot(ctx->cso); cso_save_render_condition(ctx->cso); /* bind our state */ cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color : &ctx->blend_write_color); cso_set_depth_stencil_alpha(ctx->cso, is_depth ? &ctx->dsa_write_depth : &ctx->dsa_keep_depth); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_sample_mask(ctx->cso, ~0); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); cso_set_stream_outputs(ctx->cso, 0, NULL, NULL); cso_set_render_condition(ctx->cso, NULL, FALSE, 0); set_fragment_shader(ctx, type, is_depth); set_vertex_shader(ctx); cso_set_geometry_shader_handle(ctx->cso, NULL); /* init framebuffer state */ memset(&fb, 0, sizeof(fb)); /* set min/mag to same filter for faster sw speed */ ctx->sampler.mag_img_filter = filter; ctx->sampler.min_img_filter = filter; for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; struct pipe_viewport_state vp; unsigned nr_layers, layer, i; float rcoord = 0.0f; if (pt->target == PIPE_TEXTURE_3D) nr_layers = u_minify(pt->depth0, dstLevel); else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY || pt->target == PIPE_TEXTURE_CUBE_ARRAY) nr_layers = pt->array_size; else nr_layers = 1; for (i = 0; i < nr_layers; i++) { struct pipe_surface *surf, surf_templ; if (pt->target == PIPE_TEXTURE_3D) { /* in theory with geom shaders and driver with full layer support could do that in one go. */ layer = i; /* XXX hmm really? */ rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2); } else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) { layer = i; rcoord = (float)layer; } else if (pt->target == PIPE_TEXTURE_CUBE_ARRAY) { layer = i; face = layer % 6; rcoord = layer / 6; } else layer = face; u_surface_default_template(&surf_templ, pt); surf_templ.u.tex.level = dstLevel; surf_templ.u.tex.first_layer = layer; surf_templ.u.tex.last_layer = layer; surf = pipe->create_surface(pipe, pt, &surf_templ); /* * Setup framebuffer / dest surface */ if (is_depth) { fb.nr_cbufs = 0; fb.zsbuf = surf; } else { fb.nr_cbufs = 1; fb.cbufs[0] = surf; } fb.width = u_minify(pt->width0, dstLevel); fb.height = u_minify(pt->height0, dstLevel); cso_set_framebuffer(ctx->cso, &fb); /* viewport */ vp.scale[0] = 0.5f * fb.width; vp.scale[1] = 0.5f * fb.height; vp.scale[2] = 1.0f; vp.scale[3] = 1.0f; vp.translate[0] = 0.5f * fb.width; vp.translate[1] = 0.5f * fb.height; vp.translate[2] = 0.0f; vp.translate[3] = 0.0f; cso_set_viewport(ctx->cso, &vp); /* * Setup sampler state * Note: we should only have to set the min/max LOD clamps to ensure * we grab texels from the right mipmap level. But some hardware * has trouble with min clamping so we also set the lod_bias to * try to work around that. */ ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel; ctx->sampler.lod_bias = (float) srcLevel; cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT); cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &psv); /* quad coords in clip coords */ offset = set_vertex_data(ctx, pt->target, face, rcoord); util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, cso_get_aux_vertex_buffer_slot(ctx->cso), offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ /* need to signal that the texture has changed _after_ rendering to it */ pipe_surface_reference( &surf, NULL ); } } /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_sample_mask(ctx->cso); cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_geometry_shader(ctx->cso); cso_restore_viewport(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_stream_outputs(ctx->cso); cso_restore_aux_vertex_buffer_slot(ctx->cso); cso_restore_render_condition(ctx->cso); }