X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fintel_pixel_bitmap.c;h=3a99bd8968bcafba055fcd253b0bc6da4860e611;hb=8e3696137f2cb7b4f5a3824f26186ecbb06f9282;hp=79c1fee9c07f013c9010cf6a7b1e798aa2a83abc;hpb=584b84256b07e106cd7295495355eb21226465d7;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c b/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c index 79c1fee9c07..3a99bd8968b 100644 --- a/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c +++ b/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c @@ -1,47 +1,52 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. +/* + * Copyright 2006 VMware, Inc. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to + * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portionsalloc * of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "glheader.h" -#include "enums.h" -#include "image.h" -#include "colormac.h" -#include "mtypes.h" -#include "macros.h" -#include "bufferobj.h" + */ + +#include "main/blend.h" +#include "main/enums.h" +#include "main/image.h" +#include "main/colormac.h" +#include "main/condrender.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "main/pbo.h" +#include "main/bufferobj.h" +#include "main/state.h" +#include "main/texobj.h" +#include "main/context.h" +#include "main/fbobject.h" #include "swrast/swrast.h" +#include "drivers/common/meta.h" +#include "brw_context.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" -#include "intel_buffer_objects.h" - +#include "intel_fbo.h" +#include "intel_image.h" +#include "intel_buffers.h" +#include "intel_pixel.h" #define FILE_DEBUG_FLAG DEBUG_PIXEL @@ -54,7 +59,7 @@ * PBO bitmaps. I think they are probably pretty rare though - I * wonder if Xgl uses them? */ -static const GLubyte *map_pbo( GLcontext *ctx, +static const GLubyte *map_pbo( struct gl_context *ctx, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) @@ -63,14 +68,15 @@ static const GLubyte *map_pbo( GLcontext *ctx, if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, GL_COLOR_INDEX, GL_BITMAP, - (GLvoid *) bitmap)) { + INT_MAX, (const GLvoid *) bitmap)) { _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)"); return NULL; } - buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, - GL_READ_ONLY_ARB, - unpack->BufferObj); + buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, + GL_MAP_READ_BIT, + unpack->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); return NULL; @@ -79,34 +85,27 @@ static const GLubyte *map_pbo( GLcontext *ctx, return ADD_POINTERS(buf, bitmap); } -static GLboolean test_bit( const GLubyte *src, - GLuint bit ) +static bool test_bit( const GLubyte *src, GLuint bit ) { return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0; } -static void set_bit( GLubyte *dest, - GLuint bit ) +static void set_bit( GLubyte *dest, GLuint bit ) { dest[bit/8] |= 1 << (bit % 8); } -static int align(int x, int align) -{ - return (x + align - 1) & ~(align - 1); -} - /* Extract a rectangle's worth of data from the bitmap. Called - * per-cliprect. + * per chunk of HW-sized bitmap. */ static GLuint get_bitmap_rect(GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap, - GLuint x, GLuint y, + GLuint x, GLuint y, GLuint w, GLuint h, GLubyte *dest, GLuint row_align, - GLboolean invert) + bool invert) { GLuint src_offset = (x + unpack->SkipPixels) & 0x7; GLuint mask = unpack->LsbFirst ? 0 : 7; @@ -116,9 +115,8 @@ static GLuint get_bitmap_rect(GLsizei width, GLsizei height, GLint incr; GLuint count = 0; - if (INTEL_DEBUG & DEBUG_PIXEL) - _mesa_printf("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n", - __FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask); + DBG("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n", + __func__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask); if (invert) { first = h-1; @@ -134,9 +132,9 @@ static GLuint get_bitmap_rect(GLsizei width, GLsizei height, /* Require that dest be pre-zero'd. */ for (row = first; row != (last+incr); row += incr) { - const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap, - width, height, - GL_COLOR_INDEX, GL_BITMAP, + const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap, + width, height, + GL_COLOR_INDEX, GL_BITMAP, y + row, x); for (col = 0; col < w; col++, bit++) { @@ -147,194 +145,193 @@ static GLuint get_bitmap_rect(GLsizei width, GLsizei height, } if (row_align) - bit = (bit + row_align - 1) & ~(row_align - 1); + bit = ALIGN(bit, row_align); } 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->FlipY) + return fb->Height - y - height; + else + return y; +} /* * Render a bitmap. */ -static GLboolean -do_blit_bitmap( GLcontext *ctx, +static bool +do_blit_bitmap( struct gl_context *ctx, GLint dstx, GLint dsty, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { - struct intel_context *intel = intel_context(ctx); - struct intel_region *dst = intel_drawbuf_region(intel); + struct brw_context *brw = brw_context(ctx); + struct gl_framebuffer *fb = ctx->DrawBuffer; + struct intel_renderbuffer *irb; GLfloat tmpColor[4]; + GLubyte ubcolor[4]; + GLuint color; + GLsizei bitmap_width = width; + GLsizei bitmap_height = height; + GLint px, py; + GLuint stipple[32]; + GLint orig_dstx = dstx; + GLint orig_dsty = dsty; + + /* 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 false; + } - union { - GLuint ui; - GLubyte ub[4]; - } color; + intel_prepare_render(brw); - if (!dst) - return GL_FALSE; + if (fb->_NumColorDrawBuffers != 1) { + perf_debug("accelerated glBitmap() only supports rendering to a " + "single color buffer\n"); + return false; + } + + irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); - if (unpack->BufferObj->Name) { + if (unpack->BufferObj) { bitmap = map_pbo(ctx, width, height, unpack, bitmap); if (bitmap == NULL) - return GL_TRUE; /* even though this is an error, we're done */ + return true; /* even though this is an error, we're done */ } COPY_4V(tmpColor, ctx->Current.RasterColor); - if (NEED_SECONDARY_COLOR(ctx)) { + if (_mesa_need_secondary_color(ctx)) { ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor); } - UNCLAMPED_FLOAT_TO_CHAN(color.ub[0], tmpColor[2]); - UNCLAMPED_FLOAT_TO_CHAN(color.ub[1], tmpColor[1]); - UNCLAMPED_FLOAT_TO_CHAN(color.ub[2], tmpColor[0]); - UNCLAMPED_FLOAT_TO_CHAN(color.ub[3], tmpColor[3]); - - /* Does zoom apply to bitmaps? - */ - if (!intel_check_blit_fragment_ops(ctx) || - ctx->Pixel.ZoomX != 1.0F || - ctx->Pixel.ZoomY != 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; - GLuint i; - - - 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)) - 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; + UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]); + UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]); + UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]); + UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]); + + switch (_mesa_get_render_format(ctx, intel_rb_format(irb))) { + case MESA_FORMAT_B8G8R8A8_UNORM: + case MESA_FORMAT_B8G8R8X8_UNORM: + color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]); + break; + case MESA_FORMAT_B5G6R5_UNORM: + color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]); + break; + default: + perf_debug("Unsupported format %s in accelerated glBitmap()\n", + _mesa_get_format_name(irb->mt->format)); + return false; + } - for (i = 0; i < nbox; i++) { - drm_clip_rect_t rect; - int box_w, box_h; - GLint px, py; - GLuint stipple[32]; + if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) + return false; - 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; + /* 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; + dsty = y_flip(fb, dsty, height); #define DY 32 #define DX 32 - /* Then, finally, chop it all into chunks that can be - * digested by hardware: + /* The blitter has no idea about fast color clears, so we need to resolve + * the miptree before we do anything. + */ + intel_miptree_access_raw(brw, irb->mt, irb->mt_level, irb->mt_layer, true); + + /* Chop it all into chunks that can be digested by hardware: */ + for (py = 0; py < height; py += DY) { + for (px = 0; px < width; px += DX) { + int h = MIN2(DY, height - py); + int w = MIN2(DX, width - px); + GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8; + const enum gl_logicop_mode logic_op = ctx->Color.ColorLogicOpEnabled ? + ctx->Color._LogicOp : COLOR_LOGICOP_COPY; + + assert(sz <= sizeof(stipple)); + memset(stipple, 0, sz); + + /* May need to adjust this when padding has been introduced in + * sz above: + * + * Have to translate destination coordinates back into source + * coordinates. */ - for (py = 0; py < box_h; py += DY) { - for (px = 0; px < box_w; px += DX) { - int h = MIN2(DY, box_h - py); - int w = MIN2(DX, box_w - px); - GLuint sz = align(align(w,8) * h, 64)/8; - GLenum logic_op = ctx->Color.ColorLogicOpEnabled ? - ctx->Color.LogicOp : GL_COPY; - - assert(sz <= sizeof(stipple)); - memset(stipple, 0, sz); - - /* May need to adjust this when padding has been introduced in - * sz above: - */ - if (get_bitmap_rect(width, height, unpack, - bitmap, - srcx + px, srcy + py, w, h, - (GLubyte *)stipple, - 8, - GL_TRUE) == 0) - continue; - - /* - */ - intelEmitImmediateColorExpandBlit( intel, - dst->cpp, - (GLubyte *)stipple, - sz, - color.ui, - dst->pitch, - dst->buffer, - 0, - dst->tiled, - rect.x1 + px, - rect.y2 - (py + h), - w, h, - logic_op); - } - } + int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack, + bitmap, + -orig_dstx + (dstx + px), + -orig_dsty + y_flip(fb, dsty + py, h), + w, h, + (GLubyte *)stipple, + 8, + fb->FlipY); + if (count == 0) + continue; + + if (!intelEmitImmediateColorExpandBlit(brw, + irb->mt->cpp, + (GLubyte *)stipple, + sz, + color, + irb->mt->surf.row_pitch_B, + irb->mt->bo, + irb->mt->offset, + irb->mt->surf.tiling, + dstx + px, + dsty + py, + w, h, + logic_op)) { + return false; + } + + if (ctx->Query.CurrentOcclusionObject) + ctx->Query.CurrentOcclusionObject->Result += count; } - intel->need_flush = GL_TRUE; - out: - intel_batchbuffer_flush(intel->batch); } - UNLOCK_HARDWARE(intel); +out: + if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) + intel_batchbuffer_flush(brw); - if (unpack->BufferObj->Name) { + if (unpack->BufferObj) { /* done with PBO so unmap it now */ - ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, - unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } - return GL_TRUE; + return 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 * few that spring to mind: - * + * * Blit: * - XY_MONO_SRC_BLT_CMD * - use XY_SETUP_CLIP_BLT for cliprect clipping. * - XY_TEXT_BLT * - XY_TEXT_IMMEDIATE_BLT * - blit per cliprect, subject to maximum immediate data size. - * - XY_COLOR_BLT + * - XY_COLOR_BLT * - per pixel or run of pixels * - XY_PIXEL_BLT * - good for sparse bitmaps @@ -345,18 +342,20 @@ do_blit_bitmap( GLcontext *ctx, * - Chop bitmap up into 32x32 squares and render w/polygon stipple. */ void -intelBitmap(GLcontext * ctx, +intelBitmap(struct gl_context * ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte * pixels) { - if (do_blit_bitmap(ctx, x, y, width, height, - unpack, pixels)) + struct brw_context *brw = brw_context(ctx); + + if (!_mesa_check_conditional_render(ctx)) return; - if (INTEL_DEBUG & DEBUG_PIXEL) - _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); + if (brw->screen->devinfo.gen < 6 && + do_blit_bitmap(ctx, x, y, width, height, unpack, pixels)) + return; - _swrast_Bitmap(ctx, x, y, width, height, unpack, pixels); + _mesa_meta_Bitmap(ctx, x, y, width, height, unpack, pixels); }