/**
* Create a simple fragment shader that does a TEX() instruction to get
* the fragment color.
+ * If bitmapMode, use KIL instruction to kill the "0-pixels".
*/
static struct st_fragment_program *
make_fragment_shader(struct st_context *st, GLboolean bitmapMode)
{
+ /* only make programs once and re-use */
+ static struct st_fragment_program *progs[2] = { NULL, NULL };
GLcontext *ctx = st->ctx;
struct st_fragment_program *stfp;
struct gl_program *p;
GLuint ic = 0;
+ if (progs[bitmapMode])
+ return progs[bitmapMode];
+
p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
if (!p)
return NULL;
st_translate_fragment_program(st, stfp, NULL,
stfp->tokens, ST_MAX_SHADER_TOKENS);
+ progs[bitmapMode] = stfp;
+
return stfp;
}
/**
* Create fragment shader that does a TEX() instruction to get a Z
* value, then writes to FRAG_RESULT_DEPR.
+ * Pass fragment color through as-is.
*/
static struct st_fragment_program *
make_fragment_shader_z(struct st_context *st)
{
GLcontext *ctx = st->ctx;
- struct st_fragment_program *stfp;
+ /* only make programs once and re-use */
+ static struct st_fragment_program *stfp = NULL;
struct gl_program *p;
GLuint ic = 0;
+ if (stfp)
+ return stfp;
+
p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
if (!p)
return NULL;
/**
* Create a simple vertex shader that just passes through the
- * vertex position and texcoord (and color).
+ * vertex position and texcoord (and optionally, color).
*/
static struct st_vertex_program *
make_vertex_shader(struct st_context *st, GLboolean passColor)
{
+ /* only make programs once and re-use */
+ static struct st_vertex_program *progs[2] = { NULL, NULL };
GLcontext *ctx = st->ctx;
struct st_vertex_program *stvp;
struct gl_program *p;
GLuint ic = 0;
+ if (progs[passColor])
+ return progs[passColor];
+
p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
if (!p)
return NULL;
st_translate_vertex_program(st, stvp, NULL,
stvp->tokens, ST_MAX_SHADER_TOKENS);
+ progs[passColor] = stvp;
+
return stvp;
}
+static struct pipe_mipmap_tree *
+alloc_mipmap_tree(struct st_context *st,
+ GLsizei width, GLsizei height, uint pipeFormat)
+{
+ const GLbitfield flags = PIPE_SURFACE_FLAG_TEXTURE;
+ struct pipe_mipmap_tree *mt;
+ GLuint cpp;
+
+ mt = CALLOC_STRUCT(pipe_mipmap_tree);
+ if (!mt)
+ return NULL;
+
+ cpp = st_sizeof_format(pipeFormat);
+
+ /* allocate texture region/storage */
+ mt->region = st->pipe->region_alloc(st->pipe, cpp, width, height, flags);
+
+ mt->target = PIPE_TEXTURE_2D;
+ mt->internal_format = GL_RGBA;
+ mt->format = pipeFormat;
+ mt->first_level = 0;
+ mt->last_level = 0;
+ mt->width0 = width;
+ mt->height0 = height;
+ mt->depth0 = 1;
+ mt->cpp = cpp;
+ mt->compressed = 0;
+ mt->pitch = mt->region->pitch;
+ mt->depth_pitch = 0;
+ mt->total_height = height;
+ mt->level[0].level_offset = 0;
+ mt->level[0].width = width;
+ mt->level[0].height = height;
+ mt->level[0].depth = 1;
+ mt->level[0].nr_images = 1;
+ mt->level[0].image_offset = NULL;
+ mt->refcount = 1;
+
+ return mt;
+}
+
+
/**
- * Make mipmap tree containing the glDrawPixels image.
+ * Make mipmap tree containing an image for glDrawPixels image.
+ * If 'pixels' is NULL, leave the texture image data undefined.
*/
static struct pipe_mipmap_tree *
make_mipmap_tree(struct st_context *st,
{
struct pipe_context *pipe = st->pipe;
const struct gl_texture_format *mformat;
- const GLbitfield flags = PIPE_SURFACE_FLAG_TEXTURE;
struct pipe_mipmap_tree *mt;
GLuint pipeFormat, cpp;
GLenum baseFormat;
assert(pipeFormat);
cpp = st_sizeof_format(pipeFormat);
- mt = CALLOC_STRUCT(pipe_mipmap_tree);
+ mt = alloc_mipmap_tree(st, width, height, pipeFormat);
if (!mt)
return NULL;
*/
printf("st_DrawPixels (sourcing from PBO not implemented yet)\n");
}
- else {
+
+ {
static const GLuint dstImageOffsets = 0;
GLboolean success;
+ GLuint pitch = mt->region->pitch;
GLubyte *dest;
- GLuint pitch;
-
- /* allocate texture region/storage */
- mt->region = st->pipe->region_alloc(st->pipe, cpp, width, height, flags);
- pitch = mt->region->pitch;
/* map texture region */
dest = pipe->region_map(pipe, mt->region);
/* unmap */
pipe->region_unmap(pipe, mt->region);
-
assert(success);
}
+#if 0
mt->target = PIPE_TEXTURE_2D;
mt->internal_format = GL_RGBA;
mt->format = pipeFormat;
mt->level[0].nr_images = 1;
mt->level[0].image_offset = NULL;
mt->refcount = 1;
-
+#endif
return mt;
}
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
{
- static struct st_fragment_program *stfp_c = NULL; /* color */
- static struct st_fragment_program *stfp_z = NULL; /* z */
- static struct st_vertex_program *stvp_t = NULL; /* just emit texcoord */
- static struct st_vertex_program *stvp_c = NULL; /* emit color too */
struct st_fragment_program *stfp;
struct st_vertex_program *stvp;
struct st_context *st = ctx->st;
return;
}
- /* create the fragment programs if needed */
- if (!stfp_c) {
- stfp_c = make_fragment_shader(ctx->st, GL_FALSE);
- }
- if (!stfp_z) {
- stfp_z = make_fragment_shader_z(ctx->st);
- }
-
- /* and vertex programs */
- if (!stvp_t) {
- stvp_t = make_vertex_shader(ctx->st, GL_FALSE);
- }
- if (!stvp_c) {
- stvp_c = make_vertex_shader(ctx->st, GL_TRUE);
- }
-
st_validate_state(st);
if (format == GL_DEPTH_COMPONENT) {
ps = st->state.framebuffer.zbuf;
- stfp = stfp_z;
- stvp = stvp_c;
+ stfp = make_fragment_shader_z(ctx->st);
+ stvp = make_vertex_shader(ctx->st, GL_TRUE);
color = ctx->Current.RasterColor;
}
else if (format == GL_STENCIL_INDEX) {
}
else {
ps = st->state.framebuffer.cbufs[0];
- stfp = stfp_c;
- stvp = stvp_t;
+ stfp = make_fragment_shader(ctx->st, GL_FALSE);
+ stvp = make_vertex_shader(ctx->st, GL_FALSE);
color = NULL;
}
st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
{
- static struct st_vertex_program *stvp = NULL;
- static struct st_fragment_program *stfp = NULL;
+ struct st_vertex_program *stvp;
+ struct st_fragment_program *stfp;
struct st_context *st = ctx->st;
struct pipe_mipmap_tree *mt;
- /* create the fragment program if needed */
- if (!stfp) {
- stfp = make_fragment_shader(ctx->st, GL_TRUE);
- }
+ /* create the fragment program */
+ stfp = make_fragment_shader(ctx->st, GL_TRUE);
+
/* and vertex program */
- if (!stvp) {
- stvp = make_vertex_shader(ctx->st, GL_TRUE);
- }
+ stvp = make_vertex_shader(ctx->st, GL_TRUE);
st_validate_state(st);
GLint dstx, GLint dsty, GLenum type)
{
struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct st_renderbuffer *rbRead;
+ struct st_vertex_program *stvp;
+ struct st_fragment_program *stfp;
+ struct pipe_surface *psRead;
+ struct pipe_mipmap_tree *mt;
+ GLfloat *color;
+ uint format;
st_validate_state(st);
if (type == GL_STENCIL) {
+ /* can't use texturing to do stencil */
copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
return;
}
- /* allocate a texture of size width x height */
+ if (type == GL_COLOR) {
+ rbRead = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+ color = NULL;
+ stfp = make_fragment_shader(ctx->st, GL_FALSE);
+ stvp = make_vertex_shader(ctx->st, GL_FALSE);
+ }
+ else {
+ rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
+ color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ stfp = make_fragment_shader_z(ctx->st);
+ stvp = make_vertex_shader(ctx->st, GL_TRUE);
+ }
+
+ psRead = rbRead->surface;
+ format = psRead->format;
- /* blit/copy framebuffer region into texture */
+ mt = alloc_mipmap_tree(ctx->st, width, height, format);
+ if (!mt)
+ return;
- /* draw textured quad */
+ /* copy source framebuffer region into mipmap/texture */
+ pipe->region_copy(pipe,
+ mt->region, /* dest */
+ 0, /* dest_offset */
+ 0, 0, /* destx/y */
+ psRead->region,
+ 0, /* src_offset */
+ srcx, srcy, width, height);
- fprintf(stderr, "st_CopyPixels not implemented yet\n");
+ /* draw textured quad */
+ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
+ width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
+ mt, stvp, stfp, color);
+
+ free_mipmap_tree(st->pipe, mt);
}