135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2014 Keith Packard 335c4bbdfSmrg * 435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its 535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that 635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright 735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and 835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or 935c4bbdfSmrg * publicity pertaining to distribution of the software without specific, 1035c4bbdfSmrg * written prior permission. The copyright holders make no representations 1135c4bbdfSmrg * about the suitability of this software for any purpose. It is provided "as 1235c4bbdfSmrg * is" without express or implied warranty. 1335c4bbdfSmrg * 1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2035c4bbdfSmrg * OF THIS SOFTWARE. 2135c4bbdfSmrg */ 2235c4bbdfSmrg 2335c4bbdfSmrg#include "glamor_priv.h" 2435c4bbdfSmrg#include "glamor_program.h" 2535c4bbdfSmrg#include "glamor_transform.h" 2635c4bbdfSmrg 2735c4bbdfSmrgstatic const glamor_facet glamor_facet_polyfillrect_130 = { 2835c4bbdfSmrg .name = "poly_fill_rect", 2935c4bbdfSmrg .version = 130, 305a7dfde8Smrg .source_name = "size", 315a7dfde8Smrg .vs_vars = "attribute vec2 primitive;\n" 325a7dfde8Smrg "attribute vec2 size;\n", 335a7dfde8Smrg .vs_exec = (" vec2 pos = size * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n" 3435c4bbdfSmrg GLAMOR_POS(gl_Position, (primitive.xy + pos))), 3535c4bbdfSmrg}; 3635c4bbdfSmrg 3735c4bbdfSmrgstatic const glamor_facet glamor_facet_polyfillrect_120 = { 3835c4bbdfSmrg .name = "poly_fill_rect", 3935c4bbdfSmrg .vs_vars = "attribute vec2 primitive;\n", 4035c4bbdfSmrg .vs_exec = (" vec2 pos = vec2(0,0);\n" 4135c4bbdfSmrg GLAMOR_POS(gl_Position, primitive.xy)), 4235c4bbdfSmrg}; 4335c4bbdfSmrg 4435c4bbdfSmrgstatic Bool 4535c4bbdfSmrgglamor_poly_fill_rect_gl(DrawablePtr drawable, 4635c4bbdfSmrg GCPtr gc, int nrect, xRectangle *prect) 4735c4bbdfSmrg{ 4835c4bbdfSmrg ScreenPtr screen = drawable->pScreen; 4935c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 5035c4bbdfSmrg PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); 5135c4bbdfSmrg glamor_pixmap_private *pixmap_priv; 5235c4bbdfSmrg glamor_program *prog; 5335c4bbdfSmrg int off_x, off_y; 5435c4bbdfSmrg GLshort *v; 5535c4bbdfSmrg char *vbo_offset; 5635c4bbdfSmrg int box_index; 571b5d61b8Smrg Bool ret = FALSE; 581b5d61b8Smrg BoxRec bounds = glamor_no_rendering_bounds(); 5935c4bbdfSmrg 6035c4bbdfSmrg pixmap_priv = glamor_get_pixmap_private(pixmap); 6135c4bbdfSmrg if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 6235c4bbdfSmrg goto bail; 6335c4bbdfSmrg 6435c4bbdfSmrg glamor_make_current(glamor_priv); 6535c4bbdfSmrg 661b5d61b8Smrg if (nrect < 100) { 671b5d61b8Smrg bounds = glamor_start_rendering_bounds(); 681b5d61b8Smrg for (int i = 0; i < nrect; i++) 691b5d61b8Smrg glamor_bounds_union_rect(&bounds, &prect[i]); 701b5d61b8Smrg } 711b5d61b8Smrg 72ed6184dfSmrg if (glamor_glsl_has_ints(glamor_priv)) { 7335c4bbdfSmrg prog = glamor_use_program_fill(pixmap, gc, 7435c4bbdfSmrg &glamor_priv->poly_fill_rect_program, 7535c4bbdfSmrg &glamor_facet_polyfillrect_130); 7635c4bbdfSmrg 7735c4bbdfSmrg if (!prog) 7835c4bbdfSmrg goto bail; 7935c4bbdfSmrg 8035c4bbdfSmrg /* Set up the vertex buffers for the points */ 8135c4bbdfSmrg 8235c4bbdfSmrg v = glamor_get_vbo_space(drawable->pScreen, nrect * sizeof (xRectangle), &vbo_offset); 8335c4bbdfSmrg 8435c4bbdfSmrg glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 8535c4bbdfSmrg glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); 865a7dfde8Smrg glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 8735c4bbdfSmrg 4 * sizeof (short), vbo_offset); 8835c4bbdfSmrg 895a7dfde8Smrg glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); 905a7dfde8Smrg glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1); 915a7dfde8Smrg glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_UNSIGNED_SHORT, GL_FALSE, 925a7dfde8Smrg 4 * sizeof (short), vbo_offset + 2 * sizeof (short)); 935a7dfde8Smrg 9435c4bbdfSmrg memcpy(v, prect, nrect * sizeof (xRectangle)); 9535c4bbdfSmrg 9635c4bbdfSmrg glamor_put_vbo_space(screen); 9735c4bbdfSmrg } else { 9835c4bbdfSmrg int n; 9935c4bbdfSmrg 10035c4bbdfSmrg prog = glamor_use_program_fill(pixmap, gc, 10135c4bbdfSmrg &glamor_priv->poly_fill_rect_program, 10235c4bbdfSmrg &glamor_facet_polyfillrect_120); 10335c4bbdfSmrg 10435c4bbdfSmrg if (!prog) 10535c4bbdfSmrg goto bail; 10635c4bbdfSmrg 10735c4bbdfSmrg /* Set up the vertex buffers for the points */ 10835c4bbdfSmrg 10935c4bbdfSmrg v = glamor_get_vbo_space(drawable->pScreen, nrect * 8 * sizeof (short), &vbo_offset); 11035c4bbdfSmrg 11135c4bbdfSmrg glEnableVertexAttribArray(GLAMOR_VERTEX_POS); 11235c4bbdfSmrg glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 11335c4bbdfSmrg 2 * sizeof (short), vbo_offset); 11435c4bbdfSmrg 11535c4bbdfSmrg for (n = 0; n < nrect; n++) { 11635c4bbdfSmrg v[0] = prect->x; v[1] = prect->y; 11735c4bbdfSmrg v[2] = prect->x; v[3] = prect->y + prect->height; 11835c4bbdfSmrg v[4] = prect->x + prect->width; v[5] = prect->y + prect->height; 11935c4bbdfSmrg v[6] = prect->x + prect->width; v[7] = prect->y; 12035c4bbdfSmrg prect++; 12135c4bbdfSmrg v += 8; 12235c4bbdfSmrg } 12335c4bbdfSmrg 12435c4bbdfSmrg glamor_put_vbo_space(screen); 12535c4bbdfSmrg } 12635c4bbdfSmrg 12735c4bbdfSmrg glEnable(GL_SCISSOR_TEST); 12835c4bbdfSmrg 12935c4bbdfSmrg glamor_pixmap_loop(pixmap_priv, box_index) { 13035c4bbdfSmrg int nbox = RegionNumRects(gc->pCompositeClip); 13135c4bbdfSmrg BoxPtr box = RegionRects(gc->pCompositeClip); 13235c4bbdfSmrg 1331b5d61b8Smrg if (!glamor_set_destination_drawable(drawable, box_index, TRUE, FALSE, 1341b5d61b8Smrg prog->matrix_uniform, &off_x, &off_y)) 1351b5d61b8Smrg goto bail; 13635c4bbdfSmrg 13735c4bbdfSmrg while (nbox--) { 1381b5d61b8Smrg BoxRec scissor = { 1391b5d61b8Smrg .x1 = max(box->x1, bounds.x1 + drawable->x), 1401b5d61b8Smrg .y1 = max(box->y1, bounds.y1 + drawable->y), 1411b5d61b8Smrg .x2 = min(box->x2, bounds.x2 + drawable->x), 1421b5d61b8Smrg .y2 = min(box->y2, bounds.y2 + drawable->y), 1431b5d61b8Smrg }; 1441b5d61b8Smrg 14535c4bbdfSmrg box++; 1461b5d61b8Smrg 1471b5d61b8Smrg if (scissor.x1 >= scissor.x2 || scissor.y1 >= scissor.y2) 1481b5d61b8Smrg continue; 1491b5d61b8Smrg 1501b5d61b8Smrg glScissor(scissor.x1 + off_x, 1511b5d61b8Smrg scissor.y1 + off_y, 1521b5d61b8Smrg scissor.x2 - scissor.x1, 1531b5d61b8Smrg scissor.y2 - scissor.y1); 154ed6184dfSmrg if (glamor_glsl_has_ints(glamor_priv)) 15535c4bbdfSmrg glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect); 15635c4bbdfSmrg else { 15735c4bbdfSmrg glamor_glDrawArrays_GL_QUADS(glamor_priv, nrect); 15835c4bbdfSmrg } 15935c4bbdfSmrg } 16035c4bbdfSmrg } 16135c4bbdfSmrg 1621b5d61b8Smrg ret = TRUE; 1631b5d61b8Smrg 1641b5d61b8Smrgbail: 16535c4bbdfSmrg glDisable(GL_SCISSOR_TEST); 166ed6184dfSmrg if (glamor_glsl_has_ints(glamor_priv)) { 1675a7dfde8Smrg glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0); 1685a7dfde8Smrg glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); 16935c4bbdfSmrg glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); 1705a7dfde8Smrg } 17135c4bbdfSmrg glDisableVertexAttribArray(GLAMOR_VERTEX_POS); 17235c4bbdfSmrg 1731b5d61b8Smrg return ret; 17435c4bbdfSmrg} 17535c4bbdfSmrg 17635c4bbdfSmrgstatic void 17735c4bbdfSmrgglamor_poly_fill_rect_bail(DrawablePtr drawable, 17835c4bbdfSmrg GCPtr gc, int nrect, xRectangle *prect) 17935c4bbdfSmrg{ 18035c4bbdfSmrg glamor_fallback("to %p (%c)\n", drawable, 18135c4bbdfSmrg glamor_get_drawable_location(drawable)); 18235c4bbdfSmrg if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && 18335c4bbdfSmrg glamor_prepare_access_gc(gc)) { 18435c4bbdfSmrg fbPolyFillRect(drawable, gc, nrect, prect); 18535c4bbdfSmrg } 18635c4bbdfSmrg glamor_finish_access_gc(gc); 18735c4bbdfSmrg glamor_finish_access(drawable); 18835c4bbdfSmrg} 18935c4bbdfSmrg 19035c4bbdfSmrgvoid 19135c4bbdfSmrgglamor_poly_fill_rect(DrawablePtr drawable, 19235c4bbdfSmrg GCPtr gc, int nrect, xRectangle *prect) 19335c4bbdfSmrg{ 19435c4bbdfSmrg if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect)) 19535c4bbdfSmrg return; 19635c4bbdfSmrg glamor_poly_fill_rect_bail(drawable, gc, nrect, prect); 19735c4bbdfSmrg} 198