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 renderer_draw_yuv(struct xa_context *r, float src_x, float src_y, float src_w, float src_h, int dst_x, int dst_y, int dst_w, int dst_h, struct xa_surface *srf[]) { struct pipe_context *pipe = r->pipe; struct pipe_resource *buf = 0; buf = setup_vertex_data_yuv(r, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h, srf); if (buf) { const int num_attribs = 2; /*pos + tex coord */ cso_set_vertex_elements(r->cso, num_attribs, r->velems); util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ num_attribs); /* attribs/vert */ pipe_resource_reference(&buf, NULL); } }
static void blitter_draw_rectangle(struct blitter_context *blitter, unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; switch (type) { case UTIL_BLITTER_ATTRIB_COLOR: blitter_set_clear_color(ctx, attrib); break; case UTIL_BLITTER_ATTRIB_TEXCOORD: set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8); break; default:; } blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 0, ctx->vbuf->width0); util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); }
/** Draw with the filter to the set output. */ void pp_filter_draw(struct program *p) { util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, PIPE_PRIM_QUADS, 4, 2); p->pipe->flush(p->pipe, NULL); }
/** * Draw screen-aligned textured quad. * Note: this isn't especially efficient. */ void util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso, uint vbuf_slot, float x0, float y0, float x1, float y1, float z) { uint numAttribs = 2, i, j; uint vertexBytes = 4 * (4 * numAttribs * sizeof(float)); struct pipe_resource *vbuf = NULL; float *v = NULL; v = MALLOC(vertexBytes); if (!v) goto out; /* * Load vertex buffer */ for (i = j = 0; i < 4; i++) { v[j + 2] = z; /* z */ v[j + 3] = 1.0; /* w */ v[j + 6] = 0.0; /* r */ v[j + 7] = 1.0; /* q */ j += 8; } v[0] = x0; v[1] = y0; v[4] = 0.0; /*s*/ v[5] = 0.0; /*t*/ v[8] = x1; v[9] = y0; v[12] = 1.0; v[13] = 0.0; v[16] = x1; v[17] = y1; v[20] = 1.0; v[21] = 1.0; v[24] = x0; v[25] = y1; v[28] = 0.0; v[29] = 1.0; vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STAGING, vertexBytes); if (!vbuf) goto out; pipe_buffer_write(pipe, vbuf, 0, vertexBytes, v); util_draw_vertex_buffer(pipe, cso, vbuf, vbuf_slot, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); out: if (vbuf) pipe_resource_reference(&vbuf, NULL); FREE(v); }
/** * Draw a screen-aligned quadrilateral. * Coords are window coords with y=0=bottom. These will be passed * through unmodified to the rasterizer as we have set * rasterizer->bypass_vs_clip_and_viewport. */ static void draw_quad(GLcontext *ctx, float x0, float y0, float x1, float y1, GLfloat z, const GLfloat color[4]) { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; const GLuint max_slots = 1024 / sizeof(st->clear.vertices); GLuint i; if (st->clear.vbuf_slot >= max_slots) { pipe_buffer_reference(&st->clear.vbuf, NULL); st->clear.vbuf_slot = 0; } if (!st->clear.vbuf) { st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX, max_slots * sizeof(st->clear.vertices)); } /* positions */ st->clear.vertices[0][0][0] = x0; st->clear.vertices[0][0][1] = y0; st->clear.vertices[1][0][0] = x1; st->clear.vertices[1][0][1] = y0; st->clear.vertices[2][0][0] = x1; st->clear.vertices[2][0][1] = y1; st->clear.vertices[3][0][0] = x0; st->clear.vertices[3][0][1] = y1; /* same for all verts: */ for (i = 0; i < 4; i++) { st->clear.vertices[i][0][2] = z; st->clear.vertices[i][0][3] = 1.0; st->clear.vertices[i][1][0] = color[0]; st->clear.vertices[i][1][1] = color[1]; st->clear.vertices[i][1][2] = color[2]; st->clear.vertices[i][1][3] = color[3]; } /* put vertex data into vbuf */ st_no_flush_pipe_buffer_write(st, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), sizeof(st->clear.vertices), st->clear.vertices); /* draw */ util_draw_vertex_buffer(pipe, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ /* Increment slot */ st->clear.vbuf_slot++; }
void r600_draw_rectangle(struct blitter_context *blitter, int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib) { struct r600_common_context *rctx = (struct r600_common_context*)util_blitter_get_pipe(blitter); struct pipe_viewport_state viewport; struct pipe_resource *buf = NULL; unsigned offset = 0; float *vb; if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) { util_blitter_draw_rectangle(blitter, x1, y1, x2, y2, depth, type, attrib); return; } /* Some operations (like color resolve on r6xx) don't work * with the conventional primitive types. * One that works is PT_RECTLIST, which we use here. */ /* setup viewport */ viewport.scale[0] = 1.0f; viewport.scale[1] = 1.0f; viewport.scale[2] = 1.0f; viewport.translate[0] = 0.0f; viewport.translate[1] = 0.0f; viewport.translate[2] = 0.0f; rctx->b.set_viewport_states(&rctx->b, 0, 1, &viewport); /* Upload vertices. The hw rectangle has only 3 vertices, * I guess the 4th one is derived from the first 3. * The vertex specification should match u_blitter's vertex element state. */ u_upload_alloc(rctx->uploader, 0, sizeof(float) * 24, &offset, &buf, (void**)&vb); vb[0] = x1; vb[1] = y1; vb[2] = depth; vb[3] = 1; vb[8] = x1; vb[9] = y2; vb[10] = depth; vb[11] = 1; vb[16] = x2; vb[17] = y1; vb[18] = depth; vb[19] = 1; if (attrib) { memcpy(vb+4, attrib->f, sizeof(float)*4); memcpy(vb+12, attrib->f, sizeof(float)*4); memcpy(vb+20, attrib->f, sizeof(float)*4); } /* draw */ util_draw_vertex_buffer(&rctx->b, NULL, buf, blitter->vb_slot, offset, R600_PRIM_RECTANGLE_LIST, 3, 2); pipe_resource_reference(&buf, NULL); }
/** * Draw a screen-aligned quadrilateral. * Coords are clip coords with y=0=bottom. */ static void draw_quad(struct st_context *st, float x0, float y0, float x1, float y1, GLfloat z, const union pipe_color_union *color) { struct pipe_context *pipe = st->pipe; struct pipe_resource *vbuf = NULL; GLuint i, offset; float (*vertices)[2][4]; /**< vertex pos + color */ u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]), &offset, &vbuf, (void**)&vertices); if (!vbuf) { return; } /* positions */ vertices[0][0][0] = x0; vertices[0][0][1] = y0; vertices[1][0][0] = x1; vertices[1][0][1] = y0; vertices[2][0][0] = x1; vertices[2][0][1] = y1; vertices[3][0][0] = x0; vertices[3][0][1] = y1; /* same for all verts: */ for (i = 0; i < 4; i++) { vertices[i][0][2] = z; vertices[i][0][3] = 1.0; vertices[i][1][0] = color->f[0]; vertices[i][1][1] = color->f[1]; vertices[i][1][2] = color->f[2]; vertices[i][1][3] = color->f[3]; } u_upload_unmap(st->uploader); /* draw */ util_draw_vertex_buffer(pipe, st->cso_context, vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ pipe_resource_reference(&vbuf, NULL); }
/** * Draw renderer quad. */ static void renderer_quad_draw(struct renderer *r) { struct pipe_resource *buf; buf = pipe_user_buffer_create(r->pipe->screen, r->vertices, sizeof(r->vertices), PIPE_BIND_VERTEX_BUFFER); if (buf) { util_draw_vertex_buffer(r->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, Elements(r->vertices), /* verts */ Elements(r->vertices[0])); /* attribs/vert */ pipe_resource_reference(&buf, NULL); } }
void renderer_draw_quad(struct renderer *r, VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2, VGfloat depth) { struct pipe_buffer *buf; buf = setup_vertex_data(r, x1, y1, x2, y2, depth); if (buf) { util_draw_vertex_buffer(r->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ pipe_buffer_reference( &buf, NULL ); } }
void renderer_texture_quad(struct renderer *r, struct pipe_texture *tex, VGfloat x1offset, VGfloat y1offset, VGfloat x2offset, VGfloat y2offset, VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2, VGfloat x3, VGfloat y3, VGfloat x4, VGfloat y4) { struct pipe_context *pipe = r->pipe; struct pipe_buffer *buf; VGfloat s0, t0, s1, t1; assert(tex->width0 != 0); assert(tex->height0 != 0); s0 = x1offset / tex->width0; s1 = x2offset / tex->width0; t0 = y1offset / tex->height0; t1 = y2offset / tex->height0; cso_save_vertex_shader(r->cso); /* shaders */ cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner)); /* draw quad */ buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4, s0, t0, s1, t1, 0.0f); if (buf) { util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ pipe_buffer_reference(&buf, NULL); } cso_restore_vertex_shader(r->cso); }
static INLINE void renderer_draw(struct xa_context *r) { struct pipe_context *pipe = r->pipe; struct pipe_resource *buf = 0; int num_verts = r->buffer_size / (r->attrs_per_vertex * NUM_COMPONENTS); if (!r->buffer_size) return; buf = renderer_buffer_create(r); if (buf) { cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems); util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, num_verts, /* verts */ r->attrs_per_vertex); /* attribs/vert */ pipe_resource_reference(&buf, NULL); } }
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]); }
static INLINE void renderer_draw(struct xorg_renderer *r) { struct pipe_context *pipe = r->pipe; struct pipe_buffer *buf = 0; int num_verts = r->buffer_size/(r->attrs_per_vertex * NUM_COMPONENTS); if (!r->buffer_size) return; buf = renderer_buffer_create(r); if (buf) { util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, num_verts, /* verts */ r->attrs_per_vertex); /* attribs/vert */ pipe_buffer_reference(&buf, NULL); } }
void renderer_draw_yuv(struct xorg_renderer *r, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, struct pipe_texture **textures) { struct pipe_context *pipe = r->pipe; struct pipe_buffer *buf = 0; buf = setup_vertex_data_yuv(r, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h, textures); if (buf) { const int num_attribs = 2; /*pos + tex coord*/ util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ num_attribs); /* attribs/vert */ pipe_buffer_reference(&buf, NULL); } }
static void st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; struct cso_context *cso = ctx->st->cso_context; struct pipe_resource *vbuffer; struct pipe_transfer *vbuffer_transfer; GLuint i, numTexCoords, numAttribs; GLboolean emitColor; uint semantic_names[2 + MAX_TEXTURE_UNITS]; uint semantic_indexes[2 + MAX_TEXTURE_UNITS]; struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS]; GLbitfield inputs = VERT_BIT_POS; st_validate_state(st); /* determine if we need vertex color */ if (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL0) emitColor = GL_TRUE; else emitColor = GL_FALSE; /* determine how many enabled sets of texcoords */ numTexCoords = 0; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) { inputs |= VERT_BIT_TEX(i); numTexCoords++; } } /* total number of attributes per vertex */ numAttribs = 1 + emitColor + numTexCoords; /* create the vertex buffer */ vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM, numAttribs * 4 * 4 * sizeof(GLfloat)); /* load vertex buffer */ { #define SET_ATTRIB(VERT, ATTR, X, Y, Z, W) \ do { \ GLuint k = (((VERT) * numAttribs + (ATTR)) * 4); \ assert(k < 4 * 4 * numAttribs); \ vbuf[k + 0] = X; \ vbuf[k + 1] = Y; \ vbuf[k + 2] = Z; \ vbuf[k + 3] = W; \ } while (0) const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height; GLfloat *vbuf = (GLfloat *) pipe_buffer_map(pipe, vbuffer, PIPE_TRANSFER_WRITE, &vbuffer_transfer); GLuint attr; z = CLAMP(z, 0.0f, 1.0f); /* positions (in clip coords) */ { const struct gl_framebuffer *fb = st->ctx->DrawBuffer; const GLfloat fb_width = (GLfloat)fb->Width; const GLfloat fb_height = (GLfloat)fb->Height; const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0); const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0); const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0); const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0); SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f); /* lower left */ SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f); /* lower right */ SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f); /* upper right */ SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f); /* upper left */ semantic_names[0] = TGSI_SEMANTIC_POSITION; semantic_indexes[0] = 0; } /* colors */ if (emitColor) { const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]); SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]); SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]); SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]); semantic_names[1] = TGSI_SEMANTIC_COLOR; semantic_indexes[1] = 0; attr = 2; } else { attr = 1; } /* texcoords */ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) { struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current; struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; const GLfloat wt = (GLfloat) img->Width; const GLfloat ht = (GLfloat) img->Height; const GLfloat s0 = obj->CropRect[0] / wt; const GLfloat t0 = obj->CropRect[1] / ht; const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt; const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht; /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/ SET_ATTRIB(0, attr, s0, t0, 0.0f, 1.0f); /* lower left */ SET_ATTRIB(1, attr, s1, t0, 0.0f, 1.0f); /* lower right */ SET_ATTRIB(2, attr, s1, t1, 0.0f, 1.0f); /* upper right */ SET_ATTRIB(3, attr, s0, t1, 0.0f, 1.0f); /* upper left */ semantic_names[attr] = TGSI_SEMANTIC_GENERIC; semantic_indexes[attr] = 0; attr++; } } pipe_buffer_unmap(pipe, vbuffer_transfer); #undef SET_ATTRIB } cso_save_viewport(cso); cso_save_vertex_shader(cso); cso_save_vertex_elements(cso); cso_save_vertex_buffers(cso); { void *vs = lookup_shader(pipe, numAttribs, semantic_names, semantic_indexes); cso_set_vertex_shader_handle(cso, vs); } for (i = 0; i < numAttribs; i++) { velements[i].src_offset = i * 4 * sizeof(float); velements[i].instance_divisor = 0; velements[i].vertex_buffer_index = 0; velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } cso_set_vertex_elements(cso, numAttribs, velements); /* viewport state: viewport matching window dims */ { const struct gl_framebuffer *fb = st->ctx->DrawBuffer; const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); const GLfloat width = (GLfloat)fb->Width; const GLfloat height = (GLfloat)fb->Height; struct pipe_viewport_state vp; vp.scale[0] = 0.5f * width; vp.scale[1] = height * (invert ? -0.5f : 0.5f); vp.scale[2] = 1.0f; vp.scale[3] = 1.0f; vp.translate[0] = 0.5f * width; vp.translate[1] = 0.5f * height; vp.translate[2] = 0.0f; vp.translate[3] = 0.0f; cso_set_viewport(cso, &vp); } util_draw_vertex_buffer(pipe, cso, vbuffer, 0, /* offset */ PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ numAttribs); /* attribs/vert */ pipe_resource_reference(&vbuffer, NULL); /* restore state */ cso_restore_viewport(cso); cso_restore_vertex_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); }
/** * Draw quad with texcoords and optional color. * Coords are gallium window coords with y=0=top. * \param color may be null * \param invertTex if true, flip texcoords vertically */ static void draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z, GLfloat x1, GLfloat y1, const GLfloat *color, GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */ /* setup vertex data */ { const struct gl_framebuffer *fb = st->ctx->DrawBuffer; const GLfloat fb_width = (GLfloat) fb->Width; const GLfloat fb_height = (GLfloat) fb->Height; const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f; const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f; const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f; const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f; const GLfloat sLeft = 0.0f, sRight = maxXcoord; const GLfloat tTop = invertTex ? maxYcoord : 0.0f; const GLfloat tBot = invertTex ? 0.0f : maxYcoord; GLuint i; /* upper-left */ verts[0][0][0] = clip_x0; /* v[0].attr[0].x */ verts[0][0][1] = clip_y0; /* v[0].attr[0].y */ /* upper-right */ verts[1][0][0] = clip_x1; verts[1][0][1] = clip_y0; /* lower-right */ verts[2][0][0] = clip_x1; verts[2][0][1] = clip_y1; /* lower-left */ verts[3][0][0] = clip_x0; verts[3][0][1] = clip_y1; verts[0][1][0] = sLeft; /* v[0].attr[1].S */ verts[0][1][1] = tTop; /* v[0].attr[1].T */ verts[1][1][0] = sRight; verts[1][1][1] = tTop; verts[2][1][0] = sRight; verts[2][1][1] = tBot; verts[3][1][0] = sLeft; verts[3][1][1] = tBot; /* same for all verts: */ if (color) { for (i = 0; i < 4; i++) { verts[i][0][2] = z; /* v[i].attr[0].z */ verts[i][0][3] = 1.0f; /* v[i].attr[0].w */ verts[i][2][0] = color[0]; /* v[i].attr[2].r */ verts[i][2][1] = color[1]; /* v[i].attr[2].g */ verts[i][2][2] = color[2]; /* v[i].attr[2].b */ verts[i][2][3] = color[3]; /* v[i].attr[2].a */ verts[i][1][2] = 0.0f; /* v[i].attr[1].R */ verts[i][1][3] = 1.0f; /* v[i].attr[1].Q */ } } else { for (i = 0; i < 4; i++) { verts[i][0][2] = z; /*Z*/ verts[i][0][3] = 1.0f; /*W*/ verts[i][1][2] = 0.0f; /*R*/ verts[i][1][3] = 1.0f; /*Q*/ } } } { struct pipe_resource *buf; /* allocate/load buffer object with vertex data */ buf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STATIC, sizeof(verts)); pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts); util_draw_vertex_buffer(pipe, st->cso_context, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ 3); /* attribs/vert */ pipe_resource_reference(&buf, 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, 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); }
/** * 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); }
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); }
/** * 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); }
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); }
static void st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; struct pipe_resource *vbuffer = NULL; GLuint i, numTexCoords, numAttribs; GLboolean emitColor; uint semantic_names[2 + MAX_TEXTURE_UNITS]; uint semantic_indexes[2 + MAX_TEXTURE_UNITS]; struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS]; unsigned offset; st_flush_bitmap_cache(st); st_invalidate_readpix_cache(st); st_validate_state(st, ST_PIPELINE_RENDER); /* determine if we need vertex color */ if (ctx->FragmentProgram._Current->info.inputs_read & VARYING_BIT_COL0) emitColor = GL_TRUE; else emitColor = GL_FALSE; /* determine how many enabled sets of texcoords */ numTexCoords = 0; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { if (ctx->Texture.Unit[i]._Current && ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) { numTexCoords++; } } /* total number of attributes per vertex */ numAttribs = 1 + emitColor + numTexCoords; /* load vertex buffer */ { #define SET_ATTRIB(VERT, ATTR, X, Y, Z, W) \ do { \ GLuint k = (((VERT) * numAttribs + (ATTR)) * 4); \ assert(k < 4 * 4 * numAttribs); \ vbuf[k + 0] = X; \ vbuf[k + 1] = Y; \ vbuf[k + 2] = Z; \ vbuf[k + 3] = W; \ } while (0) const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height; GLfloat *vbuf = NULL; GLuint tex_attr; u_upload_alloc(pipe->stream_uploader, 0, numAttribs * 4 * 4 * sizeof(GLfloat), 4, &offset, &vbuffer, (void **) &vbuf); if (!vbuffer) { return; } z = CLAMP(z, 0.0f, 1.0f); /* positions (in clip coords) */ { const struct gl_framebuffer *fb = ctx->DrawBuffer; const GLfloat fb_width = (GLfloat)_mesa_geometric_width(fb); const GLfloat fb_height = (GLfloat)_mesa_geometric_height(fb); const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0); const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0); const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0); const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0); SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f); /* lower left */ SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f); /* lower right */ SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f); /* upper right */ SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f); /* upper left */ semantic_names[0] = TGSI_SEMANTIC_POSITION; semantic_indexes[0] = 0; } /* colors */ if (emitColor) { const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]); SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]); SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]); SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]); semantic_names[1] = TGSI_SEMANTIC_COLOR; semantic_indexes[1] = 0; tex_attr = 2; } else { tex_attr = 1; } /* texcoords */ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { if (ctx->Texture.Unit[i]._Current && ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) { struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current; const struct gl_texture_image *img = _mesa_base_tex_image(obj); const GLfloat wt = (GLfloat) img->Width; const GLfloat ht = (GLfloat) img->Height; const GLfloat s0 = obj->CropRect[0] / wt; const GLfloat t0 = obj->CropRect[1] / ht; const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt; const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht; /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/ SET_ATTRIB(0, tex_attr, s0, t0, 0.0f, 1.0f); /* lower left */ SET_ATTRIB(1, tex_attr, s1, t0, 0.0f, 1.0f); /* lower right */ SET_ATTRIB(2, tex_attr, s1, t1, 0.0f, 1.0f); /* upper right */ SET_ATTRIB(3, tex_attr, s0, t1, 0.0f, 1.0f); /* upper left */ semantic_names[tex_attr] = st->needs_texcoord_semantic ? TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC; /* XXX: should this use semantic index i instead of 0 ? */ semantic_indexes[tex_attr] = 0; tex_attr++; } } u_upload_unmap(pipe->stream_uploader); #undef SET_ATTRIB } cso_save_state(cso, (CSO_BIT_VIEWPORT | CSO_BIT_STREAM_OUTPUTS | 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)); { void *vs = lookup_shader(pipe, numAttribs, semantic_names, semantic_indexes); cso_set_vertex_shader_handle(cso, vs); } cso_set_tessctrl_shader_handle(cso, NULL); cso_set_tesseval_shader_handle(cso, NULL); cso_set_geometry_shader_handle(cso, NULL); for (i = 0; i < numAttribs; i++) { velements[i].src_offset = i * 4 * sizeof(float); velements[i].instance_divisor = 0; velements[i].vertex_buffer_index = 0; velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } cso_set_vertex_elements(cso, numAttribs, velements); cso_set_stream_outputs(cso, 0, NULL, NULL); /* viewport state: viewport matching window dims */ { const struct gl_framebuffer *fb = ctx->DrawBuffer; const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP); const GLfloat width = (GLfloat)_mesa_geometric_width(fb); const GLfloat height = (GLfloat)_mesa_geometric_height(fb); struct pipe_viewport_state vp; vp.scale[0] = 0.5f * width; vp.scale[1] = height * (invert ? -0.5f : 0.5f); vp.scale[2] = 1.0f; vp.translate[0] = 0.5f * width; vp.translate[1] = 0.5f * height; vp.translate[2] = 0.0f; cso_set_viewport(cso, &vp); } util_draw_vertex_buffer(pipe, cso, vbuffer, cso_get_aux_vertex_buffer_slot(cso), offset, /* offset */ PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ numAttribs); /* attribs/vert */ pipe_resource_reference(&vbuffer, NULL); /* restore state */ cso_restore_state(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, 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); }
/** * 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); }
void util_blitter_copy_texture_view(struct blitter_context *blitter, struct pipe_surface *dst, unsigned dstx, unsigned dsty, struct pipe_sampler_view *src, const struct pipe_box *srcbox, unsigned src_width0, unsigned src_height0) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; struct pipe_framebuffer_state fb_state; enum pipe_texture_target src_target = src->texture->target; unsigned width = srcbox->width; unsigned height = srcbox->height; /* Sanity checks. */ if (dst->texture == src->texture && dst->u.tex.level == src->u.tex.first_level) { assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, dstx, dstx + width, dsty, dsty + height)); } /* XXX should handle 3d regions */ assert(srcbox->depth == 1); /* Check whether the states are properly saved. */ blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_textures(ctx); blitter_check_saved_fb_state(ctx); /* Initialize framebuffer state. */ fb_state.width = dst->width; fb_state.height = dst->height; if (util_format_is_depth_or_stencil(dst->format)) { pipe->bind_blend_state(pipe, ctx->blend_keep_color); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); pipe->bind_fs_state(pipe, blitter_get_fs_texfetch_depth(ctx, src_target)); fb_state.nr_cbufs = 0; fb_state.zsbuf = dst; } else { pipe->bind_blend_state(pipe, ctx->blend_write_color); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); pipe->bind_fs_state(pipe, blitter_get_fs_texfetch_col(ctx, src_target)); fb_state.nr_cbufs = 1; fb_state.cbufs[0] = dst; fb_state.zsbuf = 0; } /* Set rasterizer state, shaders, and textures. */ pipe->bind_rasterizer_state(pipe, ctx->rs_state); pipe->bind_vs_state(pipe, ctx->vs); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); pipe->set_fragment_sampler_views(pipe, 1, &src); pipe->set_framebuffer_state(pipe, &fb_state); blitter_set_dst_dimensions(ctx, dst->width, dst->height); switch (src_target) { /* Draw the quad with the draw_rectangle callback. */ case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: { /* Set texture coordinates. - use a pipe color union * for interface purposes. * XXX pipe_color_union is a wrong name since we use that to set * texture coordinates too. */ union pipe_color_union coord; get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y, srcbox->x+width, srcbox->y+height, coord.f); /* Draw. */ blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, UTIL_BLITTER_ATTRIB_TEXCOORD, &coord); } break; /* Draw the quad with the generic codepath. */ default: /* Set texture coordinates. */ switch (src_target) { case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_3D: case PIPE_TEXTURE_CUBE: blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, srcbox->y, srcbox->x, srcbox->x + width, srcbox->y + height); break; default: assert(0); } /* Draw. */ blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 0, ctx->vbuf->width0); util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); break; } blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); blitter_restore_textures(ctx); blitter_restore_fb_state(ctx); blitter_unset_running_flag(ctx); }
/** * Draw a screen-aligned quadrilateral. * Coords are clip coords with y=0=bottom. */ static void draw_quad(struct st_context *st, float x0, float y0, float x1, float y1, GLfloat z, const GLfloat color[4]) { struct pipe_context *pipe = st->pipe; /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as * no_flush) updates to buffers where we know there is no conflict * with previous data. Currently using max_slots > 1 will cause * synchronous rendering if the driver flushes its command buffers * between one bitmap and the next. Our flush hook below isn't * sufficient to catch this as the driver doesn't tell us when it * flushes its own command buffers. Until this gets fixed, pay the * price of allocating a new buffer for each bitmap cache-flush to * avoid synchronous rendering. */ const GLuint max_slots = 1; /* 1024 / sizeof(st->clear.vertices); */ GLuint i; if (st->clear.vbuf_slot >= max_slots) { pipe_resource_reference(&st->clear.vbuf, NULL); st->clear.vbuf_slot = 0; } if (!st->clear.vbuf) { st->clear.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM, max_slots * sizeof(st->clear.vertices)); } /* positions */ st->clear.vertices[0][0][0] = x0; st->clear.vertices[0][0][1] = y0; st->clear.vertices[1][0][0] = x1; st->clear.vertices[1][0][1] = y0; st->clear.vertices[2][0][0] = x1; st->clear.vertices[2][0][1] = y1; st->clear.vertices[3][0][0] = x0; st->clear.vertices[3][0][1] = y1; /* same for all verts: */ for (i = 0; i < 4; i++) { st->clear.vertices[i][0][2] = z; st->clear.vertices[i][0][3] = 1.0; st->clear.vertices[i][1][0] = color[0]; st->clear.vertices[i][1][1] = color[1]; st->clear.vertices[i][1][2] = color[2]; st->clear.vertices[i][1][3] = color[3]; } /* put vertex data into vbuf */ pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), sizeof(st->clear.vertices), st->clear.vertices); /* draw */ util_draw_vertex_buffer(pipe, st->cso_context, st->clear.vbuf, st->clear.vbuf_slot * sizeof(st->clear.vertices), PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ /* Increment slot */ st->clear.vbuf_slot++; }
/** * Draw quad with texcoords and optional color. * Coords are window coords with y=0=bottom. * \param color may be null * \param invertTex if true, flip texcoords vertically */ static void draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, GLfloat x1, GLfloat y1, const GLfloat *color, GLboolean invertTex) { struct st_context *st = ctx->st; struct pipe_context *pipe = ctx->st->pipe; GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */ /* setup vertex data */ { const struct gl_framebuffer *fb = st->ctx->DrawBuffer; const GLfloat fb_width = (GLfloat) fb->Width; const GLfloat fb_height = (GLfloat) fb->Height; const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f; const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f; const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f; const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f; const GLfloat sLeft = 0.0f, sRight = 1.0f; const GLfloat tTop = invertTex, tBot = 1.0f - tTop; GLuint tex, i; /* upper-left */ verts[0][0][0] = clip_x0; /* v[0].attr[0].x */ verts[0][0][1] = clip_y0; /* v[0].attr[0].y */ /* upper-right */ verts[1][0][0] = clip_x1; verts[1][0][1] = clip_y0; /* lower-right */ verts[2][0][0] = clip_x1; verts[2][0][1] = clip_y1; /* lower-left */ verts[3][0][0] = clip_x0; verts[3][0][1] = clip_y1; tex = color ? 2 : 1; verts[0][tex][0] = sLeft; /* v[0].attr[tex].s */ verts[0][tex][1] = tTop; /* v[0].attr[tex].t */ verts[1][tex][0] = sRight; verts[1][tex][1] = tTop; verts[2][tex][0] = sRight; verts[2][tex][1] = tBot; verts[3][tex][0] = sLeft; verts[3][tex][1] = tBot; /* same for all verts: */ if (color) { for (i = 0; i < 4; i++) { verts[i][0][2] = z; /*Z*/ verts[i][0][3] = 1.0f; /*W*/ verts[i][1][0] = color[0]; verts[i][1][1] = color[1]; verts[i][1][2] = color[2]; verts[i][1][3] = color[3]; verts[i][2][2] = 0.0f; /*R*/ verts[i][2][3] = 1.0f; /*Q*/ } } else { for (i = 0; i < 4; i++) { verts[i][0][2] = z; /*Z*/ verts[i][0][3] = 1.0f; /*W*/ verts[i][1][2] = 0.0f; /*R*/ verts[i][1][3] = 1.0f; /*Q*/ } } } { struct pipe_buffer *buf; /* allocate/load buffer object with vertex data */ buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX, sizeof(verts)); st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts); util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ 3); /* attribs/vert */ pipe_buffer_reference(&buf, NULL); } }