17ec681f3Smrg/************************************************************************** 27ec681f3Smrg * 37ec681f3Smrg * Copyright 2009, VMware, Inc. 47ec681f3Smrg * All Rights Reserved. 57ec681f3Smrg * 67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77ec681f3Smrg * copy of this software and associated documentation files (the 87ec681f3Smrg * "Software"), to deal in the Software without restriction, including 97ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish, 107ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to 117ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to 127ec681f3Smrg * the following conditions: 137ec681f3Smrg * 147ec681f3Smrg * The above copyright notice and this permission notice (including the 157ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions 167ec681f3Smrg * of the Software. 177ec681f3Smrg * 187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 197ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 207ec681f3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 217ec681f3Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 227ec681f3Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 237ec681f3Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 247ec681f3Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 257ec681f3Smrg * 267ec681f3Smrg **************************************************************************/ 277ec681f3Smrg/* 287ec681f3Smrg * Author: Keith Whitwell <keithw@vmware.com> 297ec681f3Smrg * Author: Jakob Bornecrantz <wallbraker@gmail.com> 307ec681f3Smrg */ 317ec681f3Smrg 327ec681f3Smrg#include "dri_screen.h" 337ec681f3Smrg#include "dri_context.h" 347ec681f3Smrg#include "dri_drawable.h" 357ec681f3Smrg 367ec681f3Smrg#include "pipe/p_screen.h" 377ec681f3Smrg#include "util/format/u_format.h" 387ec681f3Smrg#include "util/u_memory.h" 397ec681f3Smrg#include "util/u_inlines.h" 407ec681f3Smrg 417ec681f3Smrgstatic uint32_t drifb_ID = 0; 427ec681f3Smrg 437ec681f3Smrgstatic bool 447ec681f3Smrgdri_st_framebuffer_validate(struct st_context_iface *stctx, 457ec681f3Smrg struct st_framebuffer_iface *stfbi, 467ec681f3Smrg const enum st_attachment_type *statts, 477ec681f3Smrg unsigned count, 487ec681f3Smrg struct pipe_resource **out) 497ec681f3Smrg{ 507ec681f3Smrg struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; 517ec681f3Smrg struct dri_drawable *drawable = 527ec681f3Smrg (struct dri_drawable *) stfbi->st_manager_private; 537ec681f3Smrg struct dri_screen *screen = dri_screen(drawable->sPriv); 547ec681f3Smrg unsigned statt_mask, new_mask; 557ec681f3Smrg bool new_stamp; 567ec681f3Smrg int i; 577ec681f3Smrg unsigned int lastStamp; 587ec681f3Smrg struct pipe_resource **textures = 597ec681f3Smrg drawable->stvis.samples > 1 ? drawable->msaa_textures 607ec681f3Smrg : drawable->textures; 617ec681f3Smrg 627ec681f3Smrg statt_mask = 0x0; 637ec681f3Smrg for (i = 0; i < count; i++) 647ec681f3Smrg statt_mask |= (1 << statts[i]); 657ec681f3Smrg 667ec681f3Smrg /* record newly allocated textures */ 677ec681f3Smrg new_mask = (statt_mask & ~drawable->texture_mask); 687ec681f3Smrg 697ec681f3Smrg /* 707ec681f3Smrg * dPriv->dri2.stamp is the server stamp. dPriv->lastStamp is the 717ec681f3Smrg * client stamp. It has the value of the server stamp when last 727ec681f3Smrg * checked. 737ec681f3Smrg */ 747ec681f3Smrg do { 757ec681f3Smrg lastStamp = drawable->dPriv->lastStamp; 767ec681f3Smrg new_stamp = (drawable->texture_stamp != lastStamp); 777ec681f3Smrg 787ec681f3Smrg if (new_stamp || new_mask || screen->broken_invalidate) { 797ec681f3Smrg if (new_stamp && drawable->update_drawable_info) 807ec681f3Smrg drawable->update_drawable_info(drawable); 817ec681f3Smrg 827ec681f3Smrg drawable->allocate_textures(ctx, drawable, statts, count); 837ec681f3Smrg 847ec681f3Smrg /* add existing textures */ 857ec681f3Smrg for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 867ec681f3Smrg if (textures[i]) 877ec681f3Smrg statt_mask |= (1 << i); 887ec681f3Smrg } 897ec681f3Smrg 907ec681f3Smrg drawable->texture_stamp = lastStamp; 917ec681f3Smrg drawable->texture_mask = statt_mask; 927ec681f3Smrg } 937ec681f3Smrg } while (lastStamp != drawable->dPriv->lastStamp); 947ec681f3Smrg 957ec681f3Smrg /* Flush the pending set_damage_region request. */ 967ec681f3Smrg struct pipe_screen *pscreen = screen->base.screen; 977ec681f3Smrg 987ec681f3Smrg if (new_mask & (1 << ST_ATTACHMENT_BACK_LEFT) && 997ec681f3Smrg pscreen->set_damage_region) { 1007ec681f3Smrg struct pipe_resource *resource = textures[ST_ATTACHMENT_BACK_LEFT]; 1017ec681f3Smrg 1027ec681f3Smrg pscreen->set_damage_region(pscreen, resource, 1037ec681f3Smrg drawable->num_damage_rects, 1047ec681f3Smrg drawable->damage_rects); 1057ec681f3Smrg } 1067ec681f3Smrg 1077ec681f3Smrg if (!out) 1087ec681f3Smrg return true; 1097ec681f3Smrg 1107ec681f3Smrg /* Set the window-system buffers for the gallium frontend. */ 1117ec681f3Smrg for (i = 0; i < count; i++) 1127ec681f3Smrg pipe_resource_reference(&out[i], textures[statts[i]]); 1137ec681f3Smrg 1147ec681f3Smrg return true; 1157ec681f3Smrg} 1167ec681f3Smrg 1177ec681f3Smrgstatic bool 1187ec681f3Smrgdri_st_framebuffer_flush_front(struct st_context_iface *stctx, 1197ec681f3Smrg struct st_framebuffer_iface *stfbi, 1207ec681f3Smrg enum st_attachment_type statt) 1217ec681f3Smrg{ 1227ec681f3Smrg struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; 1237ec681f3Smrg struct dri_drawable *drawable = 1247ec681f3Smrg (struct dri_drawable *) stfbi->st_manager_private; 1257ec681f3Smrg 1267ec681f3Smrg /* XXX remove this and just set the correct one on the framebuffer */ 1277ec681f3Smrg return drawable->flush_frontbuffer(ctx, drawable, statt); 1287ec681f3Smrg} 1297ec681f3Smrg 1307ec681f3Smrg/** 1317ec681f3Smrg * The gallium frontend framebuffer interface flush_swapbuffers callback 1327ec681f3Smrg */ 1337ec681f3Smrgstatic bool 1347ec681f3Smrgdri_st_framebuffer_flush_swapbuffers(struct st_context_iface *stctx, 1357ec681f3Smrg struct st_framebuffer_iface *stfbi) 1367ec681f3Smrg{ 1377ec681f3Smrg struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; 1387ec681f3Smrg struct dri_drawable *drawable = 1397ec681f3Smrg (struct dri_drawable *) stfbi->st_manager_private; 1407ec681f3Smrg 1417ec681f3Smrg if (drawable->flush_swapbuffers) 1427ec681f3Smrg drawable->flush_swapbuffers(ctx, drawable); 1437ec681f3Smrg 1447ec681f3Smrg return true; 1457ec681f3Smrg} 1467ec681f3Smrg 1477ec681f3Smrg/** 1487ec681f3Smrg * This is called when we need to set up GL rendering to a new X window. 1497ec681f3Smrg */ 1507ec681f3Smrgbool 1517ec681f3Smrgdri_create_buffer(__DRIscreen * sPriv, 1527ec681f3Smrg __DRIdrawable * dPriv, 1537ec681f3Smrg const struct gl_config * visual, bool isPixmap) 1547ec681f3Smrg{ 1557ec681f3Smrg struct dri_screen *screen = sPriv->driverPrivate; 1567ec681f3Smrg struct dri_drawable *drawable = NULL; 1577ec681f3Smrg 1587ec681f3Smrg if (isPixmap) 1597ec681f3Smrg goto fail; /* not implemented */ 1607ec681f3Smrg 1617ec681f3Smrg drawable = CALLOC_STRUCT(dri_drawable); 1627ec681f3Smrg if (drawable == NULL) 1637ec681f3Smrg goto fail; 1647ec681f3Smrg 1657ec681f3Smrg dri_fill_st_visual(&drawable->stvis, screen, visual); 1667ec681f3Smrg 1677ec681f3Smrg /* setup the st_framebuffer_iface */ 1687ec681f3Smrg drawable->base.visual = &drawable->stvis; 1697ec681f3Smrg drawable->base.flush_front = dri_st_framebuffer_flush_front; 1707ec681f3Smrg drawable->base.validate = dri_st_framebuffer_validate; 1717ec681f3Smrg drawable->base.flush_swapbuffers = dri_st_framebuffer_flush_swapbuffers; 1727ec681f3Smrg drawable->base.st_manager_private = (void *) drawable; 1737ec681f3Smrg 1747ec681f3Smrg drawable->screen = screen; 1757ec681f3Smrg drawable->sPriv = sPriv; 1767ec681f3Smrg drawable->dPriv = dPriv; 1777ec681f3Smrg 1787ec681f3Smrg dPriv->driverPrivate = (void *)drawable; 1797ec681f3Smrg p_atomic_set(&drawable->base.stamp, 1); 1807ec681f3Smrg drawable->base.ID = p_atomic_inc_return(&drifb_ID); 1817ec681f3Smrg drawable->base.state_manager = &screen->base; 1827ec681f3Smrg 1837ec681f3Smrg return true; 1847ec681f3Smrgfail: 1857ec681f3Smrg FREE(drawable); 1867ec681f3Smrg return false; 1877ec681f3Smrg} 1887ec681f3Smrg 1897ec681f3Smrgvoid 1907ec681f3Smrgdri_destroy_buffer(__DRIdrawable * dPriv) 1917ec681f3Smrg{ 1927ec681f3Smrg struct dri_drawable *drawable = dri_drawable(dPriv); 1937ec681f3Smrg struct dri_screen *screen = drawable->screen; 1947ec681f3Smrg struct st_api *stapi = screen->st_api; 1957ec681f3Smrg int i; 1967ec681f3Smrg 1977ec681f3Smrg for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 1987ec681f3Smrg pipe_resource_reference(&drawable->textures[i], NULL); 1997ec681f3Smrg for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 2007ec681f3Smrg pipe_resource_reference(&drawable->msaa_textures[i], NULL); 2017ec681f3Smrg 2027ec681f3Smrg screen->base.screen->fence_reference(screen->base.screen, 2037ec681f3Smrg &drawable->throttle_fence, NULL); 2047ec681f3Smrg 2057ec681f3Smrg /* Notify the st manager that this drawable is no longer valid */ 2067ec681f3Smrg stapi->destroy_drawable(stapi, &drawable->base); 2077ec681f3Smrg 2087ec681f3Smrg FREE(drawable->damage_rects); 2097ec681f3Smrg FREE(drawable); 2107ec681f3Smrg} 2117ec681f3Smrg 2127ec681f3Smrg/** 2137ec681f3Smrg * Validate the texture at an attachment. Allocate the texture if it does not 2147ec681f3Smrg * exist. Used by the TFP extension. 2157ec681f3Smrg */ 2167ec681f3Smrgstatic void 2177ec681f3Smrgdri_drawable_validate_att(struct dri_context *ctx, 2187ec681f3Smrg struct dri_drawable *drawable, 2197ec681f3Smrg enum st_attachment_type statt) 2207ec681f3Smrg{ 2217ec681f3Smrg enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; 2227ec681f3Smrg unsigned i, count = 0; 2237ec681f3Smrg 2247ec681f3Smrg /* check if buffer already exists */ 2257ec681f3Smrg if (drawable->texture_mask & (1 << statt)) 2267ec681f3Smrg return; 2277ec681f3Smrg 2287ec681f3Smrg /* make sure DRI2 does not destroy existing buffers */ 2297ec681f3Smrg for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 2307ec681f3Smrg if (drawable->texture_mask & (1 << i)) { 2317ec681f3Smrg statts[count++] = i; 2327ec681f3Smrg } 2337ec681f3Smrg } 2347ec681f3Smrg statts[count++] = statt; 2357ec681f3Smrg 2367ec681f3Smrg drawable->texture_stamp = drawable->dPriv->lastStamp - 1; 2377ec681f3Smrg 2387ec681f3Smrg drawable->base.validate(ctx->st, &drawable->base, statts, count, NULL); 2397ec681f3Smrg} 2407ec681f3Smrg 2417ec681f3Smrg/** 2427ec681f3Smrg * These are used for GLX_EXT_texture_from_pixmap 2437ec681f3Smrg */ 2447ec681f3Smrgstatic void 2457ec681f3Smrgdri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, 2467ec681f3Smrg GLint format, __DRIdrawable *dPriv) 2477ec681f3Smrg{ 2487ec681f3Smrg struct dri_context *ctx = dri_context(pDRICtx); 2497ec681f3Smrg struct st_context_iface *st = ctx->st; 2507ec681f3Smrg struct dri_drawable *drawable = dri_drawable(dPriv); 2517ec681f3Smrg struct pipe_resource *pt; 2527ec681f3Smrg 2537ec681f3Smrg if (st->thread_finish) 2547ec681f3Smrg st->thread_finish(st); 2557ec681f3Smrg 2567ec681f3Smrg dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT); 2577ec681f3Smrg 2587ec681f3Smrg /* Use the pipe resource associated with the X drawable */ 2597ec681f3Smrg pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; 2607ec681f3Smrg 2617ec681f3Smrg if (pt) { 2627ec681f3Smrg enum pipe_format internal_format = pt->format; 2637ec681f3Smrg 2647ec681f3Smrg if (format == __DRI_TEXTURE_FORMAT_RGB) { 2657ec681f3Smrg /* only need to cover the formats recognized by dri_fill_st_visual */ 2667ec681f3Smrg switch (internal_format) { 2677ec681f3Smrg case PIPE_FORMAT_R16G16B16A16_FLOAT: 2687ec681f3Smrg internal_format = PIPE_FORMAT_R16G16B16X16_FLOAT; 2697ec681f3Smrg break; 2707ec681f3Smrg case PIPE_FORMAT_B10G10R10A2_UNORM: 2717ec681f3Smrg internal_format = PIPE_FORMAT_B10G10R10X2_UNORM; 2727ec681f3Smrg break; 2737ec681f3Smrg case PIPE_FORMAT_R10G10B10A2_UNORM: 2747ec681f3Smrg internal_format = PIPE_FORMAT_R10G10B10X2_UNORM; 2757ec681f3Smrg break; 2767ec681f3Smrg case PIPE_FORMAT_BGRA8888_UNORM: 2777ec681f3Smrg internal_format = PIPE_FORMAT_BGRX8888_UNORM; 2787ec681f3Smrg break; 2797ec681f3Smrg case PIPE_FORMAT_ARGB8888_UNORM: 2807ec681f3Smrg internal_format = PIPE_FORMAT_XRGB8888_UNORM; 2817ec681f3Smrg break; 2827ec681f3Smrg default: 2837ec681f3Smrg break; 2847ec681f3Smrg } 2857ec681f3Smrg } 2867ec681f3Smrg 2877ec681f3Smrg drawable->update_tex_buffer(drawable, ctx, pt); 2887ec681f3Smrg 2897ec681f3Smrg ctx->st->teximage(ctx->st, 2907ec681f3Smrg (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, 2917ec681f3Smrg 0, internal_format, pt, false); 2927ec681f3Smrg } 2937ec681f3Smrg} 2947ec681f3Smrg 2957ec681f3Smrgstatic void 2967ec681f3Smrgdri_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, 2977ec681f3Smrg __DRIdrawable *dPriv) 2987ec681f3Smrg{ 2997ec681f3Smrg dri_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 3007ec681f3Smrg} 3017ec681f3Smrg 3027ec681f3Smrgconst __DRItexBufferExtension driTexBufferExtension = { 3037ec681f3Smrg .base = { __DRI_TEX_BUFFER, 2 }, 3047ec681f3Smrg 3057ec681f3Smrg .setTexBuffer = dri_set_tex_buffer, 3067ec681f3Smrg .setTexBuffer2 = dri_set_tex_buffer2, 3077ec681f3Smrg .releaseTexBuffer = NULL, 3087ec681f3Smrg}; 3097ec681f3Smrg 3107ec681f3Smrg/** 3117ec681f3Smrg * Get the format and binding of an attachment. 3127ec681f3Smrg */ 3137ec681f3Smrgvoid 3147ec681f3Smrgdri_drawable_get_format(struct dri_drawable *drawable, 3157ec681f3Smrg enum st_attachment_type statt, 3167ec681f3Smrg enum pipe_format *format, 3177ec681f3Smrg unsigned *bind) 3187ec681f3Smrg{ 3197ec681f3Smrg switch (statt) { 3207ec681f3Smrg case ST_ATTACHMENT_FRONT_LEFT: 3217ec681f3Smrg case ST_ATTACHMENT_BACK_LEFT: 3227ec681f3Smrg case ST_ATTACHMENT_FRONT_RIGHT: 3237ec681f3Smrg case ST_ATTACHMENT_BACK_RIGHT: 3247ec681f3Smrg /* Other pieces of the driver stack get confused and behave incorrectly 3257ec681f3Smrg * when they get an sRGB drawable. st/mesa receives "drawable->stvis" 3267ec681f3Smrg * though other means and handles it correctly, so we don't really need 3277ec681f3Smrg * to use an sRGB format here. 3287ec681f3Smrg */ 3297ec681f3Smrg *format = util_format_linear(drawable->stvis.color_format); 3307ec681f3Smrg *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 3317ec681f3Smrg break; 3327ec681f3Smrg case ST_ATTACHMENT_DEPTH_STENCIL: 3337ec681f3Smrg *format = drawable->stvis.depth_stencil_format; 3347ec681f3Smrg *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ 3357ec681f3Smrg break; 3367ec681f3Smrg default: 3377ec681f3Smrg *format = PIPE_FORMAT_NONE; 3387ec681f3Smrg *bind = 0; 3397ec681f3Smrg break; 3407ec681f3Smrg } 3417ec681f3Smrg} 3427ec681f3Smrg 3437ec681f3Smrgvoid 3447ec681f3Smrgdri_pipe_blit(struct pipe_context *pipe, 3457ec681f3Smrg struct pipe_resource *dst, 3467ec681f3Smrg struct pipe_resource *src) 3477ec681f3Smrg{ 3487ec681f3Smrg struct pipe_blit_info blit; 3497ec681f3Smrg 3507ec681f3Smrg if (!dst || !src) 3517ec681f3Smrg return; 3527ec681f3Smrg 3537ec681f3Smrg /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample 3547ec681f3Smrg * Fragment Operations): 3557ec681f3Smrg * 3567ec681f3Smrg * If a framebuffer object is not bound, after all operations have 3577ec681f3Smrg * been completed on the multisample buffer, the sample values for 3587ec681f3Smrg * each color in the multisample buffer are combined to produce a 3597ec681f3Smrg * single color value, and that value is written into the 3607ec681f3Smrg * corresponding color buffers selected by DrawBuffer or 3617ec681f3Smrg * DrawBuffers. An implementation may defer the writing of the color 3627ec681f3Smrg * buffers until a later time, but the state of the framebuffer must 3637ec681f3Smrg * behave as if the color buffers were updated as each fragment was 3647ec681f3Smrg * processed. The method of combination is not specified. If the 3657ec681f3Smrg * framebuffer contains sRGB values, then it is recommended that the 3667ec681f3Smrg * an average of sample values is computed in a linearized space, as 3677ec681f3Smrg * for blending (see section 4.1.7). 3687ec681f3Smrg * 3697ec681f3Smrg * In other words, to do a resolve operation in a linear space, we have 3707ec681f3Smrg * to set sRGB formats if the original resources were sRGB, so don't use 3717ec681f3Smrg * util_format_linear. 3727ec681f3Smrg */ 3737ec681f3Smrg 3747ec681f3Smrg memset(&blit, 0, sizeof(blit)); 3757ec681f3Smrg blit.dst.resource = dst; 3767ec681f3Smrg blit.dst.box.width = dst->width0; 3777ec681f3Smrg blit.dst.box.height = dst->height0; 3787ec681f3Smrg blit.dst.box.depth = 1; 3797ec681f3Smrg blit.dst.format = dst->format; 3807ec681f3Smrg blit.src.resource = src; 3817ec681f3Smrg blit.src.box.width = src->width0; 3827ec681f3Smrg blit.src.box.height = src->height0; 3837ec681f3Smrg blit.src.box.depth = 1; 3847ec681f3Smrg blit.src.format = src->format; 3857ec681f3Smrg blit.mask = PIPE_MASK_RGBA; 3867ec681f3Smrg blit.filter = PIPE_TEX_FILTER_NEAREST; 3877ec681f3Smrg 3887ec681f3Smrg pipe->blit(pipe, &blit); 3897ec681f3Smrg} 3907ec681f3Smrg 3917ec681f3Smrgstatic void 3927ec681f3Smrgdri_postprocessing(struct dri_context *ctx, 3937ec681f3Smrg struct dri_drawable *drawable, 3947ec681f3Smrg enum st_attachment_type att) 3957ec681f3Smrg{ 3967ec681f3Smrg struct pipe_resource *src = drawable->textures[att]; 3977ec681f3Smrg struct pipe_resource *zsbuf = drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]; 3987ec681f3Smrg 3997ec681f3Smrg if (ctx->pp && src) 4007ec681f3Smrg pp_run(ctx->pp, src, src, zsbuf); 4017ec681f3Smrg} 4027ec681f3Smrg 4037ec681f3Smrgstruct notify_before_flush_cb_args { 4047ec681f3Smrg struct dri_context *ctx; 4057ec681f3Smrg struct dri_drawable *drawable; 4067ec681f3Smrg unsigned flags; 4077ec681f3Smrg enum __DRI2throttleReason reason; 4087ec681f3Smrg bool swap_msaa_buffers; 4097ec681f3Smrg}; 4107ec681f3Smrg 4117ec681f3Smrgstatic void 4127ec681f3Smrgnotify_before_flush_cb(void* _args) 4137ec681f3Smrg{ 4147ec681f3Smrg struct notify_before_flush_cb_args *args = (struct notify_before_flush_cb_args *) _args; 4157ec681f3Smrg struct st_context_iface *st = args->ctx->st; 4167ec681f3Smrg struct pipe_context *pipe = st->pipe; 4177ec681f3Smrg 4187ec681f3Smrg if (args->drawable->stvis.samples > 1 && 4197ec681f3Smrg (args->reason == __DRI2_THROTTLE_SWAPBUFFER || 4207ec681f3Smrg args->reason == __DRI2_THROTTLE_COPYSUBBUFFER)) { 4217ec681f3Smrg /* Resolve the MSAA back buffer. */ 4227ec681f3Smrg dri_pipe_blit(st->pipe, 4237ec681f3Smrg args->drawable->textures[ST_ATTACHMENT_BACK_LEFT], 4247ec681f3Smrg args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); 4257ec681f3Smrg 4267ec681f3Smrg if (args->reason == __DRI2_THROTTLE_SWAPBUFFER && 4277ec681f3Smrg args->drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && 4287ec681f3Smrg args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { 4297ec681f3Smrg args->swap_msaa_buffers = true; 4307ec681f3Smrg } 4317ec681f3Smrg 4327ec681f3Smrg /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ 4337ec681f3Smrg } 4347ec681f3Smrg 4357ec681f3Smrg dri_postprocessing(args->ctx, args->drawable, ST_ATTACHMENT_BACK_LEFT); 4367ec681f3Smrg 4377ec681f3Smrg if (pipe->invalidate_resource && 4387ec681f3Smrg (args->flags & __DRI2_FLUSH_INVALIDATE_ANCILLARY)) { 4397ec681f3Smrg if (args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) 4407ec681f3Smrg pipe->invalidate_resource(pipe, args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); 4417ec681f3Smrg if (args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]) 4427ec681f3Smrg pipe->invalidate_resource(pipe, args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]); 4437ec681f3Smrg } 4447ec681f3Smrg 4457ec681f3Smrg if (args->ctx->hud) { 4467ec681f3Smrg hud_run(args->ctx->hud, args->ctx->st->cso_context, 4477ec681f3Smrg args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); 4487ec681f3Smrg } 4497ec681f3Smrg 4507ec681f3Smrg pipe->flush_resource(pipe, args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); 4517ec681f3Smrg} 4527ec681f3Smrg 4537ec681f3Smrg/** 4547ec681f3Smrg * DRI2 flush extension, the flush_with_flags function. 4557ec681f3Smrg * 4567ec681f3Smrg * \param context the context 4577ec681f3Smrg * \param drawable the drawable to flush 4587ec681f3Smrg * \param flags a combination of _DRI2_FLUSH_xxx flags 4597ec681f3Smrg * \param throttle_reason the reason for throttling, 0 = no throttling 4607ec681f3Smrg */ 4617ec681f3Smrgvoid 4627ec681f3Smrgdri_flush(__DRIcontext *cPriv, 4637ec681f3Smrg __DRIdrawable *dPriv, 4647ec681f3Smrg unsigned flags, 4657ec681f3Smrg enum __DRI2throttleReason reason) 4667ec681f3Smrg{ 4677ec681f3Smrg struct dri_context *ctx = dri_context(cPriv); 4687ec681f3Smrg struct dri_drawable *drawable = dri_drawable(dPriv); 4697ec681f3Smrg struct st_context_iface *st; 4707ec681f3Smrg unsigned flush_flags; 4717ec681f3Smrg struct notify_before_flush_cb_args args = { 0 }; 4727ec681f3Smrg 4737ec681f3Smrg if (!ctx) { 4747ec681f3Smrg assert(0); 4757ec681f3Smrg return; 4767ec681f3Smrg } 4777ec681f3Smrg 4787ec681f3Smrg st = ctx->st; 4797ec681f3Smrg if (st->thread_finish) 4807ec681f3Smrg st->thread_finish(st); 4817ec681f3Smrg 4827ec681f3Smrg if (drawable) { 4837ec681f3Smrg /* prevent recursion */ 4847ec681f3Smrg if (drawable->flushing) 4857ec681f3Smrg return; 4867ec681f3Smrg 4877ec681f3Smrg drawable->flushing = true; 4887ec681f3Smrg } 4897ec681f3Smrg else { 4907ec681f3Smrg flags &= ~__DRI2_FLUSH_DRAWABLE; 4917ec681f3Smrg } 4927ec681f3Smrg 4937ec681f3Smrg if ((flags & __DRI2_FLUSH_DRAWABLE) && 4947ec681f3Smrg drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { 4957ec681f3Smrg /* We can't do operations on the back buffer here, because there 4967ec681f3Smrg * may be some pending operations that will get flushed by the 4977ec681f3Smrg * call to st->flush (eg: FLUSH_VERTICES). 4987ec681f3Smrg * Instead we register a callback to be notified when all operations 4997ec681f3Smrg * have been submitted but before the call to st_flush. 5007ec681f3Smrg */ 5017ec681f3Smrg args.ctx = ctx; 5027ec681f3Smrg args.drawable = drawable; 5037ec681f3Smrg args.flags = flags; 5047ec681f3Smrg args.reason = reason; 5057ec681f3Smrg } 5067ec681f3Smrg 5077ec681f3Smrg flush_flags = 0; 5087ec681f3Smrg if (flags & __DRI2_FLUSH_CONTEXT) 5097ec681f3Smrg flush_flags |= ST_FLUSH_FRONT; 5107ec681f3Smrg if (reason == __DRI2_THROTTLE_SWAPBUFFER) 5117ec681f3Smrg flush_flags |= ST_FLUSH_END_OF_FRAME; 5127ec681f3Smrg 5137ec681f3Smrg /* Flush the context and throttle if needed. */ 5147ec681f3Smrg if (dri_screen(ctx->sPriv)->throttle && 5157ec681f3Smrg drawable && 5167ec681f3Smrg (reason == __DRI2_THROTTLE_SWAPBUFFER || 5177ec681f3Smrg reason == __DRI2_THROTTLE_FLUSHFRONT)) { 5187ec681f3Smrg 5197ec681f3Smrg struct pipe_screen *screen = drawable->screen->base.screen; 5207ec681f3Smrg struct pipe_fence_handle *new_fence = NULL; 5217ec681f3Smrg 5227ec681f3Smrg st->flush(st, flush_flags, &new_fence, args.ctx ? notify_before_flush_cb : NULL, &args); 5237ec681f3Smrg 5247ec681f3Smrg /* throttle on the previous fence */ 5257ec681f3Smrg if (drawable->throttle_fence) { 5267ec681f3Smrg screen->fence_finish(screen, NULL, drawable->throttle_fence, PIPE_TIMEOUT_INFINITE); 5277ec681f3Smrg screen->fence_reference(screen, &drawable->throttle_fence, NULL); 5287ec681f3Smrg } 5297ec681f3Smrg drawable->throttle_fence = new_fence; 5307ec681f3Smrg } 5317ec681f3Smrg else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { 5327ec681f3Smrg st->flush(st, flush_flags, NULL, args.ctx ? notify_before_flush_cb : NULL, &args); 5337ec681f3Smrg } 5347ec681f3Smrg 5357ec681f3Smrg if (drawable) { 5367ec681f3Smrg drawable->flushing = false; 5377ec681f3Smrg } 5387ec681f3Smrg 5397ec681f3Smrg /* Swap the MSAA front and back buffers, so that reading 5407ec681f3Smrg * from the front buffer after SwapBuffers returns what was 5417ec681f3Smrg * in the back buffer. 5427ec681f3Smrg */ 5437ec681f3Smrg if (args.swap_msaa_buffers) { 5447ec681f3Smrg struct pipe_resource *tmp = 5457ec681f3Smrg drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; 5467ec681f3Smrg 5477ec681f3Smrg drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = 5487ec681f3Smrg drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; 5497ec681f3Smrg drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; 5507ec681f3Smrg 5517ec681f3Smrg /* Now that we have swapped the buffers, this tells the gallium 5527ec681f3Smrg * frontend to revalidate the framebuffer. 5537ec681f3Smrg */ 5547ec681f3Smrg p_atomic_inc(&drawable->base.stamp); 5557ec681f3Smrg } 5567ec681f3Smrg} 5577ec681f3Smrg 5587ec681f3Smrg/** 5597ec681f3Smrg * dri_throttle - A DRI2ThrottleExtension throttling function. 5607ec681f3Smrg */ 5617ec681f3Smrgstatic void 5627ec681f3Smrgdri_throttle(__DRIcontext *cPriv, __DRIdrawable *dPriv, 5637ec681f3Smrg enum __DRI2throttleReason reason) 5647ec681f3Smrg{ 5657ec681f3Smrg dri_flush(cPriv, dPriv, 0, reason); 5667ec681f3Smrg} 5677ec681f3Smrg 5687ec681f3Smrg 5697ec681f3Smrgconst __DRI2throttleExtension dri2ThrottleExtension = { 5707ec681f3Smrg .base = { __DRI2_THROTTLE, 1 }, 5717ec681f3Smrg 5727ec681f3Smrg .throttle = dri_throttle, 5737ec681f3Smrg}; 5747ec681f3Smrg 5757ec681f3Smrg 5767ec681f3Smrg/* vim: set sw=3 ts=8 sts=3 expandtab: */ 577