Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  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:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portionsalloc
  16.  * of the Software.
  17.  *
  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.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "main/glheader.h"
  29. #include "main/enums.h"
  30. #include "main/image.h"
  31. #include "main/colormac.h"
  32. #include "main/condrender.h"
  33. #include "main/mtypes.h"
  34. #include "main/macros.h"
  35. #include "main/pbo.h"
  36. #include "main/bufferobj.h"
  37. #include "main/state.h"
  38. #include "main/texobj.h"
  39. #include "main/context.h"
  40. #include "main/fbobject.h"
  41. #include "swrast/swrast.h"
  42. #include "drivers/common/meta.h"
  43.  
  44. #include "intel_screen.h"
  45. #include "intel_context.h"
  46. #include "intel_batchbuffer.h"
  47. #include "intel_blit.h"
  48. #include "intel_fbo.h"
  49. #include "intel_regions.h"
  50. #include "intel_buffers.h"
  51. #include "intel_pixel.h"
  52. #include "intel_reg.h"
  53.  
  54.  
  55. #define FILE_DEBUG_FLAG DEBUG_PIXEL
  56.  
  57.  
  58. /* Unlike the other intel_pixel_* functions, the expectation here is
  59.  * that the incoming data is not in a PBO.  With the XY_TEXT blit
  60.  * method, there's no benefit haveing it in a PBO, but we could
  61.  * implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
  62.  * PBO bitmaps.  I think they are probably pretty rare though - I
  63.  * wonder if Xgl uses them?
  64.  */
  65. static const GLubyte *map_pbo( struct gl_context *ctx,
  66.                                GLsizei width, GLsizei height,
  67.                                const struct gl_pixelstore_attrib *unpack,
  68.                                const GLubyte *bitmap )
  69. {
  70.    GLubyte *buf;
  71.  
  72.    if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
  73.                                   GL_COLOR_INDEX, GL_BITMAP,
  74.                                   INT_MAX, (const GLvoid *) bitmap)) {
  75.       _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
  76.       return NULL;
  77.    }
  78.  
  79.    buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size,
  80.                                                 GL_MAP_READ_BIT,
  81.                                                 unpack->BufferObj);
  82.    if (!buf) {
  83.       _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
  84.       return NULL;
  85.    }
  86.  
  87.    return ADD_POINTERS(buf, bitmap);
  88. }
  89.  
  90. static bool test_bit( const GLubyte *src, GLuint bit )
  91. {
  92.    return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0;
  93. }
  94.  
  95. static void set_bit( GLubyte *dest, GLuint bit )
  96. {
  97.    dest[bit/8] |= 1 << (bit % 8);
  98. }
  99.  
  100. /* Extract a rectangle's worth of data from the bitmap.  Called
  101.  * per chunk of HW-sized bitmap.
  102.  */
  103. static GLuint get_bitmap_rect(GLsizei width, GLsizei height,
  104.                               const struct gl_pixelstore_attrib *unpack,
  105.                               const GLubyte *bitmap,
  106.                               GLuint x, GLuint y,
  107.                               GLuint w, GLuint h,
  108.                               GLubyte *dest,
  109.                               GLuint row_align,
  110.                               bool invert)
  111. {
  112.    GLuint src_offset = (x + unpack->SkipPixels) & 0x7;
  113.    GLuint mask = unpack->LsbFirst ? 0 : 7;
  114.    GLuint bit = 0;
  115.    GLint row, col;
  116.    GLint first, last;
  117.    GLint incr;
  118.    GLuint count = 0;
  119.  
  120.    DBG("%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);
  122.  
  123.    if (invert) {
  124.       first = h-1;
  125.       last = 0;
  126.       incr = -1;
  127.    }
  128.    else {
  129.       first = 0;
  130.       last = h-1;
  131.       incr = 1;
  132.    }
  133.  
  134.    /* Require that dest be pre-zero'd.
  135.     */
  136.    for (row = first; row != (last+incr); row += incr) {
  137.       const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap,
  138.                                                     width, height,
  139.                                                     GL_COLOR_INDEX, GL_BITMAP,
  140.                                                     y + row, x);
  141.  
  142.       for (col = 0; col < w; col++, bit++) {
  143.          if (test_bit(rowsrc, (col + src_offset) ^ mask)) {
  144.             set_bit(dest, bit ^ 7);
  145.             count++;
  146.          }
  147.       }
  148.  
  149.       if (row_align)
  150.          bit = ALIGN(bit, row_align);
  151.    }
  152.  
  153.    return count;
  154. }
  155.  
  156. /**
  157.  * Returns the low Y value of the vertical range given, flipped according to
  158.  * whether the framebuffer is or not.
  159.  */
  160. static INLINE int
  161. y_flip(struct gl_framebuffer *fb, int y, int height)
  162. {
  163.    if (_mesa_is_user_fbo(fb))
  164.       return y;
  165.    else
  166.       return fb->Height - y - height;
  167. }
  168.  
  169. /*
  170.  * Render a bitmap.
  171.  */
  172. static bool
  173. do_blit_bitmap( struct gl_context *ctx,
  174.                 GLint dstx, GLint dsty,
  175.                 GLsizei width, GLsizei height,
  176.                 const struct gl_pixelstore_attrib *unpack,
  177.                 const GLubyte *bitmap )
  178. {
  179.    struct intel_context *intel = intel_context(ctx);
  180.    struct gl_framebuffer *fb = ctx->DrawBuffer;
  181.    struct intel_renderbuffer *irb;
  182.    GLfloat tmpColor[4];
  183.    GLubyte ubcolor[4];
  184.    GLuint color;
  185.    GLsizei bitmap_width = width;
  186.    GLsizei bitmap_height = height;
  187.    GLint px, py;
  188.    GLuint stipple[32];
  189.    GLint orig_dstx = dstx;
  190.    GLint orig_dsty = dsty;
  191.  
  192.    /* Update draw buffer bounds */
  193.    _mesa_update_state(ctx);
  194.  
  195.    if (ctx->Depth.Test) {
  196.       /* The blit path produces incorrect results when depth testing is on.
  197.        * It seems the blit Z coord is always 1.0 (the far plane) so fragments
  198.        * will likely be obscured by other, closer geometry.
  199.        */
  200.       return false;
  201.    }
  202.  
  203.    intel_prepare_render(intel);
  204.  
  205.    if (fb->_NumColorDrawBuffers != 1) {
  206.       perf_debug("accelerated glBitmap() only supports rendering to a "
  207.                  "single color buffer\n");
  208.       return false;
  209.    }
  210.  
  211.    irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
  212.  
  213.    if (_mesa_is_bufferobj(unpack->BufferObj)) {
  214.       bitmap = map_pbo(ctx, width, height, unpack, bitmap);
  215.       if (bitmap == NULL)
  216.          return true;   /* even though this is an error, we're done */
  217.    }
  218.  
  219.    COPY_4V(tmpColor, ctx->Current.RasterColor);
  220.  
  221.    if (_mesa_need_secondary_color(ctx)) {
  222.        ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
  223.    }
  224.  
  225.    UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]);
  226.    UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]);
  227.    UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]);
  228.    UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]);
  229.  
  230.    switch (irb->mt->format) {
  231.    case MESA_FORMAT_ARGB8888:
  232.    case MESA_FORMAT_XRGB8888:
  233.       color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]);
  234.       break;
  235.    case MESA_FORMAT_RGB565:
  236.       color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]);
  237.       break;
  238.    default:
  239.       perf_debug("Unsupported format %s in accelerated glBitmap()\n",
  240.                  _mesa_get_format_name(irb->mt->format));
  241.       return false;
  242.    }
  243.  
  244.    if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
  245.       return false;
  246.  
  247.    /* Clip to buffer bounds and scissor. */
  248.    if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
  249.                              fb->_Xmax, fb->_Ymax,
  250.                              &dstx, &dsty, &width, &height))
  251.       goto out;
  252.  
  253.    dsty = y_flip(fb, dsty, height);
  254.  
  255. #define DY 32
  256. #define DX 32
  257.  
  258.    /* Chop it all into chunks that can be digested by hardware: */
  259.    for (py = 0; py < height; py += DY) {
  260.       for (px = 0; px < width; px += DX) {
  261.          int h = MIN2(DY, height - py);
  262.          int w = MIN2(DX, width - px);
  263.          GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8;
  264.          GLenum logic_op = ctx->Color.ColorLogicOpEnabled ?
  265.             ctx->Color.LogicOp : GL_COPY;
  266.  
  267.          assert(sz <= sizeof(stipple));
  268.          memset(stipple, 0, sz);
  269.  
  270.          /* May need to adjust this when padding has been introduced in
  271.           * sz above:
  272.           *
  273.           * Have to translate destination coordinates back into source
  274.           * coordinates.
  275.           */
  276.          int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack,
  277.                                      bitmap,
  278.                                      -orig_dstx + (dstx + px),
  279.                                      -orig_dsty + y_flip(fb, dsty + py, h),
  280.                                      w, h,
  281.                                      (GLubyte *)stipple,
  282.                                      8,
  283.                                      _mesa_is_winsys_fbo(fb));
  284.          if (count == 0)
  285.             continue;
  286.  
  287.          if (!intelEmitImmediateColorExpandBlit(intel,
  288.                                                 irb->mt->cpp,
  289.                                                 (GLubyte *)stipple,
  290.                                                 sz,
  291.                                                 color,
  292.                                                 irb->mt->region->pitch,
  293.                                                 irb->mt->region->bo,
  294.                                                 0,
  295.                                                 irb->mt->region->tiling,
  296.                                                 dstx + px,
  297.                                                 dsty + py,
  298.                                                 w, h,
  299.                                                 logic_op)) {
  300.             return false;
  301.          }
  302.  
  303.          if (ctx->Query.CurrentOcclusionObject)
  304.             ctx->Query.CurrentOcclusionObject->Result += count;
  305.       }
  306.    }
  307. out:
  308.  
  309.    if (unlikely(INTEL_DEBUG & DEBUG_SYNC))
  310.       intel_batchbuffer_flush(intel);
  311.  
  312.    if (_mesa_is_bufferobj(unpack->BufferObj)) {
  313.       /* done with PBO so unmap it now */
  314.       ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
  315.    }
  316.  
  317.    intel_check_front_buffer_rendering(intel);
  318.  
  319.    return true;
  320. }
  321.  
  322.  
  323. /* There are a large number of possible ways to implement bitmap on
  324.  * this hardware, most of them have some sort of drawback.  Here are a
  325.  * few that spring to mind:
  326.  *
  327.  * Blit:
  328.  *    - XY_MONO_SRC_BLT_CMD
  329.  *         - use XY_SETUP_CLIP_BLT for cliprect clipping.
  330.  *    - XY_TEXT_BLT
  331.  *    - XY_TEXT_IMMEDIATE_BLT
  332.  *         - blit per cliprect, subject to maximum immediate data size.
  333.  *    - XY_COLOR_BLT
  334.  *         - per pixel or run of pixels
  335.  *    - XY_PIXEL_BLT
  336.  *         - good for sparse bitmaps
  337.  *
  338.  * 3D engine:
  339.  *    - Point per pixel
  340.  *    - Translate bitmap to an alpha texture and render as a quad
  341.  *    - Chop bitmap up into 32x32 squares and render w/polygon stipple.
  342.  */
  343. void
  344. intelBitmap(struct gl_context * ctx,
  345.             GLint x, GLint y,
  346.             GLsizei width, GLsizei height,
  347.             const struct gl_pixelstore_attrib *unpack,
  348.             const GLubyte * pixels)
  349. {
  350.    if (!_mesa_check_conditional_render(ctx))
  351.       return;
  352.  
  353.    if (do_blit_bitmap(ctx, x, y, width, height,
  354.                           unpack, pixels))
  355.       return;
  356.  
  357.    _mesa_meta_Bitmap(ctx, x, y, width, height, unpack, pixels);
  358. }
  359.