#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_tile.h"
#include "util/u_draw_quad.h"
#include "util/u_simple_shaders.h"
#include "shader/prog_instruction.h"
+/**
+ * glBitmaps are drawn as textured quads. The user's bitmap pattern
+ * is stored in a texture image. An alpha8 texture format is used.
+ * The fragment shader samples a bit (texel) from the texture, then
+ * discards the fragment if the bit is off.
+ *
+ * Note that we actually store the inverse image of the bitmap to
+ * simplify the fragment program. An "on" bit gets stored as texel=0x0
+ * and an "off" bit is stored as texel=0xff. Then we kill the
+ * fragment if the negated texel value is less than zero.
+ */
+
+
/**
* The bitmap cache attempts to accumulate multiple glBitmap calls in a
* buffer which is then rendered en mass upon a flush, state change, etc.
GLint xpos, ypos;
/** Bounds of region used in window coords */
GLint xmin, ymin, xmax, ymax;
+
+ GLfloat color[4];
+
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;
if (!p)
return NULL;
- p->NumInstructions = 5;
+ p->NumInstructions = 3;
p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
if (!p->Instructions) {
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++;
- /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */
- p->Instructions[ic].Opcode = OPCODE_SWZ;
- p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
- p->Instructions[ic].DstReg.Index = 0;
- p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- p->Instructions[ic].SrcReg[0].Index = 0;
- p->Instructions[ic].SrcReg[0].Swizzle
- = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE );
- ic++;
-
- /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */
- p->Instructions[ic].Opcode = OPCODE_SUB;
- p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
- p->Instructions[ic].DstReg.Index = 0;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- p->Instructions[ic].SrcReg[0].Index = 0;
- p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW;
- p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY;
- p->Instructions[ic].SrcReg[1].Index = 0;
- p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */
- ic++;
-
- /* KIL if tmp0 < 0 */
+ /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
p->Instructions[ic].Opcode = OPCODE_KIL;
p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
p->Instructions[ic].SrcReg[0].Index = 0;
+ p->Instructions[ic].SrcReg[0].NegateBase = NEGATE_XYZW;
ic++;
/* END; */
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;
- }
-
- surface = screen->get_tex_surface(screen, pt, 0, 0, 0);
+ GLint row, col;
- /* 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) ? 255 : 0;
- 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) ? 255 : 0;
- 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,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (!pt) {
+ _mesa_unmap_bitmap_pbo(ctx, unpack);
+ return NULL;
+ }
+
+ surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* map texture surface */
+ dest = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ /* Put image into texture surface */
+ memset(dest, 0xff, height * surface->stride);
+ unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
+ dest, surface->stride);
+
_mesa_unmap_bitmap_pbo(ctx, unpack);
/* Release surface */
- pipe_surface_unmap(surface);
+ screen->surface_unmap(screen, surface);
pipe_surface_reference(&surface, NULL);
- pipe->texture_update(pipe, pt, 0, 0x1);
-
- pt->format = format;
return pt;
}
{
struct pipe_context *pipe = st->pipe;
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
- const GLfloat fb_width = fb->Width;
- const GLfloat fb_height = fb->Height;
- const GLfloat x0 = x;
- 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 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;
- const GLfloat clip_y1 = y1 / fb_height * 2.0 - 1.0;
+ const GLfloat fb_width = (GLfloat)fb->Width;
+ const GLfloat fb_height = (GLfloat)fb->Height;
+ const GLfloat x0 = (GLfloat)x;
+ const GLfloat x1 = (GLfloat)(x + width);
+ const GLfloat y0 = (GLfloat)y;
+ const GLfloat y1 = (GLfloat)(y + height);
+ const GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
+ const GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
+ const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
+ const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
GLuint i;
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->screen, 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->screen, 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->screen, st->bitmap.vbuf);
}
static void
draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
GLsizei width, GLsizei height,
- struct pipe_texture *pt)
+ struct pipe_texture *pt,
+ const GLfloat *color)
{
struct st_context *st = ctx->st;
struct pipe_context *pipe = ctx->st->pipe;
* it up into chunks.
*/
maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
- assert(width <= maxSize);
- assert(height <= maxSize);
+ assert(width <= (GLsizei)maxSize);
+ assert(height <= (GLsizei)maxSize);
cso_save_rasterizer(cso);
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);
+
+ /* 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); }
- /* sampler / texture state */
- cso_single_sampler(cso, 0, &st->bitmap.sampler);
- cso_single_sampler_done(cso);
- pipe->set_sampler_textures(pipe, 1, &pt);
+ /* 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 */
{
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
- const float width = fb->Width;
- const float height = fb->Height;
+ const GLfloat width = (GLfloat)fb->Width;
+ const GLfloat height = (GLfloat)fb->Height;
struct pipe_viewport_state vp;
- vp.scale[0] = 0.5 * width;
- vp.scale[1] = height * (invert ? -0.5 : 0.5);
- vp.scale[2] = 1.0;
- vp.scale[3] = 1.0;
- vp.translate[0] = 0.5 * width;
- vp.translate[1] = 0.5 * height;
- vp.translate[2] = 0.0;
- vp.translate[3] = 0.0;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = height * (invert ? -0.5f : 0.5f);
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
cso_set_viewport(cso, &vp);
}
/* draw textured quad */
setup_bitmap_vertex_data(st, x, y, width, height,
ctx->Current.RasterPos[2],
- ctx->Current.RasterColor);
+ color);
util_draw_vertex_buffer(pipe, st->bitmap.vbuf,
PIPE_PRIM_TRIANGLE_FAN,
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, 0, sizeof(st->bitmap.cache->buffer));
- st->bitmap.cache->empty = GL_TRUE;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
- st->bitmap.cache->xmin = 1000000;
- st->bitmap.cache->xmax = -1000000;
- st->bitmap.cache->ymin = 1000000;
- st->bitmap.cache->ymax = -1000000;
-}
+ //memset(cache->buffer, 0xff, sizeof(cache->buffer));
+ cache->empty = GL_TRUE;
+ cache->xmin = 1000000;
+ cache->xmax = -1000000;
+ cache->ymin = 1000000;
+ 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;
+ if (cache->surf)
+ screen->tex_surface_release(screen, &cache->surf);
- st->bitmap.cache = CALLOC_STRUCT(bitmap_cache);
- if (!st->bitmap.cache)
- return;
+ assert(!cache->texture);
- /* 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);
- }
+ /* 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,
+ PIPE_TEXTURE_USAGE_SAMPLER);
- 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;
- }
+ /* 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,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ cache->buffer = screen->surface_map(screen, cache->surf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
- reset_cache(st);
+ /* init image to all 0xff */
+ memset(cache->buffer, 0xff, BITMAP_CACHE_WIDTH * BITMAP_CACHE_HEIGHT);
}
{
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;
- 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);
+ if (st->ctx->DrawBuffer) {
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ 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.
+ */
+ screen->surface_unmap(screen, cache->surf);
+ cache->buffer = NULL;
+
+ screen->tex_surface_release(screen, &cache->surf);
+
+ draw_bitmap_quad(st->ctx,
+ cache->xpos,
+ cache->ypos,
+ st->ctx->Current.RasterPos[2],
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ cache->texture,
+ cache->color);
+ }
+
+ /* 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 ||
px = x - cache->xpos; /* pos in buffer */
py = y - cache->ypos;
if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
- py < 0 || py + height > BITMAP_CACHE_HEIGHT) {
- /* This bitmap would extend beyond cache bounds,
+ py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
+ !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color)) {
+ /* This bitmap would extend beyond cache bounds, or the bitmap
+ * color is changing
* so flush and continue.
*/
st_flush_bitmap_cache(st);
cache->xpos = x;
cache->ypos = y - py;
cache->empty = GL_FALSE;
+ COPY_4FV(cache->color, st->ctx->Current.RasterColor);
}
assert(px != -999);
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)] = 0xff;
-
- 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 */
}
struct st_context *st = ctx->st;
struct pipe_texture *pt;
+ if (width == 0 || height == 0)
+ return;
+
st_validate_state(st);
if (!st->bitmap.vs) {
if (pt) {
assert(pt->target == PIPE_TEXTURE_2D);
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
- width, height, pt);
+ width, height, pt,
+ st->ctx->Current.RasterColor);
+ /* 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));
/* init baseline rasterizer state once */
memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
+ 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_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ 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);
}
st_destroy_bitmap(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
- 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);
- }
+ screen->surface_unmap(screen, cache->surf);
+ screen->tex_surface_release(screen, &cache->surf);
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->screen, st->bitmap.vbuf);
st->bitmap.vbuf = NULL;
}