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 #include "main/pbo.h"
37 
38 #include "s_context.h"
39 #include "s_span.h"
40 
41 
42 
43 /**
44  * Render a bitmap.
45  * Called via ctx->Driver.Bitmap()
46  * All parameter error checking will have been done before this is called.
47  */
48 void
_swrast_Bitmap(struct gl_context * ctx,GLint px,GLint py,GLsizei width,GLsizei height,const struct gl_pixelstore_attrib * unpack,const GLubyte * bitmap)49 _swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
50 		GLsizei width, GLsizei height,
51 		const struct gl_pixelstore_attrib *unpack,
52 		const GLubyte *bitmap )
53 {
54    GLint row, col;
55    GLuint count = 0;
56    SWspan span;
57 
58    ASSERT(ctx->RenderMode == GL_RENDER);
59 
60    if (!_mesa_check_conditional_render(ctx))
61       return; /* don't draw */
62 
63    bitmap = (const GLubyte *) _mesa_map_pbo_source(ctx, unpack, bitmap);
64    if (!bitmap)
65       return;
66 
67    swrast_render_start(ctx);
68 
69    if (SWRAST_CONTEXT(ctx)->NewState)
70       _swrast_validate_derived( ctx );
71 
72    INIT_SPAN(span, GL_BITMAP);
73    span.end = width;
74    span.arrayMask = SPAN_XY;
75    _swrast_span_default_attribs(ctx, &span);
76 
77    for (row = 0; row < height; row++) {
78       const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
79                  bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
80 
81       if (unpack->LsbFirst) {
82          /* Lsb first */
83          GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
84          for (col = 0; col < width; col++) {
85             if (*src & mask) {
86                span.array->x[count] = px + col;
87                span.array->y[count] = py + row;
88                count++;
89             }
90             if (mask == 128U) {
91                src++;
92                mask = 1U;
93             }
94             else {
95                mask = mask << 1;
96             }
97          }
98 
99          /* get ready for next row */
100          if (mask != 1)
101             src++;
102       }
103       else {
104          /* Msb first */
105          GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
106          for (col = 0; col < width; col++) {
107             if (*src & mask) {
108                span.array->x[count] = px + col;
109                span.array->y[count] = py + row;
110                count++;
111             }
112             if (mask == 1U) {
113                src++;
114                mask = 128U;
115             }
116             else {
117                mask = mask >> 1;
118             }
119          }
120 
121          /* get ready for next row */
122          if (mask != 128)
123             src++;
124       }
125 
126       if (count + width >= SWRAST_MAX_WIDTH || row + 1 == height) {
127          /* flush the span */
128          span.end = count;
129          _swrast_write_rgba_span(ctx, &span);
130          span.end = 0;
131          count = 0;
132       }
133    }
134 
135    swrast_render_finish(ctx);
136 
137    _mesa_unmap_pbo_source(ctx, unpack);
138 }
139 
140 
141 #if 0
142 /*
143  * XXX this is another way to implement Bitmap.  Use horizontal runs of
144  * fragments, initializing the mask array to indicate which fragments to
145  * draw or skip.
146  */
147 void
148 _swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
149 		GLsizei width, GLsizei height,
150 		const struct gl_pixelstore_attrib *unpack,
151 		const GLubyte *bitmap )
152 {
153    SWcontext *swrast = SWRAST_CONTEXT(ctx);
154    GLint row, col;
155    SWspan span;
156 
157    ASSERT(ctx->RenderMode == GL_RENDER);
158    ASSERT(bitmap);
159 
160    swrast_render_start(ctx);
161 
162    if (SWRAST_CONTEXT(ctx)->NewState)
163       _swrast_validate_derived( ctx );
164 
165    INIT_SPAN(span, GL_BITMAP);
166    span.end = width;
167    span.arrayMask = SPAN_MASK;
168    _swrast_span_default_attribs(ctx, &span);
169 
170    /*span.arrayMask |= SPAN_MASK;*/  /* we'll init span.mask[] */
171    span.x = px;
172    span.y = py;
173    /*span.end = width;*/
174 
175    for (row=0; row<height; row++, span.y++) {
176       const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
177                  bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
178 
179       if (unpack->LsbFirst) {
180          /* Lsb first */
181          GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
182          for (col=0; col<width; col++) {
183             span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
184             if (mask == 128U) {
185                src++;
186                mask = 1U;
187             }
188             else {
189                mask = mask << 1;
190             }
191          }
192 
193          _swrast_write_rgba_span(ctx, &span);
194 
195          /* get ready for next row */
196          if (mask != 1)
197             src++;
198       }
199       else {
200          /* Msb first */
201          GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
202          for (col=0; col<width; col++) {
203             span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
204             if (mask == 1U) {
205                src++;
206                mask = 128U;
207             }
208             else {
209                mask = mask >> 1;
210             }
211          }
212 
213          _swrast_write_rgba_span(ctx, &span);
214 
215          /* get ready for next row */
216          if (mask != 128)
217             src++;
218       }
219    }
220 
221    swrast_render_finish(ctx);
222 }
223 #endif
224