static void fallback_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt = st_get_texobj_texture(texObj); const uint baseLevel = texObj->BaseLevel; const uint lastLevel = pt->last_level; const uint face = _mesa_tex_target_to_face(target), zslice = 0; uint dstLevel; GLenum datatype; GLuint comps; assert(target != GL_TEXTURE_3D); /* not done yet */ _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat, &datatype, &comps); for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; struct pipe_transfer *srcTrans, *dstTrans; const ubyte *srcData; ubyte *dstData; int srcStride, dstStride; srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, srcLevel, zslice, PIPE_TRANSFER_READ, 0, 0, pt->width[srcLevel], pt->height[srcLevel]); dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, dstLevel, zslice, PIPE_TRANSFER_WRITE, 0, 0, pt->width[dstLevel], pt->height[dstLevel]); srcData = (ubyte *) screen->transfer_map(screen, srcTrans); dstData = (ubyte *) screen->transfer_map(screen, dstTrans); srcStride = srcTrans->stride / srcTrans->block.size; dstStride = dstTrans->stride / dstTrans->block.size; _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], srcData, srcStride, /* stride in texels */ pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], dstData, dstStride); /* stride in texels */ screen->transfer_unmap(screen, srcTrans); screen->transfer_unmap(screen, dstTrans); screen->tex_transfer_destroy(srcTrans); screen->tex_transfer_destroy(dstTrans); } }
static void accum_load(struct st_context *st, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, struct st_renderbuffer *acc_strb, struct st_renderbuffer *color_strb) { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_transfer *color_trans; size_t stride = acc_strb->stride; GLubyte *data = acc_strb->data; GLfloat *buf; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture, 0, 0, 0, PIPE_TRANSFER_READ, xpos, ypos, width, height); buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: { const GLfloat *color = buf; int i, j; for (i = 0; i < height; i++) { GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); for (j = 0; j < width * 4; j++) { float val = *color++ * value; *acc++ = FLOAT_TO_SHORT(val); } } } break; default: _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } _mesa_free(buf); screen->tex_transfer_destroy(color_trans); }
/** * Update the pixelmap texture with the contents of the R/G/B/A pixel maps. */ static void load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) { struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_transfer *transfer; const GLuint rSize = ctx->PixelMaps.RtoR.Size; const GLuint gSize = ctx->PixelMaps.GtoG.Size; const GLuint bSize = ctx->PixelMaps.BtoB.Size; const GLuint aSize = ctx->PixelMaps.AtoA.Size; const uint texSize = pt->width[0]; uint *dest; uint i, j; transfer = st_cond_flush_get_tex_transfer(st_context(ctx), pt, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, texSize, texSize); dest = (uint *) screen->transfer_map(screen, transfer); /* Pack four 1D maps into a 2D texture: * R map is placed horizontally, indexed by S, in channel 0 * G map is placed vertically, indexed by T, in channel 1 * B map is placed horizontally, indexed by S, in channel 2 * A map is placed vertically, indexed by T, in channel 3 */ for (i = 0; i < texSize; i++) { for (j = 0; j < texSize; j++) { int k = (i * texSize + j); ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize]; ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize]; ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize]; ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize]; util_pack_color_ub(r, g, b, a, pt->format, dest + k); } } screen->transfer_unmap(screen, transfer); screen->tex_transfer_destroy(transfer); }
static void accum_return(GLcontext *ctx, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, struct st_renderbuffer *acc_strb, struct st_renderbuffer *color_strb) { struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; const GLubyte *colormask = ctx->Color.ColorMask; enum pipe_transfer_usage usage; struct pipe_transfer *color_trans; size_t stride = acc_strb->stride; const GLubyte *data = acc_strb->data; GLfloat *buf; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; color_trans = st_cond_flush_get_tex_transfer(st_context(ctx), color_strb->texture, 0, 0, 0, usage, xpos, ypos, width, height); if (usage & PIPE_TRANSFER_READ) pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: { GLfloat *color = buf; int i, j, ch; for (i = 0; i < height; i++) { const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8); for (j = 0; j < width; j++) { for (ch = 0; ch < 4; ch++) { if (colormask[ch]) { GLfloat val = SHORT_TO_FLOAT(*acc * value); *color = CLAMP(val, 0.0f, 1.0f); } else { /* No change */ } ++acc; ++color; } } } } break; default: _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } pipe_put_tile_rgba(color_trans, 0, 0, width, height, buf); _mesa_free(buf); screen->tex_transfer_destroy(color_trans); }
static void st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type) { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *rbRead; struct st_vertex_program *stvp; struct st_fragment_program *stfp; struct pipe_texture *pt; GLfloat *color; enum pipe_format srcFormat, texFormat; 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); return; } if (type == GL_COLOR) { rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; stfp = combined_drawpix_fragment_program(ctx); stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE); } else { assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; stfp = make_fragment_shader_z(ctx->st); stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); } srcFormat = rbRead->texture->format; if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)) { texFormat = srcFormat; } else { /* srcFormat can't be used as a texture format */ if (type == GL_DEPTH) { texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL); assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ } else { /* default color format */ texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER); 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; } pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, width, height, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) return; 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); struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); pipe->surface_copy(pipe, psTex, /* dest */ 0, 0, /* destx/y */ psRead, srcx, srcy, width, height); pipe_surface_reference(&psRead, NULL); pipe_surface_reference(&psTex, NULL); } else { /* 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); 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() */ GLfloat *buf = (GLfloat *) _mesa_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); _mesa_free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) _mesa_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); _mesa_free(buf); } screen->tex_transfer_destroy(ptRead); screen->tex_transfer_destroy(ptTex); } /* draw textured quad */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, pt, stvp, stfp, color, GL_TRUE); pipe_texture_reference(&pt, NULL); }
static void copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty) { 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; int i; buffer = _mesa_malloc(width * height * sizeof(ubyte)); if (!buffer) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)"); return; } /* this will do stencil pixel transfer ops */ st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &ctx->DefaultPacking, buffer); 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); /* draw */ /* XXX PixelZoom not handled yet */ for (i = 0; i < height; i++) { ubyte *dst; const ubyte *src; int y; y = i; if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { y = height - y - 1; } dst = drawMap + y * ptDraw->stride; src = buffer + i * width; switch (ptDraw->format) { case PIPE_FORMAT_S8Z24_UNORM: { 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++; } } break; case PIPE_FORMAT_Z24S8_UNORM: { 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++; } } break; case PIPE_FORMAT_S8_UNORM: assert(usage == PIPE_TRANSFER_WRITE); memcpy(dst, src, width); break; default: assert(0); } } _mesa_free(buffer); /* unmap the stencil buffer */ screen->transfer_unmap(screen, ptDraw); screen->tex_transfer_destroy(ptDraw); }
static void draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { struct st_context *st = ctx->st; 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; strb = st_renderbuffer(ctx->DrawBuffer-> Attachment[BUFFER_STENCIL].Renderbuffer); 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_drawpix_pbo(ctx, unpack, pixels); assert(pixels); /* if width > MAX_WIDTH, have to process image in chunks */ skipPixels = 0; while (skipPixels < width) { const GLint spanX = skipPixels; const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); GLint row; for (row = 0; row < height; row++) { GLubyte sValues[MAX_WIDTH]; GLuint zValues[MAX_WIDTH]; GLenum destType = GL_UNSIGNED_BYTE; const GLvoid *source = _mesa_image_address2d(unpack, pixels, width, height, format, type, row, skipPixels); _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) { _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " "zoom not complete"); } { GLint spanY; if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 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; 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++) { 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++) { 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; default: assert(0); } } } skipPixels += spanWidth; } _mesa_unmap_drawpix_pbo(ctx, unpack); /* unmap the stencil buffer */ screen->transfer_unmap(screen, pt); screen->tex_transfer_destroy(pt); }