X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_drawpixels.c;h=c655690603865613aed7d789a8d1c41a7bd25b67;hb=79892e7976fbb91ae426f5868d5f453e977c1f17;hp=f9f139ff0737c948ec9e6aacae3a281345d1a533;hpb=e0a55dc9dae39384c18dd275081c24b7dce14eeb;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index f9f139ff073..c6556906038 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -53,11 +53,14 @@ #include "st_format.h" #include "st_mesa_to_tgsi.h" #include "st_texture.h" +#include "st_inlines.h" + #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" #include "util/u_tile.h" #include "util/u_draw_quad.h" +#include "util/u_math.h" #include "shader/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -144,6 +147,8 @@ combined_drawpix_fragment_program(GLcontext *ctx) st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo; st->pixel_xfer.user_prog_sn = st->fp->serialNo; st->pixel_xfer.combined_prog_sn = stfp->serialNo; + /* can't reference new program directly, already have a reference on it */ + st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); st->pixel_xfer.combined_prog = stfp; } @@ -309,6 +314,8 @@ _mesa_base_format(GLenum format) switch (format) { case GL_DEPTH_COMPONENT: return GL_DEPTH_COMPONENT; + case GL_DEPTH_STENCIL: + return GL_DEPTH_STENCIL; case GL_STENCIL_INDEX: return GL_STENCIL_INDEX; default: @@ -335,6 +342,7 @@ make_texture(struct st_context *st, enum pipe_format pipeFormat; GLuint cpp; GLenum baseFormat; + int ptw, pth; baseFormat = _mesa_base_format(format); @@ -345,15 +353,35 @@ make_texture(struct st_context *st, assert(pipeFormat); cpp = st_sizeof_format(pipeFormat); - pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels); + pixels = _mesa_map_pbo_source(ctx, unpack, pixels); if (!pixels) return NULL; - pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, - 1, 0, + /* 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); if (!pt) { - _mesa_unmap_drawpix_pbo(ctx, unpack); + _mesa_unmap_pbo_source(ctx, unpack); return NULL; } @@ -367,9 +395,9 @@ make_texture(struct st_context *st, /* we'll do pixel transfer in a fragment shader */ ctx->_ImageTransferState = 0x0; - transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0, - PIPE_TRANSFER_WRITE, 0, 0, - width, height); + transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, + width, height); /* map texture transfer */ dest = screen->transfer_map(screen, transfer); @@ -400,7 +428,7 @@ make_texture(struct st_context *st, ctx->_ImageTransferState = imageTransferStateSave; } - _mesa_unmap_drawpix_pbo(ctx, unpack); + _mesa_unmap_pbo_source(ctx, unpack); return pt; } @@ -415,7 +443,7 @@ make_texture(struct st_context *st, static void draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, GLfloat x1, GLfloat y1, const GLfloat *color, - GLboolean invertTex) + GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord) { struct st_context *st = ctx->st; struct pipe_context *pipe = ctx->st->pipe; @@ -430,8 +458,9 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, 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; + const GLfloat sLeft = 0.0f, sRight = maxXcoord; + const GLfloat tTop = invertTex ? maxYcoord : 0.0f; + const GLfloat tBot = invertTex ? 0.0f : maxYcoord; GLuint tex, i; /* upper-left */ @@ -489,7 +518,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, /* allocate/load buffer object with vertex data */ buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX, sizeof(verts)); - pipe_buffer_write(pipe->screen, buf, 0, sizeof(verts), verts); + st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts); util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, @@ -569,15 +598,15 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* viewport state: viewport matching window dims */ { - const float width = (float) ctx->DrawBuffer->Width; - const float height = (float) ctx->DrawBuffer->Height; + const float w = (float) ctx->DrawBuffer->Width; + const float h = (float) ctx->DrawBuffer->Height; struct pipe_viewport_state vp; - vp.scale[0] = 0.5f * width; - vp.scale[1] = -0.5f * height; + vp.scale[0] = 0.5f * w; + vp.scale[1] = -0.5f * h; vp.scale[2] = 1.0f; vp.scale[3] = 1.0f; - vp.translate[0] = 0.5f * width; - vp.translate[1] = 0.5f * height; + vp.translate[0] = 0.5f * w; + vp.translate[1] = 0.5f * h; vp.translate[2] = 0.0f; vp.translate[3] = 0.0f; cso_set_viewport(cso, &vp); @@ -603,7 +632,9 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, y0 = (GLfloat) y; y1 = y + height * ctx->Pixel.ZoomY; - draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex); + draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, + (GLfloat) width / pt->width[0], + (GLfloat) height / pt->height[0]); /* restore state */ cso_restore_rasterizer(cso); @@ -617,7 +648,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, static void draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, - GLsizei width, GLsizei height, GLenum type, + GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { @@ -625,21 +656,34 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, 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; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; GLint skipPixels; ubyte *stmap; - pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - strb = st_renderbuffer(ctx->DrawBuffer-> Attachment[BUFFER_STENCIL].Renderbuffer); - pt = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, x, y, - width, height); + + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + y = ctx->DrawBuffer->Height - y - height; + } + + if(format != GL_DEPTH_STENCIL && + pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0) + usage = PIPE_TRANSFER_READ_WRITE; + else + usage = PIPE_TRANSFER_WRITE; + + pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0, + usage, x, y, + width, height); stmap = screen->transfer_map(screen, pt); + pixels = _mesa_map_pbo_source(ctx, unpack, pixels); + assert(pixels); + /* if width > MAX_WIDTH, have to process image in chunks */ skipPixels = 0; while (skipPixels < width) { @@ -647,53 +691,79 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); GLint row; for (row = 0; row < height; row++) { - GLint spanY = row; - GLubyte values[MAX_WIDTH]; + GLubyte sValues[MAX_WIDTH]; + GLuint zValues[MAX_WIDTH]; GLenum destType = GL_UNSIGNED_BYTE; const GLvoid *source = _mesa_image_address2d(unpack, pixels, width, height, - GL_COLOR_INDEX, type, + format, type, row, skipPixels); - _mesa_unpack_stencil_span(ctx, spanWidth, destType, values, + _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues, type, source, unpack, ctx->_ImageTransferState); + + if (format == GL_DEPTH_STENCIL) { + _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, + (1 << 24) - 1, type, source, unpack); + } + if (zoom) { - /* - _swrast_write_zoomed_stencil_span(ctx, 0, 0, spanWidth, - spanX, spanY, values); - */ + _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " + "zoom not complete"); } - else { + + { + GLint spanY; + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { - spanY = height - spanY - 1; + spanY = height - row - 1; + } + else { + spanY = row; } + /* now pack the stencil (and Z) values in the dest format */ switch (pt->format) { case PIPE_FORMAT_S8_UNORM: { ubyte *dest = stmap + spanY * pt->stride + spanX; - memcpy(dest, values, spanWidth); + assert(usage == PIPE_TRANSFER_WRITE); + memcpy(dest, sValues, spanWidth); } break; case PIPE_FORMAT_S8Z24_UNORM: - { + if (format == GL_DEPTH_STENCIL) { + uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); + GLint k; + assert(usage == PIPE_TRANSFER_WRITE); + for (k = 0; k < spanWidth; k++) { + dest[k] = zValues[k] | (sValues[k] << 24); + } + } + else { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; + assert(usage == PIPE_TRANSFER_READ_WRITE); for (k = 0; k < spanWidth; k++) { - uint p = dest[k]; - p = (p & 0xffffff) | (values[k] << 24); - dest[k] = p; + dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); } } break; case PIPE_FORMAT_Z24S8_UNORM: - { + if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; + assert(usage == PIPE_TRANSFER_WRITE); for (k = 0; k < spanWidth; k++) { - uint p = dest[k]; - p = (p & 0xffffff00) | (values[k] & 0xff); - dest[k] = p; + dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); + } + } + else { + uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); + GLint k; + assert(usage == PIPE_TRANSFER_READ_WRITE); + for (k = 0; k < spanWidth; k++) { + dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); } } break; @@ -705,6 +775,8 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, skipPixels += spanWidth; } + _mesa_unmap_pbo_source(ctx, unpack); + /* unmap the stencil buffer */ screen->transfer_unmap(screen, pt); screen->tex_transfer_destroy(pt); @@ -723,16 +795,17 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, struct st_vertex_program *stvp; struct st_context *st = ctx->st; struct pipe_surface *ps; - GLuint bufferFormat; const GLfloat *color; - if (format == GL_STENCIL_INDEX) { - draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels); + if (format == GL_STENCIL_INDEX || + format == GL_DEPTH_STENCIL) { + draw_stencil_pixels(ctx, x, y, width, height, format, type, + unpack, pixels); return; } - _mesa_set_vp_override( ctx, TRUE ); - _mesa_update_state( ctx ); + /* Mesa state should be up to date by now */ + assert(ctx->NewState == 0x0); st_validate_state(st); @@ -742,11 +815,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); color = ctx->Current.RasterColor; } - else if (format == GL_STENCIL_INDEX) { - ps = st->state.framebuffer.zsbuf; - /* XXX special case - can't use texture map */ - color = NULL; - } else { ps = st->state.framebuffer.cbufs[0]; stfp = combined_drawpix_fragment_program(ctx); @@ -754,8 +822,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, color = NULL; } - bufferFormat = ps->format; - /* draw with textured quad */ { struct pipe_texture *pt @@ -767,8 +833,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, pipe_texture_reference(&pt, NULL); } } - - _mesa_set_vp_override( ctx, FALSE ); } @@ -780,6 +844,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, { struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); struct pipe_screen *screen = ctx->st->pipe->screen; + enum pipe_transfer_usage usage; struct pipe_transfer *ptDraw; ubyte *drawMap; ubyte *buffer; @@ -792,16 +857,27 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* this will do stencil pixel transfer ops */ - st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE, + st_read_stencil_pixels(ctx, srcx, srcy, width, height, + GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &ctx->DefaultPacking, buffer); - ptDraw = screen->get_tex_transfer(screen, rbDraw->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, dstx, dsty, - width, height); + if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0) + usage = PIPE_TRANSFER_READ_WRITE; + else + usage = PIPE_TRANSFER_WRITE; + + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + dsty = rbDraw->Base.Height - dsty - height; + } + + ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx), + rbDraw->texture, 0, 0, 0, + usage, dstx, dsty, + width, height); assert(ptDraw->block.width == 1); assert(ptDraw->block.height == 1); - + /* map the stencil buffer */ drawMap = screen->transfer_map(screen, ptDraw); @@ -826,6 +902,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, { uint *dst4 = (uint *) dst; int j; + assert(usage == PIPE_TRANSFER_READ_WRITE); for (j = 0; j < width; j++) { *dst4 = (*dst4 & 0xffffff) | (src[j] << 24); dst4++; @@ -836,6 +913,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, { uint *dst4 = (uint *) dst; int j; + assert(usage == PIPE_TRANSFER_READ_WRITE); for (j = 0; j < width; j++) { *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff); dst4++; @@ -843,6 +921,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } break; case PIPE_FORMAT_S8_UNORM: + assert(usage == PIPE_TRANSFER_WRITE); memcpy(dst, src, width); break; default: @@ -872,12 +951,40 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct pipe_texture *pt; GLfloat *color; enum pipe_format srcFormat, texFormat; + int ptw, pth; - /* make sure rendering has completed */ 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); @@ -919,15 +1026,45 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, } } + 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; + } + + /* 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(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, - width, height, 1, 0, + ptw, pth, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) return; - if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { - srcy = ctx->DrawBuffer->Height - srcy - height; - } if (srcFormat == texFormat) { /* copy source framebuffer surface into mipmap/texture */ @@ -947,13 +1084,19 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = - screen->get_tex_transfer(screen, rbRead->texture, 0, 0, 0, - PIPE_TRANSFER_READ, srcx, srcy, width, - height); - - struct pipe_transfer *ptTex = - screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE, - 0, 0, width, height); + st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, + PIPE_TRANSFER_READ, srcx, srcy, width, + height); + struct pipe_transfer *ptTex; + enum pipe_transfer_usage transfer_usage; + + if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format)) + transfer_usage = PIPE_TRANSFER_READ_WRITE; + else + transfer_usage = PIPE_TRANSFER_WRITE; + + ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, + 0, 0, width, height); if (type == GL_COLOR) { /* alternate path using get/put_tile() */