s_bitmap.c revision cdc920a0
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file swrast/s_bitmap.c
27 * \brief glBitmap rendering.
28 * \author Brian Paul
29 */
30
31#include "main/glheader.h"
32#include "main/bufferobj.h"
33#include "main/condrender.h"
34#include "main/image.h"
35#include "main/macros.h"
36
37#include "s_context.h"
38#include "s_span.h"
39
40
41
42/**
43 * Render a bitmap.
44 * Called via ctx->Driver.Bitmap()
45 * All parameter error checking will have been done before this is called.
46 */
47void
48_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
49		GLsizei width, GLsizei height,
50		const struct gl_pixelstore_attrib *unpack,
51		const GLubyte *bitmap )
52{
53   GLint row, col;
54   GLuint count = 0;
55   SWspan span;
56
57   ASSERT(ctx->RenderMode == GL_RENDER);
58
59   if (!_mesa_check_conditional_render(ctx))
60      return; /* don't draw */
61
62   bitmap = (const GLubyte *) _mesa_map_pbo_source(ctx, unpack, bitmap);
63   if (!bitmap)
64      return;
65
66   swrast_render_start(ctx);
67
68   if (SWRAST_CONTEXT(ctx)->NewState)
69      _swrast_validate_derived( ctx );
70
71   INIT_SPAN(span, GL_BITMAP);
72   span.end = width;
73   span.arrayMask = SPAN_XY;
74   _swrast_span_default_attribs(ctx, &span);
75
76   for (row = 0; row < height; row++) {
77      const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
78                 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
79
80      if (unpack->LsbFirst) {
81         /* Lsb first */
82         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
83         for (col = 0; col < width; col++) {
84            if (*src & mask) {
85               span.array->x[count] = px + col;
86               span.array->y[count] = py + row;
87               count++;
88            }
89            if (mask == 128U) {
90               src++;
91               mask = 1U;
92            }
93            else {
94               mask = mask << 1;
95            }
96         }
97
98         /* get ready for next row */
99         if (mask != 1)
100            src++;
101      }
102      else {
103         /* Msb first */
104         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
105         for (col = 0; col < width; col++) {
106            if (*src & mask) {
107               span.array->x[count] = px + col;
108               span.array->y[count] = py + row;
109               count++;
110            }
111            if (mask == 1U) {
112               src++;
113               mask = 128U;
114            }
115            else {
116               mask = mask >> 1;
117            }
118         }
119
120         /* get ready for next row */
121         if (mask != 128)
122            src++;
123      }
124
125      if (count + width >= MAX_WIDTH || row + 1 == height) {
126         /* flush the span */
127         span.end = count;
128         _swrast_write_rgba_span(ctx, &span);
129         span.end = 0;
130         count = 0;
131      }
132   }
133
134   swrast_render_finish(ctx);
135
136   _mesa_unmap_pbo_source(ctx, unpack);
137}
138
139
140#if 0
141/*
142 * XXX this is another way to implement Bitmap.  Use horizontal runs of
143 * fragments, initializing the mask array to indicate which fragments to
144 * draw or skip.
145 */
146void
147_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
148		GLsizei width, GLsizei height,
149		const struct gl_pixelstore_attrib *unpack,
150		const GLubyte *bitmap )
151{
152   SWcontext *swrast = SWRAST_CONTEXT(ctx);
153   GLint row, col;
154   SWspan span;
155
156   ASSERT(ctx->RenderMode == GL_RENDER);
157   ASSERT(bitmap);
158
159   swrast_render_start(ctx);
160
161   if (SWRAST_CONTEXT(ctx)->NewState)
162      _swrast_validate_derived( ctx );
163
164   INIT_SPAN(span, GL_BITMAP);
165   span.end = width;
166   span.arrayMask = SPAN_MASK;
167   _swrast_span_default_attribs(ctx, &span);
168
169   /*span.arrayMask |= SPAN_MASK;*/  /* we'll init span.mask[] */
170   span.x = px;
171   span.y = py;
172   /*span.end = width;*/
173
174   for (row=0; row<height; row++, span.y++) {
175      const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
176                 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
177
178      if (unpack->LsbFirst) {
179         /* Lsb first */
180         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
181         for (col=0; col<width; col++) {
182            span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
183            if (mask == 128U) {
184               src++;
185               mask = 1U;
186            }
187            else {
188               mask = mask << 1;
189            }
190         }
191
192         _swrast_write_rgba_span(ctx, &span);
193
194         /* get ready for next row */
195         if (mask != 1)
196            src++;
197      }
198      else {
199         /* Msb first */
200         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
201         for (col=0; col<width; col++) {
202            span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
203            if (mask == 1U) {
204               src++;
205               mask = 128U;
206            }
207            else {
208               mask = mask >> 1;
209            }
210         }
211
212         _swrast_write_rgba_span(ctx, &span);
213
214         /* get ready for next row */
215         if (mask != 128)
216            src++;
217      }
218   }
219
220   swrast_render_finish(ctx);
221}
222#endif
223