X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_drawpixels.c;h=e059002f157d6e6e1f43beb447d1eebdd9e4975c;hb=c7f5c9a3dc6350252e73b541bb85ab3ed9e64a9c;hp=236010c5b5d5ed2003bffb6ce6fde2185d3baa03;hpb=b8030c6561e019e079b5be2fe64ec804df4bfa03;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 236010c5b5d..e059002f157 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -59,7 +59,6 @@ #include "util/u_draw_quad.h" #include "util/u_format.h" #include "util/u_math.h" -#include "util/u_rect.h" #include "shader/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -250,13 +249,13 @@ make_passthrough_vertex_shader(struct st_context *st, ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ), ureg_DECL_vs_input( ureg, 0 )); - /* MOV result.texcoord0, vertex.texcoord0; */ + /* MOV result.texcoord0, vertex.attr[1]; */ ureg_MOV(ureg, ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), ureg_DECL_vs_input( ureg, 1 )); if (passColor) { - /* MOV result.color0, vertex.color0; */ + /* MOV result.color0, vertex.attr[2]; */ ureg_MOV(ureg, ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ), ureg_DECL_vs_input( ureg, 2 )); @@ -292,11 +291,56 @@ base_format(GLenum format) } +/** + * Create a temporary texture to hold an image of the given size. + * If width, height are not POT and the driver only handles POT textures, + * allocate the next larger size of texture that is POT. + */ +static struct pipe_resource * +alloc_texture(struct st_context *st, GLsizei width, GLsizei height, + enum pipe_format texFormat) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_resource *pt; + int ptw, pth; + + ptw = width; + pth = height; + + /* Need to use POT texture? */ + if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { + int l2pt, maxSize; + + l2pt = util_logbase2(width); + if (1 << l2pt != width) { + ptw = 1 << (l2pt + 1); + } + + l2pt = util_logbase2(height); + if (1 << l2pt != height) { + pth = 1 << (l2pt + 1); + } + + /* Check against maximum texture size */ + maxSize = 1 << (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + assert(ptw <= maxSize); + assert(pth <= maxSize); + } + + pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0, + ptw, pth, 1, PIPE_BIND_SAMPLER_VIEW); + + return pt; +} + + /** * Make texture containing an image for glDrawPixels image. * If 'pixels' is NULL, leave the texture image data undefined. */ -static struct pipe_texture * +static struct pipe_resource * make_texture(struct st_context *st, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, @@ -304,13 +348,11 @@ make_texture(struct st_context *st, { GLcontext *ctx = st->ctx; struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; gl_format mformat; - struct pipe_texture *pt; + struct pipe_resource *pt; enum pipe_format pipeFormat; GLuint cpp; GLenum baseFormat; - int ptw, pth; baseFormat = base_format(format); @@ -325,29 +367,8 @@ make_texture(struct st_context *st, if (!pixels) return NULL; - /* Need to use POT texture? */ - ptw = width; - pth = height; - if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { - int l2pt, maxSize; - - l2pt = util_logbase2(width); - if (1<screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); - assert(ptw <= maxSize); - assert(pth <= maxSize); - } - - pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, ptw, pth, 1, - PIPE_TEXTURE_USAGE_SAMPLER); + /* alloc temporary texture */ + pt = alloc_texture(st, width, height, pipeFormat); if (!pt) { _mesa_unmap_pbo_source(ctx, unpack); return NULL; @@ -368,7 +389,7 @@ make_texture(struct st_context *st, width, height); /* map texture transfer */ - dest = screen->transfer_map(screen, transfer); + dest = pipe_transfer_map(pipe, transfer); /* Put image into texture transfer. @@ -388,8 +409,8 @@ make_texture(struct st_context *st, unpack); /* unmap */ - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe_transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); assert(success); @@ -405,7 +426,7 @@ make_texture(struct st_context *st, /** * Draw quad with texcoords and optional color. - * Coords are window coords with y=0=bottom. + * Coords are gallium window coords with y=0=top. * \param color may be null * \param invertTex if true, flip texcoords vertically */ @@ -430,7 +451,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, const GLfloat sLeft = 0.0f, sRight = maxXcoord; const GLfloat tTop = invertTex ? maxYcoord : 0.0f; const GLfloat tBot = invertTex ? 0.0f : maxYcoord; - GLuint tex, i; + GLuint i; /* upper-left */ verts[0][0][0] = clip_x0; /* v[0].attr[0].x */ @@ -448,32 +469,31 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, 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; + 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; /*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*/ + 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][2] = z; /*Z*/ verts[i][0][3] = 1.0f; /*W*/ verts[i][1][2] = 0.0f; /*R*/ verts[i][1][3] = 1.0f; /*Q*/ @@ -482,10 +502,11 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, } { - struct pipe_buffer *buf; + struct pipe_resource *buf; /* allocate/load buffer object with vertex data */ - buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX, + buf = pipe_buffer_create(pipe->screen, + PIPE_BIND_VERTEX_BUFFER, sizeof(verts)); st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts); @@ -493,7 +514,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, PIPE_PRIM_QUADS, 4, /* verts */ 3); /* attribs/vert */ - pipe_buffer_reference(&buf, NULL); + pipe_resource_reference(&buf, NULL); } } @@ -595,10 +616,15 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_set_fragment_sampler_views(cso, 1, &sv); } - /* Compute window coords (y=0=bottom) with pixel zoom. + /* Compute Gallium window coords (y=0=top) with pixel zoom. * Recall that these coords are transformed by the current * vertex shader and viewport transformation. */ + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { + y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY); + invertTex = !invertTex; + } + x0 = (GLfloat) x; x1 = x + width * ctx->Pixel.ZoomX; y0 = (GLfloat) y; @@ -630,7 +656,6 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *strb; enum pipe_transfer_usage usage; struct pipe_transfer *pt; @@ -664,7 +689,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, usage, x, y, width, height); - stmap = screen->transfer_map(screen, pt); + stmap = pipe_transfer_map(pipe, pt); pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); assert(pixels); @@ -709,15 +734,15 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, } /* now pack the stencil (and Z) values in the dest format */ - switch (pt->texture->format) { - case PIPE_FORMAT_S8_UNORM: + switch (pt->resource->format) { + case PIPE_FORMAT_S8_USCALED: { ubyte *dest = stmap + spanY * pt->stride + spanX; assert(usage == PIPE_TRANSFER_WRITE); memcpy(dest, sValues, spanWidth); } break; - case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; @@ -735,7 +760,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, } } break; - case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; @@ -764,8 +789,8 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, _mesa_unmap_pbo_source(ctx, &clippedUnpack); /* unmap the stencil buffer */ - screen->transfer_unmap(screen, pt); - screen->tex_transfer_destroy(pt); + pipe_transfer_unmap(pipe, pt); + pipe->transfer_destroy(pipe, pt); } @@ -806,10 +831,10 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* draw with textured quad */ { - struct pipe_texture *pt + struct pipe_resource *pt = make_texture(st, width, height, format, type, unpack, pixels); if (pt) { - struct pipe_sampler_view *sv = st_sampler_view_from_texture(st->pipe, pt); + struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt); if (sv) { draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], @@ -820,7 +845,7 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, color, GL_FALSE); pipe_sampler_view_reference(&sv, NULL); } - pipe_texture_reference(&pt, NULL); + pipe_resource_reference(&pt, NULL); } } } @@ -833,7 +858,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint dstx, GLint dsty) { struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); - struct pipe_screen *screen = ctx->st->pipe->screen; + struct pipe_context *pipe = st_context(ctx)->pipe; enum pipe_transfer_usage usage; struct pipe_transfer *ptDraw; ubyte *drawMap; @@ -865,11 +890,11 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, usage, dstx, dsty, width, height); - assert(util_format_get_blockwidth(ptDraw->texture->format) == 1); - assert(util_format_get_blockheight(ptDraw->texture->format) == 1); + assert(util_format_get_blockwidth(ptDraw->resource->format) == 1); + assert(util_format_get_blockheight(ptDraw->resource->format) == 1); /* map the stencil buffer */ - drawMap = screen->transfer_map(screen, ptDraw); + drawMap = pipe_transfer_map(pipe, ptDraw); /* draw */ /* XXX PixelZoom not handled yet */ @@ -887,8 +912,8 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, dst = drawMap + y * ptDraw->stride; src = buffer + i * width; - switch (ptDraw->texture->format) { - case PIPE_FORMAT_Z24S8_UNORM: + switch (ptDraw->resource->format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: { uint *dst4 = (uint *) dst; int j; @@ -899,7 +924,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } } break; - case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: { uint *dst4 = (uint *) dst; int j; @@ -910,7 +935,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } } break; - case PIPE_FORMAT_S8_UNORM: + case PIPE_FORMAT_S8_USCALED: assert(usage == PIPE_TRANSFER_WRITE); memcpy(dst, src, width); break; @@ -922,8 +947,8 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, free(buffer); /* unmap the stencil buffer */ - screen->transfer_unmap(screen, ptDraw); - screen->tex_transfer_destroy(ptDraw); + pipe_transfer_unmap(pipe, ptDraw); + pipe->transfer_destroy(pipe, ptDraw); } @@ -937,44 +962,18 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *rbRead; void *driver_vp, *driver_fp; - struct pipe_texture *pt; + struct pipe_resource *pt; struct pipe_sampler_view *sv; GLfloat *color; enum pipe_format srcFormat, texFormat; - int ptw, pth; + GLboolean invertTex = GL_FALSE; + GLint readX, readY, readW, readH; + struct gl_pixelstore_attrib pack = ctx->DefaultPacking; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); st_validate_state(st); - if (srcx < 0) { - width -= -srcx; - dstx += -srcx; - srcx = 0; - } - - if (srcy < 0) { - height -= -srcy; - dsty += -srcy; - srcy = 0; - } - - if (dstx < 0) { - width -= -dstx; - srcx += -dstx; - dstx = 0; - } - - if (dsty < 0) { - height -= -dsty; - srcy += -dsty; - dsty = 0; - } - - if (width < 0 || height < 0) - return; - - if (type == GL_STENCIL) { /* can't use texturing to do stencil */ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); @@ -998,7 +997,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, srcFormat = rbRead->texture->format; if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)) { + PIPE_BIND_SAMPLER_VIEW, 0)) { texFormat = srcFormat; } else { @@ -1006,82 +1005,70 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, if (type == GL_DEPTH) { texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL); - assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ + PIPE_BIND_DEPTH_STENCIL); + assert(texFormat != PIPE_FORMAT_NONE); } else { /* default color format */ texFormat = st_choose_format(screen, GL_RGBA, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER); + PIPE_BIND_SAMPLER_VIEW); assert(texFormat != PIPE_FORMAT_NONE); } } - if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { - srcy = ctx->DrawBuffer->Height - srcy - height; - - if (srcy < 0) { - height -= -srcy; - srcy = 0; - } - - if (height < 0) - return; + /* Invert src region if needed */ + if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + srcy = ctx->ReadBuffer->Height - srcy - height; + invertTex = !invertTex; } - /* Need to use POT texture? */ - ptw = width; - pth = height; - if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { - int l2pt, maxSize; - - l2pt = util_logbase2(width); - if (1<screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); - assert(ptw <= maxSize); - assert(pth <= maxSize); - } - - pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0, - ptw, pth, 1, - PIPE_TEXTURE_USAGE_SAMPLER); + /* Clip the read region against the src buffer bounds. + * We'll still allocate a temporary buffer/texture for the original + * src region size but we'll only read the region which is on-screen. + * This may mean that we draw garbage pixels into the dest region, but + * that's expected. + */ + readX = srcx; + readY = srcy; + readW = width; + readH = height; + _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); + readW = MAX2(0, readW); + readH = MAX2(0, readH); + + /* alloc temporary texture */ + pt = alloc_texture(st, width, height, texFormat); if (!pt) return; - sv = st_sampler_view_from_texture(st->pipe, pt); + sv = st_create_texture_sampler_view(st->pipe, pt); if (!sv) { - pipe_texture_reference(&pt, NULL); + pipe_resource_reference(&pt, NULL); return; } + /* Make temporary texture which is a copy of the src region. + */ if (srcFormat == texFormat) { /* copy source framebuffer surface into mipmap/texture */ struct pipe_surface *psRead = screen->get_tex_surface(screen, rbRead->texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ); + PIPE_BIND_BLIT_SOURCE); struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE ); - if (pipe->surface_copy) { - pipe->surface_copy(pipe, - psTex, /* dest */ - 0, 0, /* destx/y */ - psRead, - srcx, srcy, width, height); - } else { - util_surface_copy(pipe, FALSE, - psTex, - 0, 0, - psRead, - srcx, srcy, width, height); + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_BLIT_DESTINATION); + pipe->surface_copy(pipe, + psTex, /* dest surf */ + pack.SkipPixels, pack.SkipRows, /* dest pos */ + psRead, /* src surf */ + readX, readY, readW, readH); /* src region */ + + if (0) { + /* debug */ + debug_dump_surface(pipe, "copypixsrcsurf", psRead); + debug_dump_surface(pipe, "copypixtemptex", psTex); } + pipe_surface_reference(&psRead, NULL); pipe_surface_reference(&psTex, NULL); } @@ -1089,8 +1076,8 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, - PIPE_TRANSFER_READ, srcx, srcy, width, - height); + PIPE_TRANSFER_READ, + readX, readY, readW, readH); struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; @@ -1105,36 +1092,39 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, 0, 0, width, height); + /* copy image from ptRead surface to ptTex surface */ if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - - pipe_get_tile_rgba(ptRead, 0, 0, width, height, buf); - pipe_put_tile_rgba(ptTex, 0, 0, width, height, buf); - + pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows, + readW, readH, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(ptRead, 0, 0, width, height, buf); - pipe_put_tile_z(ptTex, 0, 0, width, height, buf); + pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, + readW, readH, buf); free(buf); } - screen->tex_transfer_destroy(ptRead); - screen->tex_transfer_destroy(ptTex); + pipe->transfer_destroy(pipe, ptRead); + pipe->transfer_destroy(pipe, ptTex); } - /* draw textured quad */ + /* OK, the texture 'pt' contains the src image/pixels. Now draw a + * textured quad with that texture. + */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, sv, driver_vp, driver_fp, - color, GL_TRUE); + color, invertTex); - pipe_texture_reference(&pt, NULL); + pipe_resource_reference(&pt, NULL); pipe_sampler_view_reference(&sv, NULL); }