1
/**************************************************************************
3
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sub license, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
14
* The above copyright notice and this permission notice (including the
15
* next paragraph) shall be included in all copies or substantial portionsalloc
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
**************************************************************************/
34
#include "bufferobj.h"
35
#include "swrast/swrast.h"
37
#include "intel_screen.h"
38
#include "intel_context.h"
39
#include "intel_ioctl.h"
40
#include "intel_batchbuffer.h"
41
#include "intel_blit.h"
42
#include "intel_regions.h"
43
#include "intel_buffer_objects.h"
47
#define FILE_DEBUG_FLAG DEBUG_PIXEL
50
/* Unlike the other intel_pixel_* functions, the expectation here is
51
* that the incoming data is not in a PBO. With the XY_TEXT blit
52
* method, there's no benefit haveing it in a PBO, but we could
53
* implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
54
* PBO bitmaps. I think they are probably pretty rare though - I
55
* wonder if Xgl uses them?
57
static const GLubyte *map_pbo( GLcontext *ctx,
58
GLsizei width, GLsizei height,
59
const struct gl_pixelstore_attrib *unpack,
60
const GLubyte *bitmap )
64
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
65
GL_COLOR_INDEX, GL_BITMAP,
67
_mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
71
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
75
_mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
79
return ADD_POINTERS(buf, bitmap);
82
static GLboolean test_bit( const GLubyte *src,
85
return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0;
88
static void set_bit( GLubyte *dest,
91
dest[bit/8] |= 1 << (bit % 8);
94
static int align(int x, int align)
96
return (x + align - 1) & ~(align - 1);
99
/* Extract a rectangle's worth of data from the bitmap. Called
102
static GLuint get_bitmap_rect(GLsizei width, GLsizei height,
103
const struct gl_pixelstore_attrib *unpack,
104
const GLubyte *bitmap,
111
GLuint src_offset = (x + unpack->SkipPixels) & 0x7;
112
GLuint mask = unpack->LsbFirst ? 0 : 7;
119
if (INTEL_DEBUG & DEBUG_PIXEL)
120
_mesa_printf("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n",
121
__FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask);
134
/* Require that dest be pre-zero'd.
136
for (row = first; row != (last+incr); row += incr) {
137
const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap,
139
GL_COLOR_INDEX, GL_BITMAP,
142
for (col = 0; col < w; col++, bit++) {
143
if (test_bit(rowsrc, (col + src_offset) ^ mask)) {
144
set_bit(dest, bit ^ 7);
150
bit = (bit + row_align - 1) & ~(row_align - 1);
163
do_blit_bitmap( GLcontext *ctx,
164
GLint dstx, GLint dsty,
165
GLsizei width, GLsizei height,
166
const struct gl_pixelstore_attrib *unpack,
167
const GLubyte *bitmap )
169
struct intel_context *intel = intel_context(ctx);
170
struct intel_region *dst = intel_drawbuf_region(intel);
178
if (unpack->BufferObj->Name) {
179
bitmap = map_pbo(ctx, width, height, unpack, bitmap);
181
return GL_TRUE; /* even though this is an error, we're done */
184
UNCLAMPED_FLOAT_TO_CHAN(color.ub[0], ctx->Current.RasterColor[2]);
185
UNCLAMPED_FLOAT_TO_CHAN(color.ub[1], ctx->Current.RasterColor[1]);
186
UNCLAMPED_FLOAT_TO_CHAN(color.ub[2], ctx->Current.RasterColor[0]);
187
UNCLAMPED_FLOAT_TO_CHAN(color.ub[3], ctx->Current.RasterColor[3]);
189
/* Does zoom apply to bitmaps?
191
if (!intel_check_blit_fragment_ops(ctx) ||
192
ctx->Pixel.ZoomX != 1.0F ||
193
ctx->Pixel.ZoomY != 1.0F)
196
LOCK_HARDWARE(intel);
198
if (intel->driDrawable->numClipRects) {
199
__DRIdrawablePrivate *dPriv = intel->driDrawable;
200
drm_clip_rect_t *box = dPriv->pClipRects;
201
drm_clip_rect_t dest_rect;
202
GLint nbox = dPriv->numClipRects;
203
GLint srcx = 0, srcy = 0;
204
GLint orig_screen_x1, orig_screen_y2;
208
orig_screen_x1 = dPriv->x + dstx;
209
orig_screen_y2 = dPriv->y + (dPriv->h - dsty);
211
/* Do scissoring in GL coordinates:
213
if (ctx->Scissor.Enabled)
215
GLint x = ctx->Scissor.X;
216
GLint y = ctx->Scissor.Y;
217
GLuint w = ctx->Scissor.Width;
218
GLuint h = ctx->Scissor.Height;
220
if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height))
224
/* Convert from GL to hardware coordinates:
226
dsty = dPriv->y + (dPriv->h - dsty - height);
227
dstx = dPriv->x + dstx;
231
dest_rect.x2 = dstx + width;
232
dest_rect.y2 = dsty + height;
234
for (i = 0; i < nbox; i++) {
235
drm_clip_rect_t rect;
240
if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
243
/* Now go back to GL coordinates to figure out what subset of
244
* the bitmap we are uploading for this cliprect:
246
box_w = rect.x2 - rect.x1;
247
box_h = rect.y2 - rect.y1;
248
srcx = rect.x1 - orig_screen_x1;
249
srcy = orig_screen_y2 - rect.y2;
255
/* Then, finally, chop it all into chunks that can be
256
* digested by hardware:
258
for (py = 0; py < box_h; py += DY) {
259
for (px = 0; px < box_w; px += DX) {
260
int h = MIN2(DY, box_h - py);
261
int w = MIN2(DX, box_w - px);
262
GLuint sz = align(align(w,8) * h, 64)/8;
264
assert(sz <= sizeof(stipple));
265
memset(stipple, 0, sz);
267
/* May need to adjust this when padding has been introduced in
270
if (get_bitmap_rect(width, height, unpack,
272
srcx + px, srcy + py, w, h,
280
intelEmitImmediateColorExpandBlit( intel,
295
intel->need_flush = GL_TRUE;
297
intel_batchbuffer_flush(intel->batch);
299
UNLOCK_HARDWARE(intel);
302
if (unpack->BufferObj->Name) {
303
/* done with PBO so unmap it now */
304
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
315
/* There are a large number of possible ways to implement bitmap on
316
* this hardware, most of them have some sort of drawback. Here are a
317
* few that spring to mind:
320
* - XY_MONO_SRC_BLT_CMD
321
* - use XY_SETUP_CLIP_BLT for cliprect clipping.
323
* - XY_TEXT_IMMEDIATE_BLT
324
* - blit per cliprect, subject to maximum immediate data size.
326
* - per pixel or run of pixels
328
* - good for sparse bitmaps
332
* - Translate bitmap to an alpha texture and render as a quad
333
* - Chop bitmap up into 32x32 squares and render w/polygon stipple.
336
intelBitmap(GLcontext * ctx,
338
GLsizei width, GLsizei height,
339
const struct gl_pixelstore_attrib *unpack,
340
const GLubyte * pixels)
342
if (do_blit_bitmap(ctx, x, y, width, height,
346
if (INTEL_DEBUG & DEBUG_PIXEL)
347
_mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
349
_swrast_Bitmap(ctx, x, y, width, height, unpack, pixels);