2 * Copyright © 2008 Intel Corporation
3 * Copyright © 1998 Keith Packard
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.
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.
24 * Eric Anholt <eric@anholt.net>
25 * Zhigang Gong <zhigang.gong@linux.intel.com>
28 #include "glamor_priv.h"
30 /** @file glamor_fill.c
32 * GC fill implementation, based loosely on fb_fill.c
36 * Fills the given rectangle of a drawable with the GC's fill style.
39 glamor_fill(DrawablePtr drawable,
40 GCPtr gc, int x, int y, int width, int height, Bool fallback)
42 PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable);
44 PixmapPtr sub_pixmap = NULL;
45 glamor_access_t sub_pixmap_access;
46 DrawablePtr saved_drawable = NULL;
47 int saved_x = x, saved_y = y;
49 glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y);
51 switch (gc->fillStyle) {
53 if (!glamor_solid(dst_pixmap,
56 width, height, gc->alu, gc->planemask, gc->fgPixel))
60 case FillOpaqueStippled:
61 if (!glamor_stipple(dst_pixmap,
70 gc->bgPixel, gc->patOrg.x, gc->patOrg.y))
74 if (!glamor_tile(dst_pixmap,
82 x - drawable->x - gc->patOrg.x,
83 y - drawable->y - gc->patOrg.y))
91 if (glamor_ddx_fallback_check_pixmap(&dst_pixmap->drawable)
92 && glamor_ddx_fallback_check_gc(gc))
95 /* Is it possible to set the access as WO? */
97 sub_pixmap_access = GLAMOR_ACCESS_RW;
99 sub_pixmap = glamor_get_sub_pixmap(dst_pixmap, x + off_x,
100 y + off_y, width, height,
103 if (sub_pixmap != NULL) {
104 if (gc->fillStyle != FillSolid) {
105 gc->patOrg.x += (drawable->x - x);
106 gc->patOrg.y += (drawable->y - y);
108 saved_drawable = drawable;
109 drawable = &sub_pixmap->drawable;
115 if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
116 glamor_prepare_access_gc(gc)) {
117 fbFill(drawable, gc, x, y, width, height);
119 glamor_finish_access_gc(gc);
120 glamor_finish_access(drawable);
122 if (sub_pixmap != NULL) {
123 if (gc->fillStyle != FillSolid) {
124 gc->patOrg.x -= (saved_drawable->x - saved_x);
125 gc->patOrg.y -= (saved_drawable->y - saved_y);
131 glamor_put_sub_pixmap(sub_pixmap, dst_pixmap,
132 x + off_x, y + off_y,
133 width, height, sub_pixmap_access);
140 glamor_init_solid_shader(ScreenPtr screen)
142 glamor_screen_private *glamor_priv;
143 const char *solid_vs =
144 "attribute vec4 v_position;"
147 " gl_Position = v_position;\n"
149 const char *solid_fs =
150 GLAMOR_DEFAULT_PRECISION
151 "uniform vec4 color;\n"
154 " gl_FragColor = color;\n"
156 GLint fs_prog, vs_prog;
158 glamor_priv = glamor_get_screen_private(screen);
159 glamor_make_current(glamor_priv);
160 glamor_priv->solid_prog = glCreateProgram();
161 vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs);
162 fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs);
163 glAttachShader(glamor_priv->solid_prog, vs_prog);
164 glAttachShader(glamor_priv->solid_prog, fs_prog);
166 glBindAttribLocation(glamor_priv->solid_prog,
167 GLAMOR_VERTEX_POS, "v_position");
168 glamor_link_glsl_prog(screen, glamor_priv->solid_prog, "solid");
170 glamor_priv->solid_color_uniform_location =
171 glGetUniformLocation(glamor_priv->solid_prog, "color");
175 glamor_fini_solid_shader(ScreenPtr screen)
177 glamor_screen_private *glamor_priv;
179 glamor_priv = glamor_get_screen_private(screen);
180 glamor_make_current(glamor_priv);
181 glDeleteProgram(glamor_priv->solid_prog);
185 _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
187 ScreenPtr screen = pixmap->drawable.pScreen;
188 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
189 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
190 GLfloat xscale, yscale;
191 float stack_vertices[32];
192 float *vertices = stack_vertices;
193 int valid_nbox = ARRAY_SIZE(stack_vertices) / (4 * 2);
195 glamor_set_destination_pixmap_priv_nc(pixmap_priv);
197 glamor_make_current(glamor_priv);
198 glUseProgram(glamor_priv->solid_prog);
200 glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
202 pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
204 if (nbox > valid_nbox) {
208 if (nbox > GLAMOR_COMPOSITE_VBO_VERT_CNT / 6)
209 allocated_nbox = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6;
211 allocated_nbox = nbox;
212 new_vertices = malloc(allocated_nbox * 4 * 2 * sizeof(float));
214 vertices = new_vertices;
215 valid_nbox = allocated_nbox;
219 glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
220 GL_FALSE, 2 * sizeof(float), vertices);
221 glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
228 box_cnt = nbox > valid_nbox ? valid_nbox : nbox;
229 for (i = 0; i < box_cnt; i++) {
230 glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
231 box[i].x1, box[i].y1,
232 box[i].x2, box[i].y2,
233 glamor_priv->yInverted,
238 glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
240 if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
241 glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6,
242 GL_UNSIGNED_SHORT, NULL);
244 glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT,
252 if (vertices != stack_vertices)
255 glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
256 glamor_priv->state = RENDER_STATE;
257 glamor_priv->render_idle_cnt = 0;
261 * Fills the given rectangles of pixmap with an X pixel value.
263 * This is a helper used by other code after clipping and translation
264 * of coordinates to a glamor backing pixmap.
267 glamor_solid_boxes(PixmapPtr pixmap,
268 BoxPtr box, int nbox, unsigned long fg_pixel)
270 glamor_pixmap_private *pixmap_priv;
273 pixmap_priv = glamor_get_pixmap_private(pixmap);
275 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
278 glamor_get_rgba_from_pixel(fg_pixel,
281 &color[2], &color[3], format_for_pixmap(pixmap));
283 if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
286 glamor_pixmap_clipped_regions *clipped_regions;
289 RegionInitBoxes(®ion, box, nbox);
291 glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0,
293 for (i = 0; i < n_region; i++) {
297 SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
299 inner_box = RegionRects(clipped_regions[i].region);
300 inner_nbox = RegionNumRects(clipped_regions[i].region);
301 _glamor_solid_boxes(pixmap, inner_box, inner_nbox, color);
302 RegionDestroy(clipped_regions[i].region);
304 free(clipped_regions);
305 RegionUninit(®ion);
308 _glamor_solid_boxes(pixmap, box, nbox, color);
314 * Fills a rectangle of a pixmap with an X pixel value.
316 * This is a helper used by other glamor code mostly for clearing of
320 glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
321 unsigned char alu, unsigned long planemask, unsigned long fg_pixel)
323 ScreenPtr screen = pixmap->drawable.pScreen;
324 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
325 glamor_pixmap_private *pixmap_priv;
328 pixmap_priv = glamor_get_pixmap_private(pixmap);
330 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
333 if (!glamor_set_planemask(pixmap, planemask)) {
334 glamor_fallback("Failedto set planemask in glamor_solid.\n");
338 glamor_make_current(glamor_priv);
339 if (!glamor_set_alu(screen, alu)) {
343 glamor_fallback("unsupported alu %x\n", alu);
351 glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
353 glamor_set_alu(screen, GXcopy);