Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

intel_pixel_bitmap.c 10KB

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