glamor_fill.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright © 2008 Intel Corporation
  3. * Copyright © 1998 Keith Packard
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and its
  6. * documentation for any purpose is hereby granted without fee, provided that
  7. * the above copyright notice appear in all copies and that both that
  8. * copyright notice and this permission notice appear in supporting
  9. * documentation, and that the name of Keith Packard not be used in
  10. * advertising or publicity pertaining to distribution of the software without
  11. * specific, written prior permission. Keith Packard makes no
  12. * representations about the suitability of this software for any purpose. It
  13. * is provided "as is" without express or implied warranty.
  14. *
  15. * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  17. * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  19. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  20. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. * PERFORMANCE OF THIS SOFTWARE.
  22. *
  23. * Authors:
  24. * Eric Anholt <eric@anholt.net>
  25. * Zhigang Gong <zhigang.gong@linux.intel.com>
  26. */
  27. #include "glamor_priv.h"
  28. /** @file glamor_fill.c
  29. *
  30. * GC fill implementation, based loosely on fb_fill.c
  31. */
  32. /**
  33. * Fills the given rectangle of a drawable with the GC's fill style.
  34. */
  35. Bool
  36. glamor_fill(DrawablePtr drawable,
  37. GCPtr gc, int x, int y, int width, int height, Bool fallback)
  38. {
  39. PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable);
  40. int off_x, off_y;
  41. PixmapPtr sub_pixmap = NULL;
  42. glamor_access_t sub_pixmap_access;
  43. DrawablePtr saved_drawable = NULL;
  44. int saved_x = x, saved_y = y;
  45. glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y);
  46. switch (gc->fillStyle) {
  47. case FillSolid:
  48. if (!glamor_solid(dst_pixmap,
  49. x + off_x,
  50. y + off_y,
  51. width, height, gc->alu, gc->planemask, gc->fgPixel))
  52. goto fail;
  53. break;
  54. case FillStippled:
  55. case FillOpaqueStippled:
  56. if (!glamor_stipple(dst_pixmap,
  57. gc->stipple,
  58. x + off_x,
  59. y + off_y,
  60. width,
  61. height,
  62. gc->alu,
  63. gc->planemask,
  64. gc->fgPixel,
  65. gc->bgPixel, gc->patOrg.x, gc->patOrg.y))
  66. goto fail;
  67. break;
  68. case FillTiled:
  69. if (!glamor_tile(dst_pixmap,
  70. gc->tile.pixmap,
  71. x + off_x,
  72. y + off_y,
  73. width,
  74. height,
  75. gc->alu,
  76. gc->planemask,
  77. x - drawable->x - gc->patOrg.x,
  78. y - drawable->y - gc->patOrg.y))
  79. goto fail;
  80. break;
  81. }
  82. return TRUE;
  83. fail:
  84. if (!fallback) {
  85. if (glamor_ddx_fallback_check_pixmap(&dst_pixmap->drawable)
  86. && glamor_ddx_fallback_check_gc(gc))
  87. return FALSE;
  88. }
  89. /* Is it possible to set the access as WO? */
  90. sub_pixmap_access = GLAMOR_ACCESS_RW;
  91. sub_pixmap = glamor_get_sub_pixmap(dst_pixmap, x + off_x,
  92. y + off_y, width, height,
  93. sub_pixmap_access);
  94. if (sub_pixmap != NULL) {
  95. if (gc->fillStyle != FillSolid) {
  96. gc->patOrg.x += (drawable->x - x);
  97. gc->patOrg.y += (drawable->y - y);
  98. }
  99. saved_drawable = drawable;
  100. drawable = &sub_pixmap->drawable;
  101. saved_x = x;
  102. saved_y = y;
  103. x = 0;
  104. y = 0;
  105. }
  106. if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
  107. glamor_prepare_access_gc(gc)) {
  108. fbFill(drawable, gc, x, y, width, height);
  109. }
  110. glamor_finish_access_gc(gc);
  111. glamor_finish_access(drawable);
  112. if (sub_pixmap != NULL) {
  113. if (gc->fillStyle != FillSolid) {
  114. gc->patOrg.x -= (saved_drawable->x - saved_x);
  115. gc->patOrg.y -= (saved_drawable->y - saved_y);
  116. }
  117. x = saved_x;
  118. y = saved_y;
  119. glamor_put_sub_pixmap(sub_pixmap, dst_pixmap,
  120. x + off_x, y + off_y,
  121. width, height, sub_pixmap_access);
  122. }
  123. return TRUE;
  124. }
  125. void
  126. glamor_init_solid_shader(ScreenPtr screen)
  127. {
  128. glamor_screen_private *glamor_priv;
  129. const char *solid_vs =
  130. "attribute vec4 v_position;"
  131. "void main()\n"
  132. "{\n"
  133. " gl_Position = v_position;\n"
  134. "}\n";
  135. const char *solid_fs =
  136. GLAMOR_DEFAULT_PRECISION
  137. "uniform vec4 color;\n"
  138. "void main()\n"
  139. "{\n"
  140. " gl_FragColor = color;\n"
  141. "}\n";
  142. GLint fs_prog, vs_prog;
  143. glamor_priv = glamor_get_screen_private(screen);
  144. glamor_make_current(glamor_priv);
  145. glamor_priv->solid_prog = glCreateProgram();
  146. vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs);
  147. fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs);
  148. glAttachShader(glamor_priv->solid_prog, vs_prog);
  149. glAttachShader(glamor_priv->solid_prog, fs_prog);
  150. glBindAttribLocation(glamor_priv->solid_prog,
  151. GLAMOR_VERTEX_POS, "v_position");
  152. glamor_link_glsl_prog(screen, glamor_priv->solid_prog, "solid");
  153. glamor_priv->solid_color_uniform_location =
  154. glGetUniformLocation(glamor_priv->solid_prog, "color");
  155. }
  156. void
  157. glamor_fini_solid_shader(ScreenPtr screen)
  158. {
  159. glamor_screen_private *glamor_priv;
  160. glamor_priv = glamor_get_screen_private(screen);
  161. glamor_make_current(glamor_priv);
  162. glDeleteProgram(glamor_priv->solid_prog);
  163. }
  164. static void
  165. _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
  166. {
  167. ScreenPtr screen = pixmap->drawable.pScreen;
  168. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  169. glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
  170. GLfloat xscale, yscale;
  171. float stack_vertices[32];
  172. float *vertices = stack_vertices;
  173. int valid_nbox = ARRAY_SIZE(stack_vertices) / (4 * 2);
  174. glamor_set_destination_pixmap_priv_nc(pixmap_priv);
  175. glamor_make_current(glamor_priv);
  176. glUseProgram(glamor_priv->solid_prog);
  177. glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
  178. pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
  179. if (nbox > valid_nbox) {
  180. int allocated_nbox;
  181. float *new_vertices;
  182. if (nbox > GLAMOR_COMPOSITE_VBO_VERT_CNT / 6)
  183. allocated_nbox = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6;
  184. else
  185. allocated_nbox = nbox;
  186. new_vertices = malloc(allocated_nbox * 4 * 2 * sizeof(float));
  187. if (new_vertices) {
  188. vertices = new_vertices;
  189. valid_nbox = allocated_nbox;
  190. }
  191. }
  192. glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
  193. GL_FALSE, 2 * sizeof(float), vertices);
  194. glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
  195. while (nbox) {
  196. int box_cnt, i;
  197. float *next_box;
  198. next_box = vertices;
  199. box_cnt = nbox > valid_nbox ? valid_nbox : nbox;
  200. for (i = 0; i < box_cnt; i++) {
  201. glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
  202. box[i].x1, box[i].y1,
  203. box[i].x2, box[i].y2,
  204. glamor_priv->yInverted,
  205. next_box);
  206. next_box += 4 * 2;
  207. }
  208. if (box_cnt == 1)
  209. glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
  210. else {
  211. if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
  212. glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6,
  213. GL_UNSIGNED_SHORT, NULL);
  214. } else {
  215. glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT,
  216. NULL);
  217. }
  218. }
  219. nbox -= box_cnt;
  220. box += box_cnt;
  221. }
  222. if (vertices != stack_vertices)
  223. free(vertices);
  224. glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
  225. glamor_priv->state = RENDER_STATE;
  226. glamor_priv->render_idle_cnt = 0;
  227. }
  228. /**
  229. * Fills the given rectangles of pixmap with an X pixel value.
  230. *
  231. * This is a helper used by other code after clipping and translation
  232. * of coordinates to a glamor backing pixmap.
  233. */
  234. Bool
  235. glamor_solid_boxes(PixmapPtr pixmap,
  236. BoxPtr box, int nbox, unsigned long fg_pixel)
  237. {
  238. glamor_pixmap_private *pixmap_priv;
  239. GLfloat color[4];
  240. pixmap_priv = glamor_get_pixmap_private(pixmap);
  241. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  242. return FALSE;
  243. glamor_get_rgba_from_pixel(fg_pixel,
  244. &color[0],
  245. &color[1],
  246. &color[2], &color[3], format_for_pixmap(pixmap));
  247. if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
  248. RegionRec region;
  249. int n_region;
  250. glamor_pixmap_clipped_regions *clipped_regions;
  251. int i;
  252. RegionInitBoxes(&region, box, nbox);
  253. clipped_regions =
  254. glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0,
  255. 0, 0);
  256. for (i = 0; i < n_region; i++) {
  257. BoxPtr inner_box;
  258. int inner_nbox;
  259. SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
  260. inner_box = RegionRects(clipped_regions[i].region);
  261. inner_nbox = RegionNumRects(clipped_regions[i].region);
  262. _glamor_solid_boxes(pixmap, inner_box, inner_nbox, color);
  263. RegionDestroy(clipped_regions[i].region);
  264. }
  265. free(clipped_regions);
  266. RegionUninit(&region);
  267. }
  268. else
  269. _glamor_solid_boxes(pixmap, box, nbox, color);
  270. return TRUE;
  271. }
  272. /**
  273. * Fills a rectangle of a pixmap with an X pixel value.
  274. *
  275. * This is a helper used by other glamor code mostly for clearing of
  276. * buffers to 0.
  277. */
  278. Bool
  279. glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
  280. unsigned char alu, unsigned long planemask, unsigned long fg_pixel)
  281. {
  282. ScreenPtr screen = pixmap->drawable.pScreen;
  283. glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  284. glamor_pixmap_private *pixmap_priv;
  285. BoxRec box;
  286. pixmap_priv = glamor_get_pixmap_private(pixmap);
  287. if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
  288. return FALSE;
  289. if (!glamor_set_planemask(pixmap, planemask)) {
  290. glamor_fallback("Failedto set planemask in glamor_solid.\n");
  291. return FALSE;
  292. }
  293. glamor_make_current(glamor_priv);
  294. if (!glamor_set_alu(screen, alu)) {
  295. if (alu == GXclear)
  296. fg_pixel = 0;
  297. else {
  298. glamor_fallback("unsupported alu %x\n", alu);
  299. return FALSE;
  300. }
  301. }
  302. box.x1 = x;
  303. box.y1 = y;
  304. box.x2 = x + width;
  305. box.y2 = y + height;
  306. glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
  307. glamor_set_alu(screen, GXcopy);
  308. return TRUE;
  309. }