/** * Set renderer sampler and view states. * * This function modifies samplers and fragment_sampler_views states. */ static void renderer_set_samplers(struct renderer *r, uint num_views, struct pipe_sampler_view **views) { struct pipe_sampler_state sampler; unsigned tex_filter = PIPE_TEX_FILTER_NEAREST; unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE; uint i; memset(&sampler, 0, sizeof(sampler)); sampler.min_img_filter = tex_filter; sampler.mag_img_filter = tex_filter; sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; sampler.wrap_s = tex_wrap; sampler.wrap_t = tex_wrap; sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.normalized_coords = 1; /* set samplers */ for (i = 0; i < num_views; i++) cso_single_sampler(r->cso, PIPE_SHADER_FRAGMENT, i, &sampler); cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT); /* set views */ cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, num_views, views); }
static void update_textures(struct st_context *st, unsigned shader_stage, const struct gl_program *prog, unsigned max_units, struct pipe_sampler_view **sampler_views, unsigned *num_textures) { const GLuint old_max = *num_textures; GLbitfield samplers_used = prog->SamplersUsed; GLuint unit, new_count; if (samplers_used == 0x0 && old_max == 0) return; *num_textures = 0; /* loop over sampler units (aka tex image units) */ for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) { struct pipe_sampler_view *sampler_view = NULL; if (samplers_used & 1) { const GLuint texUnit = prog->SamplerUnits[unit]; GLboolean retval; retval = update_single_texture(st, &sampler_view, texUnit); if (retval == GL_FALSE) continue; *num_textures = unit + 1; } else if (samplers_used == 0 && unit >= old_max) { /* if we've reset all the old views and we have no more new ones */ break; } pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view); } /* Ex: if old_max = 3 and *num_textures = 1, we need to pass an * array of views={X, NULL, NULL} to unref the old texture views * at positions [1] and [2]. */ new_count = MAX2(*num_textures, old_max); assert(new_count <= max_units); cso_set_sampler_views(st->cso_context, shader_stage, new_count, sampler_views); }
static void update_textures(struct st_context *st, gl_shader_stage mesa_shader, const struct gl_program *prog, unsigned max_units, struct pipe_sampler_view **sampler_views, unsigned *num_textures) { const GLuint old_max = *num_textures; GLbitfield samplers_used = prog->SamplersUsed; GLuint unit; struct gl_shader_program *shader = st->ctx->_Shader->CurrentProgram[mesa_shader]; unsigned glsl_version = shader ? shader->Version : 0; unsigned shader_stage = st_shader_stage_to_ptarget(mesa_shader); if (samplers_used == 0x0 && old_max == 0) return; *num_textures = 0; /* loop over sampler units (aka tex image units) */ for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) { struct pipe_sampler_view *sampler_view = NULL; if (samplers_used & 1) { const GLuint texUnit = prog->SamplerUnits[unit]; GLboolean retval; retval = update_single_texture(st, &sampler_view, texUnit, glsl_version); if (retval == GL_FALSE) continue; *num_textures = unit + 1; } else if (samplers_used == 0 && unit >= old_max) { /* if we've reset all the old views and we have no more new ones */ break; } pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view); } cso_set_sampler_views(st->cso_context, shader_stage, *num_textures, sampler_views); }
XA_EXPORT int xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, uint32_t fg) { unsigned vs_traits, fs_traits; struct xa_shader shader; int width, height; int ret; ret = xa_ctx_srf_create(ctx, dst); if (ret != XA_ERR_NONE) return ret; if (ctx->srf->format == PIPE_FORMAT_L8_UNORM) xa_pixel_to_float4_a8(fg, ctx->solid_color); else xa_pixel_to_float4(fg, ctx->solid_color); ctx->has_solid_color = 1; ctx->dst = dst; width = ctx->srf->width; height = ctx->srf->height; #if 0 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", (fg >> 24) & 0xff, (fg >> 16) & 0xff, (fg >> 8) & 0xff, (fg >> 0) & 0xff, exa->solid_color[0], exa->solid_color[1], exa->solid_color[2], exa->solid_color[3]); #endif vs_traits = VS_SOLID_FILL; fs_traits = FS_SOLID_FILL; renderer_bind_destination(ctx, ctx->srf, width, height); bind_solid_blend_state(ctx); cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL); cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL); shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); cso_set_vertex_shader_handle(ctx->cso, shader.vs); cso_set_fragment_shader_handle(ctx->cso, shader.fs); renderer_begin_solid(ctx); xa_ctx_srf_destroy(ctx); return XA_ERR_NONE; }
/** * Set custom renderer fragment shader, and optionally set samplers and views * and upload the fragment constant buffer. * * This function modifies fragment_shader, samplers and fragment_sampler_views * states. */ static void renderer_set_custom_fs(struct renderer *renderer, void *fs, const struct pipe_sampler_state **samplers, struct pipe_sampler_view **views, VGint num_samplers, const void *const_buffer, VGint const_buffer_len) { cso_set_fragment_shader_handle(renderer->cso, fs); /* set samplers and views */ if (num_samplers) { cso_set_samplers(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, samplers); cso_set_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, views); } /* upload fs constant buffer */ if (const_buffer_len) { struct pipe_resource *cbuf = renderer->fs_cbuf; if (!cbuf || renderer->fs_cbuf_len != const_buffer_len || memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) { pipe_resource_reference(&cbuf, NULL); cbuf = pipe_buffer_create(renderer->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC, const_buffer_len); pipe_buffer_write(renderer->pipe, cbuf, 0, const_buffer_len, const_buffer); pipe_set_constant_buffer(renderer->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); renderer->fs_cbuf = cbuf; if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) { memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len); renderer->fs_cbuf_len = const_buffer_len; } else { renderer->fs_cbuf_len = 0; } } } }
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]); }
boolean xorg_solid_bind_state(struct exa_context *exa, struct exa_pixmap_priv *pixmap, Pixel fg) { struct pipe_surface *dst_surf = xorg_gpu_surface(exa->pipe, pixmap); unsigned vs_traits, fs_traits; struct xorg_shader shader; pixel_to_float4(fg, exa->solid_color, pixmap->tex->format); exa->has_solid_color = TRUE; #if 0 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", (fg >> 24) & 0xff, (fg >> 16) & 0xff, (fg >> 8) & 0xff, (fg >> 0) & 0xff, exa->solid_color[0], exa->solid_color[1], exa->solid_color[2], exa->solid_color[3]); #endif vs_traits = VS_SOLID_FILL; fs_traits = FS_SOLID_FILL; renderer_bind_destination(exa->renderer, dst_surf, pixmap->width, pixmap->height); bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL); cso_set_samplers(exa->renderer->cso, PIPE_SHADER_FRAGMENT, 0, NULL); cso_set_sampler_views(exa->renderer->cso, PIPE_SHADER_FRAGMENT, 0, NULL); shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs); renderer_begin_solid(exa->renderer); pipe_surface_reference(&dst_surf, NULL); return TRUE; }
void renderer_copy_prepare(struct xa_context *r, struct pipe_surface *dst_surface, struct pipe_resource *src_texture, const enum xa_formats src_xa_format, const enum xa_formats dst_xa_format) { struct pipe_context *pipe = r->pipe; struct pipe_screen *screen = pipe->screen; struct xa_shader shader; uint32_t fs_traits = FS_COMPOSITE; assert(screen->is_format_supported(screen, dst_surface->format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)); (void)screen; /* set misc state we care about */ { 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; blend.rt[0].colormask = PIPE_MASK_RGBA; cso_set_blend(r->cso, &blend); } /* sampler */ { struct pipe_sampler_state sampler; 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_NONE; sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; sampler.normalized_coords = 1; cso_single_sampler(r->cso, PIPE_SHADER_FRAGMENT, 0, &sampler); cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT); } renderer_bind_destination(r, dst_surface, dst_surface->width, dst_surface->height); /* texture/sampler view */ { struct pipe_sampler_view templ; struct pipe_sampler_view *src_view; u_sampler_view_default_template(&templ, src_texture, src_texture->format); src_view = pipe->create_sampler_view(pipe, src_texture, &templ); cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 1, &src_view); pipe_sampler_view_reference(&src_view, NULL); } /* shaders */ if (src_texture->format == PIPE_FORMAT_L8_UNORM) fs_traits |= FS_SRC_LUMINANCE; if (dst_surface->format == PIPE_FORMAT_L8_UNORM) fs_traits |= FS_DST_LUMINANCE; if (xa_format_a(dst_xa_format) != 0 && xa_format_a(src_xa_format) == 0) fs_traits |= FS_SRC_SET_ALPHA; shader = xa_shaders_get(r->shaders, VS_COMPOSITE, fs_traits); cso_set_vertex_shader_handle(r->cso, shader.vs); cso_set_fragment_shader_handle(r->cso, shader.fs); r->buffer_size = 0; r->attrs_per_vertex = 2; }
static void bind_samplers(struct exa_context *exa, int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, struct exa_pixmap_priv *pSrc, struct exa_pixmap_priv *pMask, struct exa_pixmap_priv *pDst) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS] = {0}; struct pipe_sampler_state src_sampler, mask_sampler; struct pipe_sampler_view view_templ; struct pipe_sampler_view *src_view; struct pipe_context *pipe = exa->pipe; exa->num_bound_samplers = 0; memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); if (pSrcPicture && pSrc) { if (exa->has_solid_color) { debug_assert(!"solid color with textures"); samplers[0] = NULL; pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); } else { unsigned src_wrap = render_repeat_to_gallium( pSrcPicture->repeatType); int filter; render_filter_to_gallium(pSrcPicture->filter, &filter); src_sampler.wrap_s = src_wrap; src_sampler.wrap_t = src_wrap; src_sampler.min_img_filter = filter; src_sampler.mag_img_filter = filter; src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; src_sampler.normalized_coords = 1; samplers[0] = &src_sampler; exa->num_bound_samplers = 1; u_sampler_view_default_template(&view_templ, pSrc->tex, pSrc->tex->format); src_view = pipe->create_sampler_view(pipe, pSrc->tex, &view_templ); pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); exa->bound_sampler_views[0] = src_view; } } if (pMaskPicture && pMask) { unsigned mask_wrap = render_repeat_to_gallium( pMaskPicture->repeatType); int filter; render_filter_to_gallium(pMaskPicture->filter, &filter); mask_sampler.wrap_s = mask_wrap; mask_sampler.wrap_t = mask_wrap; mask_sampler.min_img_filter = filter; mask_sampler.mag_img_filter = filter; src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; mask_sampler.normalized_coords = 1; samplers[1] = &mask_sampler; exa->num_bound_samplers = 2; u_sampler_view_default_template(&view_templ, pMask->tex, pMask->tex->format); src_view = pipe->create_sampler_view(pipe, pMask->tex, &view_templ); pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); exa->bound_sampler_views[1] = src_view; } cso_set_samplers(exa->renderer->cso, PIPE_SHADER_FRAGMENT, exa->num_bound_samplers, (const struct pipe_sampler_state **)samplers); cso_set_sampler_views(exa->renderer->cso, PIPE_SHADER_FRAGMENT, exa->num_bound_samplers, exa->bound_sampler_views); }
/** * 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); }
static void update_textures(struct st_context *st, gl_shader_stage mesa_shader, const struct gl_program *prog, unsigned max_units, struct pipe_sampler_view **sampler_views, unsigned *num_textures) { const GLuint old_max = *num_textures; GLbitfield samplers_used = prog->SamplersUsed; GLbitfield free_slots = ~prog->SamplersUsed; GLbitfield external_samplers_used = prog->ExternalSamplersUsed; GLuint unit; enum pipe_shader_type shader_stage = st_shader_stage_to_ptarget(mesa_shader); if (samplers_used == 0x0 && old_max == 0) return; *num_textures = 0; /* loop over sampler units (aka tex image units) */ for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) { struct pipe_sampler_view *sampler_view = NULL; if (samplers_used & 1) { /* prog->sh.data is NULL if it's ARB_fragment_program */ unsigned glsl_version = prog->sh.data ? prog->sh.data->Version : 0; const GLuint texUnit = prog->SamplerUnits[unit]; GLboolean retval; retval = update_single_texture(st, &sampler_view, texUnit, glsl_version); if (retval == GL_FALSE) continue; *num_textures = unit + 1; } else if (samplers_used == 0 && unit >= old_max) { /* if we've reset all the old views and we have no more new ones */ break; } pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view); } /* For any external samplers with multiplaner YUV, stuff the additional * sampler views we need at the end. * * Trying to cache the sampler view in the stObj looks painful, so just * re-create the sampler view for the extra planes each time. Main use * case is video playback (ie. fps games wouldn't be using this) so I * guess no point to try to optimize this feature. */ while (unlikely(external_samplers_used)) { GLuint unit = u_bit_scan(&external_samplers_used); GLuint extra = 0; struct st_texture_object *stObj = st_get_texture_object(st->ctx, prog, unit); struct pipe_sampler_view tmpl; if (!stObj) continue; /* use original view as template: */ tmpl = *sampler_views[unit]; switch (st_get_view_format(stObj)) { case PIPE_FORMAT_NV12: /* we need one additional R8G8 view: */ tmpl.format = PIPE_FORMAT_RG88_UNORM; tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R8 */ extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); break; case PIPE_FORMAT_IYUV: /* we need two additional R8 views: */ tmpl.format = PIPE_FORMAT_R8_UNORM; extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next->next, &tmpl); break; default: break; } *num_textures = MAX2(*num_textures, extra + 1); } cso_set_sampler_views(st->cso_context, shader_stage, *num_textures, sampler_views); }
static void update_textures(struct st_context *st, enum pipe_shader_type shader_stage, const struct gl_program *prog, struct pipe_sampler_view **sampler_views, unsigned *out_num_textures) { const GLuint old_max = *out_num_textures; GLbitfield samplers_used = prog->SamplersUsed; GLbitfield texel_fetch_samplers = prog->info.textures_used_by_txf; GLbitfield free_slots = ~prog->SamplersUsed; GLbitfield external_samplers_used = prog->ExternalSamplersUsed; GLuint unit; if (samplers_used == 0x0 && old_max == 0) return; unsigned num_textures = 0; /* prog->sh.data is NULL if it's ARB_fragment_program */ bool glsl130 = (prog->sh.data ? prog->sh.data->Version : 0) >= 130; /* loop over sampler units (aka tex image units) */ for (unit = 0; samplers_used || unit < old_max; unit++, samplers_used >>= 1, texel_fetch_samplers >>= 1) { struct pipe_sampler_view *sampler_view = NULL; if (samplers_used & 1) { const GLuint texUnit = prog->SamplerUnits[unit]; /* The EXT_texture_sRGB_decode extension says: * * "The conversion of sRGB color space components to linear color * space is always performed if the texel lookup function is one * of the texelFetch builtin functions. * * Otherwise, if the texel lookup function is one of the texture * builtin functions or one of the texture gather functions, the * conversion of sRGB color space components to linear color space * is controlled by the TEXTURE_SRGB_DECODE_EXT parameter. * * If the TEXTURE_SRGB_DECODE_EXT parameter is DECODE_EXT, the * conversion of sRGB color space components to linear color space * is performed. * * If the TEXTURE_SRGB_DECODE_EXT parameter is SKIP_DECODE_EXT, * the value is returned without decoding. However, if the texture * is also [statically] accessed with a texelFetch function, then * the result of texture builtin functions and/or texture gather * functions may be returned with decoding or without decoding." * * Note: the "statically" will be added to the language per * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=14934 * * So we simply ignore the setting entirely for samplers that are * (statically) accessed with a texelFetch function. */ st_update_single_texture(st, &sampler_view, texUnit, glsl130, texel_fetch_samplers & 1); num_textures = unit + 1; } pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view); } /* For any external samplers with multiplaner YUV, stuff the additional * sampler views we need at the end. * * Trying to cache the sampler view in the stObj looks painful, so just * re-create the sampler view for the extra planes each time. Main use * case is video playback (ie. fps games wouldn't be using this) so I * guess no point to try to optimize this feature. */ while (unlikely(external_samplers_used)) { GLuint unit = u_bit_scan(&external_samplers_used); GLuint extra = 0; struct st_texture_object *stObj = st_get_texture_object(st->ctx, prog, unit); struct pipe_sampler_view tmpl; if (!stObj) continue; /* use original view as template: */ tmpl = *sampler_views[unit]; switch (st_get_view_format(stObj)) { case PIPE_FORMAT_NV12: /* we need one additional R8G8 view: */ tmpl.format = PIPE_FORMAT_RG88_UNORM; tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R8 */ extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); break; case PIPE_FORMAT_IYUV: /* we need two additional R8 views: */ tmpl.format = PIPE_FORMAT_R8_UNORM; extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); extra = u_bit_scan(&free_slots); sampler_views[extra] = st->pipe->create_sampler_view(st->pipe, stObj->pt->next->next, &tmpl); break; default: break; } num_textures = MAX2(num_textures, extra + 1); } cso_set_sampler_views(st->cso_context, shader_stage, num_textures, sampler_views); *out_num_textures = num_textures; }
/** * 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 bind_samplers(struct xa_context *ctx, const struct xa_composite *comp) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state src_sampler, mask_sampler; struct pipe_sampler_view view_templ; struct pipe_sampler_view *src_view; struct pipe_context *pipe = ctx->pipe; struct xa_picture *src_pic = comp->src; struct xa_picture *mask_pic = comp->mask; ctx->num_bound_samplers = 0; memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); if (src_pic) { if (ctx->has_solid_color) { samplers[0] = NULL; pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); } else { unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); int filter; (void) xa_filter_to_gallium(src_pic->filter, &filter); src_sampler.wrap_s = src_wrap; src_sampler.wrap_t = src_wrap; src_sampler.min_img_filter = filter; src_sampler.mag_img_filter = filter; src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; src_sampler.normalized_coords = 1; samplers[0] = &src_sampler; ctx->num_bound_samplers = 1; u_sampler_view_default_template(&view_templ, src_pic->srf->tex, src_pic->srf->tex->format); src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, &view_templ); pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); ctx->bound_sampler_views[0] = src_view; } } if (mask_pic) { unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); int filter; (void) xa_filter_to_gallium(mask_pic->filter, &filter); mask_sampler.wrap_s = mask_wrap; mask_sampler.wrap_t = mask_wrap; mask_sampler.min_img_filter = filter; mask_sampler.mag_img_filter = filter; src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; mask_sampler.normalized_coords = 1; samplers[1] = &mask_sampler; ctx->num_bound_samplers = 2; u_sampler_view_default_template(&view_templ, mask_pic->srf->tex, mask_pic->srf->tex->format); src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, &view_templ); pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL); ctx->bound_sampler_views[1] = src_view; /* * If src is a solid color, we have no src view, so set up a * dummy one that will not be used anyway. */ if (ctx->bound_sampler_views[0] == NULL) pipe_sampler_view_reference(&ctx->bound_sampler_views[0], src_view); } cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, ctx->num_bound_samplers, (const struct pipe_sampler_state **)samplers); cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, ctx->num_bound_samplers, ctx->bound_sampler_views); }
/** * Setup pipeline state prior to rendering the bitmap textured quad. */ static void setup_render_state(struct gl_context *ctx, struct pipe_sampler_view *sv, const GLfloat *color, bool atlas) { struct st_context *st = st_context(ctx); struct cso_context *cso = st->cso_context; struct st_fp_variant *fpv; struct st_fp_variant_key key; memset(&key, 0, sizeof(key)); key.st = st->has_shareable_shaders ? NULL : st; key.bitmap = GL_TRUE; key.clamp_color = st->clamp_frag_color_in_shader && ctx->Color._ClampFragmentColor; fpv = st_get_fp_variant(st, st->fp, &key); /* As an optimization, Mesa's fragment programs will sometimes get the * primary color from a statevar/constant rather than a varying variable. * when that's the case, we need to ensure that we use the 'color' * parameter and not the current attribute color (which may have changed * through glRasterPos and state validation. * So, we force the proper color here. Not elegant, but it works. */ { GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); st_upload_constants(st, st->fp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } cso_save_state(cso, (CSO_BIT_RASTERIZER | CSO_BIT_FRAGMENT_SAMPLERS | CSO_BIT_FRAGMENT_SAMPLER_VIEWS | CSO_BIT_VIEWPORT | CSO_BIT_STREAM_OUTPUTS | CSO_BIT_VERTEX_ELEMENTS | CSO_BIT_AUX_VERTEX_BUFFER_SLOT | CSO_BITS_ALL_SHADERS)); /* rasterizer state: just scissor */ st->bitmap.rasterizer.scissor = ctx->Scissor.EnableFlags & 1; cso_set_rasterizer(cso, &st->bitmap.rasterizer); /* fragment shader state: TEX lookup program */ cso_set_fragment_shader_handle(cso, fpv->driver_shader); /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); /* disable other shaders */ cso_set_tessctrl_shader_handle(cso, NULL); cso_set_tesseval_shader_handle(cso, NULL); cso_set_geometry_shader_handle(cso, NULL); /* user samplers, plus our bitmap sampler */ { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers[PIPE_SHADER_FRAGMENT]); uint i; for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++) { samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i]; } if (atlas) samplers[fpv->bitmap_sampler] = &st->bitmap.atlas_sampler; else samplers[fpv->bitmap_sampler] = &st->bitmap.sampler; cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, (const struct pipe_sampler_state **) samplers); } /* user textures, plus the bitmap texture */ { struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]); memcpy(sampler_views, st->state.sampler_views[PIPE_SHADER_FRAGMENT], sizeof(sampler_views)); sampler_views[fpv->bitmap_sampler] = sv; cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num, sampler_views); } /* viewport state: viewport matching window dims */ cso_set_viewport_dims(cso, st->state.framebuffer.width, st->state.framebuffer.height, st->state.fb_orientation == Y_0_TOP); cso_set_vertex_elements(cso, 3, st->util_velems); cso_set_stream_outputs(st->cso_context, 0, NULL, NULL); }
/** * Render a glBitmap by drawing a textured quad */ static void draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLsizei width, GLsizei height, struct pipe_sampler_view *sv, const GLfloat *color) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; struct st_fp_variant *fpv; struct st_fp_variant_key key; GLuint maxSize; GLuint offset; struct pipe_resource *vbuf = NULL; memset(&key, 0, sizeof(key)); key.st = st; key.bitmap = GL_TRUE; key.clamp_color = st->clamp_frag_color_in_shader && st->ctx->Color._ClampFragmentColor; fpv = st_get_fp_variant(st, st->fp, &key); /* As an optimization, Mesa's fragment programs will sometimes get the * primary color from a statevar/constant rather than a varying variable. * when that's the case, we need to ensure that we use the 'color' * parameter and not the current attribute color (which may have changed * through glRasterPos and state validation. * So, we force the proper color here. Not elegant, but it works. */ { GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } /* limit checks */ /* XXX if the bitmap is larger than the 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 <= (GLsizei)maxSize); assert(height <= (GLsizei)maxSize); cso_save_rasterizer(cso); cso_save_samplers(cso, PIPE_SHADER_FRAGMENT); cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT); cso_save_viewport(cso); cso_save_fragment_shader(cso); cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); cso_save_tessctrl_shader(cso); cso_save_tesseval_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); cso_save_aux_vertex_buffer_slot(cso); /* rasterizer state: just scissor */ st->bitmap.rasterizer.scissor = ctx->Scissor.EnableFlags & 1; cso_set_rasterizer(cso, &st->bitmap.rasterizer); /* fragment shader state: TEX lookup program */ cso_set_fragment_shader_handle(cso, fpv->driver_shader); /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); /* disable other shaders */ cso_set_tessctrl_shader_handle(cso, NULL); cso_set_tesseval_shader_handle(cso, NULL); cso_set_geometry_shader_handle(cso, NULL); /* user samplers, plus our bitmap sampler */ { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers[PIPE_SHADER_FRAGMENT]); uint i; for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++) { samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i]; } samplers[fpv->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, (const struct pipe_sampler_state **) samplers); } /* user textures, plus the bitmap texture */ { struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]); memcpy(sampler_views, st->state.sampler_views[PIPE_SHADER_FRAGMENT], sizeof(sampler_views)); sampler_views[fpv->bitmap_sampler] = sv; cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num, sampler_views); } /* viewport state: viewport matching window dims */ { const GLboolean invert = st->state.fb_orientation == Y_0_TOP; const GLfloat width = (GLfloat)st->state.framebuffer.width; const GLfloat height = (GLfloat)st->state.framebuffer.height; struct pipe_viewport_state vp; vp.scale[0] = 0.5f * width; vp.scale[1] = height * (invert ? -0.5f : 0.5f); vp.scale[2] = 0.5f; vp.translate[0] = 0.5f * width; vp.translate[1] = 0.5f * height; vp.translate[2] = 0.5f; cso_set_viewport(cso, &vp); } cso_set_vertex_elements(cso, 3, st->velems_util_draw); cso_set_stream_outputs(st->cso_context, 0, NULL, NULL); /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ z = z * 2.0f - 1.0f; /* draw textured quad */ setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color, &vbuf, &offset); if (vbuf) { util_draw_vertex_buffer(pipe, st->cso_context, vbuf, cso_get_aux_vertex_buffer_slot(st->cso_context), offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 3); /* attribs/vert */ } /* restore state */ cso_restore_rasterizer(cso); cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT); cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT); cso_restore_viewport(cso); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); cso_restore_tessctrl_shader(cso); cso_restore_tesseval_shader(cso); cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_aux_vertex_buffer_slot(cso); cso_restore_stream_outputs(cso); pipe_resource_reference(&vbuf, NULL); }
/** 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); }