#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
-#include "pipe/p_winsys.h"
#include "util/p_tile.h"
#include "util/u_draw_quad.h"
#include "util/u_simple_shaders.h"
GLint xpos, ypos;
/** Bounds of region used in window coords */
GLint xmin, ymin, xmax, ymax;
+
struct pipe_texture *texture;
+ struct pipe_surface *surf;
+
GLboolean empty;
+
/** An I8 texture image: */
- GLubyte buffer[BITMAP_CACHE_HEIGHT][BITMAP_CACHE_WIDTH];
+ ubyte *buffer;
};
* This program will be combined with the user's fragment program.
*/
static struct st_fragment_program *
-make_bitmap_fragment_program(GLcontext *ctx)
+make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
{
struct st_fragment_program *stfp;
struct gl_program *p;
p->Instructions[ic].DstReg.Index = 0;
p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
- p->Instructions[ic].TexSrcUnit = 0;
+ p->Instructions[ic].TexSrcUnit = samplerIndex;
p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
p->InputsRead = FRAG_BIT_TEX0;
p->OutputsWritten = 0x0;
+ p->SamplersUsed = (1 << samplerIndex);
stfp = (struct st_fragment_program *) p;
stfp->Base.UsesKill = GL_TRUE;
}
+static int
+find_free_bit(uint bitfield)
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ if ((bitfield & (1 << i)) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
/**
* Combine basic bitmap fragment program with the user-defined program.
*/
combined_bitmap_fragment_program(GLcontext *ctx)
{
struct st_context *st = ctx->st;
- struct st_fragment_program *stfp;
+ struct st_fragment_program *stfp = st->fp;
- if (!st->bitmap.program) {
- /* create the basic bitmap fragment program */
- st->bitmap.program = make_bitmap_fragment_program(ctx);
- }
-
- if (st->bitmap.user_prog_sn == st->fp->serialNo) {
- /* re-use */
- stfp = st->bitmap.combined_prog;
- }
- else {
- /* Concatenate the bitmap program with the current user-defined program.
+ if (!stfp->bitmap_program) {
+ /*
+ * Generate new program which is the user-defined program prefixed
+ * with the bitmap sampler/kill instructions.
*/
- stfp = (struct st_fragment_program *)
+ struct st_fragment_program *bitmap_prog;
+ uint sampler;
+
+ sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
+ bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
+
+ stfp->bitmap_program = (struct st_fragment_program *)
_mesa_combine_programs(ctx,
- &st->bitmap.program->Base.Base,
- &st->fp->Base.Base);
+ &bitmap_prog->Base.Base, &stfp->Base.Base);
+ stfp->bitmap_program->bitmap_sampler = sampler;
+
+ /* done with this after combining */
+ st_reference_fragprog(st, &bitmap_prog, NULL);
#if 0
{
- struct gl_program *p = &stfp->Base.Base;
+ struct gl_program *p = &stfp->bitmap_program->Base.Base;
printf("Combined bitmap program:\n");
_mesa_print_program(p);
printf("InputsRead: 0x%x\n", p->InputsRead);
#endif
/* translate to TGSI tokens */
- st_translate_fragment_program(st, stfp, NULL);
-
- /* save new program, update serial numbers */
- st->bitmap.user_prog_sn = st->fp->serialNo;
- st->bitmap.combined_prog = stfp;
+ st_translate_fragment_program(st, stfp->bitmap_program, NULL);
}
/* Ideally we'd have updated the pipe constants during the normal
*/
st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
- return stfp;
+ return stfp->bitmap_program;
}
/**
- * Create a texture which represents a bitmap image.
+ * Copy user-provide bitmap bits into texture buffer, expanding
+ * bits into texels.
+ * "On" bits will set texels to 0xff.
+ * "Off" bits will not modify texels.
+ * Note that the image is actually going to be upside down in
+ * the texture. We deal with that with texcoords.
*/
-static struct pipe_texture *
-make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap)
+static void
+unpack_bitmap(struct st_context *st,
+ GLint px, GLint py, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ ubyte *destBuffer, uint destStride)
{
- struct pipe_context *pipe = ctx->st->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_surface *surface;
- uint format = 0, cpp, comp;
- ubyte *dest;
- struct pipe_texture *pt;
- int row, col;
-
- /* find a texture format we know */
- if (screen->is_format_supported( screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE )) {
- format = PIPE_FORMAT_U_I8;
- cpp = 1;
- comp = 0;
- }
- else if (screen->is_format_supported( screen, PIPE_FORMAT_A8R8G8B8_UNORM, PIPE_TEXTURE )) {
- format = PIPE_FORMAT_A8R8G8B8_UNORM;
- cpp = 4;
- comp = 3; /* alpha channel */ /*XXX little-endian dependency */
- }
- else {
- /* XXX support more formats */
- assert( 0 );
- }
-
- /* PBO source... */
- bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap);
- if (!bitmap) {
- return NULL;
- }
-
- /**
- * Create texture to hold bitmap pattern.
- */
- pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height,
- 1, 0);
- if (!pt) {
- _mesa_unmap_bitmap_pbo(ctx, unpack);
- return NULL;
- }
+ GLint row, col;
- surface = screen->get_tex_surface(screen, pt, 0, 0, 0);
-
- /* map texture surface */
- dest = pipe_surface_map(surface);
-
- /* Put image into texture surface.
- * Note that the image is actually going to be upside down in
- * the texture. We deal with that with texcoords.
- */
+#define SET_PIXEL(COL, ROW) \
+ destBuffer[(py + (ROW)) * destStride + px + (COL)] = 0x0;
for (row = 0; row < height; row++) {
const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
- ubyte *destRow = dest + row * surface->pitch * cpp;
if (unpack->LsbFirst) {
/* Lsb first */
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
for (col = 0; col < width; col++) {
- /* set texel to 255 if bit is set */
- destRow[comp] = (*src & mask) ? 0x0 : 0xff;
- destRow += cpp;
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
if (mask == 128U) {
src++;
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col = 0; col < width; col++) {
- /* set texel to 255 if bit is set */
- destRow[comp] =(*src & mask) ? 0x0 : 0xff;
- destRow += cpp;
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
if (mask == 1U) {
src++;
} /* row */
+#undef SET_PIXEL
+}
+
+
+/**
+ * Create a texture which represents a bitmap image.
+ */
+static struct pipe_texture *
+make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surface;
+ ubyte *dest;
+ struct pipe_texture *pt;
+
+ /* PBO source... */
+ bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap);
+ if (!bitmap) {
+ return NULL;
+ }
+
+ /**
+ * Create texture to hold bitmap pattern.
+ */
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format,
+ 0, width, height, 1, 0);
+ if (!pt) {
+ _mesa_unmap_bitmap_pbo(ctx, unpack);
+ return NULL;
+ }
+
+ surface = screen->get_tex_surface(screen, pt, 0, 0, 0);
+
+ /* map texture surface */
+ dest = pipe_surface_map(surface);
+
+ /* Put image into texture surface */
+ memset(dest, 0xff, height * surface->pitch);
+ unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
+ dest, surface->pitch);
+
_mesa_unmap_bitmap_pbo(ctx, unpack);
/* Release surface */
pipe_surface_reference(&surface, NULL);
pipe->texture_update(pipe, pt, 0, 0x1);
- pt->format = format;
-
return pt;
}
const GLfloat x1 = x + width;
const GLfloat y0 = y;
const GLfloat y1 = y + height;
- const GLfloat bias = st->bitmap_texcoord_bias;
- const GLfloat xBias = bias / (x1-x0);
- const GLfloat yBias = bias / (y1-y0);
- const GLfloat sLeft = 0.0 + xBias, sRight = 1.0 + xBias;
- const GLfloat tTop = yBias, tBot = 1.0 - tTop - yBias;
+ const GLfloat sLeft = 0.0F, sRight = 1.0F;
+ const GLfloat tTop = 0.0, tBot = 1.0 - tTop;
const GLfloat clip_x0 = x0 / fb_width * 2.0 - 1.0;
const GLfloat clip_y0 = y0 / fb_height * 2.0 - 1.0;
const GLfloat clip_x1 = x1 / fb_width * 2.0 - 1.0;
void *buf;
if (!st->bitmap.vbuf) {
- st->bitmap.vbuf = pipe->winsys->buffer_create(pipe->winsys, 32,
- PIPE_BUFFER_USAGE_VERTEX,
- sizeof(st->bitmap.vertices));
+ st->bitmap.vbuf = pipe_buffer_create(pipe, 32, PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(st->bitmap.vertices));
}
/* Positions are in clip coords since we need to do clipping in case
}
/* put vertex data into vbuf */
- buf = pipe->winsys->buffer_map(pipe->winsys, st->bitmap.vbuf,
- PIPE_BUFFER_USAGE_CPU_WRITE);
+ buf = pipe_buffer_map(pipe, st->bitmap.vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
memcpy(buf, st->bitmap.vertices, sizeof(st->bitmap.vertices));
- pipe->winsys->buffer_unmap(pipe->winsys, st->bitmap.vbuf);
+ pipe_buffer_unmap(pipe, st->bitmap.vbuf);
}
cso_save_samplers(cso);
cso_save_sampler_textures(cso);
cso_save_viewport(cso);
+ cso_save_fragment_shader(cso);
+ cso_save_vertex_shader(cso);
/* rasterizer state: just scissor */
st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
cso_set_rasterizer(cso, &st->bitmap.rasterizer);
/* fragment shader state: TEX lookup program */
- pipe->bind_fs_state(pipe, stfp->driver_shader);
+ cso_set_fragment_shader_handle(cso, stfp->driver_shader);
/* vertex shader state: position + texcoord pass-through */
- pipe->bind_vs_state(pipe, st->bitmap.vs);
+ cso_set_vertex_shader_handle(cso, st->bitmap.vs);
- /* sampler / texture state */
- cso_single_sampler(cso, 0, &st->bitmap.sampler);
- cso_single_sampler_done(cso);
- pipe->set_sampler_textures(pipe, 1, &pt);
+ /* user samplers, plus our bitmap sampler */
+ {
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers);
+ uint i;
+ for (i = 0; i < st->state.num_samplers; i++) {
+ samplers[i] = &st->state.samplers[i];
+ }
+ samplers[stfp->bitmap_sampler] = &st->bitmap.sampler;
+ cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers); }
+
+ /* user textures, plus the bitmap texture */
+ {
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures);
+ memcpy(textures, st->state.sampler_texture, sizeof(textures));
+ textures[stfp->bitmap_sampler] = pt;
+ cso_set_sampler_textures(cso, num, textures);
+ }
/* viewport state: viewport matching window dims */
{
cso_restore_samplers(cso);
cso_restore_sampler_textures(cso);
cso_restore_viewport(cso);
- /* shaders don't go through cso yet */
- pipe->bind_fs_state(pipe, st->fp->driver_shader);
- pipe->bind_vs_state(pipe, st->vp->driver_shader);
+ cso_restore_fragment_shader(cso);
+ cso_restore_vertex_shader(cso);
}
static void
reset_cache(struct st_context *st)
-{
- memset(st->bitmap.cache->buffer, 0xff, sizeof(st->bitmap.cache->buffer));
- st->bitmap.cache->empty = GL_TRUE;
-
- st->bitmap.cache->xmin = 1000000;
- st->bitmap.cache->xmax = -1000000;
- st->bitmap.cache->ymin = 1000000;
- st->bitmap.cache->ymax = -1000000;
-}
-
-
-static void
-init_bitmap_cache(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
- enum pipe_format format;
+ struct bitmap_cache *cache = st->bitmap.cache;
- st->bitmap.cache = CALLOC_STRUCT(bitmap_cache);
- if (!st->bitmap.cache)
- return;
+ //memset(cache->buffer, 0xff, sizeof(cache->buffer));
+ cache->empty = GL_TRUE;
- /* find a usable texture format */
- if (screen->is_format_supported(screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE)) {
- format = PIPE_FORMAT_U_I8;
- }
- else {
- /* XXX support more formats */
- assert(0);
- }
+ cache->xmin = 1000000;
+ cache->xmax = -1000000;
+ cache->ymin = 1000000;
+ cache->ymax = -1000000;
- st->bitmap.cache->texture
- = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
- BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, 1, 0);
- if (!st->bitmap.cache->texture) {
- FREE(st->bitmap.cache);
- st->bitmap.cache = NULL;
- return;
- }
+ assert(!cache->texture);
- reset_cache(st);
+ /* allocate a new texture */
+ cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
+ st->bitmap.tex_format, 0,
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ 1, 0);
+
+ /* Map the texture surface.
+ * Subsequent glBitmap calls will write into the texture image.
+ */
+ cache->surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0);
+ cache->buffer = pipe_surface_map(cache->surf);
+
+ /* init image to all 0xff */
+ memset(cache->buffer, 0xff, BITMAP_CACHE_WIDTH * BITMAP_CACHE_HEIGHT);
}
st_flush_bitmap_cache(struct st_context *st)
{
if (!st->bitmap.cache->empty) {
- struct bitmap_cache *cache = st->bitmap.cache;
- struct pipe_context *pipe = st->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_surface *surf;
- void *dest;
+ if (st->ctx->DrawBuffer) {
+ struct bitmap_cache *cache = st->bitmap.cache;
+ struct pipe_context *pipe = st->pipe;
+
+ assert(cache->xmin <= cache->xmax);
+ /*
+ printf("flush size %d x %d at %d, %d\n",
+ cache->xmax - cache->xmin,
+ cache->ymax - cache->ymin,
+ cache->xpos, cache->ypos);
+ */
+
+ /* The texture surface has been mapped until now.
+ * So unmap and release the texture surface before drawing.
+ */
+ pipe_surface_unmap(cache->surf);
+ pipe_surface_reference(&cache->surf, NULL);
- assert(cache->xmin <= cache->xmax);
- /*
- printf("flush size %d x %d at %d, %d\n",
- cache->xmax - cache->xmin,
- cache->ymax - cache->ymin,
- cache->xpos, cache->ypos);
- */
-
- /* update the texture map image */
- surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0);
- dest = pipe_surface_map(surf);
- memcpy(dest, cache->buffer, sizeof(cache->buffer));
- pipe_surface_unmap(surf);
- pipe_surface_reference(&surf, NULL);
-
- pipe->texture_update(pipe, cache->texture, 0, 0x1);
-
- draw_bitmap_quad(st->ctx,
- cache->xpos,
- cache->ypos,
- st->ctx->Current.RasterPos[2],
- BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
- cache->texture);
+ /* XXX is this needed? */
+ pipe->texture_update(pipe, cache->texture, 0, 0x1);
+
+ draw_bitmap_quad(st->ctx,
+ cache->xpos,
+ cache->ypos,
+ st->ctx->Current.RasterPos[2],
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ cache->texture);
+ /* release/free the texture */
+ pipe_texture_reference(&cache->texture, NULL);
+ }
reset_cache(st);
}
}
const GLubyte *bitmap )
{
struct bitmap_cache *cache = st->bitmap.cache;
- int row, col;
int px = -999, py;
if (width > BITMAP_CACHE_WIDTH ||
if (y + height > cache->ymax)
cache->ymax = y + height;
- /* XXX try to combine this code with code in make_bitmap_texture() */
-#define SET_PIXEL(COL, ROW) \
- cache->buffer[py + (ROW)][px + (COL)] = 0x0;
-
- for (row = 0; row < height; row++) {
- const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
- bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
-
- if (unpack->LsbFirst) {
- /* Lsb first */
- GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
- for (col = 0; col < width; col++) {
-
- if (*src & mask) {
- SET_PIXEL(col, row);
- }
-
- if (mask == 128U) {
- src++;
- mask = 1U;
- }
- else {
- mask = mask << 1;
- }
- }
-
- /* get ready for next row */
- if (mask != 1)
- src++;
- }
- else {
- /* Msb first */
- GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
- for (col = 0; col < width; col++) {
-
- if (*src & mask) {
- SET_PIXEL(col, row);
- }
-
- if (mask == 1U) {
- src++;
- mask = 128U;
- }
- else {
- mask = mask >> 1;
- }
- }
-
- /* get ready for next row */
- if (mask != 128)
- src++;
- }
-
- } /* row */
+ unpack_bitmap(st, px, py, width, height, unpack, bitmap,
+ cache->buffer, BITMAP_CACHE_WIDTH);
return GL_TRUE; /* accumulated */
}
assert(pt->target == PIPE_TEXTURE_2D);
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
width, height, pt);
+ /* release/free the texture */
pipe_texture_reference(&pt, NULL);
}
}
st_init_bitmap(struct st_context *st)
{
struct pipe_sampler_state *sampler = &st->bitmap.sampler;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
/* init sampler state once */
memset(sampler, 0, sizeof(*sampler));
st->bitmap.rasterizer.gl_rasterization_rules = 1;
st->bitmap.rasterizer.bypass_vs = 1;
- init_bitmap_cache(st);
+ /* find a usable texture format */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE)) {
+ st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
+ }
+ else {
+ /* XXX support more formats */
+ assert(0);
+ }
+
+ /* alloc bitmap cache object */
+ st->bitmap.cache = CALLOC_STRUCT(bitmap_cache);
+
+ reset_cache(st);
}
{
struct pipe_context *pipe = st->pipe;
- if (st->bitmap.combined_prog) {
- st_delete_program(st->ctx, &st->bitmap.combined_prog->Base.Base);
- }
-
- if (st->bitmap.program) {
- st_delete_program(st->ctx, &st->bitmap.program->Base.Base);
- }
-
if (st->bitmap.vs) {
- pipe->delete_vs_state(pipe, st->bitmap.vs);
+ cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
st->bitmap.vs = NULL;
}
if (st->bitmap.vbuf) {
- pipe->winsys->buffer_destroy(pipe->winsys, st->bitmap.vbuf);
+ pipe_buffer_destroy(pipe, st->bitmap.vbuf);
st->bitmap.vbuf = NULL;
}