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]); }
void st_resize_framebuffer(struct st_framebuffer *stfb, uint width, uint height) { struct vg_context *ctx = vg_current_context(); struct st_renderbuffer *strb = stfb->strb; struct pipe_framebuffer_state *state; if (!ctx) return; state = &ctx->state.g3d.fb; /* If this is a noop, exit early and don't do the clear, etc below. */ if (strb->width == width && strb->height == height && state->zsbuf) return; if (strb->width != width || strb->height != height) st_renderbuffer_alloc_storage(ctx, strb, width, height); if (stfb->dsrb->width != width || stfb->dsrb->height != height) st_renderbuffer_alloc_storage(ctx, stfb->dsrb, width, height); { VGuint i; memset(state, 0, sizeof(struct pipe_framebuffer_state)); state->width = width; state->height = height; state->nr_cbufs = 1; state->cbufs[0] = strb->surface; for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) state->cbufs[i] = 0; state->zsbuf = stfb->dsrb->surface; cso_set_framebuffer(ctx->cso_context, state); } ctx->state.dirty |= VIEWPORT_DIRTY; ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/ ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0); /* we need all the other state already set */ setup_new_alpha_mask(ctx, stfb, width, height); pipe_texture_reference( &stfb->blend_texture, NULL ); stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_A8R8G8B8_UNORM, width, height); }
/* Set up framebuffer, viewport and vertex shader constant buffer * state for a particular destinaton surface. In all our rendering, * these concepts are linked. */ void renderer_bind_destination(struct xa_context *r, struct pipe_surface *surface) { int width = surface->width; int height = surface->height; struct pipe_framebuffer_state fb; struct pipe_viewport_state viewport; xa_scissor_reset(r); /* Framebuffer uses actual surface width/height */ memset(&fb, 0, sizeof fb); fb.width = surface->width; fb.height = surface->height; fb.nr_cbufs = 1; fb.cbufs[0] = surface; fb.zsbuf = 0; /* Viewport just touches the bit we're interested in: */ viewport.scale[0] = width / 2.f; viewport.scale[1] = height / 2.f; viewport.scale[2] = 1.0; viewport.scale[3] = 1.0; viewport.translate[0] = width / 2.f; viewport.translate[1] = height / 2.f; viewport.translate[2] = 0.0; viewport.translate[3] = 0.0; /* Constant buffer set up to match viewport dimensions: */ if (r->fb_width != width || r->fb_height != height) { float vs_consts[8] = { 2.f / width, 2.f / height, 1, 1, -1, -1, 0, 0 }; r->fb_width = width; r->fb_height = height; renderer_set_constants(r, PIPE_SHADER_VERTEX, vs_consts, sizeof vs_consts); } cso_set_framebuffer(r->cso, &fb); cso_set_viewport(r->cso, &viewport); }
/** * Set renderer target. * * This function modifies framebuffer and viewport states. */ static void renderer_set_target(struct renderer *r, struct pipe_surface *cbuf, struct pipe_surface *zsbuf, VGboolean y0_top) { struct pipe_framebuffer_state fb; memset(&fb, 0, sizeof(fb)); fb.width = cbuf->width; fb.height = cbuf->height; fb.cbufs[0] = cbuf; fb.nr_cbufs = 1; fb.zsbuf = zsbuf; cso_set_framebuffer(r->cso, &fb); vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM); }
static void util_set_framebuffer_cb0(struct cso_context *cso, struct pipe_context *ctx, struct pipe_resource *tex) { struct pipe_surface templ = {{0}}, *surf; struct pipe_framebuffer_state fb = {0}; templ.format = tex->format; surf = ctx->create_surface(ctx, tex, &templ); fb.width = tex->width0; fb.height = tex->height0; fb.cbufs[0] = surf; fb.nr_cbufs = 1; cso_set_framebuffer(cso, &fb); pipe_surface_reference(&surf, NULL); }
/** * 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); }
static void vg_context_update_draw_buffer(struct vg_context *ctx, struct pipe_resource *pt) { struct st_framebuffer *stfb = ctx->draw_buffer; boolean new_cbuf, new_zsbuf, new_size; new_cbuf = vg_context_update_color_rb(ctx, pt); new_zsbuf = vg_context_update_depth_stencil_rb(ctx, pt->width0, pt->height0); new_size = (stfb->width != pt->width0 || stfb->height != pt->height0); stfb->width = pt->width0; stfb->height = pt->height0; if (new_cbuf || new_zsbuf || new_size) { struct pipe_framebuffer_state *state = &ctx->state.g3d.fb; memset(state, 0, sizeof(struct pipe_framebuffer_state)); state->width = stfb->width; state->height = stfb->height; state->nr_cbufs = 1; state->cbufs[0] = stfb->strb->surface; state->zsbuf = stfb->dsrb->surface; cso_set_framebuffer(ctx->cso_context, state); } if (new_zsbuf || new_size) { ctx->state.dirty |= VIEWPORT_DIRTY; ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/ ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0); /* we need all the other state already set */ setup_new_alpha_mask(ctx, stfb); pipe_sampler_view_reference( &stfb->blend_texture_view, NULL); stfb->blend_texture_view = create_tex_and_view(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM, stfb->width, stfb->height); } }
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]); }
/** * 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); }
/** Set the framebuffer as active and clear it. */ void pp_filter_set_clear_fb(struct program *p) { cso_set_framebuffer(p->cso, &p->framebuffer); p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0); }
/** Set the framebuffer as active. */ void pp_filter_set_fb(struct program *p) { cso_set_framebuffer(p->cso, &p->framebuffer); }
/** * Update framebuffer state (color, depth, stencil, etc. buffers) */ void st_update_framebuffer_state( struct st_context *st ) { struct pipe_framebuffer_state framebuffer; struct gl_framebuffer *fb = st->ctx->DrawBuffer; struct st_renderbuffer *strb; GLuint i; st_flush_bitmap_cache(st); st_invalidate_readpix_cache(st); st->state.fb_orientation = st_fb_orientation(fb); /** * Quantize the derived default number of samples: * * A query to the driver of supported MSAA values the * hardware supports is done as to legalize the number * of application requested samples, NumSamples. * See commit eb9cf3c for more information. */ fb->DefaultGeometry._NumSamples = framebuffer_quantize_num_samples(st, fb->DefaultGeometry.NumSamples); framebuffer.width = _mesa_geometric_width(fb); framebuffer.height = _mesa_geometric_height(fb); framebuffer.samples = _mesa_geometric_samples(fb); framebuffer.layers = _mesa_geometric_layers(fb); /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state * to determine which surfaces to draw to */ framebuffer.nr_cbufs = fb->_NumColorDrawBuffers; for (i = 0; i < fb->_NumColorDrawBuffers; i++) { framebuffer.cbufs[i] = NULL; strb = st_renderbuffer(fb->_ColorDrawBuffers[i]); if (strb) { if (strb->is_rtt || (strb->texture && _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB)) { /* rendering to a GL texture, may have to update surface */ st_update_renderbuffer_surface(st, strb); } if (strb->surface) { framebuffer.cbufs[i] = strb->surface; update_framebuffer_size(&framebuffer, strb->surface); } strb->defined = GL_TRUE; /* we'll be drawing something */ } } for (i = framebuffer.nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) { framebuffer.cbufs[i] = NULL; } /* Remove trailing GL_NONE draw buffers. */ while (framebuffer.nr_cbufs && !framebuffer.cbufs[framebuffer.nr_cbufs-1]) { framebuffer.nr_cbufs--; } /* * Depth/Stencil renderbuffer/surface. */ strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); if (!strb) strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); if (strb) { if (strb->is_rtt) { /* rendering to a GL texture, may have to update surface */ st_update_renderbuffer_surface(st, strb); } framebuffer.zsbuf = strb->surface; update_framebuffer_size(&framebuffer, strb->surface); } else framebuffer.zsbuf = NULL; #ifdef DEBUG /* Make sure the resource binding flags were set properly */ for (i = 0; i < framebuffer.nr_cbufs; i++) { assert(!framebuffer.cbufs[i] || framebuffer.cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET); } if (framebuffer.zsbuf) { assert(framebuffer.zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL); } #endif if (framebuffer.width == USHRT_MAX) framebuffer.width = 0; if (framebuffer.height == USHRT_MAX) framebuffer.height = 0; cso_set_framebuffer(st->cso_context, &framebuffer); st->state.fb_width = framebuffer.width; st->state.fb_height = framebuffer.height; st->state.fb_num_samples = util_framebuffer_get_num_samples(&framebuffer); st->state.fb_num_layers = util_framebuffer_get_num_layers(&framebuffer); st->state.fb_num_cb = framebuffer.nr_cbufs; }
/** * Update framebuffer state (color, depth, stencil, etc. buffers) */ static void update_framebuffer_state( struct st_context *st ) { struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer; struct gl_framebuffer *fb = st->ctx->DrawBuffer; struct st_renderbuffer *strb; GLuint i; st_flush_bitmap_cache(st); st->state.fb_orientation = st_fb_orientation(fb); framebuffer->width = fb->Width; framebuffer->height = fb->Height; /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/ /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state * to determine which surfaces to draw to */ framebuffer->nr_cbufs = fb->_NumColorDrawBuffers; for (i = 0; i < fb->_NumColorDrawBuffers; i++) { pipe_surface_reference(&framebuffer->cbufs[i], NULL); strb = st_renderbuffer(fb->_ColorDrawBuffers[i]); if (strb) { if (strb->is_rtt || (strb->texture && util_format_is_srgb(strb->texture->format))) { /* rendering to a GL texture, may have to update surface */ st_update_renderbuffer_surface(st, strb); } if (strb->surface) { pipe_surface_reference(&framebuffer->cbufs[i], strb->surface); } strb->defined = GL_TRUE; /* we'll be drawing something */ } } for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) { pipe_surface_reference(&framebuffer->cbufs[i], NULL); } /* * Depth/Stencil renderbuffer/surface. */ strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); if (strb) { if (strb->is_rtt) { /* rendering to a GL texture, may have to update surface */ st_update_renderbuffer_surface(st, strb); } pipe_surface_reference(&framebuffer->zsbuf, strb->surface); } else { strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); if (strb) { assert(strb->surface); pipe_surface_reference(&framebuffer->zsbuf, strb->surface); } else pipe_surface_reference(&framebuffer->zsbuf, NULL); } #ifdef DEBUG /* Make sure the resource binding flags were set properly */ for (i = 0; i < framebuffer->nr_cbufs; i++) { assert(!framebuffer->cbufs[i] || framebuffer->cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET); } if (framebuffer->zsbuf) { assert(framebuffer->zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL); } #endif cso_set_framebuffer(st->cso_context, framebuffer); }
/** * 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); }
/** * 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); }
void renderer_copy_surface(struct renderer *ctx, struct pipe_surface *src, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, int dstX0, int dstY0, int dstX1, int dstY1, float z, unsigned filter) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_buffer *buf; struct pipe_texture texTemp, *tex; struct pipe_surface *texSurf; struct pipe_framebuffer_state fb; struct st_framebuffer *stfb = ctx->owner->draw_buffer; const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); 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; } assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); /* * XXX for now we're always creating a temporary texture. * Strictly speaking that's not always needed. */ /* create temp texture */ memset(&texTemp, 0, sizeof(texTemp)); texTemp.target = PIPE_TEXTURE_2D; texTemp.format = src->format; texTemp.last_level = 0; texTemp.width0 = srcW; texTemp.height0 = srcH; texTemp.depth0 = 1; tex = screen->texture_create(screen, &texTemp); if (!tex) return; texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); /* load temp texture */ if (pipe->surface_copy) { pipe->surface_copy(pipe, texSurf, 0, 0, /* dest */ src, srcLeft, srcTop, /* src */ srcW, srcH); /* size */ } else { util_surface_copy(pipe, FALSE, texSurf, 0, 0, /* dest */ src, srcLeft, srcTop, /* src */ srcW, srcH); /* size */ } /* free the surface, update the texture if necessary.*/ screen->tex_surface_destroy(texSurf); /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); cso_save_sampler_textures(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_viewport(ctx->cso); /* 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(ctx->cso, &blend); } vg_set_viewport(ctx->owner, VEGA_Y0_TOP); /* 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(ctx->cso, 0, &sampler); cso_single_sampler_done(ctx->cso); } /* texture */ cso_set_sampler_textures(ctx->cso, 1, &tex); /* shaders */ cso_set_fragment_shader_handle(ctx->cso, ctx->fs); cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); /* drawing dest */ if (stfb->strb->surface != dst) { memset(&fb, 0, sizeof(fb)); fb.width = dst->width; fb.height = dst->height; fb.nr_cbufs = 1; fb.cbufs[0] = dst; fb.zsbuf = stfb->dsrb->surface; cso_set_framebuffer(ctx->cso, &fb); } /* draw quad */ buf = setup_vertex_data(ctx, (float) dstX0, (float) dstY0, (float) dstX1, (float) dstY1, z); if (buf) { util_draw_vertex_buffer(ctx->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ pipe_buffer_reference( &buf, NULL ); } /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); cso_restore_sampler_textures(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_viewport(ctx->cso); pipe_texture_reference(&tex, NULL); }
void renderer_copy_texture(struct renderer *ctx, struct pipe_texture *src, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, struct pipe_texture *dst, VGfloat dx1, VGfloat dy1, VGfloat dx2, VGfloat dy2) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_buffer *buf; struct pipe_surface *dst_surf = screen->get_tex_surface( screen, dst, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); struct pipe_framebuffer_state fb; float s0, t0, s1, t1; assert(src->width0 != 0); assert(src->height0 != 0); assert(dst->width0 != 0); assert(dst->height0 != 0); #if 0 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n", sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2); #endif #if 1 s0 = sx1 / src->width0; s1 = sx2 / src->width0; t0 = sy1 / src->height0; t1 = sy2 / src->height0; #else s0 = 0; s1 = 1; t0 = 0; t1 = 1; #endif assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); cso_save_sampler_textures(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_viewport(ctx->cso); /* 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(ctx->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(ctx->cso, 0, &sampler); cso_single_sampler_done(ctx->cso); } vg_set_viewport(ctx->owner, VEGA_Y0_TOP); /* texture */ cso_set_sampler_textures(ctx->cso, 1, &src); /* shaders */ cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); cso_set_fragment_shader_handle(ctx->cso, ctx->fs); /* drawing dest */ memset(&fb, 0, sizeof(fb)); fb.width = dst_surf->width; fb.height = dst_surf->height; fb.nr_cbufs = 1; fb.cbufs[0] = dst_surf; { VGint i; for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) fb.cbufs[i] = 0; } cso_set_framebuffer(ctx->cso, &fb); /* draw quad */ buf = setup_vertex_data_tex(ctx, dx1, dy1, dx2, dy2, s0, t0, s1, t1, 0.0f); if (buf) { util_draw_vertex_buffer(ctx->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ pipe_buffer_reference( &buf, NULL ); } /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); cso_restore_sampler_textures(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_viewport(ctx->cso); pipe_surface_reference(&dst_surf, NULL); }
/** * 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); }