glamor_spans.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * Copyright © 2014 Keith Packard
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * the above copyright notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting documentation, and
  8. * that the name of the copyright holders not be used in advertising or
  9. * publicity pertaining to distribution of the software without specific,
  10. * written prior permission. The copyright holders make no representations
  11. * about the suitability of this software for any purpose. It is provided "as
  12. * is" without express or implied warranty.
  13. *
  14. * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20. * OF THIS SOFTWARE.
  21. */
  22. #include "glamor_priv.h"
  23. #include "glamor_transform.h"
  24. #include "glamor_transfer.h"
  25. glamor_program fill_spans_progs[4];
  26. static const glamor_facet glamor_facet_fillspans_130 = {
  27. .name = "fill_spans",
  28. .version = 130,
  29. .vs_vars = "attribute vec3 primitive;\n",
  30. .vs_exec = (" vec2 pos = vec2(primitive.z,1) * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
  31. GLAMOR_POS(gl_Position, (primitive.xy + pos))),
  32. };
  33. static const glamor_facet glamor_facet_fillspans_120 = {
  34. .name = "fill_spans",
  35. .vs_vars = "attribute vec2 primitive;\n",
  36. .vs_exec = (" vec2 pos = vec2(0,0);\n"
  37. GLAMOR_POS(gl_Position, primitive.xy)),
  38. };
  39. static Bool
  40. glamor_fill_spans_gl(DrawablePtr drawable,
  41. GCPtr gc,
  42. int n, DDXPointPtr points, int *widths, int sorted)
  43. {
  44. ScreenPtr screen = drawable->pScreen;
  45. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  46. PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  47. glamor_pixmap_private *pixmap_priv;
  48. glamor_program *prog;
  49. int off_x, off_y;
  50. GLshort *v;
  51. char *vbo_offset;
  52. int c;
  53. int box_x, box_y;
  54. pixmap_priv = glamor_get_pixmap_private(pixmap);
  55. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  56. goto bail;
  57. glamor_make_current(glamor_priv);
  58. if (glamor_priv->glsl_version >= 130) {
  59. prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
  60. &glamor_facet_fillspans_130);
  61. if (!prog)
  62. goto bail_ctx;
  63. /* Set up the vertex buffers for the points */
  64. v = glamor_get_vbo_space(drawable->pScreen, n * (4 * sizeof (GLshort)), &vbo_offset);
  65. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  66. glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
  67. glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
  68. 4 * sizeof (GLshort), vbo_offset);
  69. for (c = 0; c < n; c++) {
  70. v[0] = points->x;
  71. v[1] = points->y;
  72. v[2] = *widths++;
  73. points++;
  74. v += 4;
  75. }
  76. glamor_put_vbo_space(screen);
  77. } else {
  78. prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
  79. &glamor_facet_fillspans_120);
  80. if (!prog)
  81. goto bail_ctx;
  82. /* Set up the vertex buffers for the points */
  83. v = glamor_get_vbo_space(drawable->pScreen, n * 8 * sizeof (short), &vbo_offset);
  84. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  85. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
  86. 2 * sizeof (short), vbo_offset);
  87. for (c = 0; c < n; c++) {
  88. v[0] = points->x; v[1] = points->y;
  89. v[2] = points->x; v[3] = points->y + 1;
  90. v[4] = points->x + *widths; v[5] = points->y + 1;
  91. v[6] = points->x + *widths; v[7] = points->y;
  92. widths++;
  93. points++;
  94. v += 8;
  95. }
  96. glamor_put_vbo_space(screen);
  97. }
  98. glEnable(GL_SCISSOR_TEST);
  99. glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
  100. int nbox = RegionNumRects(gc->pCompositeClip);
  101. BoxPtr box = RegionRects(gc->pCompositeClip);
  102. glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, FALSE, prog->matrix_uniform, &off_x, &off_y);
  103. while (nbox--) {
  104. glScissor(box->x1 + off_x,
  105. box->y1 + off_y,
  106. box->x2 - box->x1,
  107. box->y2 - box->y1);
  108. box++;
  109. if (glamor_priv->glsl_version >= 130)
  110. glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n);
  111. else {
  112. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
  113. glDrawArrays(GL_QUADS, 0, 4 * n);
  114. } else {
  115. int i;
  116. for (i = 0; i < n; i++) {
  117. glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
  118. }
  119. }
  120. }
  121. }
  122. }
  123. glDisable(GL_SCISSOR_TEST);
  124. glDisable(GL_COLOR_LOGIC_OP);
  125. if (glamor_priv->glsl_version >= 130)
  126. glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
  127. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  128. return TRUE;
  129. bail_ctx:
  130. glDisable(GL_COLOR_LOGIC_OP);
  131. bail:
  132. return FALSE;
  133. }
  134. static void
  135. glamor_fill_spans_bail(DrawablePtr drawable,
  136. GCPtr gc,
  137. int n, DDXPointPtr points, int *widths, int sorted)
  138. {
  139. if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
  140. glamor_prepare_access_gc(gc)) {
  141. fbFillSpans(drawable, gc, n, points, widths, sorted);
  142. }
  143. glamor_finish_access_gc(gc);
  144. glamor_finish_access(drawable);
  145. }
  146. void
  147. glamor_fill_spans(DrawablePtr drawable,
  148. GCPtr gc,
  149. int n, DDXPointPtr points, int *widths, int sorted)
  150. {
  151. if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted))
  152. return;
  153. glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted);
  154. }
  155. Bool
  156. glamor_fill_spans_nf(DrawablePtr drawable,
  157. GCPtr gc,
  158. int n, DDXPointPtr points, int *widths, int sorted)
  159. {
  160. if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted))
  161. return TRUE;
  162. if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
  163. return FALSE;
  164. glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted);
  165. return TRUE;
  166. }
  167. static Bool
  168. glamor_get_spans_gl(DrawablePtr drawable, int wmax,
  169. DDXPointPtr points, int *widths, int count, char *dst)
  170. {
  171. ScreenPtr screen = drawable->pScreen;
  172. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  173. PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  174. glamor_pixmap_private *pixmap_priv;
  175. int box_x, box_y;
  176. int n;
  177. char *d;
  178. GLenum type;
  179. GLenum format;
  180. int off_x, off_y;
  181. pixmap_priv = glamor_get_pixmap_private(pixmap);
  182. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  183. goto bail;
  184. glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
  185. glamor_format_for_pixmap(pixmap, &format, &type);
  186. glamor_make_current(glamor_priv);
  187. glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
  188. BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y);
  189. glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y);
  190. glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fb);
  191. glPixelStorei(GL_PACK_ALIGNMENT, 4);
  192. d = dst;
  193. for (n = 0; n < count; n++) {
  194. int x1 = points[n].x + off_x;
  195. int y = points[n].y + off_y;
  196. int w = widths[n];
  197. int x2 = x1 + w;
  198. char *l;
  199. l = d;
  200. d += PixmapBytePad(w, drawable->depth);
  201. /* clip */
  202. if (x1 < box->x1) {
  203. l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3);
  204. x1 = box->x1;
  205. }
  206. if (x2 > box->x2)
  207. x2 = box->x2;
  208. if (x1 >= x2)
  209. continue;
  210. if (y < box->y1)
  211. continue;
  212. if (y >= box->y2)
  213. continue;
  214. glReadPixels(x1 - box->x1, y - box->y1, x2 - x1, 1, format, type, l);
  215. }
  216. }
  217. return TRUE;
  218. bail:
  219. return FALSE;
  220. }
  221. static void
  222. glamor_get_spans_bail(DrawablePtr drawable, int wmax,
  223. DDXPointPtr points, int *widths, int count, char *dst)
  224. {
  225. if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO))
  226. fbGetSpans(drawable, wmax, points, widths, count, dst);
  227. glamor_finish_access(drawable);
  228. }
  229. void
  230. glamor_get_spans(DrawablePtr drawable, int wmax,
  231. DDXPointPtr points, int *widths, int count, char *dst)
  232. {
  233. if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst))
  234. return;
  235. glamor_get_spans_bail(drawable, wmax, points, widths, count, dst);
  236. }
  237. Bool
  238. glamor_get_spans_nf(DrawablePtr drawable, int wmax,
  239. DDXPointPtr points, int *widths, int count, char *dst)
  240. {
  241. if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst))
  242. return TRUE;
  243. if (glamor_ddx_fallback_check_pixmap(drawable))
  244. return FALSE;
  245. glamor_get_spans_bail(drawable, wmax, points, widths, count, dst);
  246. return TRUE;
  247. }
  248. static Bool
  249. glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src,
  250. DDXPointPtr points, int *widths, int numPoints, int sorted)
  251. {
  252. ScreenPtr screen = drawable->pScreen;
  253. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  254. PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  255. glamor_pixmap_private *pixmap_priv;
  256. int box_x, box_y;
  257. int n;
  258. char *s;
  259. GLenum type;
  260. GLenum format;
  261. int off_x, off_y;
  262. pixmap_priv = glamor_get_pixmap_private(pixmap);
  263. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  264. goto bail;
  265. if (gc->alu != GXcopy)
  266. goto bail;
  267. if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask))
  268. goto bail;
  269. glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
  270. glamor_format_for_pixmap(pixmap, &format, &type);
  271. glamor_make_current(glamor_priv);
  272. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  273. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  274. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  275. glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
  276. BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y);
  277. glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y);
  278. glActiveTexture(GL_TEXTURE0);
  279. glBindTexture(GL_TEXTURE_2D, fbo->tex);
  280. s = src;
  281. for (n = 0; n < numPoints; n++) {
  282. BoxPtr clip_box = RegionRects(gc->pCompositeClip);
  283. int nclip_box = RegionNumRects(gc->pCompositeClip);
  284. int w = widths[n];
  285. int y = points[n].y;
  286. int x = points[n].x;
  287. while (nclip_box--) {
  288. int x1 = x;
  289. int x2 = x + w;
  290. int y1 = y;
  291. char *l = s;
  292. /* clip to composite clip */
  293. if (x1 < clip_box->x1) {
  294. l += (clip_box->x1 - x1) * (drawable->bitsPerPixel >> 3);
  295. x1 = clip_box->x1;
  296. }
  297. if (x2 > clip_box->x2)
  298. x2 = clip_box->x2;
  299. if (y < clip_box->y1)
  300. continue;
  301. if (y >= clip_box->y2)
  302. continue;
  303. /* adjust to pixmap coordinates */
  304. x1 += off_x;
  305. x2 += off_x;
  306. y1 += off_y;
  307. if (x1 < box->x1) {
  308. l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3);
  309. x1 = box->x1;
  310. }
  311. if (x2 > box->x2)
  312. x2 = box->x2;
  313. if (x1 >= x2)
  314. continue;
  315. if (y1 < box->y1)
  316. continue;
  317. if (y1 >= box->y2)
  318. continue;
  319. glTexSubImage2D(GL_TEXTURE_2D, 0,
  320. x1 - box->x1, y1 - box->y1, x2 - x1, 1,
  321. format, type,
  322. l);
  323. }
  324. s += PixmapBytePad(w, drawable->depth);
  325. }
  326. }
  327. return TRUE;
  328. bail:
  329. return FALSE;
  330. }
  331. static void
  332. glamor_set_spans_bail(DrawablePtr drawable, GCPtr gc, char *src,
  333. DDXPointPtr points, int *widths, int numPoints, int sorted)
  334. {
  335. if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && glamor_prepare_access_gc(gc))
  336. fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted);
  337. glamor_finish_access_gc(gc);
  338. glamor_finish_access(drawable);
  339. }
  340. void
  341. glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
  342. DDXPointPtr points, int *widths, int numPoints, int sorted)
  343. {
  344. if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted))
  345. return;
  346. glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted);
  347. }
  348. Bool
  349. glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src,
  350. DDXPointPtr points, int *widths, int numPoints, int sorted)
  351. {
  352. if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted))
  353. return TRUE;
  354. if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
  355. return FALSE;
  356. glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted);
  357. return TRUE;
  358. }