#include "main/macros.h"
#include "main/texformat.h"
#include "main/texstore.h"
-#include "main/state.h"
#include "shader/program.h"
-#include "shader/prog_parameter.h"
#include "shader/prog_print.h"
#include "st_debug.h"
#include "st_context.h"
#include "st_atom.h"
#include "st_atom_constbuf.h"
-#include "st_draw.h"
#include "st_program.h"
#include "st_cb_drawpixels.h"
#include "st_cb_readpixels.h"
#include "st_cb_fbo.h"
-#include "st_cb_texture.h"
-#include "st_draw.h"
#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_inlines.h"
#include "tgsi/tgsi_ureg.h"
#include "util/u_tile.h"
#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"
/**
* Make fragment shader for glDraw/CopyPixels. This shader is made
* by combining the pixel transfer shader with the user-defined shader.
+ * \return pointer to Gallium driver fragment shader
*/
-static struct st_fragment_program *
+static void *
combined_drawpix_fragment_program(GLcontext *ctx)
{
struct st_context *st = st_context(ctx);
*/
if (is_passthrough_program(&st->fp->Base)) {
stfp = (struct st_fragment_program *)
- _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
+ _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base);
}
else {
#if 0
#endif
/* translate to TGSI tokens */
- st_translate_fragment_program(st, stfp, NULL);
+ st_translate_fragment_program(st, stfp);
/* save new program, update serial numbers */
st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
*/
st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
- return stfp;
+ return stfp->driver_shader;
}
* Create fragment shader that does a TEX() instruction to get a Z
* value, then writes to FRAG_RESULT_DEPTH.
* Pass fragment color through as-is.
+ * \return pointer to the Gallium driver fragment shader
*/
-static struct st_fragment_program *
+static void *
make_fragment_shader_z(struct st_context *st)
{
GLcontext *ctx = st->ctx;
GLuint ic = 0;
if (st->drawpix.z_shader) {
- return st->drawpix.z_shader;
+ return st->drawpix.z_shader->driver_shader;
}
/*
p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
st->drawpix.z_shader = (struct st_fragment_program *) p;
- st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
+ st_translate_fragment_program(st, st->drawpix.z_shader);
- return st->drawpix.z_shader;
+ return st->drawpix.z_shader->driver_shader;
}
* vertex position and texcoord (and optionally, color).
*/
static void *
-st_make_passthrough_vertex_shader(struct st_context *st,
- GLboolean passColor)
+make_passthrough_vertex_shader(struct st_context *st,
+ GLboolean passColor)
{
if (!st->drawpix.vert_shaders[passColor]) {
struct ureg_program *ureg =
}
+/**
+ * Return a texture internalFormat for drawing/copying an image
+ * of the given type.
+ */
static GLenum
-_mesa_base_format(GLenum format)
+base_format(GLenum format)
{
switch (format) {
case GL_DEPTH_COMPONENT:
GLenum baseFormat;
int ptw, pth;
- baseFormat = _mesa_base_format(format);
+ baseFormat = base_format(format);
mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
assert(mformat);
pipeFormat = st_mesa_format_to_pipe_format(mformat);
assert(pipeFormat);
- cpp = st_sizeof_format(pipeFormat);
+ cpp = util_format_get_blocksize(pipeFormat);
pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
if (!pixels)
/**
* 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
*/
struct pipe_viewport_state vp;
vp.scale[0] = 0.5f * w;
vp.scale[1] = -0.5f * h;
- vp.scale[2] = 1.0f;
+ vp.scale[2] = 0.5f;
vp.scale[3] = 1.0f;
vp.translate[0] = 0.5f * w;
vp.translate[1] = 0.5f * h;
- vp.translate[2] = 0.0f;
+ vp.translate[2] = 0.5f;
vp.translate[3] = 0.0f;
cso_set_viewport(cso, &vp);
}
struct pipe_texture *textures[2];
textures[0] = pt;
textures[1] = st->pixel_xfer.pixelmap_texture;
- pipe->set_sampler_textures(pipe, 2, textures);
+ pipe->set_fragment_sampler_textures(pipe, 2, textures);
}
else {
- pipe->set_sampler_textures(pipe, 1, &pt);
+ pipe->set_fragment_sampler_textures(pipe, 1, &pt);
}
- /* 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;
y1 = y + height * ctx->Pixel.ZoomY;
+ /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
+ z = z * 2.0 - 1.0;
+
draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
- (GLfloat) width / pt->width[0],
- (GLfloat) height / pt->height[0]);
+ (GLfloat) width / pt->width0,
+ (GLfloat) height / pt->height0);
/* restore state */
cso_restore_rasterizer(cso);
}
if(format != GL_DEPTH_STENCIL &&
- pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0)
+ util_format_get_component_bits(strb->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0)
usage = PIPE_TRANSFER_READ_WRITE;
else
usage = PIPE_TRANSFER_WRITE;
}
/* now pack the stencil (and Z) values in the dest format */
- switch (pt->format) {
+ switch (pt->texture->format) {
case PIPE_FORMAT_S8_UNORM:
{
ubyte *dest = stmap + spanY * pt->stride + spanX;
memcpy(dest, sValues, spanWidth);
}
break;
- case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
if (format == GL_DEPTH_STENCIL) {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
}
}
break;
- case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
if (format == GL_DEPTH_STENCIL) {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
{
- struct st_fragment_program *stfp;
- void *driver_vp;
+ void *driver_vp, *driver_fp;
struct st_context *st = st_context(ctx);
- struct pipe_surface *ps;
const GLfloat *color;
if (format == GL_STENCIL_INDEX ||
st_validate_state(st);
if (format == GL_DEPTH_COMPONENT) {
- ps = st->state.framebuffer.zsbuf;
- stfp = make_fragment_shader_z(st);
- driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE);
+ driver_fp = make_fragment_shader_z(st);
+ driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
color = ctx->Current.RasterColor;
}
else {
- ps = st->state.framebuffer.cbufs[0];
- stfp = combined_drawpix_fragment_program(ctx);
- driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE);
+ driver_fp = combined_drawpix_fragment_program(ctx);
+ driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
color = NULL;
}
width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
pt,
driver_vp,
- stfp->driver_shader,
+ driver_fp,
color, GL_FALSE);
pipe_texture_reference(&pt, NULL);
}
ubyte *buffer;
int i;
- buffer = _mesa_malloc(width * height * sizeof(ubyte));
+ buffer = malloc(width * height * sizeof(ubyte));
if (!buffer) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
return;
GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
&ctx->DefaultPacking, buffer);
- if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0)
+ if(util_format_get_component_bits(rbDraw->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0)
usage = PIPE_TRANSFER_READ_WRITE;
else
usage = PIPE_TRANSFER_WRITE;
usage, dstx, dsty,
width, height);
- assert(ptDraw->block.width == 1);
- assert(ptDraw->block.height == 1);
+ assert(util_format_get_blockwidth(ptDraw->texture->format) == 1);
+ assert(util_format_get_blockheight(ptDraw->texture->format) == 1);
/* map the stencil buffer */
drawMap = screen->transfer_map(screen, ptDraw);
dst = drawMap + y * ptDraw->stride;
src = buffer + i * width;
- switch (ptDraw->format) {
- case PIPE_FORMAT_S8Z24_UNORM:
+ switch (ptDraw->texture->format) {
+ case PIPE_FORMAT_Z24S8_UNORM:
{
uint *dst4 = (uint *) dst;
int j;
}
}
break;
- case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
{
uint *dst4 = (uint *) dst;
int j;
}
}
- _mesa_free(buffer);
+ free(buffer);
/* unmap the stencil buffer */
screen->transfer_unmap(screen, ptDraw);
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
struct st_renderbuffer *rbRead;
- void *driver_vp;
- struct st_fragment_program *stfp;
+ void *driver_vp, *driver_fp;
struct pipe_texture *pt;
GLfloat *color;
enum pipe_format srcFormat, texFormat;
int ptw, pth;
+ GLboolean invertTex = GL_FALSE;
+ GLint readX, readY, readW, readH;
+ struct gl_pixelstore_attrib unpack = 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);
if (type == GL_COLOR) {
rbRead = st_get_color_read_renderbuffer(ctx);
color = NULL;
- stfp = combined_drawpix_fragment_program(ctx);
- driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE);
+ driver_fp = combined_drawpix_fragment_program(ctx);
+ driver_vp = make_passthrough_vertex_shader(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(st);
- driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE);
+ driver_fp = make_fragment_shader_z(st);
+ driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
}
srcFormat = rbRead->texture->format;
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??? */
+ assert(texFormat != PIPE_FORMAT_NONE);
}
else {
/* default color format */
}
}
- 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;
}
+ /* 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, &unpack);
+ readW = MAX2(0, readW);
+ readH = MAX2(0, readH);
+
/* Need to use POT texture? */
ptw = width;
pth = height;
if (!pt)
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,
PIPE_BUFFER_USAGE_GPU_WRITE );
if (pipe->surface_copy) {
pipe->surface_copy(pipe,
- psTex, /* dest */
- 0, 0, /* destx/y */
- psRead,
- srcx, srcy, width, height);
+ psTex, /* dest surf */
+ unpack.SkipPixels, unpack.SkipRows, /* dest pos */
+ psRead, /* src surf */
+ readX, readY, readW, readH); /* src region */
} else {
util_surface_copy(pipe, FALSE,
psTex,
- 0, 0,
+ unpack.SkipPixels, unpack.SkipRows,
psRead,
- srcx, srcy, width, height);
+ readX, readY, readW, readH);
}
+
+ if (0) {
+ /* debug */
+ debug_dump_surface("copypixsrcsurf", psRead);
+ debug_dump_surface("copypixtemptex", psTex);
+ }
+
pipe_surface_reference(&psRead, NULL);
pipe_surface_reference(&psTex, NULL);
}
/* 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;
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
- if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format))
+ if (type == GL_DEPTH && util_format_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);
+ /* copy image from ptRead surface to ptTex surface */
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);
+ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+ pipe_get_tile_rgba(ptRead, readX, readY, readW, readH, buf);
+ pipe_put_tile_rgba(ptTex, unpack.SkipPixels, unpack.SkipRows,
+ readW, readH, buf);
+ 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);
+ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
+ pipe_get_tile_z(ptRead, readX, readY, readW, readH, buf);
+ pipe_put_tile_z(ptTex, unpack.SkipPixels, unpack.SkipRows,
+ readW, readH, buf);
+ free(buf);
}
screen->tex_transfer_destroy(ptRead);
screen->tex_transfer_destroy(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,
pt,
driver_vp,
- stfp->driver_shader,
- color, GL_TRUE);
+ driver_fp,
+ color, invertTex);
pipe_texture_reference(&pt, NULL);
}
{
st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
- st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL);
- st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL);
+ if (st->drawpix.vert_shaders[0])
+ free(st->drawpix.vert_shaders[0]);
+ if (st->drawpix.vert_shaders[1])
+ free(st->drawpix.vert_shaders[1]);
}