X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fintel%2Fintel_pixel_bitmap.c;h=1db7f5594e9dd3849c242621071cce19692d748b;hb=f085147258713741895945dcb81fdb251bb6c9cc;hp=7e0d20e6810b5828a4ca6e298de802d2bed14416;hpb=0397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1;p=mesa.git diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c index 7e0d20e6810..1db7f5594e9 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c @@ -25,18 +25,29 @@ * **************************************************************************/ -#include "glheader.h" -#include "enums.h" -#include "image.h" -#include "colormac.h" -#include "mtypes.h" -#include "macros.h" -#include "bufferobj.h" +#include "main/glheader.h" +#include "main/enums.h" +#include "main/image.h" +#include "main/colormac.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "main/bufferobj.h" +#include "main/pixelstore.h" +#include "main/state.h" +#include "main/teximage.h" +#include "main/texenv.h" +#include "main/texobj.h" +#include "main/texstate.h" +#include "main/texparam.h" +#include "main/varray.h" +#include "main/attrib.h" +#include "main/enable.h" +#include "shader/arbprogram.h" +#include "glapi/dispatch.h" #include "swrast/swrast.h" #include "intel_screen.h" #include "intel_context.h" -#include "intel_ioctl.h" #include "intel_batchbuffer.h" #include "intel_blit.h" #include "intel_regions.h" @@ -87,6 +98,11 @@ static GLboolean test_bit( const GLubyte *src, return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0; } +static GLboolean test_msb_bit(const GLubyte *src, GLuint bit) +{ + return (src[bit/8] & (1<<(7 - (bit % 8)))) ? 1 : 0; +} + static void set_bit( GLubyte *dest, GLuint bit ) { @@ -150,8 +166,18 @@ static GLuint get_bitmap_rect(GLsizei width, GLsizei height, return count; } - - +/** + * Returns the low Y value of the vertical range given, flipped according to + * whether the framebuffer is or not. + */ +static inline int +y_flip(struct gl_framebuffer *fb, int y, int height) +{ + if (fb->Name != 0) + return y; + else + return fb->Height - y - height; +} /* * Render a bitmap. @@ -165,9 +191,26 @@ do_blit_bitmap( GLcontext *ctx, { struct intel_context *intel = intel_context(ctx); struct intel_region *dst = intel_drawbuf_region(intel); + struct gl_framebuffer *fb = ctx->DrawBuffer; GLfloat tmpColor[4]; GLubyte ubcolor[4]; GLuint color8888, color565; + unsigned int num_cliprects; + drm_clip_rect_t *cliprects; + int x_off, y_off; + GLsizei bitmap_width = width; + GLsizei bitmap_height = height; + + /* Update draw buffer bounds */ + _mesa_update_state(ctx); + + if (ctx->Depth.Test) { + /* The blit path produces incorrect results when depth testing is on. + * It seems the blit Z coord is always 1.0 (the far plane) so fragments + * will likely be obscured by other, closer geometry. + */ + return GL_FALSE; + } if (!dst) return GL_FALSE; @@ -192,68 +235,43 @@ do_blit_bitmap( GLcontext *ctx, color8888 = INTEL_PACKCOLOR8888(ubcolor[0], ubcolor[1], ubcolor[2], ubcolor[3]); color565 = INTEL_PACKCOLOR565(ubcolor[0], ubcolor[1], ubcolor[2]); - /* Does zoom apply to bitmaps? - */ - if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F) || - ctx->Pixel.ZoomX != 1.0F || - ctx->Pixel.ZoomY != 1.0F) + if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) return GL_FALSE; LOCK_HARDWARE(intel); - if (intel->driDrawable->numClipRects) { - __DRIdrawablePrivate *dPriv = intel->driDrawable; - drm_clip_rect_t *box = dPriv->pClipRects; - drm_clip_rect_t dest_rect; - GLint nbox = dPriv->numClipRects; - GLint srcx = 0, srcy = 0; - GLint orig_screen_x1, orig_screen_y2; + intel_get_cliprects(intel, &cliprects, &num_cliprects, &x_off, &y_off); + if (num_cliprects != 0) { GLuint i; + GLint orig_dstx = dstx; + GLint orig_dsty = dsty; - - orig_screen_x1 = dPriv->x + dstx; - orig_screen_y2 = dPriv->y + (dPriv->h - dsty); - - /* Do scissoring in GL coordinates: - */ - if (ctx->Scissor.Enabled) - { - GLint x = ctx->Scissor.X; - GLint y = ctx->Scissor.Y; - GLuint w = ctx->Scissor.Width; - GLuint h = ctx->Scissor.Height; - - if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height)) + /* Clip to buffer bounds and scissor. */ + if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, + fb->_Xmax, fb->_Ymax, + &dstx, &dsty, &width, &height)) goto out; - } - - /* Convert from GL to hardware coordinates: - */ - dsty = dPriv->y + (dPriv->h - dsty - height); - dstx = dPriv->x + dstx; - dest_rect.x1 = dstx < 0 ? 0 : dstx; - dest_rect.y1 = dsty < 0 ? 0 : dsty; - dest_rect.x2 = dstx + width < 0 ? 0 : dstx + width; - dest_rect.y2 = dsty + height < 0 ? 0 : dsty + height; + dstx = x_off + dstx; + dsty = y_off + y_flip(fb, dsty, height); - for (i = 0; i < nbox; i++) { - drm_clip_rect_t rect; - int box_w, box_h; + for (i = 0; i < num_cliprects; i++) { + int box_x, box_y, box_w, box_h; GLint px, py; GLuint stipple[32]; - if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i])) - continue; - - /* Now go back to GL coordinates to figure out what subset of - * the bitmap we are uploading for this cliprect: - */ - box_w = rect.x2 - rect.x1; - box_h = rect.y2 - rect.y1; - srcx = rect.x1 - orig_screen_x1; - srcy = orig_screen_y2 - rect.y2; + box_x = dstx; + box_y = dsty; + box_w = width; + box_h = height; + /* Clip to drawable cliprect */ + if (!_mesa_clip_to_region(cliprects[i].x1, + cliprects[i].y1, + cliprects[i].x2, + cliprects[i].y2, + &box_x, &box_y, &box_w, &box_h)) + continue; #define DY 32 #define DX 32 @@ -274,13 +292,19 @@ do_blit_bitmap( GLcontext *ctx, /* May need to adjust this when padding has been introduced in * sz above: + * + * Have to translate destination coordinates back into source + * coordinates. */ - if (get_bitmap_rect(width, height, unpack, + if (get_bitmap_rect(bitmap_width, bitmap_height, unpack, bitmap, - srcx + px, srcy + py, w, h, + -orig_dstx + (box_x + px - x_off), + -orig_dsty + y_flip(fb, + box_y + py - y_off, h), + w, h, (GLubyte *)stipple, 8, - GL_TRUE) == 0) + fb->Name == 0 ? GL_TRUE : GL_FALSE) == 0) continue; /* @@ -294,8 +318,8 @@ do_blit_bitmap( GLcontext *ctx, dst->buffer, 0, dst->tiling, - rect.x1 + px, - rect.y2 - (py + h), + box_x + px, + box_y + py, w, h, logic_op); } @@ -305,6 +329,8 @@ do_blit_bitmap( GLcontext *ctx, out: UNLOCK_HARDWARE(intel); + if (INTEL_DEBUG & DEBUG_SYNC) + intel_batchbuffer_flush(intel->batch); if (unpack->BufferObj->Name) { /* done with PBO so unmap it now */ @@ -315,9 +341,179 @@ out: return GL_TRUE; } +static GLboolean +intel_texture_bitmap(GLcontext * ctx, + GLint dst_x, GLint dst_y, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + struct intel_context *intel = intel_context(ctx); + static const char *fp = + "!!ARBfp1.0\n" + "TEMP val;\n" + "PARAM color=program.local[0];\n" + "TEX val, fragment.texcoord[0], texture[0], 2D;\n" + "ADD val, val.wwww, {-.5, -.5, -.5, -.5};\n" + "KIL val;\n" + "MOV result.color, color;\n" + "END\n"; + GLuint texname; + GLfloat vertices[4][4]; + GLfloat texcoords[4][2]; + GLint old_active_texture; + GLubyte *unpacked_bitmap; + GLubyte *a8_bitmap; + int x, y; + GLfloat dst_z; + + /* We need a fragment program for the KIL effect */ + if (!ctx->Extensions.ARB_fragment_program || + !ctx->Extensions.ARB_vertex_program) { + if (INTEL_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, + "glBitmap fallback: No fragment/vertex program support\n"); + return GL_FALSE; + } + /* We're going to mess with texturing with no regard to existing texture + * state, so if there is some set up we have to bail. + */ + if (ctx->Texture._EnabledUnits != 0) { + if (INTEL_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "glBitmap fallback: texturing enabled\n"); + return GL_FALSE; + } + /* Can't do textured DrawPixels with a fragment program, unless we were + * to generate a new program that sampled our texture and put the results + * in the fragment color before the user's program started. + */ + if (ctx->FragmentProgram.Enabled) { + if (INTEL_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "glBitmap fallback: fragment program enabled\n"); + return GL_FALSE; + } + if (ctx->VertexProgram.Enabled) { + if (INTEL_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "glBitmap fallback: vertex program enabled\n"); + return GL_FALSE; + } + + /* Check that we can load in a texture this big. */ + if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) || + height > (1 << (ctx->Const.MaxTextureLevels - 1))) { + if (INTEL_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "glBitmap fallback: bitmap too large (%dx%d)\n", + width, height); + return GL_FALSE; + } + + /* Convert the A1 bitmap to an A8 format suitable for glTexImage */ + if (unpack->BufferObj->Name) { + bitmap = map_pbo(ctx, width, height, unpack, bitmap); + if (bitmap == NULL) + return GL_TRUE; /* even though this is an error, we're done */ + } + unpacked_bitmap = _mesa_unpack_bitmap(width, height, bitmap, + unpack); + a8_bitmap = _mesa_calloc(width * height); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + if (test_msb_bit(unpacked_bitmap, ALIGN(width, 8) * y + x)) + a8_bitmap[y * width + x] = 0xff; + } + } + _mesa_free(unpacked_bitmap); + if (unpack->BufferObj->Name) { + /* done with PBO so unmap it now */ + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + unpack->BufferObj); + } + + /* Save GL state before we start setting up our drawing */ + _mesa_PushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | + GL_VIEWPORT_BIT); + _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT | + GL_CLIENT_PIXEL_STORE_BIT); + old_active_texture = ctx->Texture.CurrentUnit; + + _mesa_Disable(GL_POLYGON_STIPPLE); + + /* Upload our bitmap data to an alpha texture */ + _mesa_ActiveTextureARB(GL_TEXTURE0_ARB); + _mesa_Enable(GL_TEXTURE_2D); + _mesa_GenTextures(1, &texname); + _mesa_BindTexture(GL_TEXTURE_2D, texname); + _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + _mesa_PixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + _mesa_PixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + _mesa_PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + _mesa_PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + _mesa_PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, 1); + _mesa_TexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, a8_bitmap); + _mesa_free(a8_bitmap); + + intel_meta_set_fragment_program(intel, &intel->meta.bitmap_fp, fp); + _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, + ctx->Current.RasterColor); + intel_meta_set_passthrough_vertex_program(intel); + intel_meta_set_passthrough_transform(intel); + + /* convert rasterpos Z from [0,1] to NDC coord in [-1,1] */ + dst_z = -1.0 + 2.0 * ctx->Current.RasterPos[2]; + + vertices[0][0] = dst_x; + vertices[0][1] = dst_y; + vertices[0][2] = dst_z; + vertices[0][3] = 1.0; + vertices[1][0] = dst_x + width; + vertices[1][1] = dst_y; + vertices[1][2] = dst_z; + vertices[1][3] = 1.0; + vertices[2][0] = dst_x + width; + vertices[2][1] = dst_y + height; + vertices[2][2] = dst_z; + vertices[2][3] = 1.0; + vertices[3][0] = dst_x; + vertices[3][1] = dst_y + height; + vertices[3][2] = dst_z; + vertices[3][3] = 1.0; + + texcoords[0][0] = 0.0; + texcoords[0][1] = 0.0; + texcoords[1][0] = 1.0; + texcoords[1][1] = 0.0; + texcoords[2][0] = 1.0; + texcoords[2][1] = 1.0; + texcoords[3][0] = 0.0; + texcoords[3][1] = 1.0; + + _mesa_VertexPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &vertices); + _mesa_ClientActiveTextureARB(GL_TEXTURE0); + _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords); + _mesa_Enable(GL_VERTEX_ARRAY); + _mesa_Enable(GL_TEXTURE_COORD_ARRAY); + CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4)); + + intel_meta_restore_transform(intel); + intel_meta_restore_fragment_program(intel); + intel_meta_restore_vertex_program(intel); + + _mesa_PopClientAttrib(); + _mesa_Disable(GL_TEXTURE_2D); /* asserted that it was disabled at entry */ + _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + old_active_texture); + _mesa_PopAttrib(); + + _mesa_DeleteTextures(1, &texname); + + return GL_TRUE; +} /* There are a large number of possible ways to implement bitmap on * this hardware, most of them have some sort of drawback. Here are a @@ -350,6 +546,10 @@ intelBitmap(GLcontext * ctx, unpack, pixels)) return; + if (intel_texture_bitmap(ctx, x, y, width, height, + unpack, pixels)) + return; + if (INTEL_DEBUG & DEBUG_PIXEL) _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);