GLfloat color[4];
+ /** Bitmap's Z position */
+ GLfloat zpos;
+
struct pipe_texture *texture;
struct pipe_transfer *trans;
};
+/** Epsilon for Z comparisons */
+#define Z_EPSILON 1e-06
/**
/**
* Copy user-provide bitmap bits into texture buffer, expanding
* bits into texels.
- * "On" bits will set texels to 0xff.
+ * "On" bits will set texels to 0x0.
* "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.
const GLubyte *bitmap,
ubyte *destBuffer, uint destStride)
{
- GLint row, col;
-
-#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);
-
- 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 */
+ destBuffer += py * destStride + px;
-#undef SET_PIXEL
+ _mesa_expand_bitmap(width, height, unpack, bitmap,
+ destBuffer, destStride, 0x0);
}
struct pipe_texture *pt;
/* PBO source... */
- bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap);
+ bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
if (!bitmap) {
return NULL;
}
0, width, height, 1,
PIPE_TEXTURE_USAGE_SAMPLER);
if (!pt) {
- _mesa_unmap_bitmap_pbo(ctx, unpack);
+ _mesa_unmap_pbo_source(ctx, unpack);
return NULL;
}
unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
dest, transfer->stride);
- _mesa_unmap_bitmap_pbo(ctx, unpack);
+ _mesa_unmap_pbo_source(ctx, unpack);
/* Release transfer */
screen->transfer_unmap(screen, transfer);
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);
- const GLuint max_slots = 4096 / sizeof(st->bitmap.vertices);
+
+ /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
+ * no_flush) updates to buffers where we know there is no conflict
+ * with previous data. Currently using max_slots > 1 will cause
+ * synchronous rendering if the driver flushes its command buffers
+ * between one bitmap and the next. Our flush hook below isn't
+ * sufficient to catch this as the driver doesn't tell us when it
+ * flushes its own command buffers. Until this gets fixed, pay the
+ * price of allocating a new buffer for each bitmap cache-flush to
+ * avoid synchronous rendering.
+ */
+ const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
GLuint i;
if (st->bitmap.vbuf_slot >= max_slots) {
}
/* draw textured quad */
- offset = setup_bitmap_vertex_data(st, x, y, width, height,
- ctx->Current.RasterPos[2],
- color);
+ offset = setup_bitmap_vertex_data(st, x, y, width, height, z, color);
util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
PIPE_PRIM_TRIANGLE_FAN,
struct pipe_screen *screen = pipe->screen;
struct bitmap_cache *cache = st->bitmap.cache;
- //memset(cache->buffer, 0xff, sizeof(cache->buffer));
+ /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/
cache->empty = GL_TRUE;
cache->xmin = 1000000;
cache->ymin = 1000000;
cache->ymax = -1000000;
- if (cache->trans)
+ if (cache->trans) {
screen->tex_transfer_destroy(cache->trans);
+ cache->trans = NULL;
+ }
assert(!cache->texture);
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
1, PIPE_TEXTURE_USAGE_SAMPLER);
+}
+
+static void
+create_cache_trans(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (cache->trans)
+ return;
+
/* Map the texture transfer.
* Subsequent glBitmap calls will write into the texture image.
*/
/* The texture transfer has been mapped until now.
* So unmap and release the texture transfer before drawing.
*/
- screen->transfer_unmap(screen, cache->trans);
- cache->buffer = NULL;
+ if (cache->trans) {
+ screen->transfer_unmap(screen, cache->trans);
+ cache->buffer = NULL;
- screen->tex_transfer_destroy(cache->trans);
- cache->trans = NULL;
+ screen->tex_transfer_destroy(cache->trans);
+ cache->trans = NULL;
+ }
draw_bitmap_quad(st->ctx,
cache->xpos,
cache->ypos,
- st->ctx->Current.RasterPos[2],
+ cache->zpos,
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
cache->texture,
cache->color);
{
struct bitmap_cache *cache = st->bitmap.cache;
int px = -999, py;
+ const GLfloat z = st->ctx->Current.RasterPos[2];
if (width > BITMAP_CACHE_WIDTH ||
height > BITMAP_CACHE_HEIGHT)
py = y - cache->ypos;
if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
- !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color)) {
+ !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
+ ((fabs(z - cache->zpos) > Z_EPSILON))) {
/* This bitmap would extend beyond cache bounds, or the bitmap
* color is changing
* so flush and continue.
py = (BITMAP_CACHE_HEIGHT - height) / 2;
cache->xpos = x;
cache->ypos = y - py;
+ cache->zpos = z;
cache->empty = GL_FALSE;
COPY_4FV(cache->color, st->ctx->Current.RasterColor);
}
if (y + height > cache->ymax)
cache->ymax = y + height;
+ /* create the transfer if needed */
+ create_cache_trans(st);
+
unpack_bitmap(st, px, py, width, height, unpack, bitmap,
cache->buffer, BITMAP_CACHE_WIDTH);
struct pipe_screen *screen = pipe->screen;
struct bitmap_cache *cache = st->bitmap.cache;
- screen->transfer_unmap(screen, cache->trans);
- screen->tex_transfer_destroy(cache->trans);
+
if (st->bitmap.vs) {
cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
st->bitmap.vbuf = NULL;
}
- if (st->bitmap.cache) {
+ if (cache) {
+ if (cache->trans) {
+ screen->transfer_unmap(screen, cache->trans);
+ screen->tex_transfer_destroy(cache->trans);
+ }
pipe_texture_reference(&st->bitmap.cache->texture, NULL);
_mesa_free(st->bitmap.cache);
st->bitmap.cache = NULL;