diff options
Diffstat (limited to 'xorg-server/glamor')
-rw-r--r-- | xorg-server/glamor/Makefile.am | 1 | ||||
-rw-r--r-- | xorg-server/glamor/glamor.c | 17 | ||||
-rw-r--r-- | xorg-server/glamor/glamor.h | 1 | ||||
-rw-r--r-- | xorg-server/glamor/glamor_gradient.c | 5 | ||||
-rw-r--r-- | xorg-server/glamor/glamor_pixmap.c | 3 | ||||
-rw-r--r-- | xorg-server/glamor/glamor_priv.h | 25 | ||||
-rw-r--r-- | xorg-server/glamor/glamor_render.c | 108 | ||||
-rw-r--r-- | xorg-server/glamor/glamor_trapezoid.c | 128 | ||||
-rw-r--r-- | xorg-server/glamor/glamor_utils.h | 2 | ||||
-rw-r--r-- | xorg-server/glamor/glamor_vbo.c | 186 |
10 files changed, 309 insertions, 167 deletions
diff --git a/xorg-server/glamor/Makefile.am b/xorg-server/glamor/Makefile.am index 77492bcaa..ffc8c23d8 100644 --- a/xorg-server/glamor/Makefile.am +++ b/xorg-server/glamor/Makefile.am @@ -34,6 +34,7 @@ libglamor_la_SOURCES = \ glamor_pixmap.c\ glamor_largepixmap.c\ glamor_picture.c\ + glamor_vbo.c \ glamor_window.c\ glamor_fbo.c\ glamor_compositerects.c\ diff --git a/xorg-server/glamor/glamor.c b/xorg-server/glamor/glamor.c index fa753bb1a..e85617927 100644 --- a/xorg-server/glamor/glamor.c +++ b/xorg-server/glamor/glamor.c @@ -319,6 +319,19 @@ glamor_init(ScreenPtr screen, unsigned int flags) gl_version = glamor_gl_get_version(); + /* We'd like to require GL_ARB_map_buffer_range or + * GL_OES_map_buffer_range, since it offers more information to + * the driver than plain old glMapBuffer() or glBufferSubData(). + * It's been supported on Mesa on the desktop since 2009 and on + * GLES2 since October 2012. It's supported on Apple's iOS + * drivers for SGX535 and A7, but apparently not on most Android + * devices (the OES extension spec wasn't released until June + * 2012). + * + * 82% of 0 A.D. players (desktop GL) submitting hardware reports + * have support for it, with most of the ones lacking it being on + * Windows with Intel 4-series (G45) graphics or older. + */ if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) { ErrorF("Require OpenGL version 1.3 or later.\n"); @@ -340,6 +353,8 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_gl_has_extension("GL_MESA_pack_invert"); glamor_priv->has_fbo_blit = glamor_gl_has_extension("GL_EXT_framebuffer_blit"); + glamor_priv->has_buffer_storage = + glamor_gl_has_extension("GL_ARB_buffer_storage"); glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); #ifdef MAX_FBO_SIZE glamor_priv->max_fbo_size = MAX_FBO_SIZE; @@ -426,6 +441,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) ps->DestroyPicture = glamor_destroy_picture; glamor_init_composite_shaders(screen); #endif + glamor_init_vbo(screen); glamor_init_pixmap_fbo(screen); glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); @@ -465,6 +481,7 @@ glamor_release_screen_priv(ScreenPtr screen) #ifdef RENDER glamor_fini_composite_shaders(screen); #endif + glamor_fini_vbo(screen); glamor_fini_pixmap_fbo(screen); glamor_fini_solid_shader(screen); glamor_fini_tile_shader(screen); diff --git a/xorg-server/glamor/glamor.h b/xorg-server/glamor/glamor.h index e12f497cb..e25dc735c 100644 --- a/xorg-server/glamor/glamor.h +++ b/xorg-server/glamor/glamor.h @@ -324,6 +324,7 @@ extern _X_EXPORT int glamor_create_gc(GCPtr gc); extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable); + /* Glamor rendering/drawing functions with XXX_nf. * nf means no fallback within glamor internal if possible. If glamor * fail to accelerate the operation, glamor will return a false, and the diff --git a/xorg-server/glamor/glamor_gradient.c b/xorg-server/glamor/glamor_gradient.c index 9f6f1b1cf..6a7b528f9 100644 --- a/xorg-server/glamor/glamor_gradient.c +++ b/xorg-server/glamor/glamor_gradient.c @@ -46,8 +46,6 @@ static const char * _glamor_create_getcolor_fs_source(ScreenPtr screen, int stops_count, int use_array) { - glamor_screen_private *glamor_priv; - char *gradient_fs = NULL; #define gradient_fs_getcolor\ @@ -174,9 +172,6 @@ _glamor_create_getcolor_fs_source(ScreenPtr screen, int stops_count, " return gradient_color;\n" "}\n"; - glamor_priv = glamor_get_screen_private(screen); - glamor_get_context(glamor_priv); - if (use_array) { XNFasprintf(&gradient_fs, gradient_fs_getcolor, stops_count, stops_count); diff --git a/xorg-server/glamor/glamor_pixmap.c b/xorg-server/glamor/glamor_pixmap.c index 77197b5d1..119e4d9d1 100644 --- a/xorg-server/glamor/glamor_pixmap.c +++ b/xorg-server/glamor/glamor_pixmap.c @@ -697,7 +697,6 @@ glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, * Upload pixmap to a specified texture. * This texture may not be the one attached to it. **/ -int in_restore = 0; static void __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, GLenum format, @@ -1529,7 +1528,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) drawable = &pixmap_priv->base.pixmap->drawable; - if (!GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)) + if (!GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv)) return TRUE; old_fbo = pixmap_priv->base.fbo; diff --git a/xorg-server/glamor/glamor_priv.h b/xorg-server/glamor/glamor_priv.h index fe4b42332..d15eabd9e 100644 --- a/xorg-server/glamor/glamor_priv.h +++ b/xorg-server/glamor/glamor_priv.h @@ -208,6 +208,7 @@ typedef struct glamor_screen_private { enum glamor_gl_flavor gl_flavor; int has_pack_invert; int has_fbo_blit; + int has_buffer_storage; int max_fbo_size; struct xorg_list @@ -220,8 +221,15 @@ typedef struct glamor_screen_private { /* vertext/elment_index buffer object for render */ GLuint vbo, ebo; + /** Next offset within the VBO that glamor_get_vbo_space() will use. */ int vbo_offset; int vbo_size; + /** + * Pointer to glamor_get_vbo_space()'s current VBO mapping. + * + * Note that this is not necessarily equal to the pointer returned + * by glamor_get_vbo_space(), so it can't be used in place of that. + */ char *vb; int vb_stride; Bool has_source_coords, has_mask_coords; @@ -702,11 +710,7 @@ void glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, glamor_composite_shader *shader, struct blendinfo *op_info); -void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts); -void glamor_emit_composite_vert(ScreenPtr screen, - const float *src_coords, - const float *mask_coords, - const float *dst_coords, int i); +void *glamor_setup_composite_vbo(ScreenPtr screen, int n_verts); /* glamor_trapezoid.c */ void glamor_trapezoids(CARD8 op, @@ -748,6 +752,17 @@ void glamor_triangles(CARD8 op, void glamor_pixmap_init(ScreenPtr screen); void glamor_pixmap_fini(ScreenPtr screen); +/* glamor_vbo.c */ + +void glamor_init_vbo(ScreenPtr screen); +void glamor_fini_vbo(ScreenPtr screen); + +void * +glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset); + +void +glamor_put_vbo_space(ScreenPtr screen); + /** * Download a pixmap's texture to cpu memory. If success, * One copy of current pixmap's texture will be put into diff --git a/xorg-server/glamor/glamor_render.c b/xorg-server/glamor/glamor_render.c index 093a2151d..086526d2e 100644 --- a/xorg-server/glamor/glamor_render.c +++ b/xorg-server/glamor/glamor_render.c @@ -403,12 +403,10 @@ glamor_init_composite_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv; unsigned short *eb; - float *vb = NULL; int eb_size; glamor_priv = glamor_get_screen_private(screen); glamor_get_context(glamor_priv); - glGenBuffers(1, &glamor_priv->vbo); glGenBuffers(1, &glamor_priv->ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); @@ -419,9 +417,6 @@ glamor_init_composite_shaders(ScreenPtr screen) eb = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); } else { - vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2); - if (vb == NULL) - FatalError("Failed to allocate vb memory.\n"); eb = malloc(eb_size); } @@ -438,14 +433,7 @@ glamor_init_composite_shaders(ScreenPtr screen) glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - glBufferData(GL_ARRAY_BUFFER, - GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * - 2, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - free(eb); - glamor_priv->vb = (char *) vb; } glamor_put_context(glamor_priv); @@ -460,7 +448,6 @@ glamor_fini_composite_shaders(ScreenPtr screen) glamor_priv = glamor_get_screen_private(screen); glamor_get_context(glamor_priv); - glDeleteBuffers(1, &glamor_priv->vbo); glDeleteBuffers(1, &glamor_priv->ebo); for (i = 0; i < SHADER_SOURCE_COUNT; i++) @@ -470,8 +457,6 @@ glamor_fini_composite_shaders(ScreenPtr screen) if (shader->prog) glDeleteProgram(shader->prog); } - if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && glamor_priv->vb) - free(glamor_priv->vb); glamor_put_context(glamor_priv); } @@ -584,7 +569,7 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { if (picture->transform - || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) + || (GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv))) repeat_type += RepeatFix; } if (repeat_type >= RepeatFix) { @@ -701,11 +686,13 @@ glamor_composite_with_copy(CARD8 op, return ret; } -void +void * glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int vert_size; + char *vbo_offset; + float *vb; glamor_priv->render_nr_verts = 0; glamor_priv->vb_stride = 2 * sizeof(float); @@ -717,78 +704,32 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) vert_size = n_verts * glamor_priv->vb_stride; glamor_get_context(glamor_priv); - glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) { - glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * - glamor_priv->vb_stride; - glamor_priv->vbo_offset = 0; - glBufferData(GL_ARRAY_BUFFER, - glamor_priv->vbo_size, NULL, GL_STREAM_DRAW); - } - - glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER, - glamor_priv->vbo_offset, - vert_size, - GL_MAP_WRITE_BIT | - GL_MAP_UNSYNCHRONIZED_BIT); - assert(glamor_priv->vb != NULL); - glamor_priv->vb -= glamor_priv->vbo_offset; - } - else - glamor_priv->vbo_offset = 0; + vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - glamor_priv->vb_stride, - (void *) ((long) - glamor_priv->vbo_offset)); + glamor_priv->vb_stride, vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); if (glamor_priv->has_source_coords) { glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) glamor_priv->vbo_offset + - 2 * sizeof(float))); + vbo_offset + 2 * sizeof(float)); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); } if (glamor_priv->has_mask_coords) { glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) glamor_priv->vbo_offset + - (glamor_priv->has_source_coords ? - 4 : 2) * sizeof(float))); + vbo_offset + (glamor_priv->has_source_coords ? + 4 : 2) * sizeof(float)); glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); } glamor_put_context(glamor_priv); -} - -void -glamor_emit_composite_vert(ScreenPtr screen, - const float *src_coords, - const float *mask_coords, - const float *dst_coords, int i) -{ - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - float *vb = (float *) (glamor_priv->vb + glamor_priv->vbo_offset); - int j = 0; - vb[j++] = dst_coords[i * 2 + 0]; - vb[j++] = dst_coords[i * 2 + 1]; - if (glamor_priv->has_source_coords) { - vb[j++] = src_coords[i * 2 + 0]; - vb[j++] = src_coords[i * 2 + 1]; - } - if (glamor_priv->has_mask_coords) { - vb[j++] = mask_coords[i * 2 + 0]; - vb[j++] = mask_coords[i * 2 + 1]; - } - - glamor_priv->render_nr_verts++; - glamor_priv->vbo_offset += glamor_priv->vb_stride; + return vb; } static void @@ -797,14 +738,6 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_get_context(glamor_priv); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - glUnmapBuffer(GL_ARRAY_BUFFER); - else { - - glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, - glamor_priv->vb, GL_DYNAMIC_DRAW); - } if (!glamor_priv->render_nr_verts) return; @@ -1250,14 +1183,12 @@ glamor_composite_with_shader(CARD8 op, GLfloat dst_xscale, dst_yscale; GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; struct shader_key key, key_ca; - float *vertices; int dest_x_off, dest_y_off; int source_x_off, source_y_off; int mask_x_off, mask_y_off; PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; float *psrc_matrix = NULL, *pmask_matrix = NULL; - int vert_stride = 4; int nrect_max; Bool ret = FALSE; glamor_composite_shader *shader = NULL, *shader_ca = NULL; @@ -1306,7 +1237,6 @@ glamor_composite_with_shader(CARD8 op, psrc_matrix = src_matrix; glamor_picture_get_matrixf(source, psrc_matrix); } - vert_stride += 4; } if (glamor_priv->has_mask_coords) { @@ -1318,18 +1248,17 @@ glamor_composite_with_shader(CARD8 op, pmask_matrix = mask_matrix; glamor_picture_get_matrixf(mask, pmask_matrix); } - vert_stride += 4; } - nrect_max = (vert_stride * nrect) > GLAMOR_COMPOSITE_VBO_VERT_CNT ? - (GLAMOR_COMPOSITE_VBO_VERT_CNT / vert_stride) : nrect; + nrect_max = MIN(nrect, GLAMOR_COMPOSITE_VBO_VERT_CNT / 4); while (nrect) { int mrect, rect_processed; int vb_stride; + float *vertices; mrect = nrect > nrect_max ? nrect_max : nrect; - glamor_setup_composite_vbo(screen, mrect * vert_stride); + vertices = glamor_setup_composite_vbo(screen, mrect * 4); rect_processed = mrect; vb_stride = glamor_priv->vb_stride / sizeof(float); while (mrect--) { @@ -1355,9 +1284,7 @@ glamor_composite_with_shader(CARD8 op, ("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n", x_dest, y_dest, x_source, y_source, x_mask, y_mask, width, height); - vertices = (float *) (glamor_priv->vb + glamor_priv->vbo_offset); - assert(glamor_priv->vbo_offset < - glamor_priv->vbo_size - glamor_priv->vb_stride); + glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale, dst_yscale, x_dest, y_dest, x_dest + width, y_dest + height, @@ -1385,11 +1312,15 @@ glamor_composite_with_shader(CARD8 op, y_mask + height, glamor_priv->yInverted, vertices, vb_stride); + vertices += 2; } glamor_priv->render_nr_verts += 4; - glamor_priv->vbo_offset += glamor_priv->vb_stride * 4; rects++; + + /* We've incremented by one of our 4 verts, now do the other 3. */ + vertices += 3 * vb_stride; } + glamor_put_vbo_space(screen); glamor_flush_composite_rects(screen); nrect -= rect_processed; if (two_pass_ca) { @@ -1402,7 +1333,6 @@ glamor_composite_with_shader(CARD8 op, } } - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); diff --git a/xorg-server/glamor/glamor_trapezoid.c b/xorg-server/glamor/glamor_trapezoid.c index 7bc925a25..0064f2a24 100644 --- a/xorg-server/glamor/glamor_trapezoid.c +++ b/xorg-server/glamor/glamor_trapezoid.c @@ -190,14 +190,44 @@ point_inside_trapezoid(int point[2], xTrapezoid *trap, xFixed cut_y) } static void +glamor_emit_composite_vert(ScreenPtr screen, + float *vb, + const float *src_coords, + const float *mask_coords, + const float *dst_coords, int i) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + int j = 0; + + vb += i * glamor_priv->vb_stride / sizeof(float); + + vb[j++] = dst_coords[i * 2 + 0]; + vb[j++] = dst_coords[i * 2 + 1]; + if (glamor_priv->has_source_coords) { + vb[j++] = src_coords[i * 2 + 0]; + vb[j++] = src_coords[i * 2 + 1]; + } + if (glamor_priv->has_mask_coords) { + vb[j++] = mask_coords[i * 2 + 0]; + vb[j++] = mask_coords[i * 2 + 1]; + } + + glamor_priv->render_nr_verts++; +} + +static void glamor_emit_composite_triangle(ScreenPtr screen, + float *vb, const float *src_coords, const float *mask_coords, const float *dst_coords) { - glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 0); - glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 1); - glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 2); + glamor_emit_composite_vert(screen, vb, + src_coords, mask_coords, dst_coords, 0); + glamor_emit_composite_vert(screen, vb, + src_coords, mask_coords, dst_coords, 1); + glamor_emit_composite_vert(screen, vb, + src_coords, mask_coords, dst_coords, 2); } static void @@ -206,14 +236,7 @@ glamor_flush_composite_triangles(ScreenPtr screen) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_get_context(glamor_priv); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - glUnmapBuffer(GL_ARRAY_BUFFER); - else { - - glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, - glamor_priv->vb, GL_DYNAMIC_DRAW); - } + glamor_put_vbo_space(screen); if (!glamor_priv->render_nr_verts) return; @@ -576,12 +599,14 @@ _glamor_clip_trapezoid_vertex(xTrapezoid *trap, BoxPtr pbox, return TRUE; } -static void +static void * glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int stride; int vert_size; + char *vbo_offset; + void *vb; glamor_priv->render_nr_verts = 0; @@ -610,66 +635,43 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts) glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM); glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM); - glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) { - glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * - glamor_priv->vb_stride; - glamor_priv->vbo_offset = 0; - glBufferData(GL_ARRAY_BUFFER, - glamor_priv->vbo_size, NULL, GL_STREAM_DRAW); - } - - glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER, - glamor_priv->vbo_offset, - vert_size, - GL_MAP_WRITE_BIT | - GL_MAP_UNSYNCHRONIZED_BIT); - - assert(glamor_priv->vb != NULL); - glamor_priv->vb -= glamor_priv->vbo_offset; - } - else { - glamor_priv->vbo_offset = 0; - } + vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); /* Set the vertex pointer. */ glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) glamor_priv->vbo_offset)); + vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); stride = 2; glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) glamor_priv->vbo_offset + - stride * sizeof(float))); + vbo_offset + stride * sizeof(float)); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); stride += 2; glVertexAttribPointer(GLAMOR_VERTEX_TOP_BOTTOM, 2, GL_FLOAT, - GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) glamor_priv->vbo_offset + - stride * sizeof(float))); + GL_FALSE, glamor_priv->vb_stride, + vbo_offset + stride * sizeof(float)); glEnableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM); stride += 2; glVertexAttribPointer(GLAMOR_VERTEX_LEFT_PARAM, 4, GL_FLOAT, - GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) glamor_priv->vbo_offset + - stride * sizeof(float))); + GL_FALSE, glamor_priv->vb_stride, + vbo_offset + stride * sizeof(float)); glEnableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM); stride += 4; glVertexAttribPointer(GLAMOR_VERTEX_RIGHT_PARAM, 4, GL_FLOAT, - GL_FALSE, glamor_priv->vb_stride, - (void *) ((long) glamor_priv->vbo_offset + - stride * sizeof(float))); + GL_FALSE, glamor_priv->vb_stride, + vbo_offset + stride * sizeof(float)); glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM); glamor_put_context(glamor_priv); + + return vb; } static Bool @@ -862,6 +864,8 @@ _glamor_trapezoids_with_shader(CARD8 op, nclip_rect = nbox; while (nclip_rect) { + float *vb; + mclip_rect = (nclip_rect * ntrap * 4) > ntriangle_per_loop ? (ntriangle_per_loop / (4 * ntrap)) : nclip_rect; @@ -879,8 +883,9 @@ _glamor_trapezoids_with_shader(CARD8 op, NTRAPS_LOOP_AGAIN: - glamor_setup_composite_vbo(screen, - mclip_rect * traps_count * 4 * vert_stride); + vb = glamor_setup_composite_vbo(screen, + (mclip_rect * traps_count * + 4 * vert_stride)); clip_processed = mclip_rect; while (mclip_rect--) { @@ -938,8 +943,10 @@ _glamor_trapezoids_with_shader(CARD8 op, source_texcoords[4], source_texcoords[5]); } - glamor_emit_composite_triangle(screen, source_texcoords, + glamor_emit_composite_triangle(screen, vb, + source_texcoords, NULL, vertices); + vb += 3 * glamor_priv->vb_stride / sizeof(float); } } @@ -970,7 +977,6 @@ _glamor_trapezoids_with_shader(CARD8 op, ret = TRUE; TRAPEZOID_RESET_GL: - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); @@ -1384,7 +1390,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, BoxRec one_trap_bound; int nrect_max; int i, j; - float *vertices; float params[4]; glamor_priv = glamor_get_screen_private(screen); @@ -1413,7 +1418,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale)); - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); /* Now draw the Trapezoid mask. */ @@ -1425,11 +1429,12 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, nrect_max = GLAMOR_COMPOSITE_VBO_VERT_CNT / (4 * GLAMOR_VERTEX_RIGHT_PARAM); for (i = 0; i < ntrap;) { + float *vertices; int mrect; int stride; mrect = (ntrap - i) > nrect_max ? nrect_max : (ntrap - i); - glamor_setup_composite_vbo_for_trapezoid(screen, 4 * mrect); + vertices = glamor_setup_composite_vbo_for_trapezoid(screen, 4 * mrect); stride = glamor_priv->vb_stride / sizeof(float); for (j = 0; j < mrect; j++) { @@ -1452,8 +1457,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, miTrapezoidBounds(1, ptrap, &one_trap_bound); - vertices = - (float *) (glamor_priv->vb + glamor_priv->vbo_offset) + 2; + vertices += 2; glamor_set_tcoords_ext((pixmap_priv->base.pixmap->drawable.width), (pixmap_priv->base.pixmap->drawable.height), (one_trap_bound.x1), (one_trap_bound.y1), @@ -1525,6 +1529,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, } params[2] = right_slope; glamor_set_const_ext(params, 4, vertices, 4, stride); + vertices += 4; DEBUGF("trap_top = %f, trap_bottom = %f, " "trap_left_x = %f, trap_left_y = %f, left_slope = %f, " @@ -1537,23 +1542,17 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, ((float) ptrap->right.p1.y) / 65536, right_slope); glamor_priv->render_nr_verts += 4; - glamor_priv->vbo_offset += glamor_priv->vb_stride * 4; + vertices += 3 * stride; } i += mrect; + glamor_put_vbo_space(screen); + /* Now rendering. */ if (!glamor_priv->render_nr_verts) continue; - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - glUnmapBuffer(GL_ARRAY_BUFFER); - else { - glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, - glamor_priv->vb, GL_DYNAMIC_DRAW); - } - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts, @@ -1566,7 +1565,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, } } - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBlendFunc(GL_ONE, GL_ZERO); glDisable(GL_BLEND); diff --git a/xorg-server/glamor/glamor_utils.h b/xorg-server/glamor/glamor_utils.h index 9374c9d4d..f9550b73c 100644 --- a/xorg-server/glamor/glamor_utils.h +++ b/xorg-server/glamor/glamor_utils.h @@ -53,7 +53,7 @@ *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.fbo->height; \ } while(0) -#define GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(priv) \ +#define GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(priv) \ (priv->base.fbo->width != priv->base.pixmap->drawable.width \ || priv->base.fbo->height != priv->base.pixmap->drawable.height) \ diff --git a/xorg-server/glamor/glamor_vbo.c b/xorg-server/glamor/glamor_vbo.c new file mode 100644 index 000000000..5e98bfe47 --- /dev/null +++ b/xorg-server/glamor/glamor_vbo.c @@ -0,0 +1,186 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * @file glamor_vbo.c + * + * Helpers for managing streamed vertex bufffers used in glamor. + */ + +#include "glamor_priv.h" + +/** Default size of the VBO, in bytes. + * + * If a single request is larger than this size, we'll resize the VBO + * and return an appropriate mapping, but we'll resize back down after + * that to avoid hogging that memory forever. We don't anticipate + * normal usage actually requiring larger VBO sizes. + */ +#define GLAMOR_VBO_SIZE (512 * 1024) + +/** + * Returns a pointer to @size bytes of VBO storage, which should be + * accessed by the GL using vbo_offset within the VBO. + */ +void * +glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + void *data; + + glamor_get_context(glamor_priv); + + glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + + if (glamor_priv->has_buffer_storage) { + if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) { + if (glamor_priv->vbo_size) + glUnmapBuffer(GL_ARRAY_BUFFER); + + if (size > glamor_priv->vbo_size) { + glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size); + + /* We aren't allowed to resize glBufferStorage() + * buffers, so we need to gen a new one. + */ + glDeleteBuffers(1, &glamor_priv->vbo); + glGenBuffers(1, &glamor_priv->vbo); + glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + + assert(glGetError() == GL_NO_ERROR); + glBufferStorage(GL_ARRAY_BUFFER, glamor_priv->vbo_size, NULL, + GL_MAP_WRITE_BIT | + GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT); + + if (glGetError() != GL_NO_ERROR) { + /* If the driver failed our coherent mapping, fall + * back to the ARB_mbr path. + */ + glamor_priv->has_buffer_storage = false; + glamor_priv->vbo_size = 0; + glamor_put_context(glamor_priv); + + return glamor_get_vbo_space(screen, size, vbo_offset); + } + } + + glamor_priv->vbo_offset = 0; + glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER, + 0, glamor_priv->vbo_size, + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT); + } + *vbo_offset = (void *)(uintptr_t)glamor_priv->vbo_offset; + data = glamor_priv->vb + glamor_priv->vbo_offset; + glamor_priv->vbo_offset += size; + } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) { + glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size); + glamor_priv->vbo_offset = 0; + glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_size, NULL, GL_STREAM_DRAW); + } + + data = glMapBufferRange(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + size, + GL_MAP_WRITE_BIT | + GL_MAP_UNSYNCHRONIZED_BIT | + GL_MAP_INVALIDATE_RANGE_BIT); + assert(data != NULL); + *vbo_offset = (char *)(uintptr_t)glamor_priv->vbo_offset; + glamor_priv->vbo_offset += size; + } else { + /* Return a pointer to the statically allocated non-VBO + * memory. We'll upload it through glBufferData() later. + */ + if (glamor_priv->vbo_size < size) { + glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size); + free(glamor_priv->vb); + glamor_priv->vb = XNFalloc(size); + } + *vbo_offset = NULL; + /* We point to the start of glamor_priv->vb every time, and + * the vbo_offset determines the size of the glBufferData(). + */ + glamor_priv->vbo_offset = size; + data = glamor_priv->vb; + } + + glamor_put_context(glamor_priv); + + return data; +} + +void +glamor_put_vbo_space(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + glamor_get_context(glamor_priv); + + if (glamor_priv->has_buffer_storage) { + /* If we're in the ARB_buffer_storage path, we have a + * persistent mapping, so we can leave it around until we + * reach the end of the buffer. + */ + } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glUnmapBuffer(GL_ARRAY_BUFFER); + } else { + glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, + glamor_priv->vb, GL_DYNAMIC_DRAW); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glamor_put_context(glamor_priv); +} + +void +glamor_init_vbo(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + glamor_get_context(glamor_priv); + + glGenBuffers(1, &glamor_priv->vbo); + + glamor_put_context(glamor_priv); +} + +void +glamor_fini_vbo(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + glamor_get_context(glamor_priv); + + glDeleteBuffers(1, &glamor_priv->vbo); + if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP) + free(glamor_priv->vb); + + glamor_put_context(glamor_priv); +} |